convoy docs
Search

Deploy a Helm chart

Deploy the podinfo Helm chart from a HelmRegistry, and from an OCIRegistry as a variant.

This guide deploys the podinfo Helm chart to the cluster where convoy runs. The chart comes from a HelmRegistry, which is an HTTP Helm repository with an index.yaml. The Release selects the chart name and an exact chart version. It also adds two Helm values layers: a file from a Git repository and an inline layer. At the end, the guide shows the same task with an OCIRegistry source.

Before you start#

  • convoy runs in the cluster.
  • kubectl and the kubectl convoy plugin are on your PATH.
  • You can create convoy objects in the default namespace. All examples use this namespace.

Steps#

1. Create the target Cluster#

  1. Save this manifest as cluster-auth-in-cluster.yaml:

    clusters/cluster-auth-in-cluster.yaml
    apiVersion: core.convoy.kumodo.io/v1alpha1
       kind: Cluster
       metadata:
         name: dev-local
         namespace: default
       spec:
         connectionMode: inCluster
         metadata:
           type: kind
           role: managed
       
  2. Apply the manifest:

    sh
    kubectl apply -f cluster-auth-in-cluster.yaml
  3. Wait until the Cluster is ready:

    sh
    kubectl wait --for=condition=Ready clusters.core.convoy.kumodo.io/dev-local -n default --timeout=2m

The inCluster mode uses the credentials of the convoy pod. A Release does not render or apply while its Cluster is not reachable. The Applied reason is then ClusterNotReady.

2. Create the sources#

  1. Save this manifest as helmregistry-podinfo.yaml:

    sources/helmregistry-podinfo.yaml
    apiVersion: source.convoy.kumodo.io/v1alpha1
       kind: HelmRegistry
       metadata:
         name: podinfo
         namespace: default
       spec:
         auth:
           type: none
         interval: 1m0s
         minSyncInterval: 30s
         tls:
           insecureSkipVerify: true
         url: https://stefanprodan.github.io/podinfo
       
  2. Save this manifest as gitrepository-podinfo-values.yaml:

    sources/gitrepository-podinfo-values.yaml
    apiVersion: source.convoy.kumodo.io/v1alpha1
       kind: GitRepository
       metadata:
         name: podinfo-values
         namespace: default
       spec:
         auth:
           type: none
         interval: 1m0s
         minSyncInterval: 30s
         tls:
           insecureSkipVerify: true
         url: https://github.com/BROngineer/podinfo-values.git
       
  3. Apply the two manifests:

    sh
    kubectl apply -f helmregistry-podinfo.yaml -f gitrepository-podinfo-values.yaml

The HelmRegistry holds the chart. The GitRepository holds a values file for the chart. A source does not select a version. The Release selects it.

A Release does not wait for the Ready condition of a source. It fetches the content directly. If the fetch fails, the Applied reason of the Release is SourceNotReady or ValuesNotReady.

3. Create the Release#

  1. Save this manifest as release-helmregistry-helm-in-cluster.yaml:

    releases/release-helmregistry-helm-in-cluster.yaml
    apiVersion: core.convoy.kumodo.io/v1alpha1
       kind: Release
       metadata:
         name: podinfo-helmreg-in-cluster
         namespace: default
       spec:
         clusterRef:
           name: dev-local
         source:
           type: helmRegistry
           helmRegistry:
             name: podinfo
             namespace: default
             chart:
               name: podinfo
               version: "6.12.0"
         content:
           type: helm
           helm:
             releaseName: podinfo-from-helmreg
             releaseNamespace: default
             dependencyMode: vendored
             values:
               - type: gitRepository
                 gitRepository:
                   name: podinfo-values
                   namespace: default
                   ref:
                     branch: main
                   paths:
                     - podinfo/values.yaml
               - type: inline
                 inline:
                   image:
                     tag: 6.13.0
         syncPolicy:
           automatic: true
           prune:
             orphaned: false
             includeCRDs: false
             includeNamespaces: false
           interval: 1m
       
  2. Apply the manifest:

    sh
    kubectl apply -f release-helmregistry-helm-in-cluster.yaml
  3. Wait until convoy applies the render:

    sh
    kubectl wait --for=condition=Applied release/podinfo-helmreg-in-cluster -n default --timeout=5m

The Release has these parts:

  • spec.source.helmRegistry.chart. The chart name and the chart version. The version must be exact. convoy does not resolve a version range.
  • spec.content.helm.values. Two values layers. convoy merges them in list order, and a later layer wins. The inline image.tag replaces the tag from the Git file. Helm then merges the result over the values.yaml of the chart.
  • dependencyMode: vendored. The chart must contain its dependencies in charts/. convoy does not download dependencies.
  • spec.syncPolicy.automatic: true. convoy applies the render at each reconcile.

All references of a Release must be in the namespace of the Release. This includes the Cluster, the source and each gitRepository values layer. The API server rejects a reference to another namespace.

releaseNamespace sets only .Release.Namespace in the chart templates. convoy applies a namespaced object without metadata.namespace to the default namespace.

Check the result#

  1. Show the Release:

    sh
    kubectl get releases -n default

    The header line is NAME CONTENT SOURCE CLUSTER STATE APPLIED INSYNC HEALTHY LIFECYCLE AGE. For podinfo-helmreg-in-cluster, make sure that APPLIED is True.

  2. Show the objects of the render:

    sh
    kubectl convoy release preview podinfo-helmreg-in-cluster -n default
  3. Show the health of each object:

    sh
    kubectl convoy release health podinfo-helmreg-in-cluster -n default

The Release has no spec.healthAssessment. The observer then sets Healthy=True with reason NotConfigured.

If APPLIED is not True, read the reason of the Applied condition:

sh
kubectl describe release podinfo-helmreg-in-cluster -n default

Applied · written by convoy-controller-manager (field manager convoy-release)

ReasonStatusMeaning
AppliedTrueconvoy applied the current render. In manual sync mode, the current render is equal to the last applied render.
SourceNotReadyFalseconvoy could not fetch the source. convoy retries.
ValuesNotReadyFalseconvoy could not read a Helm values layer (a ConfigMap, a Secret or a GitRepository path). convoy retries.
ClusterNotReadyFalseThe Cluster does not exist or is not reachable. convoy retries.
UnsupportedFalseThe Release uses a feature that convoy does not implement, for example a Git semver ref, Helm dependencyMode: resolve or jsonnet content. This is a configuration error, so convoy does not retry with backoff.
UnappliableFalseThe target cluster rejected the render in the pre-apply server-side dry run. convoy applies nothing. A forced /sync skips the dry run.
DeployFailedFalseRendering, mutation or the apply failed. The message and status.lastAttempted.failure.stage tell which step failed. convoy retries.
PruneFailedFalseconvoy applied the render, but could not delete an object that the render no longer contains. convoy retries.
PinnedFalseconvoy cannot apply the pinned render, because no render store is configured or the store does not contain that render.
WaitingForSyncFalseManual sync mode. The current render differs from the last applied render. convoy waits for a /sync request.
WaitingForWaveHealthFalseA sync wave waits until the resources of the previous wave are healthy.
WaveFailedFalseA sync wave timed out while it waited for the previous wave. The Release has no failurePolicy.
RolloutFailedFalseA sync wave timed out while it waited for the previous wave, and the failurePolicy did not roll back.
RolledBackTrueThe rollout failed and convoy applied the last healthy render again.
WaitingForClusterWaveFalseThe Release waits for the Releases of a lower cluster wave on the same Cluster.
ClusterWaveFailedFalseThe Releases of a lower cluster wave did not become ready before the cluster-wave timeout.
WaitingForHookFalseconvoy waits for the workloads of a lifecycle hook phase to complete.
HookFailedFalseA lifecycle hook with onFailure: Fail failed. convoy stops the sync.

Variant: deploy the chart from an OCIRegistry#

An OCIRegistry source pulls Helm charts from an OCI registry. It does not pull other artifact types. The Release selects the artifact name and an exact tag.

  1. Save this manifest as ociregistry-podinfo.yaml:

    sources/ociregistry-podinfo.yaml
    apiVersion: source.convoy.kumodo.io/v1alpha1
       kind: OCIRegistry
       metadata:
         name: podinfo
         namespace: default
       spec:
         auth:
           type: none
         interval: 1m0s
         minSyncInterval: 30s
         tls:
           insecureSkipVerify: true
         url: oci://ghcr.io/stefanprodan/charts
         defaultContentType: helm
       
  2. Save this manifest as release-ociregistry-helm-in-cluster.yaml:

    releases/release-ociregistry-helm-in-cluster.yaml
    apiVersion: core.convoy.kumodo.io/v1alpha1
       kind: Release
       metadata:
         name: podinfo-ocireg-in-cluster
         namespace: default
       spec:
         clusterRef:
           name: dev-local
         source:
           type: ociRegistry
           ociRegistry:
             name: podinfo
             namespace: default
             artifact:
               name: podinfo
               version: "6.10.2"
         content:
           type: helm
           helm:
             releaseName: podinfo-from-ocireg
             releaseNamespace: default
             dependencyMode: vendored
         syncPolicy:
           automatic: true
           prune:
             orphaned: false
             includeCRDs: false
             includeNamespaces: false
           interval: 1m
           waveStrategy:
             strategy: waitForApplied
             wave: 1
       
  3. Apply the two manifests:

    sh
    kubectl apply -f ociregistry-podinfo.yaml -f release-ociregistry-helm-in-cluster.yaml
  4. Wait until convoy applies the render:

    sh
    kubectl wait --for=condition=Applied release/podinfo-ocireg-in-cluster -n default --timeout=5m

This Release has no values layers. Helm uses the values.yaml of the chart.

This Release sets spec.syncPolicy.waveStrategy to wave 1 with waitForApplied. convoy applies it only after each Release with a lower wave on the same Cluster has Applied=True. The Release from step 3 has wave 0. Until that Release has Applied=True, the Applied reason of this Release is WaitingForClusterWave. See Sync waves.

Clean up#

  1. Delete the Releases:

    sh
    kubectl delete release podinfo-helmreg-in-cluster podinfo-ocireg-in-cluster -n default
  2. Delete the sources:

    sh
    kubectl delete -f helmregistry-podinfo.yaml -f gitrepository-podinfo-values.yaml -f ociregistry-podinfo.yaml
  3. Delete the Cluster, if no other Release uses it:

    sh
    kubectl delete -f cluster-auth-in-cluster.yaml

Delete the Releases before the Cluster. A Release finalizer deletes the objects of the Release from the target cluster. If the Cluster does not exist, the objects stay on the cluster. See Deletion.

Next steps#

In the code

convoy v0.9.0