Lesson 8 · This repo's library-chart architecture
Releases & how Skaffold drives Helm
From template to a live release — and the config that turns "ENV=local ORG=manabie" into a deploy.
Your win: distinguish helm template from helm upgrade
--install, explain what a release identity is, and read the Skaffold
deploy.helm config that wires this repo's charts to Helm.
Two things you can do with a chart
helm template— render the chart to manifests locally, without touching a cluster. Pure output. This is Course 1'sskaffold render.1helm upgrade --install— create the release if it doesn't exist, or upgrade it in place if it does. Idempotent, and the actual deploy. This is Course 1'sskaffold run.2
Release identity = name + namespace
A release is identified by its name within a namespace. Deploy the same
chart under two names, or into two namespaces, and you get two independent releases with
separate revision histories. That's exactly how one
bob chart becomes a
distinct release in local-manabie-backend, prod-tokyo-backend, and
every other env×org namespace.
How Skaffold drives Helm here
You don't type helm in this repo — Skaffold does, from a declarative
deploy.helm.releases block.
Anchor — the release list
skaffold.backend.yaml:5-76 lists a release per service. The
first,
common, sets createNamespace: true
(:14) so the env×org namespace exists before anything else. A
reusable YAML anchor &ReleaseObject defines the shape once and each service
reuses it, overriding just name/chartPath/valuesFiles.
Anchor — a per-service release (bob)
backend/bob/skaffold.yaml:8-38 shows one release fully:
name: bob,chartPath: .,namespace: '{{.ENV}}-{{.ORG}}-backend'(:10).- four
valuesFilesin precedence order (Lesson 4). setValueTemplatesinjectingglobal.environment: "{{.ENV}}",global.vendor: "{{.ORG}}", and the image tag.wait: true,statusCheck: true(:24) — Skaffold waits for the rollout to be healthy (readiness probes, Course 2 L8).profiles: local→ setskubeContext: kind-kind(Course 1's kind cluster).
ENV/ORG (exported by deployments/env.bash)
flow into the templated namespace, the values-file paths, and the injected globals — one set
of env vars parameterises the entire deploy.
ENV=local ORG=manabie
│
▼
skaffold run ──► helm upgrade --install bob ./ \
--namespace local-manabie-backend --create-namespace \
-f gateway/local-manabie -f backend/values.yaml \
-f backend/local-manabie -f backend/bob/local-manabie \
--set global.environment=local --set global.vendor=manabie \
--wait
│
▼
release "bob" (revision N) live in local-manabie-backend
One release per (service, env, org)
Because the namespace is templated from ENV/ORG and the release name is the service, the
same chart yields a clean grid of releases — the env×org matrix (Course 1) realised as Helm
releases. Change a value,
skaffold run again → a new revision, in place.
Read this next
Helm docs — Using Helm (install/upgrade) +
Helm docs — Using Helm (install/upgrade) + helm template
The release lifecycle commands and how template differs from an actual
install/upgrade.
→ helm.sh — Using Helm
→ helm.sh — helm upgrade ·
helm template
Check yourself (from memory)
Q1. helm upgrade --install is used because it…
Idempotent deploy — that's why it's the standard command
(and what
skaffold run invokes).
Q2. A release is uniquely identified by…
Name + namespace. Same chart in two namespaces = two
independent releases — the env×org grid.
Q3. How do ENV/ORG reach the deploy in this repo?
{{.ENV}}/{{.ORG}} template the
namespace + valuesFiles + setValueTemplates globals.
template vs upgrade --install, release identity, and how Skaffold drives Helm here.
recall, then click to reveal
helm template = render manifests locally, no cluster (=
skaffold render). helm upgrade --install = install-or-upgrade in
place, idempotent (= skaffold run). RELEASE IDENTITY = name + namespace → same
chart in two namespaces = two independent releases with separate revision histories. REPO:
Skaffold deploy.helm.releases (skaffold.backend.yaml) — a release
per service; common does createNamespace: true. Per-service
(bob/skaffold.yaml): namespace: {{.ENV}}-{{.ORG}}-backend, four
valuesFiles, setValueTemplates (global.environment/vendor, tag),
wait: true+statusCheck, local profile → kind-kind. So
ENV/ORG (from env.bash) parameterise the whole deploy → one release per
(service, env, org).
✅ Part 2 complete
You now understand this repo's Helm architecture: named templates & helpers (L5), the
libs/util library chart + the copy model (L6), lifecycle hooks incl. the
local-only migration (L7), and how Skaffold turns charts into releases (L8).
Part 3 covers the production concerns: SOPS secrets, values at scale,
upgrade/rollback, and chart quality.
Ready for Part 3 (SOPS secrets, scale, upgrades, quality)? Or a
mock interview across Parts 1–2 — the copy-vs-dependency and
template-vs-install distinctions are great to say out loud. Ask me.