TT Lab
Get started
Learn Learning paths Courses

CNPA — Cloud Native Platform Engineering Associate

Building One Golden Path End to End

Continue in TT Lab

Goal

You bundle the things that must always be attached when a new service is born — standard labels, resource requests/limits, autoscaling, a disruption budget, and a network policy — into one set, and deploy it for real into a namespace that has guardrails. Next you package the same service as a Helm chart, branch it with per-environment values, and deploy the render result.

Why it matters

The value of a golden path lies less in 'what was put in' than in 'whether it is there even though the developer did not ask for it.' If the scaffold attaches resource limits and a network policy by default, the developer's effort to follow those rules drops to 0. Conversely, if you write 'Be sure to set limits' on a wiki, half of people forget. The location of guardrails is in the same vein — ResourceQuota and LimitRange judge immediately at creation time, so they create a much better developer experience than an after-the-fact audit report. The combination of these two in particular often appears on the exam. If a quota limits CPU, a Pod that does not specify requests is rejected, and the LimitRange default fills that gap. The Helm part later is the golden path's second face, 'branching the same scaffold by values' — it is a way to satisfy both dev and prod with a single template.

Steps

  1. Write the Deployment payments in /root/cnpa-path/manifests/deployment.yaml — spec.replicas: 2, app.kubernetes.io/name: payments in the selector and Pod labels, app.kubernetes.io/name: payments and app.kubernetes.io/part-of: cnpa-platform in the metadata labels, container name app, image ghcr.io/labhub/payments:1.0.0, containerPort 8080, resources.requests of cpu 100m / memory 128Mi, and resources.limits of cpu 300m / memory 256Mi. Write the Service payments in /root/cnpa-path/manifests/service.yaml — type ClusterIP, port 80, targetPort 8080, selector app.kubernetes.io/name: payments.
  2. Write the HorizontalPodAutoscaler payments in /root/cnpa-path/manifests/hpa.yaml (apiVersion autoscaling/v2, scaleTargetRef pointing to the apps/v1 Deployment payments, minReplicas: 2, maxReplicas: 6, cpu Utilization target 70). Write the PodDisruptionBudget payments (minAvailable: 1, selector app.kubernetes.io/name: payments) in /root/cnpa-path/manifests/pdb.yaml, and the NetworkPolicy payments in /root/cnpa-path/manifests/netpol.yaml (podSelector app.kubernetes.io/name: payments, first policyTypes entry Ingress, and an ingress that allows only TCP 8080 from Pods that have the label app.kubernetes.io/part-of: cnpa-platform).
  3. Create the namespace cnpa-app, and in it create the ResourceQuota cnpa-app-quota (requests.cpu: "1", requests.memory: 1Gi, limits.cpu: "2", limits.memory: 2Gi, pods: "8") and the LimitRange cnpa-app-limits (type Container, default cpu 200m / memory 256Mi, defaultRequest cpu 100m / memory 128Mi).
  4. Apply all five manifests in /root/cnpa-path/manifests/ to the cnpa-app namespace.
  5. Create a chart with helm create /root/cnpa-path/payments, and edit values.yaml — replicaCount: 2, image.repository: ghcr.io/labhub/payments, image.tag: "1.0.0".
  6. Create /root/cnpa-path/payments/values-dev.yaml (replicaCount: 1, image.tag: "1.0.0") and /root/cnpa-path/payments/values-prod.yaml (replicaCount: 3, image.tag: "1.2.0", fullnameOverride: payments-v2). Then save the result of helm template payments-v2 /root/cnpa-path/payments -f /root/cnpa-path/payments/values-prod.yaml -n cnpa-app to /root/cnpa-path/render-prod.yaml.
  7. Apply /root/cnpa-path/render-prod.yaml to the cnpa-app namespace. After applying, the payments-v2 Deployment must be running with replicas 3 and image ghcr.io/labhub/payments:1.2.0, and the quota from step 3 must remain intact.

Notes

Service scaffold — Deployment and Service

Write the Deployment payments in /root/cnpa-path/manifests/deployment.yaml — spec.replicas: 2, app.kubernetes.io/name: payments in the selector and Pod labels, app.kubernetes.io/name: payments and app.kubernetes.io/part-of: cnpa-platform in the metadata labels, container name app, image ghcr.io/labhub/payments:1.0.0, containerPort 8080, resources.requests of cpu 100m / memory 128Mi, and resources.limits of cpu 300m / memory 256Mi. Write the Service payments in /root/cnpa-path/manifests/service.yaml — type ClusterIP, port 80, targetPort 8080, selector app.kubernetes.io/name: payments.

A golden path's defaults are 'things nobody asked for but that are always there.' Standard labels and resource requests/limits are examples.

HPA · PDB · NetworkPolicy

Write the HorizontalPodAutoscaler payments in /root/cnpa-path/manifests/hpa.yaml (apiVersion autoscaling/v2, scaleTargetRef pointing to the apps/v1 Deployment payments, minReplicas: 2, maxReplicas: 6, cpu Utilization target 70). Write the PodDisruptionBudget payments (minAvailable: 1, selector app.kubernetes.io/name: payments) in /root/cnpa-path/manifests/pdb.yaml, and the NetworkPolicy payments in /root/cnpa-path/manifests/netpol.yaml (podSelector app.kubernetes.io/name: payments, first policyTypes entry Ingress, and an ingress that allows only TCP 8080 from Pods that have the label app.kubernetes.io/part-of: cnpa-platform).

All three resources find their target workload with a selector. Only the HPA uses a target reference instead of a selector.

A namespace with guardrails

Create the namespace cnpa-app, and in it create the ResourceQuota cnpa-app-quota (requests.cpu: "1", requests.memory: 1Gi, limits.cpu: "2", limits.memory: 2Gi, pods: "8") and the LimitRange cnpa-app-limits (type Container, default cpu 200m / memory 256Mi, defaultRequest cpu 100m / memory 128Mi).

If a quota limits a resource, every container in that namespace must declare requests/limits. There is a separate object that rescues containers that did not declare them.

Apply the scaffold to the cluster

Apply all five manifests in /root/cnpa-path/manifests/ to the cnpa-app namespace.

Deploy all five resources into the same namespace. There is an option that applies a whole directory at once.

A local chart with helm create

Create a chart with helm create /root/cnpa-path/payments, and edit values.yaml — replicaCount: 2, image.repository: ghcr.io/labhub/payments, image.tag: "1.0.0".

helm create makes a chart skeleton locally without the internet. Edit the generated values.yaml to fit this service.

Per-environment values and checking the render

Create /root/cnpa-path/payments/values-dev.yaml (replicaCount: 1, image.tag: "1.0.0") and /root/cnpa-path/payments/values-prod.yaml (replicaCount: 3, image.tag: "1.2.0", fullnameOverride: payments-v2). Then save the result of helm template payments-v2 /root/cnpa-path/payments -f /root/cnpa-path/payments/values-prod.yaml -n cnpa-app to /root/cnpa-path/render-prod.yaml.

Values files are layered. The file given later wins. Do the render with a command that does not touch the cluster.

Deploy the render result inside the guardrails

Apply /root/cnpa-path/render-prod.yaml to the cnpa-app namespace. After applying, the payments-v2 Deployment must be running with replicas 3 and image ghcr.io/labhub/payments:1.2.0, and the quota from step 3 must remain intact.

Make sure the name is pinned in the values so that no name collision occurs. You can simply apply the rendered file as it is.