Skip to content

Lab 6: Consume a Helm Chart, Build Kustomize Overlays

Pairs with Phase 6. Two halves: install third-party software the way the ecosystem ships it (Helm), then make your own app multi-environment without copy-paste (Kustomize).

Part 1: Helm - consume a chart

We'll install podinfo, a small demo web app with a well-maintained chart - the consumption workflow is identical for Postgres, Redis, or cert-manager charts.

bash
helm repo add podinfo https://stefanprodan.github.io/podinfo
helm repo update

Before installing anything, see what knobs a chart exposes:

bash
helm show values podinfo/podinfo | less

That output is the chart's whole API. Create lab-6/podinfo-values.yaml overriding a few:

yaml
replicaCount: 2
ui:
  color: "#34577c"
  message: "deployed via helm by me"

Install and inspect:

bash
helm install my-podinfo podinfo/podinfo -f lab-6/podinfo-values.yaml
helm list
kubectl get pods -l app.kubernetes.io/name=podinfo

Expected: 2 pods, and helm list shows release my-podinfo, status deployed. See your values live:

bash
kubectl port-forward svc/my-podinfo 9898:9898

Open http://localhost:9898 - your message and color. The chart rendered a Deployment, Service, and more from your 4 lines of values; see exactly what with helm get manifest my-podinfo.

Now the lifecycle - upgrade, history, rollback (notice it mirrors kubectl rollout, one level up):

bash
helm upgrade my-podinfo podinfo/podinfo -f lab-6/podinfo-values.yaml --set replicaCount=3
helm history my-podinfo
helm rollback my-podinfo 1
helm uninstall my-podinfo

On Bitnami charts

Older tutorials all use Bitnami charts (bitnami/postgresql etc.). Since Bitnami's 2025 licensing changes, their free images are limited and many guides are broken. The chart mechanics you just learned are identical; just check a chart's maintenance status before relying on it.

Part 2: Kustomize - your app, per environment

Goal: the whoami app from Lab 2, where prod runs 3 replicas with real resource limits and dev runs 1 replica, lean - without duplicating the manifests.

Build this tree in lab-6/:

lab-6/
  base/
    kustomization.yaml
    deployment.yaml
    service.yaml
  overlays/
    dev/
      kustomization.yaml
    prod/
      kustomization.yaml
      replicas-and-resources.yaml

base/deployment.yaml and base/service.yaml: copy your Lab 2 files verbatim, but set replicas: 1 in the deployment (the base should be the minimal common shape).

base/kustomization.yaml:

yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - deployment.yaml
  - service.yaml

overlays/dev/kustomization.yaml - dev just namespaces the base:

yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: whoami-dev
resources:
  - ../../base

overlays/prod/kustomization.yaml:

yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: whoami-prod
resources:
  - ../../base
patches:
  - path: replicas-and-resources.yaml

overlays/prod/replicas-and-resources.yaml - only the fields that differ:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoami
spec:
  replicas: 3
  template:
    spec:
      containers:
        - name: whoami
          resources:
            requests:
              cpu: 100m
              memory: 64Mi
            limits:
              memory: 128Mi

The patch is matched to the base resource by kind + metadata.name, and merged field-by-field. The base never mentions prod; prod only states its delta.

Step 3: Render, compare, apply

Always render before applying - this is the Kustomize habit that saves you:

bash
kubectl kustomize lab-6/overlays/dev | less
kubectl kustomize lab-6/overlays/prod | less

Confirm: dev shows 1 replica and no resources block; prod shows 3 replicas with resources, and both have their namespace stamped on every resource. Then:

bash
kubectl create namespace whoami-dev
kubectl create namespace whoami-prod
kubectl apply -k lab-6/overlays/dev
kubectl apply -k lab-6/overlays/prod

kubectl get pods -n whoami-dev
kubectl get pods -n whoami-prod

Expected: 1 pod in dev, 3 in prod, from one set of base manifests.

Clean up:

bash
kubectl delete namespace whoami-dev whoami-prod

Verify it worked

  • [ ] You can explain chart / values / release using the podinfo install as the example
  • [ ] You used helm show values before installing - and will every time from now on
  • [ ] You rolled a Helm release back and saw it in helm history
  • [ ] Your prod overlay changed replicas and resources without touching the base
  • [ ] You rendered with kubectl kustomize before applying

That's the last lab. Next: Phase 7, the migration - take your real compose file and apply everything from Labs 2-6 to it.

A VineLab lab. Released under the MIT License.