12 - Reading Other People's Manifests¶
What this session is¶
About 30 minutes. The strategy for reading a real-world Helm chart or set of K8s manifests - without trying to memorize everything at once.
The five-minute orientation¶
For any Kubernetes-deployed project:
- Read the project's README. What does it do? How is it deployed?
- Find the deployment artifacts. Common locations:
deploy/,kubernetes/,manifests/,helm/,charts/,k8s/. - Identify the deployment style:
- Plain YAML files in
manifests/- apply withkubectl apply -f manifests/. - Kustomize: look for
kustomization.yamlfiles. - Helm: look for
Chart.yaml+values.yaml. - Operator: look for CRDs and a controller pod.
- Find a values file or example. The project's own dev environment is often the most-realistic example to study.
- Render to YAML if it's not already:
helm template chart/ -f values.yamlkubectl kustomize manifests/overlays/dev/- Read the rendered output top to bottom, in this order: Deployments → Services → ConfigMaps/Secrets → Ingress → others.
After this orientation, you should be able to write a paragraph: "This project deploys A, B, and C, connected by a Service named D, exposed externally via Ingress E."
Reading a Helm chart¶
Open Chart.yaml:
apiVersion: v2
name: myapp
version: 1.2.0
appVersion: "2.5.0"
dependencies:
- name: postgresql
version: "11.6.0"
repository: https://charts.bitnami.com/bitnami
You learn: it's an app called myapp, with Postgres as a sub-chart.
Open values.yaml. The defaults plus the structure of what users can override. Skim it; come back when you need to tune something.
Open templates/. Each file is a (Go-templated) Kubernetes manifest. Common ones:
- deployment.yaml
- service.yaml
- ingress.yaml
- configmap.yaml
- secret.yaml
- serviceaccount.yaml
- _helpers.tpl (reusable snippets)
Read deployment.yaml first - that's where the main app spec is. Templated bits like {{ .Values.image.repository }} come from values.yaml.
Render to see what's actually produced:
Reading rendered YAML is often easier than reading templates.
Common patterns you'll see¶
A Deployment + Service per service. The fundamental pattern.
An Ingress at the front. Often one Ingress with multiple host- or path-based routes.
A ConfigMap for application config. Often mounted as files or injected as env.
A Secret for credentials. Sometimes generated by the chart (random passwords); sometimes you provide.
A StatefulSet + Headless Service for stateful workloads (databases, message brokers).
A Job or CronJob for migrations / scheduled tasks. Run-once or run-periodically pods.
HorizontalPodAutoscaler for stateless services. Scales based on CPU/memory/custom metrics.
PodDisruptionBudget for important services. Limits voluntary disruption during node drains.
NetworkPolicy for zero-trust networking. Allow/deny rules for pod-to-pod traffic.
A CustomResource (CRD instance) for operator-managed apps. E.g., Prometheus is a CR for the Prometheus Operator.
You don't need to know every detail. Recognize the type; understand what role it plays; look up specifics when needed.
CRDs and Operators¶
A CustomResourceDefinition (CRD) lets you add new resource types to Kubernetes. An Operator is code (usually a pod running in the cluster) that watches a CRD and reconciles real-world state to match.
Examples:
- cert-manager defines Certificate. The cert-manager operator watches them, provisions actual TLS certs via Let's Encrypt, stores them as Secrets.
- Prometheus Operator defines Prometheus, ServiceMonitor. The operator watches them and configures Prometheus instances.
- Postgres Operator (Zalando) defines postgresql. The operator manages a Postgres HA cluster.
When you see kubectl get <something-unusual>, you're likely looking at a CRD installed by an operator.
kubectl get crd # list all CRDs in the cluster
kubectl api-resources # all resource types, including CRDs
Things that look scary¶
- A wall of
{{ .Values.xxx }}in a Helm template - those are placeholders; render to see actual values. - Long
nodeSelector/tolerations/affinityblocks - scheduling rules. You can usually ignore; they affect placement, not behavior. initContainers- run BEFORE the main containers in a pod. Used for setup (waiting for the DB, fetching configs).hostPath,hostNetwork: true,privileged: true- bad signs in untrusted contexts; required for some system pods (network plugins, log collectors). Recognize.- Long
securityContextblocks - security hardening. Read what's restricted; it's usually self-explanatory. spec.template.spec.containers[0].resources.limits.ephemeral-storage- controls pod-local disk usage. Rare but real.
Exercise¶
Pick a real Kubernetes-deployed OSS project. Suggestions:
grafana/grafana- Grafana itself, plus its Helm chart. Well-documented.prometheus-community/helm-charts- Prometheus and friends.cert-manager/cert-manager- TLS automation.bitnami/charts- wide variety of well-organized charts.
Pick one's Helm chart. Apply orientation:
- README - what does it do?
Chart.yaml- what version + dependencies?values.yaml- what's configurable?templates/- what resources?- Render with your own simple values:
- Read the rendered output. Write a paragraph summarizing what gets deployed.
What you might wonder¶
"What if the project uses Kustomize instead of Helm?"
Same idea, different mechanism. kustomization.yaml lists base resources + patches. kubectl kustomize <dir> renders. Read the base first, then the overlays.
"What if the project uses Jsonnet, CUE, or Pulumi?" Less common but exists. Same approach: render to YAML, read the YAML.
"What if there are CRDs I don't recognize?"
kubectl explain <crd> shows the schema. The CRD's project has docs. Read.
Done¶
- Apply five-minute orientation to a K8s OSS project.
- Read Helm chart structure (
Chart.yaml,values.yaml,templates/). - Render charts to readable YAML.
- Recognize common resource patterns.
- Know CRDs / Operators exist.