Step 6: Deploy to Cluster

Deploy helm charts to cluster with helmfile and chamber

The deployment step leverages helmfile to define releases and orchestrate the deployment to the cluster with helm.

We typically store the helmfile.yaml in the application repo under the config/ directory. If a chart depends on some values, then we store these values in config/chart.yaml, which is an envsubst formatted template rendered upon deployment.

Here’s an example of what a typical helmfile looks like:

config/helmfile.yaml

repositories:
  # Cloud Posse incubator repo of helm charts
  - name: "cloudposse-incubator"
    url: "https://charts.cloudposse.com/incubator/"

  # Local chart repo
  - name: "chart-repo"
    url: '{{ env "CHART_REPO_URL" }}'

#
# Kubernetes
#
context: '{{ env "KUBE_CONTEXT" }}'

#
# Helm Releases
#
releases:
  # Pull Secret (.dockercfg)
  - name: '{{ env "NAMESPACE" }}-pull-secret'
    labels:
      chart: "dockercfg"
      component: "secrets"
    chart: "cloudposse-incubator/dockercfg"
    version: "0.1.0"
    namespace: '{{ env "NAMESPACE" }}'
    set:
    - name: "image.pullSecret.registry"
      value: '{{ env "IMAGE_PULL_SECRET_REGISTRY" }}'
    - name: "image.pullSecret.username"
      value: '{{ env "IMAGE_PULL_SECRET_USERNAME" }}'
    - name: "image.pullSecret.password"
      value: '{{ env "IMAGE_PULL_SECRET_PASSWORD" }}'

  # Application
  - name: '{{ env "RELEASE_NAME" }}'
    labels:
      chart: "app"
      component: "app"
    version: '{{ env "CHART_VERSION" }}'
    chart: 'chart-repo/{{ env "CHART_NAME" }}'
    namespace: '{{ env "NAMESPACE" }}'
    values:
      - '{{ env "RELEASE_NAME" }}.yaml'

Here’s an example of what a typical envsubst parameterized helm values file looks like:

config/chart.yaml

env:
  secret:
    API_KEY: "$APP_API_KEY"
    SERVICE_KEY: "$APP_SERVICE_KEY"
resources:
  limits:
    cpu: 300m
    memory: 4128Mi
  requests:
    cpu: 150m
    memory: 1024Mi
persistence:
  Size: 500Gi
ingress:
 - name: default
   annotations:
     kubernetes.io/ingress.class: nginx
     kubernetes.io/tls-acme: "true"
     ingress.annotations.external-dns.alpha.kubernetes.io/target: "$EXTERNAL_DNS_ALPHA_KUBERNETES_IO_TARGET"
   hosts:
     $INGRESS_HOST: /
   tls:
   - secretName: app-external-ssl
     hosts:
     - $INGRESS_HOST

When we need to pass secrets, we advise using chamber to store application secrets. Our strategy for that is documented under [secrets management for CI/CD]/secrets-management/cicd/)

Dependencies

Examples

Deploy with Codefresh

version: '1.0'
steps:
  build_chart:
    title: Build Chart and publish to chartmuseum
    image: cloudposse/build-harness:${{BUILD_HARNESS_VERSION}}
    commands:
    # Add the helm chart registry
    - make helm/repo/add REPO_NAME=example REPO_ENDPOINT=${{STAGING_REPO_ENDPOINT}}
    # Add other standard remotes
    - make helm/repo/add-remote
    # Create a clean workspace
    - make helm/chart/clean
    # Build all the charts
    - make helm/chart/build-all
    # Publish charts to helm registry
    - make helm/chart/publish REPO_GATEWAY_ENDPOINT=${{STAGING_REPO_GATEWAY_ENDPOINT}}