mirror of
https://github.com/holos-run/holos.git
synced 2026-03-20 01:04:59 +00:00
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.
362 lines
9.4 KiB
Plaintext
362 lines
9.4 KiB
Plaintext
---
|
||
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
|
||
|
||
Here’s 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
|