Files
holos/doc/md/tutorial/hello-holos.mdx
Nate McCurdy 767ea69d2e docs: Add a tree view to Hello Holos
A tree view of the `holos-tutorial/` directory should give readers a
quick, high-level understanding of the folder structure of a typical
Holos platform project.
2024-11-11 14:04:40 -07:00

362 lines
9.4 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
slug: hello-holos
title: Hello Holos
description: Configure a simple Hello World service with Holos.
sidebar_position: 30
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import RenderingOverview from '@site/src/diagrams/rendering-overview.mdx';
import PlatformSequence from '@site/src/diagrams/render-platform-sequence.mdx';
import ComponentSequence from '@site/src/diagrams/render-component-sequence.mdx';
# Hello Holos
## Overview
One of the first exercises we do when learning a new programming language is
printing out a "Hello World!" greeting. Hello Holos configures the [podinfo Helm
chart][podinfo] producing a similar greeting from a Kubernetes Service.
By the end of this tutorial you have an understanding of how to wrap a Helm
Chart as a Holos Component.
## The Code
### Generating the structure
Use `holos` to generate a minimal platform directory structure. First, create
and cd into a blank directory. Then use the `holos init platform` command to
generate a minimal platform.
```shell
mkdir holos-tutorial
cd holos-tutorial
holos init platform v1alpha5
```
Holos creates a `platform` directory containing a `platform.gen.cue` file. This
file is the entry point for your new platform configuration. You'll integrate
components into the platform using the CUE code in this `platform` directory.
### Creating a component
Start by creating a directory for the `podinfo` component. Create an empty file
and then add the following CUE configuration to it.
<Tabs groupId="tutorial-hello-podinfo-helm-cue-code">
<TabItem value="components/podinfo/podinfo.cue" label="Podinfo Helm Chart">
```bash
mkdir -p components/podinfo
touch components/podinfo/podinfo.cue
```
```cue showLineNumbers
package holos
// Produce a helm chart build plan.
holos: HelmChart.BuildPlan
HelmChart: #Helm & {
Name: "podinfo"
Chart: {
version: "6.6.2"
repository: {
name: "podinfo"
url: "https://stefanprodan.github.io/podinfo"
}
}
}
```
</TabItem>
</Tabs>
### Integrating the component
Integrate the `podinfo` component by creating a new file in the `platform`
directory with the following CUE code:
<Tabs groupId="tutorial-hello-register-podinfo-component">
<TabItem value="platform/podinfo.cue" label="Register Podinfo">
```bash
touch platform/podinfo.cue
```
```cue showLineNumbers
package holos
Platform: Components: podinfo: {
name: "podinfo"
path: "components/podinfo"
}
```
</TabItem>
</Tabs>
## Rendering manifests
Render a manifest for `podinfo` using the `holos render platform ./platform`
command.
<Tabs groupId="tutorial-hello-render-manifests">
<TabItem value="command" label="Command">
```bash
holos render platform ./platform
```
</TabItem>
<TabItem value="output" label="Output">
```
cached podinfo 6.6.2
rendered podinfo in 1.938665041s
rendered platform in 1.938759417s
```
</TabItem>
<TabItem value="manifest" label="Rendered Manifest">
```txt
deploy/components/podinfo/podinfo.gen.yaml
```
```yaml showLineNumbers
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: podinfo
app.kubernetes.io/version: 6.6.2
helm.sh/chart: podinfo-6.6.2
name: podinfo
spec:
ports:
- name: http
port: 9898
protocol: TCP
targetPort: http
- name: grpc
port: 9999
protocol: TCP
targetPort: grpc
selector:
app.kubernetes.io/name: podinfo
type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: podinfo
app.kubernetes.io/version: 6.6.2
helm.sh/chart: podinfo-6.6.2
name: podinfo
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: podinfo
strategy:
rollingUpdate:
maxUnavailable: 1
type: RollingUpdate
template:
metadata:
annotations:
prometheus.io/port: "9898"
prometheus.io/scrape: "true"
labels:
app.kubernetes.io/name: podinfo
spec:
containers:
- command:
- ./podinfo
- --port=9898
- --cert-path=/data/cert
- --port-metrics=9797
- --grpc-port=9999
- --grpc-service-name=podinfo
- --level=info
- --random-delay=false
- --random-error=false
env:
- name: PODINFO_UI_COLOR
value: '#34577c'
image: ghcr.io/stefanprodan/podinfo:6.6.2
imagePullPolicy: IfNotPresent
livenessProbe:
exec:
command:
- podcli
- check
- http
- localhost:9898/healthz
failureThreshold: 3
initialDelaySeconds: 1
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
name: podinfo
ports:
- containerPort: 9898
name: http
protocol: TCP
- containerPort: 9797
name: http-metrics
protocol: TCP
- containerPort: 9999
name: grpc
protocol: TCP
readinessProbe:
exec:
command:
- podcli
- check
- http
- localhost:9898/readyz
failureThreshold: 3
initialDelaySeconds: 1
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
resources:
limits: null
requests:
cpu: 1m
memory: 16Mi
volumeMounts:
- mountPath: /data
name: data
terminationGracePeriodSeconds: 30
volumes:
- emptyDir: {}
name: data
```
</TabItem>
</Tabs>
Holos rendered the `deploy/components/podinfo/podinfo.gen.yaml` file by
executing `helm template` after caching `podinfo` locally.
## Breaking it down
Heres a quick review of the files we created and their purpose:
```text
holos-tutorial/
├── components/
│   └── podinfo/
│   └── podinfo.cue
├── cue.mod/
├── platform/
│   ├── platform.gen.cue
│   └── podinfo.cue
├── resources.cue
├── schema.cue
└── tags.cue
```
#### `components/podinfo/podinfo.cue`
Configures the `podinfo` Helm chart as a holos component.
#### `cue.mod`
[CUE Module] directory containing schema definitions for Kubernetes resources.
#### `platform/platform.gen.cue`
Exports the [Platform] spec from CUE to `holos` for processing.
#### `platform/podinfo.cue`
Integrates the `podinfo` Helm component into the platform.
#### `resources.cue`
Defines the `#Resources` schema of common Kubernetes resources.
#### `schema.cue`
Configures the `#Helm`, `#Kustomize`, and `#Kubernetes` common component kinds
by composing the `#ComponentConfig` schema definition into each schema
definition. The component kinds behave consistently as a result.
#### `tags.cue`
Holds parameter values passed from `holos render platform` to `holos render
component` injected via [CUE Tags].
<Tabs groupId="67C1EE71-3EA8-4568-9F6D-0072BA09FF12">
<TabItem value="overview" label="Rendering Overview">
Take a look at the other tabs for more detailed sequence diagrams.
<RenderingOverview />
</TabItem>
<TabItem value="platform" label="Platform Sequence">
<PlatformSequence />
</TabItem>
<TabItem value="component" label="Component Sequence">
<ComponentSequence />
</TabItem>
</Tabs>
We run `holos render platform` against the `platform` directory because that
directory exports a [Platform] resource to `holos`. The platform directory is
effectively the entrypoint into the rendering process.
Components are the building blocks for a Platform, and without them `holos
render platform` does nothing. The `platform/podinfo.cue` file integrates the
`podinfo` Component with the Platform.
Holos requires two things to integrate a component with the platform.
1. A unique name for the component.
2. The component filesystem path.
:::important
Components can be parameterized.
:::
The Platform spec can re-use the same component path providing it varying input
parameters. This is covered in the [Component Parameters] topic.
:::tip
Holos makes it easy to re-use a Helm chart with multiple customers and
environments. This is not well supported by Helm alone.
:::
The `components/podinfo/podinfo.cue` file unifies the `#Helm`
definition, indicating that we're configuring a Helm chart, along with the
`podinfo` chart's version and repository information. If we wanted to customize
the `podinfo` chart and change any of the chart's values, we would make those
changes here. For example, we could change the message being displayed by
passing the `ui.message` value to the chart:
```cue
HelmChart: #Helm & {
Name: "podinfo"
Chart: {
version: "6.6.2"
repository: {
name: "podinfo"
url: "https://stefanprodan.github.io/podinfo"
}
}
Values: {
ui: message: "Hello Holos from Podinfo!"
}
}
```
Holos repeats this process for every Component added to the Platform, and since `podinfo`
is the only Component, we're done!
## Next Steps
We've shown how to add a single Helm chart to the Platform, but what if you have
more than one Helm chart and they all need to access the same data? Continue on
with the next tutorial to learn how Holos makes it easy to pass data to multiple
components and Helm Charts.
[podinfo]: https://github.com/stefanprodan/podinfo
[CUE Module]: https://cuelang.org/docs/reference/modules/
[CUE Tags]: https://cuelang.org/docs/howto/inject-value-into-evaluation-using-tag-attribute/
[Platform]: ../api/author.md#Platform
[Component Parameters]: ../topics/component-parameters.mdx