Skip to content

Deploying Helm Charts#

Examples of using a Helm chart as a Template's body. For the chart-source rules, Helm SDK selection, valuesTemplate, release-name semantics, and validation behavior, see Helm. For private repositories, see Deploying private Helm charts.

Scenario 1: public HTTPS repository#

Bill publishes the upstream nginx chart from Bitnami, parameterized so each consumer can pick a replica count.

apiVersion: templates.v2.stakater.com/v2alpha1
kind: Template
metadata:
  name: nginx-template
  namespace: provider
spec:
  helm:
    version: v4   # the default v3 SDK renders this chart's PodDisruptionBudget with the removed policy/v1beta1 API
    chart:
      repository:
        url: https://charts.bitnami.com/bitnami
        name: nginx
        version: 18.1.0
    releaseName: nginx
    valuesTemplate: |
      replicaCount: {{ .parameters.replicas }}
      image:
        repository: bitnamilegacy/nginx   # Bitnami moved its versioned images here
      service:
        type: ClusterIP
  parameters:
    - name: replicas
      value: "2"
  targetNamespaces:
    explicit:
      allow:
        literal:
          - team-a

A consuming TemplateInstance:

apiVersion: templates.v2.stakater.com/v2alpha1
kind: TemplateInstance
metadata:
  name: nginx
  namespace: team-a
spec:
  templateRef:
    name: nginx-template
    namespace: provider
  parameters:
    - name: replicas
      value: "3"

Scenario 2: OCI registry#

OCI-hosted charts use the oci:// scheme. Everything else is identical to the HTTPS case:

spec:
  helm:
    chart:
      repository:
        url: oci://ghcr.io/stakater/charts
        name: my-chart
        version: 0.1.0

Scenario 3: driving values from instance metadata#

valuesTemplate is a Go template, so the consuming TemplateInstance's name, namespace, and labels are available alongside parameters:

spec:
  helm:
    chart:
      repository:
        url: https://charts.example.com
        name: app
        version: 1.0.0
    valuesTemplate: |
      ingress:
        enabled: true
        hosts:
          - host: {{ .instance.name }}.example.com
            paths:
              - path: /
                pathType: Prefix
      resources:
        limits:
          cpu: {{ .parameters.cpuLimit }}
          memory: {{ .parameters.memLimit }}
  parameters:
    - name: cpuLimit
      value: "500m"
    - name: memLimit
      value: "256Mi"

Each TemplateInstance automatically gets an ingress host derived from its own name.

Repository URL rules#

  • spec.helm.chart.repository.url must match the pattern ^(https?|oci)://.
  • version must follow SemVer 2, e.g. 1.2.3, 1.2.3-rc.1+meta. Ranges, latest, and floating versions are rejected at admission time. Write the version without a v prefix: the API accepts v1.2.3, but the chart then fails to load.

Status on failure#

If the chart cannot be pulled, the Template reports:

status:
  phase: Error
  conditions:
    - type: SourceAccessible
      status: "False"
      reason: RepositoryUnreachable
      message: "source access failed: failed to pull chart..."

The reconcile is retried after 60 seconds, so transient registry outages self-heal. See Helm for the full set of conditions and reasons set during validation.

See also#