Stage 5 · Platform
GitOps & Progressive Delivery
Declarative Deploys
Representing Kubernetes desired state with Helm, Kustomize, Jsonnet, and environment overlays.
Declarative vs Imperative
Imperative commands describe how to achieve a state: kubectl set image, kubectl scale. Declarative manifests describe the desired state: this is what the cluster should look like. GitOps is declarative — the repository contains the desired state, and controllers reconcile the cluster to match.
Declarative configuration is version-controlled, reviewable, and auditable. Every change goes through a pull request. Every state is captured in git. The cluster state is always derivable from the repository state.
Helm Charts
# Chart.yaml
apiVersion: v2
name: myapp
version: 1.0.0
appVersion: "2.0.0"
dependencies:
- name: postgresql
version: "13.2.24"
repository: "https://charts.bitnami.com/bitnami"
# values.yaml
replicaCount: 3
image:
repository: ghcr.io/myorg/myapp
tag: "2.0.0"
pullPolicy: IfNotPresent
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
ingress:
enabled: true
hosts:
- host: app.example.com
paths:
- path: /
pathType: Prefix
# values-production.yaml
replicaCount: 6
resources:
limits:
cpu: "1"
memory: 1Gi
requests:
cpu: 500m
memory: 512MiHelm charts package Kubernetes manifests with configurable values. The base values.yaml defines defaults. values-production.yaml overrides for production. Helm templates generate the final manifests from values.
Kustomize
# base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: ghcr.io/myorg/myapp
ports:
- containerPort: 8080
# base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
# overlays/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
replicas:
- name: myapp
count: 6
patches:
- target:
kind: Deployment
name: myapp
patch: |
- op: add
path: /spec/template/spec/containers/0/resources/limits/memory
value: 1GiKustomize generates manifests by layering overlays on a base. The production overlay increases replicas and memory limits. kubectl kustomize overlays/production/ generates the final manifests.
Jsonnet
local base = {
deployment: {
apiVersion: "apps/v1",
kind: "Deployment",
metadata: { name: "myapp" },
spec: {
replicas: 3,
selector: { matchLabels: { app: "myapp" } },
template: {
metadata: { labels: { app: "myapp" } },
spec: {
containers: [{
name: "myapp",
image: "ghcr.io/myorg/myapp:2.0.0",
ports: [{ containerPort: 8080 }],
}],
},
},
},
},
};
local withEnvironment(env) = base + {
deployment+: {
spec+: {
replicas: if env == "production" then 6 else 2,
template+: {
spec+: {
containers: [base.deployment.spec.template.spec.containers[0] + {
env: [{ name: "ENVIRONMENT", value: env }],
}],
},
},
},
},
};
{
staging: withEnvironment("staging"),
production: withEnvironment("production"),
}Jsonnet generates environment-specific manifests from a single source of truth. The withEnvironment function parameterizes the deployment for each environment. This eliminates duplication while maintaining flexibility.
GitOps Repository Structure
infrastructure/
base/
namespace.yaml
network-policies.yaml
overlays/
staging/
kustomization.yaml
namespace-patch.yaml
production/
kustomization.yaml
namespace-patch.yaml
applications/
myapp/
base/
deployment.yaml
service.yaml
kustomization.yaml
overlays/
staging/
kustomization.yaml
replicas-patch.yaml
production/
kustomization.yaml
replicas-patch.yamlSeparate infrastructure from application manifests. Use base/overlays for environment differentiation. This structure scales from a single application to a fleet of hundreds.
Manifest Generation
Generate final manifests in your CI pipeline using helm template or kustomize build. Store the generated manifests in a separate repository or branch. This way, your GitOps controller only needs to apply manifests — it does not need Helm, Kustomize, or other tools installed.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.