apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
labels:
- pairs:
app.kubernetes.io/name: shop
includeSelectors: true
configMapGenerator:
- name: shop-config
literals:
- LOG_LEVEL=info
- FEATURE_ORDERS=false
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: shop
spec:
replicas: 1
selector:
matchLabels:
app: shop
template:
metadata:
labels:
app: shop
spec:
containers:
- name: shop
image: ghcr.io/acme/shop
envFrom:
- configMapRef:
name: shop-config
---
apiVersion: kustomize.config.k8s.io/v1alpha1
kind: Component
patches:
- target:
kind: Deployment
name: shop
patch: |-
- op: add
path: /spec/template/metadata/annotations
value:
prometheus.io/scrape: "true"
prometheus.io/port: "9090"
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: shop-staging
namePrefix: staging-
resources:
- ../../base
images:
- name: ghcr.io/acme/shop
newTag: 2.5.0-rc.1
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: shop
resources:
- ../../base
components:
- ../../components/metrics
images:
- name: ghcr.io/acme/shop
newTag: 2.4.1
replicas:
- name: shop
count: 3
patches:
- path: resources.yaml
configMapGenerator:
- name: shop-config
behavior: merge
literals:
- FEATURE_ORDERS=true
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: shop
spec:
template:
spec:
containers:
- name: shop
resources:
requests:
cpu: 250m
memory: 256MiKustomize graph
Kustomize: a base, two overlays, a component and generated ConfigMaps
How kustomize build assembles manifests: a base that lists resources, overlays that patch it per environment, a reusable component, a configMapGenerator with its hash suffix, image and replica transformers, and the objects that come out.
Kustomize builds manifests from other manifests, with no templates. A kustomization.yaml lists resources and the changes to make to them. An overlay points at a base and adds its own changes on top, so each environment is a short file of differences.
The nodes here are files in a repository, apart from the last three, which are what kubectl apply -k overlays/production sends to the cluster.
Interactive graph
Click a resource to see what it does, or follow the setup step by step.
How it works
All 9 resources and what they do
- Kustomization base/kustomization.yamlkustomize.config.k8s.io/v1beta1
- What every environment shares: the Deployment and Service, common labels and a generated ConfigMap. It builds on its own, which is a good test of a base.
- Deployment base/deployment.yamlapps/v1
- A plain manifest with sensible defaults. It refers to the ConfigMap by its short name,
shop-config, and Kustomize rewrites the reference when it adds the hash. - Component components/metrics/kustomization.yamlkustomize.config.k8s.io/v1alpha1
- An optional feature that any overlay can switch on. Unlike a base, it patches whatever the overlay has built so far, here by adding a metrics port and scrape annotations.
- Kustomization overlays/staging/kustomization.yamlkustomize.config.k8s.io/v1beta1
- The smallest overlay: a namespace, a name prefix and an image tag. Everything else comes from the base unchanged.
- Kustomization overlays/production/kustomization.yamlkustomize.config.k8s.io/v1beta1
- Production's differences: a pinned image tag, three replicas, the metrics component, a patch file for resources and one changed key merged into the base's ConfigMap.
- Patch file overlays/production/resources.yaml
- A strategic merge patch: a partial Deployment with only the fields to change. Kustomize matches it to its target by kind and name, and merges containers by their
name. - ConfigMap shop-config-7m2k9t4f8hv1
- The merged ConfigMap, named with a hash of its content. Change a value and the name changes, which changes the Deployment's Pod template and rolls the Pods.
- Deployment shopapps/v1
- The base Deployment after every change: image
ghcr.io/acme/shop:2.4.1, three replicas, requests, the scrape annotations, the shared label on selector and template, andenvFrompointing at the hashed ConfigMap name. - Service shopv1
- From
base/service.yaml, with the namespace set and the shared label added to its selector, so it still matches the Pods.
Common mistakes
- A patch that names an object the build doesn't contain fails with
no matches for Id. WithnamePrefixin play, patches still target the original name from the base. - A generator in an overlay with the same name as one in the base needs
behavior: mergeorreplace. Without it the build fails on the duplicate. - Each change to a generated ConfigMap leaves the old one behind, since its name differs. Apply with
--pruneand a label, or let Flux or Argo CD prune. imagesmatches on the image name without the tag. A manifest that writes the registry differently, such asdocker.io/library/nginxagainstnginx, isn't matched.commonLabelsadds labels to selectors, which are immutable on a Deployment. Adding it to a base that is already deployed breaks the next apply;labelswithincludeSelectors: falsedoesn't.
The manifests you write
Everything above that is marked "You write it", in one file. The rest comes from add-ons and controllers.
Keep going
More graphs
- Deployment, Service and Ingress: how a request reaches your Pods
- Gateway API: GatewayClass, Gateway and HTTPRoute with a canary split
- PVC, StorageClass and CSI: how a cloud disk ends up in your Pod
- RBAC: how a ServiceAccount gets its permissions
- cert-manager with Let's Encrypt: Certificate, CertificateRequest, Order and Challenge
- A private CA with cert-manager and trust-manager
- Istio traffic management: Gateway, VirtualService, DestinationRule and policies
- Flux dependencies: Git and OCI sources, Kustomizations and HelmReleases
- Argo CD: ApplicationSet, AppProject and the Applications it generates
- Inside an OCI image: tag, index, manifests, config and layers
- OCI artifacts: Helm charts, Flux artifacts and image volumes
- A Helm release: chart, values, revisions and the objects Helm owns
- A StatefulSet database: headless Service, per-Pod volumes, snapshots and restore
- Autoscaling end to end: KEDA, the HPA it creates and Karpenter adding nodes
- Prometheus Operator: ServiceMonitor, PrometheusRule and the path to an alert
- External Secrets Operator: from a cloud secret manager to a Pod, with rotation
- Kyverno CEL policies: ValidatingPolicy, MutatingPolicy, GeneratingPolicy and exceptions
- Cilium egress to a domain: CiliumNetworkPolicy, the DNS proxy and toFQDNs
- Istio ambient mode: ztunnel, waypoint proxies and authorization without sidecars
- Argo Rollouts canary: traffic weights on an HTTPRoute and analysis from Prometheus