TT Lab
Get started
Learn Learning paths Courses

CNPE — Cloud Native Platform Engineer

Designing Delivery Gates and Progressive Rollout

Continue in TT Lab

Goal

You create a kustomize base and a production overlay, apply schema and policy gates to the rendered result, and confirm that the gates actually block violations. Then you decide which Service to attach the canary and blue/green to and move them into Rollouts.

Why it matters

The GitOps domain of CNPE has the largest weighting at 25%. And what both real work and the exam ask for in this domain is not how to use the tools but the order. Render comes first, check comes next, and the check result must become an exit code. A pipeline that does not keep this order goes green while protecting nothing.

The cluster in this lab has neither an Argo CD controller nor an Argo Rollouts controller. Only the CRDs are registered, so the manifests are truly validated and stored, but no reconcile happens. So what you learn here is not "what does the controller do for me" but "what did I declare." In the real exam too, what gets graded is the declaration.

The working directory is /root/cnpe-delivery, and the production namespace is cnpe-prod.

Steps

  1. In /root/cnpe-delivery/base, create Deployment checkout and Service checkout and bundle them with kustomization.yaml. The container port and the Service's targetPort are 8080, and replicas is 1. Do not put a namespace in the base.
  2. In /root/cnpe-delivery/overlays/prod, create the production overlay. The namespace is cnpe-prod, replicas is 4, and the image is pinned by digest (64 hexadecimal digits after @sha256:). Put both requests and limits on the container and set runAsNonRoot: true.
  3. In /root/cnpe-delivery/policy/require-pinned.yaml, write a Kyverno ClusterPolicy. validationFailureAction is Enforce, and for Deployments it checks two things: (a) whether the image is pinned by digest and (b) whether every container has resources.limits.cpu and memory.
  4. Create /root/cnpe-delivery/gate.sh. It must render the prod overlay, apply the policy to that result, and exit with a non-zero code if there is a violation. Make the script first move to its own location so that it behaves the same no matter where it is called from.
  5. In /root/cnpe-delivery/rollout/checkout-canary.yaml, write the canary Rollout checkout and apply it to cnpe-prod. The setWeight values are 10, 30, 60 in that order with a pause between each, and the first step must be a setWeight. Set canaryService and stableService to different values and keep progressDeadlineSeconds at 600 or less. The container image must be exactly the same as the image in the prod render result.
  6. In /root/cnpe-delivery/argocd/application.yaml, write an Argo CD Application. project is a dedicated project, not default, source.path is overlays/prod, targetRevision is a pinned reference, not HEAD, turn on prune and selfHeal in syncPolicy.automated, and put CreateNamespace=true in syncOptions. destination.namespace must be the same as the namespace in the render result.
  7. In /root/cnpe-delivery/rollout/ledger-bluegreen.yaml, write the AnalysisTemplate ledger-smoke and the blue/green Rollout ledger and apply them to cnpe-prod. activeService and previewService are different from each other, autoPromotionEnabled is false, prePromotionAnalysis references ledger-smoke, and scaleDownDelaySeconds is 300 or more.
  8. In /root/cnpe-delivery/delivery-report.txt, write four lines, prod_image, prod_replicas, canary_weights, and auto_promotion, in the 키=값 format (key=value). All values must be ones you queried directly from the render result and the cluster.

Reference

Create the base and confirm that it renders

In /root/cnpe-delivery/base, create Deployment checkout and Service checkout and bundle them with kustomization.yaml. The container port and the Service's targetPort are 8080, and replicas is 1. Do not put a namespace in the base.

The base holds only the common denominator that is independent of the environment. If you put a namespace or per-environment replicas here, the overlay ends up fighting to override them. Confirm the render by running kustomize build directly.

What the production overlay adds

In /root/cnpe-delivery/overlays/prod, create the production overlay. The namespace is cnpe-prod, replicas is 4, and the image is pinned by digest (64 hexadecimal digits after @sha256:). Put both requests and limits on the container and set runAsNonRoot: true.

In kustomize's images entry, you can use digest instead of newTag. Set replicas with the replicas entry, and layer the resources and security settings on with patches. Confirm using the kustomize build result, not the file.

Decide what the policy will block

In /root/cnpe-delivery/policy/require-pinned.yaml, write a Kyverno ClusterPolicy. validationFailureAction is Enforce, and for Deployments it checks two things: (a) whether the image is pinned by digest and (b) whether every container has resources.limits.cpu and memory.

In Kyverno's validate.pattern, *@sha256:* is a partial match and ?* means "a non-empty value." If the policy is too broad, even healthy manifests get blocked, so test both what should pass and what should be blocked.

Confirm that the gate really blocks

Create /root/cnpe-delivery/gate.sh. It must render the prod overlay, apply the policy to that result, and exit with a non-zero code if there is a violation. Make the script first move to its own location so that it behaves the same no matter where it is called from.

The core of a gate is not the check but turning the check result into an exit code. And for the script to behave the same wherever it is called from, it must move to its own directory on the first line. After you build it, deliberately put in a violation and see the red light once.

Make room in the canary for judgment

In /root/cnpe-delivery/rollout/checkout-canary.yaml, write the canary Rollout checkout and apply it to cnpe-prod. The setWeight values are 10, 30, 60 in that order with a pause between each, and the first step must be a setWeight. Set canaryService and stableService to different values and keep progressDeadlineSeconds at 600 or less. The container image must be exactly the same as the image in the prod render result.

Listing only weights gives you a slightly slower full rollout. Put a pause between weights, and split the Services so that you can observe the canary by itself. It is safer to copy the image from the render result.

Pin the sync source and destination

In /root/cnpe-delivery/argocd/application.yaml, write an Argo CD Application. project is a dedicated project, not default, source.path is overlays/prod, targetRevision is a pinned reference, not HEAD, turn on prune and selfHeal in syncPolicy.automated, and put CreateNamespace=true in syncOptions. destination.namespace must be the same as the namespace in the render result.

This Pod has no Argo CD controller, so you look at the declaration, not the sync result. Even so, destination.namespace must be exactly the same as the namespace in the render result. If the two values differ, the sync succeeds but nothing is reflected anywhere.

A strategy for a service whose writes cannot be split

In /root/cnpe-delivery/rollout/ledger-bluegreen.yaml, write the AnalysisTemplate ledger-smoke and the blue/green Rollout ledger and apply them to cnpe-prod. activeService and previewService are different from each other, autoPromotionEnabled is false, prePromotionAnalysis references ledger-smoke, and scaleDownDelaySeconds is 300 or more.

This step checks the blue/green declaration and the analysis template reference. A preview Service and manual promotion do not block data writes. For a real ledger, you must verify single-writer control, schema compatibility, and recovery separately. Here, create the referenced analysis template as well and distinguish activeService from previewService.

Record the deployment as values

In /root/cnpe-delivery/delivery-report.txt, write four lines, prod_image, prod_replicas, canary_weights, and auto_promotion, in the 키=값 format (key=value). All values must be ones you queried directly from the render result and the cluster.

Do not make up any of the four values; query them and write them down. The image and replicas come from the render result, and the weights and whether auto promotion is on come from the Rollout in the cluster. The grader recomputes the same values and compares them.