§9 deploy nginx helm
Source: examples/09-deploy-nginx-helm/ · ← Back to examples index
Authors a small helm chart that deploys the same nginx-custom:v1
image as §6/§7/§8, but with content templated through helm’s
values.yaml mechanism and injected via a ConfigMap. The demo
exercises the full helm lifecycle: lint, dry-run render, install,
upgrade, history, uninstall.
What’s in the chart
chart/
├── Chart.yaml # nginx-helm 0.1.0, app nginx 1.20.1
├── values.yaml # defaults: 1 replica, NodePort 80 -> 30080,
│ # placeholder content title/message
└── templates/
├── _helpers.tpl # fullname/labels/selectorLabels templates
├── configmap.yaml # index.html populated from values.content.*
├── deployment.yaml # mounts the ConfigMap at /usr/share/nginx/html
│ # with a checksum annotation that rotates
│ # when ConfigMap content changes (triggers
│ # Pod rollout on `helm upgrade` even when
│ # only values changed)
└── service.yaml # NodePort (values: service.nodePort, 30080)
What it tests
Eight §9 claims (the served-HTML checks go through
http://127.0.0.1:18080/, the host port the minikube profile
publishes for nodePort 30080 via --ports=127.0.0.1:18080:30080):
- helm 4.x can lint a chart with
apiVersion: v2cleanly helm templaterenders all three resource kinds (ConfigMap, Deployment, Service) from the templateshelm install --set key=valueoverrides default values- The installed Deployment serves the install-time title in its HTML response (templating worked end-to-end)
helm upgrade --set ...updates the release to revision 2- The
checksum/configmapannotation in the Deployment template triggers a Pod rollout when only the ConfigMap changes (otherwise upgrading onlycontent.*values wouldn’t roll the Pods — the Deployment spec itself would be unchanged) - After upgrade rollout, the served HTML contains the upgrade-time title — old content gone
helm uninstallremoves Deployment + Service + ConfigMap with no leftovers (and frees the shared nodePort 30080)
Running
./demo.sh
Expected duration: 30-60 seconds. Most of it is the rollout-after- upgrade phase.
If nginx-custom:v1 isn’t loaded, add 2-4 minutes for the first
build (docker build from §6’s Containerfile, then minikube image
load).
What you should see
==> step lines for each phase, ending in:
==> SUCCESS — helm install + upgrade + history + uninstall all green
Notable mid-flow checkpoints:
==> verifying installed title appears in served HTML
✓ served HTML contains 'First install via helm'
==> verifying upgraded title appears in served HTML
✓ served HTML contains 'Upgraded title via helm'
==> running 'helm history nginx-helm'
REVISION UPDATED STATUS CHART ... DESCRIPTION
1 superseded nginx-helm-0.1.0 ... Install complete
2 deployed nginx-helm-0.1.0 ... Upgrade complete
==> verifying no chart resources remain
✓ no leftover resources — helm uninstall cleaned everything
Cluster scope
Uses the default minikube cluster with the release name
nginx-helm. Chart-generated resources are named nginx-helm
(via the fullname helper) and labeled
app.kubernetes.io/instance=nginx-helm, distinct from §6/§7/§8.
The cleanup label selector relies on the
app.kubernetes.io/instance=nginx-helm label that the chart
applies to all resources — that’s how the post-uninstall
leftover check works.
The release Service is type: NodePort with nodePort: 30080. That
slot is shared with §6, §8 and §12-http, one at a time: the demo
calls require_free_nodeport 30080 and fails with a “delete X first”
message if another Service holds it. The demo pins every kubectl
and helm call to the minikube context.
Cleanup
demo.sh installs a trap cleanup EXIT that:
- Runs
helm uninstall nginx-helm(idempotent — succeeds even if no release exists)
nginx-custom:v1 stays in the cluster’s image cache.
Manual cleanup if needed:
helm --kube-context minikube uninstall nginx-helm
# verify:
kubectl --context minikube get all,configmap -l app.kubernetes.io/instance=nginx-helm
# should return nothing
When this fails
helm lintfails — likely a Chart.yaml field missing or a template syntax error. The lint output points at the offending file and linehelm templatefails — usually a `` syntax error or a value reference that doesn’t resolve. The template output is full Go-template error messages with file:line markershelm installsucceeds but Deployment never goes Available — typically image not loaded (the pre-flight should have built and loaded it; checkminikube -p minikube image ls; the chart usespullPolicy: Never)- First curl returns wrong content — values weren’t
templated as expected.
helm get values nginx-helmshows what helm thought your values were - Upgrade rollout doesn’t happen / served HTML still shows
old title — likely the
checksum/configmapannotation isn’t working.kubectl --context minikube get deployment nginx-helm -o yaml | grep checksumto confirm the annotation is present and changing across revisions nodePort 30080 is held by Service ...ordoes not publish nodePort 30080— another example holds the shared slot, or the profile was created without the port map. Run the command the script printshelm uninstallleaves resources behind — check the chart for any resource that doesn’t have the standard labels (every resource the chart creates should include thenginx-helm.labelsblock from_helpers.tpl)
For any of these, paste the failing output back.