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 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. Start by
creating a blank directory to hold the platform configuration.
mkdir holos-tutorial && cd holos-tutorial
Use the holos init platform
command to initialize a minimal platform in the
blank directory.
holos init platform v1alpha5
Here's the filesystem tree we'll build in this tutorial.
- Tree
- Details
holos-tutorial/
├── components/
│ └── podinfo/
│ └── podinfo.cue
├── cue.mod/
├── platform/
│ ├── platform.gen.cue
│ └── podinfo.cue
├── resources.cue
├── schema.cue
└── tags.cue
holos-tutorial/
├── components/
│ └── podinfo/
│ └── podinfo.cue
├── cue.mod/
├── platform/
│ ├── platform.gen.cue
│ └── podinfo.cue
├── resources.cue
├── schema.cue
└── tags.cue
- Line 1 The platform root is the
holos-tutorial
directory we created. - Line 2 This tutorial places components in
components/
. They may reside anywhere. - Line 3 A component is a collection of
*.cue
files at a path. - Line 4 We'll create this file and configure the podinfo helm chart in the next section.
- Line 5 The CUE module directory. Schema definitions for Kubernetes and
Holos resources reside within the
cue.mod
directory. - Line 6 The platform directory is the main entrypoint for the
holos render platform
command. - Line 7
platform.gen.cue
is initialized byholos init platform
and contains the Platform spec. - Line 8
podinfo.cue
integrates podinfo with the platform by adding the component to the platform spec. We'll add ths file after the next section. - Line 9
resources.cue
Defines the Kubernetes resources available to manage in CUE. - Line 10
schema.cue
Defines the configuration common to all component kinds. - Line 11
tags.cue
Defines where component parameter values are injected into the overall platform configuration. We don't need to be concerned with this file until we cover component parameters. - Lines 9-11 Initialized by
holos init platform
, user editable after initialization.
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.
- Podinfo Helm Chart
mkdir -p components/podinfo
touch components/podinfo/podinfo.cue
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"
}
}
// Holos marshals Values into values.yaml for Helm.
Values: {
// message is a string with a default value. @tag indicates a value may
// be injected from the platform spec component parameters.
ui: {
message: string | *"Hello World" @tag(greeting, type=string)
}
}
}
CUE loads all of *.cue
files in the component directory to define component,
similar to Go packages.
CUE also loads all *.cue
files from the component leaf directory to the
platform root directory. In this example, #Helm
on line 6 is defined in
schema.cue
at the root.
Integrating the component
Integrate the podinfo
component into the platform by creating a new cue file
in the platform
directory with the following content.
- Register Podinfo
touch platform/podinfo.cue
package holos
Platform: Components: podinfo: {
name: "podinfo"
path: "components/podinfo"
// Inject a value into the component.
parameters: greeting: "Hello Holos!"
}
Component parameters may have any name as long as they don't start with
holos_
.
Rendering manifests
Render a manifest for podinfo
using the holos render platform ./platform
command. The platform/
directory is the main entrypoint for this command.
- Command
- Output
holos render platform ./platform
cached podinfo 6.6.2
rendered podinfo in 1.938665041s
rendered platform in 1.938759417s
Holos rendered the following manifest file by executing helm template
after
caching podinfo
locally.
deploy/components/podinfo/podinfo.gen.yaml
- Service
- Deployment
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_MESSAGE
value: Hello Holos!
- 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
Holos renders the component with the greeting injected from the platform spec.
grep -B2 Hello deploy/components/podinfo/podinfo.gen.yaml
env:
- name: PODINFO_UI_MESSAGE
value: Hello Holos!
Breaking it down
We run holos render platform ./platform
because the cue files in the platform
directory export a Platform resource to holos
. The platform directory is
the entrypoint to the platform rendering process.
Components are the building blocks for a Platform. The platform/podinfo.cue
file integrates the podinfo
Component with the Platform.
Holos requires two fields to integrate a component with the platform.
- A unique name for the component.
- The component path to the directory containing the cue files exporting a
BuildPlan
defining the component.
Component parameters are optional. They allow re-use of the same component. Refer to the Component Parameters topic for more information.
- Rendering Overview
- Platform Sequence
- Component Sequence
Take a look at the other tabs for more detailed sequence diagrams.
Next Steps
We've shown how to integrate one Helm chart to the Platform, but we haven't yet covered multiple Helm charts. Continue on with the next tutorial to learn how Holos makes it easy to inject values into multiple components safely and easily.