Skip to main content

Quickstart

In this guide, you'll experience how Holos makes the process of operating a Platform safer, easier, and more consistent. We'll use Holos to manage a vendor-provided Helm chart as a Component. Next, we'll mix in our own custom resources to manage the Component with GitOps. Finally, you'll see how Holos makes it safer and easier to maintain software over time by surfacing the exact changes that will be applied when upgrading the vendor's chart to a new version, before they are actually made.

The Concepts page defines capitalized terms such as Platform and Component.

What you'll need

You'll need the following tools installed to complete this guide.

  1. holos - to build the Platform.
  2. helm - to render Holos Components that wrap upstream Helm charts.

Optionally, if you'd like to apply the rendered manifests to a real Cluster, first complete the Local Cluster Guide.

Install Holos

Install Holos with the following command or other methods listed on the Installation page.

go install github.com/holos-run/holos/cmd/holos@latest

Create a Git Repository

Start by initializing an empty Git repository. Holos operates on local files stored in a Git repository.

mkdir holos-quickstart
cd holos-quickstart
git init

This guide assumes you will run commands from the root directory of the Git repository unless stated otherwise.

Generate the Platform

Generate the Platform code in the repository root. A Platform refers to the entire set of software holistically integrated to provide a software development platform for your organization. In this guide, the Platform will include a single Component to demonstrate how the concepts fit together.

holos generate platform quickstart

Commit the generated platform config to the repository.

git add .
git commit -m "holos generate platform quickstart - $(holos --version)"

Generate a Component

The platform you generated is currently empty. Run the following command to generate the CUE code that defines a Helm Component.

holos generate component podinfo --component-version 6.6.1

The --component-version 6.6.1 flag intentionally installs an older release. You'll see how Holos assists with software upgrades later in this guide.

The generate component command creates two files: a leaf file, components/podinfo/podinfo.gen.cue, and a root file, podinfo.gen.cue. Holos leverages the fact that order is irrelevant in CUE to register the component with the Platform by adding a file to the root of the Git repository. The second file defines the component in the leaf component directory.

components/podinfo/podinfo.gen.cue

package holos

// Produce a helm chart build plan.
(#Helm & Chart).Output

let Chart = {
Name: "podinfo"
Version: "6.6.1"
Namespace: "default"

Repo: name: "podinfo"
Repo: url: "https://stefanprodan.github.io/podinfo"

Values: {}
}

In this example, we provide the minimal information needed to manage the Helm chart: the name, version, Kubernetes namespace for deployment, and the chart repository location.

This chart deploys cleanly without any values provided, but we include an empty Values struct to show how Holos improves consistency and safety in Helm by leveraging the strong type-checking in CUE. You can safely pass shared values, such as the organization’s domain name, to all Components across all clusters in the Platform by defining them at the root of the configuration.

Commit the generated component config to the repository.

git add .
git commit -m "holos generate component podinfo - $(holos --version)"

Render the Component

You can render individual components without adding them to a Platform, which is helpful when developing a new component.

holos render component ./components/podinfo --cluster-name=default

First, the command caches the Helm chart locally to speed up subsequent renderings. Then, the command runs Helm to produce the output and writes it into the deploy directory.

tree deploy

The component deploys to one cluster named default. In practice, the same component is often deployed to multiple clusters, such as east and west to provide redundancy and increase availability.

tip

This example is equivalent to running helm template on the chart and saving the output to a file. Holos simplifies this task, making it safer and more consistent when managing many charts.

Mix in an ArgoCD Application

We've seen how Holos works with Helm, but we haven't yet explored how Holos makes it easier to consistently and safely manage all of the software in a Platform.

Holos allows you to easily mix in resources that differentiate your Platform. We'll use this feature to mix in an ArgoCD Application to manage the podinfo Component with GitOps. We'll define this configuration in a way that can be automatically and consistently reused across all future Components added to the Platform.

Create a new file named argocd.cue in the root of your Git repository with the following contents:

package holos

#ArgoConfig: {
Enabled: true
RepoURL: "https://github.com/holos-run/holos-quickstart-guide"
}
tip

If you plan to apply the rendered output to a real cluster, change the example.com RepoURL to the URL of the Git repository you created in this guide. You don't need to change the example if you're just exploring Holos by inspecting the rendered output without applying it to a live cluster.

With this file in place, render the component again.

holos render component ./components/podinfo --cluster-name=default

Holos uses the locally cached chart to improve performance and reliability. It then renders the Helm template output along with an ArgoCD Application resource for GitOps.

tip

By defining the ArgoCD configuration at the root, we again take advantage of the fact that order is irrelevant in CUE.

Defining the configuration at the root ensures all future leaf Components take the ArgoCD configuration and render an Application manifest for GitOps management.

tree deploy

Notice the new podinfo.application.gen.yaml file created by enabling ArgoCD in the Helm component. The Application resource in the file looks like this:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: podinfo
namespace: argocd
spec:
destination:
server: https://kubernetes.default.svc
project: default
source:
path: ./deploy/clusters/default/components/podinfo
repoURL: https://example.com/holos-quickstart.git
targetRevision: main
tip

Holos generates a similar Application resource for every additional Component added to your Platform.

Finally, add and commit the results to your Platform's Git repository.

git add .
git commit -m "holos render component ./components/podinfo --cluster-name=default"

In this section, we learned how Holos simplifies mixing resources into Components, like an ArgoCD Application. Holos ensures consistency by managing an Application resource for every Component added to the Platform through the configuration you define in argocd.cue at the root of the repository.

Define Workload Clusters

We've generated a Component to manage podinfo and integrated it with our Platform, but rendering the Platform doesn't render podinfo. Podinfo isn't rendered because we haven't assigned any Clusters to the workload Fleet.

Define two new clusters, east and west, and assign them to the workload Fleet. Create a new file named clusters.cue in the root of your Git repository with the following contents:

package holos

// Define two workload clusters for disaster recovery.
#Fleets: workload: clusters: {
// In CUE _ indicates values are defined elsewhere.
east: _
west: _
}

This example shows how Holos simplifies configuring multiple clusters with similar configuration by grouping them into a Fleet.

tip

Fleets help segment a group of Clusters into one leader and multiple followers by designating one cluster as the primary. Holos makes it safer, easier, and more consistent to reconfigure which cluster is the primary. The primary can be set to automatically restore persistent data from backups, while non-primary clusters can be configured to automatically replicate from the primary.

Automatic database backup, restore, and streaming replication is an advanced topic enabled by Cloud Native PG and CUE. Check back for a guide on this and other Day 2 operations topics.

Render the Platform

Render the Platform to render the podinfo Component for each of the workload clusters.

holos render platform ./platform

The render platform command iterates over every Cluster in the Fleet and renders each Component assigned to the Fleet. Notice the two additional subdirectories created under the deploy directory, one for each cluster: east and west.

tree deploy

Holos ensures consistency and safety by defining the ArgoCD Application once, with strong type checking, at the configuration root.

New Application resources are automatically generated for the east and west workload Clusters.

deploy/clusters/east/gitops/podinfo.application.gen.yaml

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: podinfo
namespace: argocd
spec:
destination:
server: https://kubernetes.default.svc
project: default
source:
path: ./deploy/clusters/east/components/podinfo
repoURL: https://example.com/holos-quickstart.git
targetRevision: main

Add and commit the rendered Platform and workload Clusters.

git add .
git commit -m "holos render platform ./platform - $(holos --version)"

Upgrade a Helm Chart

Holos is designed to ease the burden of Day 2 operations. With Holos, upgrading software, integrating new software, and making safe platform-wide configuration changes become easier.

Let's upgrade the podinfo Component to see how this works in practice. First, update the Component version field to the latest upstream Helm chart version.

holos generate component podinfo --component-version 6.6.2

Remove the cached chart version.

rm -rf components/podinfo/vendor

Now re-render the Platform.

holos render platform ./platform

Notice we're still using the upstream chart without modifying it. The Holos component wraps around the chart to mix in additional resources and integrate the component with the broader Platform.

Visualize the Changes

Holos makes it easier to see exactly what changes are made and which resources will be applied to the API server. By design, Holos operates on local files, leaving the task of applying them to ecosystem tools like kubectl and ArgoCD. This allows platform operators to inspect changes during code review, or before committing the change at all.

For example, using git diff, we see that the only functional change when upgrading this Helm chart is the deployment of a new container image tag to each cluster. Additionally, we can roll out this change gradually by applying it to the east cluster first, then to the west cluster, limiting the potential blast radius of a problematic change.

git diff deploy/clusters/east
tip

Holos is designed to surface the fully rendered manifests intended for the Kubernetes API server, making it easier to see and reason about platform-wide configuration changes.

Recap

In this quickstart guide, we learned how Holos makes it easier, safer, and more consistent to manage a Platform composed of multiple Clusters and upstream Helm charts.

We covered how to:

  1. Generate a Git repository for the Platform config.
  2. Wrap the unmodified upstream podinfo Helm chart into a Component.
  3. Render an individual Component.
  4. Mix-in your Platform's unique resources to all Components. For example, ArgoCD Application resources.
  5. Define multiple similar, but not identical, workload clusters.
  6. Render the manifests for the entire Platform with the holos render platform command.
  7. Upgrade a Helm chart to the latest version as an important Day 2 task.
  8. Visualize and surface the details of planned changes Platform wide.

Dive Deeper

If you'd like to dive deeper, check out the Schema API and Core API reference docs. The main difference between the schema and core packages is that the schema is used by users to write refined CUE, while the core package is what the schema produces for holos to execute. Users rarely need to interact with the Core API when on the happy path, but can use the core package as an escape hatch when the happy path doesn't go where you want.