Practice — Delivery & Platform APIs
Sixteen single-best-answer questions across two CNPA domains that are really one idea wearing two hats: Continuous Delivery & Platform Engineering (16%) and Platform APIs and Provisioning Infrastructure (12%). Nine questions on delivery — desired state, pull versus push, drift and self-healing, canaries and blue/green, rollback, promotion and environments-as-config. Seven on platform APIs — CRDs and controllers, the operator pattern, infrastructure as Kubernetes objects, API design for self-service, versioning and conversion, and admission in the request path. Every question is labelled with its domain, every one carries an explanation of why the key is right and why the tempting wrong answer is wrong, and the whole thing reshuffles on reset so you can never pass by remembering “it was the third one.”
This is a small test — sixteen questions — about two things. The first is how new code safely gets to the place where real people use it. The second is how you teach the computer a new word, like “database,” so anybody on the team can just ask for one instead of filing a ticket. They sound like different topics, but underneath they’re the same trick: you write down what you want, and a tireless helper keeps checking reality against what you wrote and fixing the difference. Once you really see that, half of these questions answer themselves.
What these two domains actually reward
☺ Like you’re 10: These questions almost never ask “what does this word mean?” They ask “here’s something that went wrong — which idea explains it?”
Together these two domains are 28% of the CNPA blueprint — better than a quarter of the paper, and second only to Core Fundamentals. But their weight is not the interesting part. What makes them worth drilling as a pair is that they are the two most scenario-driven domains on the blueprint. Very few questions here reward memorising a definition. Almost all of them describe a situation — drift that survived three days, a rollback that did not restore service, a CRD nobody uses — and ask which principle explains it, or what you would do next.
That shape has a direct consequence for how you revise. Reciting “the four OpenGitOps principles are declarative, versioned and immutable, pulled automatically, continuously reconciled” earns you very little on its own, because the exam will hand you a symptom and ask which of the four is missing. Being able to name a canary earns you very little, because the exam will hand you a constraint — “two versions must never serve traffic at the same time” — and ask which strategy fits. The unit of knowledge that pays is not the term. It is the term plus the situation it explains.
Nine and seven, and why in that ratio
Sixteen questions split nine to delivery and seven to APIs, which tracks the published 16:12 ratio about as closely as sixteen whole questions allow. Use the domain chips to re-sit one half on its own once you know which half is weak — but take the full sixteen mixed on the first pass, because part of what you are training is the ability to switch context between “how does change reach production?” and “how do I extend the API?” without losing a beat.
| Domain | Blueprint weight | Questions here | Where it is taught |
|---|---|---|---|
| 🦫 Continuous Delivery & Platform Engineering | 16% | 9 | CNPA · Continuous Delivery → GitOps workflows, CI/CD & progressive delivery |
| 🦋 Platform APIs and Provisioning Infrastructure | 12% | 7 | CNPA · Platform APIs → Platform APIs, CRDs & operators, Crossplane |
| Combined | 28% | 16 | How the banks work · where they sit in the plan |
The one idea underneath both halves
The reason these two domains share a bank is that they share a mechanism. A GitOps controller watching a config repo and a custom controller watching a Database resource are the same program shape: read desired state, observe actual state, compute the difference, act, repeat forever. The delivery domain looks at that loop from the outside and asks how change flows through it. The APIs domain looks at it from the inside and asks how you build one for a capability of your own.
Every question in this bank can be attacked with two sentences. “What is the desired state here, and who wrote it?” and “What is continuously comparing that to reality?” If the answer to the second question is “nothing, until the next merge” or “a human, on Tuesday,” you have almost certainly found the defect the question is describing.
The delivery half — what a delivery question looks like
☺ Like you’re 10: Delivery questions are about the journey a change takes from your laptop to real users — and all the ways that journey quietly goes wrong.
The delivery competencies are CI pipelines, the CI/CD relationship, GitOps basics and workflows, GitOps for application environments, and incident response. In question form they cluster into four recognisable shapes, and knowing the shapes is worth as much as knowing the content.
“Where does truth live?” questions
These hand you a setup and ask what is authoritative. The right answer is nearly always the tracked revision of the config repository — not the cluster, not the pipeline log, not the registry’s latest tag. The distractors are all things that describe reality rather than define it. A cluster tells you what is running; only Git tells you what is supposed to be. Get that distinction automatic and a surprising number of questions collapse into one line.
“Why did this drift survive?” questions
The most characteristic CNPA delivery question. Something was changed by hand, and the question is why nothing put it back. There are only a few possible answers: nothing reconciles at all; something reconciles but only when a commit lands; something reconciles continuously but self-healing is switched off; or the change is in Git, in which case reconciliation is faithfully enforcing your mistake. Practise saying which of those four you are looking at before you read the options.
# three ways to ask "does the cluster still match the repo?" — one per tool argocd app diff checkout --refresh flux diff kustomization checkout --path ./apps/checkout/overlays/prod # and the tool-agnostic one, straight from the manifests kubectl diff -k apps/checkout/overlays/prod
“Which rollout strategy fits this constraint?” questions
Never “what is a canary.” Always a constraint — a cutover that must be instant, a version that must never run concurrently with its predecessor, a change whose blast radius must be limited to 5% of users, a behaviour that must be switchable without a deploy. Map the constraint to the mechanism. Canary means two versions serving simultaneously with a weighted split; blue/green means two complete environments and one atomic flip; a feature flag means one artifact whose behaviour is chosen at run time.
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: checkout
namespace: checkout
spec:
replicas: 6
selector:
matchLabels: { app: checkout }
template:
metadata:
labels: { app: checkout }
spec:
containers:
- name: checkout
image: ghcr.io/acme/checkout@sha256:8f1c… # pinned by digest, not tag
strategy:
canary:
canaryService: checkout-canary
stableService: checkout-stable
steps:
- setWeight: 10
- pause: { duration: 5m }
- analysis:
templates:
- templateName: success-rate
- setWeight: 50
- pause: { duration: 10m }The same resource in blue/green form is a completely different promise — two full stacks, nothing shared, and a manual flip you control:
strategy:
blueGreen:
activeService: checkout
previewService: checkout-preview
autoPromotionEnabled: false # a human flips 0% → 100% in one step
scaleDownDelaySeconds: 600 # keep the old stack warm for a fast flip back“The rollback did not work — why?” questions
The trap here is that GitOps makes rollback look trivially easy: revert the commit, the reconciler restores the previous desired state, done. That is true for everything the reconciler manages — and completely silent about everything it does not. Database schemas, queue contents, third-party state and anything a migration touched are all outside the declarative model. Whenever a question mentions a migration, expect the answer to be about state the reconciler never owned. More on the surrounding discipline in release engineering and reliability & incidents.
The APIs half — what an API question looks like
☺ Like you’re 10: API questions are about teaching the cluster a new word — and about who is allowed to say it, what happens when they do, and who cleans up afterwards.
The API competencies are the reconciliation loop, CRDs as self-service APIs, provisioning infrastructure with Kubernetes, and the operator pattern. The questions divide almost perfectly into three groups.
“What does the CRD give you, and what doesn’t it?” questions
A CustomResourceDefinition gives you API surface: a new kind the API server stores, validates, authorises with RBAC and serves to kubectl, watches and GitOps alike. It gives you no behaviour whatsoever. Behaviour is the controller, and controller plus CRD plus operational knowledge is what we call an operator. Half the questions in this group are testing whether you can keep those three nouns apart under time pressure.
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: databases.platform.acme.com
spec:
group: platform.acme.com
scope: Namespaced
names:
kind: Database
plural: databases
singular: database
shortNames: [db]
conversion:
strategy: None # schemas are compatible; otherwise: Webhook
versions:
- name: v1alpha1
served: true # still answerable by the API server
storage: false # but nothing new is persisted at this version
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
engine: { type: string }
size: { type: string }
- name: v1beta1
served: true
storage: true # exactly one version may be the storage version
subresources:
status: {} # users own spec, the controller owns status
additionalPrinterColumns:
- name: Engine
type: string
jsonPath: .spec.engine
- name: Ready
type: string
jsonPath: .status.conditions[?(@.type=="Ready")].status
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
required: [engine, size]
properties:
engine: { type: string, enum: [postgres, mysql] }
size: { type: string, enum: [small, medium, large], default: small }
status:
type: object
properties:
conditions:
type: array
items:
type: object
properties:
type: { type: string }
status: { type: string }
reason: { type: string }
message: { type: string }Two commands make the versioning story concrete, and they are worth running once on a throwaway cluster so the exam question feels like a memory rather than a puzzle:
# which versions do objects actually exist at in etcd?
kubectl get crd databases.platform.acme.com -o jsonpath='{.status.storedVersions}'
# ask for an old version explicitly — the API server converts on the way out
kubectl get databases.v1alpha1.platform.acme.com -A -o yaml“Is this API designed for the person using it?” questions
This is the self-service half, and it is where Mira lives. A platform API is a product surface: it should ask the developer for what the developer actually knows — an engine, a size, an environment — and let the platform supply the sixty parameters the cloud provider wants. When a question describes low adoption, a queue of “what do I put in this field?” questions, or a developer copying a colleague’s YAML without understanding it, the answer is nearly always that the API is leaking implementation detail rather than expressing intent. Crossplane exists to make that separation concrete:
# what the developer writes — intent, and nothing else
apiVersion: platform.acme.com/v1alpha1
kind: PostgreSQLInstance
metadata:
name: orders-db
namespace: payments
spec:
parameters:
size: small
version: "16"
compositionRef:
name: postgres-aws-standard # the platform team's implementation
writeConnectionSecretToRef:
name: orders-db-connEverything the cloud actually needs — VPC, subnet group, parameter group, encryption, backups, tags — lives in the Composition the platform team owns. The developer never sees it, never copies it wrong, and never has to be told when it changes. (Newer Crossplane releases also allow namespaced composite resources directly, which can remove the need for a separate claim; the design principle is unchanged.)
“Where in the request path does this happen?” questions
The third group is about the API request path, and it is the single most reliable source of “right idea, wrong layer” distractors on the whole blueprint. Authentication, then authorisation, then mutating admission, then schema validation, then validating admission, then the object is persisted — and only after all of that does any controller see it. That ordering answers a whole family of questions: a controller cannot prevent a bad object from being stored, a pipeline check cannot stop somebody running kubectl apply by hand, and a portal’s form validation protects only the people who use the portal.
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: require-cost-centre
spec:
failurePolicy: Fail
matchConstraints:
resourceRules:
- apiGroups: ["platform.acme.com"]
apiVersions: ["*"]
operations: ["CREATE", "UPDATE"]
resources: ["databases"]
validations:
- expression: "has(object.metadata.labels) && 'cost-centre' in object.metadata.labels"
message: "every Database must carry a cost-centre label"
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: require-cost-centre
spec:
policyName: require-cost-centre
validationActions: [Deny]
matchResources:
namespaceSelector: {}That rule holds no matter who submits the object — the portal, a pipeline, a GitOps controller, or an engineer at 2am with a terminal. That is the whole argument for enforcing at admission, and Kyverno and OPA Gatekeeper make the same argument with richer policy languages.
How to sit this bank
☺ Like you’re 10: Answer without looking anything up, even when you’re only half sure. A wrong answer here is a free lesson.
Sixteen questions is a half-hour sitting, which makes this bank easy to abuse — it is short enough that you can nibble at it between other things and learn nothing. Don’t. Do it in one block, cold, with the domain pages closed. The value of a practice bank is entirely in the retrieval, and retrieval only happens when the answer is genuinely not in front of you.
The protocol
- Budget about two minutes a question — roughly thirty-two minutes for the sixteen. The CNPA’s 120 minutes is published; its question count is not, so two minutes each is those published minutes spread across the 60-question paper this site uses as a study convention. Drill at it regardless — it is slow enough to work the elimination properly and fast enough to finish.
- Answer before you read the options. Read the stem, read the lead-in, form your own answer, then look. A well-built distractor is designed to be attractive only once you have seen it.
- Commit on every question, including the ones you are guessing. Nothing published indicates that Linux Foundation multiple-choice exams penalise a wrong answer — confirm that in the candidate handbook rather than trusting this page — but the habit of deciding under uncertainty is the thing you are training.
- Read every explanation, including the ones you got right. Each explanation names the tempting wrong answer as well as the key. If you had not spotted why that option was wrong, you got the question right for the wrong reason, and it will catch you next time in a different costume.
- Re-sit 48 hours later, not tonight. A second pass an hour after the first measures short-term memory and flatters you badly. The bank manual has the full review loop and the miss-log format.
The standard for “I know this one”
A question is finished when you can state why the key is right and say in one sentence why each of the other three was built. That is a high bar and it is the right one: on the real paper the wording will not match ours, so recognising a sentence is worth nothing and understanding a distinction is worth everything. If you can only defend your answer by pointing at the green highlight, you have not finished the question.
Price, retake terms, eligibility window and certification validity are all set by the Linux Foundation and revised over time, so confirm them before you book. The timing and cut score are published: the CNPA runs 120 minutes and requires 75% to pass — the Linux Foundation multiple-choice exam FAQ names the CNPA as the exception to the 90 minutes its other multiple-choice exams get. Structurally it is an associate-level, knowledge-based, multiple-choice exam over six weighted domains (36 / 20 / 16 / 12 / 8 / 8), delivered online under remote proctoring with no published prerequisite. It is not the performance-based CNPE, which drops you into a live terminal for 2 hours with a 64% cut score — both figures published in the official CNPE FAQ — across 15–20 hands-on tasks, a range that comes from the exam page rather than that FAQ. Confirm everything else on the official Linux Foundation CNPA page and the CNCF certification page before you register or pay.
The bank — sixteen questions
☺ Like you’re 10: Pick an answer. It turns green or red straight away and tells you why — including why the sneaky one was sneaky.
Click an option to lock it in — the correct answer is marked, your mistake is marked, and the explanation appears underneath. The counter and bar track how far through you are and how many you have right. The chips filter by domain; Shuffle / reset reshuffles both the question order and the options and starts a fresh attempt. Your best score for this bank is remembered in this browser only.
What the examiners are really testing here
☺ Like you’re 10: Almost every question is really asking “can you tell these two very similar things apart?”
Strip the scenarios away and this bank is testing a small number of boundaries, over and over. That is not a quirk of our writing — it follows from the blueprint, which is full of neighbouring concepts. Learn the boundary and you have learned every question that can be built on it, including the ones we did not write.
The distinctions this bank leans on
| The pair | The one-line discriminator | Read more |
|---|---|---|
| Desired state vs actual state | What Git says should be running vs what the cluster is really running. Reconciliation is the act of shrinking the gap. | GitOps |
| Push vs pull | Push: something outside reaches in, holding credentials. Pull: an agent inside reaches out, and the credentials never leave the cluster. | GitOps |
prune vs selfHeal | Prune deletes live resources removed from Git. Self-heal reverts changes made outside Git. | Argo CD |
| Canary vs blue/green | Canary: both versions serve, weighted, gradually. Blue/green: two whole stacks, one atomic flip, never concurrent. | Argo Rollouts · Flagger |
| Deploy vs release | Deploy puts the code on the cluster. Release exposes the behaviour to users — which is what a feature flag decouples. | Progressive delivery |
| Tag vs digest | A tag is a mutable pointer. A digest names exact bytes — the only way to prove production runs what staging tested. | Release engineering |
| CRD vs CR vs controller vs operator | The type · an instance · the loop that reconciles it · controller plus CRD plus domain knowledge, packaged. | Platform APIs |
| Served version vs storage version | Many versions may be served; exactly one is stored. The API server converts between them in the request path. | Kubebuilder |
| Admission vs controller | Admission decides whether the object is allowed to exist. The controller acts on it after it exists. | Security & policy |
| Declarative infrastructure vs a scheduled IaC job | Both express intent. Only the first has something continuously comparing that intent to reality. | IaC & control planes |
The layer question, asked every time
The most productive habit for this pair of domains is to ask, of every option: at what point in the lifecycle does this act? Commit time, build time, admission time, reconcile time, or run time. An enormous share of distractors are correct statements placed at the wrong point — a scanner in the pipeline offered as a way to stop a hand-applied Pod, a controller offered as a way to reject a malformed object, a merge-triggered job offered as protection against drift that happens between merges. If you can place each option on that timeline in five seconds, you can eliminate two options in ten.
The qualifier in the lead-in
Watch for most directly, first, best, NOT. Several questions in this bank contain an option that is a perfectly true statement and still the wrong answer, because it answers a different question than the one asked. When two options both survive, apply the repair test from the bank manual: if I fixed only this one, would the symptom described in the stem go away? The option whose repair removes the symptom is the key. That single test resolves most two-survivor standoffs in this domain, because delivery scenarios always describe a symptom.
Turning misses into reps
☺ Like you’re 10: If you got one wrong, don’t just read the answer — go and make the thing happen on a cluster you don’t care about. Then you’ll never forget it.
These two domains are unusual among the CNPA’s six in that almost everything they test can be seen in about fifteen minutes on a throwaway cluster. That matters because the CNPA is a knowledge exam, but knowledge that has been watched happening is far stickier than knowledge that has only been read. If a question in this bank surprised you, the corresponding experiment is short.
Three experiments, one per common miss
# 1 — watch reconciliation defeat drift (Argo CD, self-heal on) kubectl scale deployment/checkout --replicas=9 -n checkout kubectl get deployment/checkout -n checkout -w # it goes back on its own. Now disable self-heal and repeat: it does not. # 2 — prove a controller cannot stop a bad object from being stored kubectl apply -f bad-database.yaml kubectl get database orders-db -o yaml # the object exists and is invalid. Add the ValidatingAdmissionPolicy above and retry: # now the API server refuses it, and the object never reaches etcd at all. # 3 — prove a tag is not an artifact crane digest ghcr.io/acme/checkout:1.4.3 # rebuild from the identical commit, push the identical tag, and run it again. # Same tag, different digest — which is exactly why you promote by digest.
The GitOps lab and the platform-APIs lab walk through longer versions of all three on a kind cluster, and the CI/CD lab covers the promotion and canary halves. Fifteen minutes each, and the domain stops being abstract.
Take the three questions you found hardest and write the stem of a new question for each — same idea, different scenario, four options of your own. Writing a plausible distractor is much harder than spotting one, and it forces you to articulate the misconception the original was built on. If you cannot invent a convincing wrong answer, you have not understood the boundary the question was testing. Ten minutes of this is worth an hour of re-reading.
If you missed these, read this
☺ Like you’re 10: Every question here comes from a page on this site. Go back to the page, not to a search engine.
Nothing in this bank is examined that is not taught somewhere in this course. Find the theme you missed, read the middle column to pass, and read the right column if you want to actually be good at it — which is a different and more durable goal.
When you have worked the misses, the next steps are ordered: the bank manual for technique and the miss log, the CNPA study plan for where this bank sits in the week, the flashcards and self-check quiz for mixed recall, know it cold for the handful of things that must be automatic, the glossary for any term an explanation assumed — and, once every domain is drilled, the full weighted CNPA mock exam. Save that one until last: it is the only instrument that reproduces the shape of the real paper, and it is only informative while it is still unfamiliar.
Foxy: Fourteen out of sixteen. The two I lost were both “which principle is missing,” which feels unfair — I can list the four principles.
Benny: Nobody asked you to list them. They gave you a symptom and asked which one, if it had been there, would have prevented it. That is a different skill and it is the one the job needs.
Recon: BEEP. Observe. Compare. Act. Repeat. If a question describes something surviving that should not have survived, ask what stopped repeating.
Mira: And it is the same on my half. Nobody asks “what is a CRD.” They describe an API with forty-seven fields that nobody uses and ask you what that tells you.
Gizmo: Easy — it tells you the developers are lazy. Give them a wiki page explaining all forty-seven fields! 😈
Dot: Gizmo, I have read that wiki page. Four times. I still copy Ravi’s YAML and change the name.
Timmy: Which is exactly the failure mode. A documented bad API is still a bad API — and the copied YAML carries whatever was wrong in the original straight into production.
Benny: Two domains, one lesson: if a human has to remember to do the right thing, the platform has not done its job yet.
Without scrolling up. 1. In a GitOps platform, what is the authoritative answer to “what should be running in production right now,” and what are the three things that are not? 2. Name the one kind of failure continuous reconciliation cannot protect you from. 3. Which rollout strategy do you pick when two versions must never serve traffic concurrently, and why does that rule out a canary? 4. Why can reverting a commit fail to restore service after a schema migration? 5. What does a CRD give you, and what does it conclusively not give you? 6. At which point in the API request path must a rule live if it has to hold even when someone bypasses your portal and pipeline? 7. How many versions of a CRD may be served, and how many may be stored?
Check your answers
- The config repository at the revision the reconciler tracks. Not the live cluster (that is actual state), not the pipeline log (a record of one past action), and not the registry’s
latesttag (a mutable pointer that nobody reviewed). - A bad change that was committed and merged. Reconciliation enforces Git faithfully — including Git’s mistakes. Its protection is against divergence, not against wrong intent; that is what review, tests and progressive delivery are for.
- Blue/green. A canary works by running both versions simultaneously behind a weighted traffic split — concurrency is its mechanism, not a side effect — so it cannot satisfy a constraint that forbids concurrency. Blue/green flips all traffic in one step.
- Because the database schema is not part of the declarative state the reconciler manages. Reverting the manifests restores the old code, which now runs against an already-migrated schema. Backward-compatible (expand/contract) migrations are what make a revert safe.
- A CRD gives you API surface — a new kind with storage, schema validation, RBAC, admission,
kubectland watch support. It gives you no behaviour: without a controller the object simply sits in etcd looking correct. - At admission, in the API server’s request path — every client goes through it, including
kubectl, pipelines and GitOps controllers. A portal check protects portal users only; a pipeline check protects pipeline users only; a controller check happens after the object is already stored. - Many served, exactly one stored. The API server converts between served versions in the request path using the CRD’s conversion strategy; existing objects are only rewritten to the new storage version when something touches them.