KCA — the exam
Self-service only works if something is still allowed to say no. The Kyverno Certified Associate (KCA) is the CNCF and Linux Foundation's associate-level, knowledge-based credential for exactly that job: writing the rules that check every resource at the moment it tries to enter a cluster, in plain Kubernetes-shaped YAML rather than a separate policy language. It is the narrowest exam on this shelf in scope — one project, one engine — and also the most concrete: nearly a third of the paper is the single competency of writing policies, and the whole exam reduces to knowing four rule types cold. This page is the hub: what the exam tests, all four rule types worked as one policy file, the complete domain table straight from the CNCF curriculum, and the logistics worth verifying before you register.
Imagine a school where anyone can bring a backpack in, but there's a robot standing at the door with a checklist. The robot doesn't just say yes or no — it can also quietly fix small stuff without asking (zip up an open pocket), it can hand you a name badge you forgot to bring, and for anything really important, like a glass bottle, it checks a wax seal before letting it through at all. Four different jobs, one robot: check and reject, quietly fix, hand out something new, and check the seal. Kyverno is that robot at the door of a Kubernetes cluster, and the KCA tests whether you can program all four of its jobs correctly.
What the KCA actually tests
☺ Like you're 10: A test about one specific door-robot, not door-robots in general.
The KCA is a project-specific associate certification: an online, remote-proctored, multiple-choice knowledge exam covering Kyverno, the policy engine that validates, mutates, generates and verifies Kubernetes resources at admission time. It sits beside CGOA, CAPA, CBA, CCA, ICA, OTCA and PCA on this course's nine-certification shelf — all ninety minutes of pure multiple choice, unlike the hybrid ICA or the fully performance-based LFCS. It's narrow on purpose: nothing on the paper asks you to weigh Kyverno against an alternative admission controller. You are tested on this engine's idioms, in depth.
It suits platform engineers who own the guardrails — if you're the one who decides whether a team can run privileged pods, this exam formalizes your daily work — and security or SRE folk inheriting a cluster with policies nobody documented. It does not teach general Kubernetes security the way the sibling Kubernetes course's KCSA and CKS do — this course assumes those five core exams are already cleared (see What Is Kubestronaut?) and builds one specialist layer on top of them.
Nearly every question on this exam is a variation of one shape: a policy holds a list of rules, and every rule has a match, optional preconditions, and exactly one of validate / mutate / generate / verifyImages. Get that skeleton into muscle memory — which of the four, and which field lives inside it — and the exam stops feeling like thirty-one separate facts and starts feeling like one shape applied thirty-one times.
All four rule types, worked as one policy
☺ Like you're 10: One rulebook, four completely different kinds of rule inside it.
A policy is just a Kubernetes resource — you write YAML that looks exactly like the YAML it's policing. There are two policy kinds with an identical schema: ClusterPolicy (cpol) applies cluster-wide and is the only one that can match cluster-scoped resources like Namespace; Policy (pol) is confined to its own namespace, the way a tenant owns rules for their own space. Both hold spec.rules[], and Kyverno registers itself as a validating and mutating admission webhook, so every create and update passes through it before the API server ever persists the object — that fact alone answers most of the "Admission Controllers" competency.
Below is one ClusterPolicy carrying all four rule types, each doing a genuinely different job. Read it top to bottom once and you have touched roughly a third of the whole exam.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: mission-control-guardrails
spec:
background: true # also scan resources that already existed
rules:
# 1) VALIDATE — allow or reject the request outright
- name: require-team-label
match:
any:
- resources: { kinds: [Deployment, StatefulSet, DaemonSet] }
preconditions: # cheap gate — skip the rule if this is false
all:
- key: "{{ request.operation }}"
operator: AnyIn
value: [CREATE, UPDATE]
validate:
failureAction: Enforce # without this, the rule only audits — never blocks
message: "Workloads need a team label. Add metadata.labels.team."
pattern:
metadata:
labels:
team: "?*" # ?* means "at least one character"
# 2) MUTATE — rewrite the object on its way in, via an RFC 6902 JSON patch
- name: default-pull-policy
match:
any:
- resources: { kinds: [Pod] }
mutate:
patchesJson6902: |-
- op: add
path: "/spec/containers/0/imagePullPolicy"
value: IfNotPresent
# 3) GENERATE — every new namespace launches with a default-deny NetworkPolicy
- name: default-deny-per-namespace
match:
any:
- resources: { kinds: [Namespace] }
generate:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
name: default-deny
namespace: "{{ request.object.metadata.name }}" # a variable, resolved at runtime
synchronize: true # keep the copy in step if the source changes
data:
spec:
podSelector: {}
policyTypes: [Ingress, Egress]
# 4) VERIFYIMAGES — no valid signature, no pod. Also pins tag -> digest.
- name: verify-signed-images
match:
any:
- resources: { kinds: [Pod] }
verifyImages:
- imageReferences: ["ghcr.io/mission-control/*"]
mutateDigest: true # rewrite the tag to the digest once verified
attestors:
- entries:
- keyless:
subject: "https://github.com/mission-control/*"
issuer: "https://token.actions.githubusercontent.com"Three exam-shaped details hide in that file. failureAction: Enforce is what turns a report into an actual rejection — leave it off and the rule only ever audits, quietly, forever. background: true lets the background controller scan objects that already existed before the policy was installed, but background scanning cannot see admission-only context such as request.userInfo — a rule that depends on who made the request can only run at admission time, never in the background. And verifyImages runs in the mutating phase, on purpose: a successful verification rewrites the tag to the digest you just verified, closing the tag-mutation race — a security control that works by mutating, which is exactly the kind of fact multiple-choice writers love.
One competency worth naming on its own: autogen. When a rule matches Pod, Kyverno automatically generates equivalent rules for the pod controllers — Deployment, StatefulSet, DaemonSet, Job, CronJob — so the rejection message actually lands where the developer applied their manifest. Steer or disable it with the pod-policies.kyverno.io/autogen-controllers annotation. Rounding out the 32% domain: variables and API calls (the {{ ... }} JMESPath expressions above, plus context entries that read a ConfigMap or call the Kubernetes API mid-rule), CEL as an alternative expression language inside validate — the same language the API server itself uses natively for ValidatingAdmissionPolicy — and CleanupPolicy / ClusterCleanupPolicy, separate CRDs served by their own controller that delete matching resources on a cron schedule, not a fifth rule type bolted onto a policy.
The six official domains and their weights
☺ Like you're 10: Six chunks, wildly uneven sizes — one of them is nearly a third of the whole test on its own.
The official Kyverno Certified Associate (KCA) curriculum, published by the CNCF, splits the exam into six weighted domains covering thirty-one competencies in total. The bars below are that blueprint, drawn to scale, and the six weights sum to exactly 100% (32 + 18 + 18 + 12 + 10 + 10):
| Domain | Weight | Competencies |
|---|---|---|
| Writing Policies | 32% | Validation Rules · Preconditions · Background Scans · Mutation Rules · Generation Rules · VerifyImage Rules · Variables & API Calls in Policies · JSON Patches · Autogen Rules · Cleanup Policies · Common Expression Language (CEL) |
| Fundamentals of Kyverno | 18% | Kyverno Policies & Rules · YAML Manifests · Admission Controllers · OCI Images |
| Installation, Configuration, and Upgrades | 18% | Helm-based Installation and Configuration · Kyverno Custom Resource Definitions (CRDs) · Controller Configuration with Flags · Configuring Kyverno RBAC, Roles, and Permissions · High Availability Installations · Upgrading Kyverno |
| Kyverno CLI | 12% | apply · test · jp · Installing the Kyverno CLI |
| Applying Policies | 10% | Applying Policy in Cluster · Resource Selection · Common Policy Settings for Kyverno Rules |
| Policy Management | 10% | Policy Reports · PolicyExceptions · Kyverno Metrics |
Writing Policies carries eleven of the thirty-one competencies — more than the next two domains combined — so if your time is limited, that's where it goes. The two 18% domains differ in character: Fundamentals is conceptual and cheap to secure, while Installation, Configuration and Upgrades is operational — Helm values, controller flags, RBAC, high availability, upgrade mechanics — and is the domain people underestimate precisely because it's boring. Kyverno CLI at 12% is the best value on the paper: it names exactly four things, three of which are subcommands, and an evening of practice locks it in.
Installing, configuring, and the CLI
☺ Like you're 10: Four little robots share the door-guard job, and there's a separate tool that lets you rehearse the rules before anyone actually walks through.
A modern Kyverno install is four separate controllers, and knowing which does what turns a confusing outage into a fast diagnosis: the admission controller (the only one actually in the request path — scale it first for HA), the background controller (background scans, generate, mutate-existing — and it needs RBAC for whatever it creates or modifies), the reports controller (aggregates rule results into PolicyReport objects) and the cleanup controller (runs CleanupPolicy schedules). Helm is the named installation method.
# install — HA means scaling the admission controller first, it's the one in the request path helm repo add kyverno https://kyverno.github.io/kyverno/ helm repo update helm install kyverno kyverno/kyverno -n kyverno --create-namespace \ --set admissionController.replicas=3 \ --set backgroundController.replicas=2 \ --set reportsController.replicas=2 # controller configuration with flags — chart values move between releases, # so `helm show values` is the authority, never a blog post helm show values kyverno/kyverno | grep -A4 extraArgs # RBAC — Kyverno can only touch what its ClusterRoles allow. Read it, don't guess. kubectl get clusterrole | grep kyverno kubectl get clusterrole kyverno:background-controller -o yaml # upgrades — CRD handling has varied between chart versions; read the release notes first helm search repo kyverno/kyverno --versions | head helm upgrade kyverno kyverno/kyverno -n kyverno --version YOUR_TARGET_VERSION # --- the CLI: rehearse policies with no cluster required --- kyverno apply ./policies/ --resource ./manifests/ # what would this do? kyverno apply ./policies/ --resource ./manifests/ --policy-report kyverno apply ./policies/ --cluster --policy-report # dry-run a LIVE cluster kyverno test ./policies/ # kyverno-test.yaml, auto-discovered kyverno jp query -i pod.yaml 'spec.containers[*].image' # debug an expression kyverno jp function # list custom functions
One dynamic-configuration detail the exam likes: Kyverno only registers webhook rules for the kinds your installed policies actually reference. Install one Pod policy and the API server only ever calls Kyverno for Pod admission — nothing else pays the latency cost.
"My deploy got rejected the first week these landed. No resource limits, no team label, and an image tag of latest. Then I actually read the rejection — it named the rule, told me the fix, linked the docs. Twenty seconds later I was through. The old process was a ticket and a two-day wait for a human to notice the same three things. Once I found kyverno test, I stopped finding out my own policy changes were wrong from a teammate's failed deploy — I found out from my own laptop, before I ever pushed."
Applying policies and policy management
☺ Like you're 10: How the robot decides which bags to check, and the report card showing what it caught.
Resource Selection is its own named competency for a reason: every rule's match and exclude take any or all lists of filters that can pin kinds, namespaces, names, label selectors, subjects and operations — and getting the selector wrong is the single commonest reason a policy "does nothing" in practice. Common Policy Settings covers the knobs sitting outside any one rule: background, failureAction's current per-rule form versus the older, deprecated spec.validationFailureAction (expect to recognize both), and webhookTimeoutSeconds for slow external calls inside a rule.
What you see afterward is the Policy Management domain, in full:
kubectl get polr -A -o wide # PolicyReports — one per namespace, pass/fail/warn/skip/error kubectl get cpolr # ClusterPolicyReports — the cluster-scoped equivalent kubectl get polex -A # PolicyExceptions currently in force kubectl -n kyverno port-forward svc/kyverno-svc-metrics 8000:8000 # Prometheus-format metrics
PolicyReports and ClusterPolicyReports hold machine-readable results per resource per rule — how you measure a whole fleet before enforcing anything against it. PolicyExceptions are a declarative, reviewable carve-out: one named workload skips one named rule, through Git and code review, instead of permanently weakening the policy for everyone. Kyverno metrics are ordinary Prometheus metrics — admission counts, rule-result totals, latencies — so guardrails land on the same dashboards as everything else you already watch.
On a throwaway kind cluster: install Kyverno with Helm, apply require-team-label above with failureAction: Audit, create a Deployment with no team label, and find your own violation sitting unblocked in kubectl get polr -A -o wide — the false comfort of audit mode, seen with your own eyes. Flip it to Enforce and watch the same command return a rejection carrying your message. Write a kyverno-test.yaml for that rule, run kyverno test ., then break the policy on purpose and watch the test fail. Finally, create a fresh namespace and watch the generated NetworkPolicy arrive before you do.
How to prepare using this course
☺ Like you're 10: Most of what's on the test already has a page here — this is the shortcut.
Work the heaviest domain first, then drill. Continue with the KCA study plan for a week-by-week pacing schedule, then the practice question bank and two timed papers, Mock Exam · Set 1 and Mock Exam · Set 2. For the underlying concepts, read the Kyverno deep-dive and Policy-as-Code Philosophy; for what verifyImages is actually checking, read Cosign & Sigstore. Before exam day, run the readiness checklist.
Because Kyverno enforces admission control, it overlaps heavily with the security material in the sibling Kubernetes course — assumed background here, not re-taught. Skim the sibling Kubernetes course's CKS blueprint and CKS overview for how a CKS candidate reasons about admission control and pod security more broadly — KCA goes deep on one engine that implements that same layer, while CKS is the hands-on exam that assumes you already understand the surrounding cluster. If you're sequencing the whole ladder, The Order of Attack groups KCA together with CCA and ICA as its "policy and connectivity" phase — all three are largely standalone and can be taken in any order once CKA is active.
Exam logistics — and go verify them yourself
☺ Like you're 10: Here's what's published today. Numbers move — check before you pay.
The KCA is administered by The Linux Foundation on behalf of the CNCF. Every figure below is a snapshot read from the official Linux Foundation and CNCF KCA pages — treat it as a starting point, not a guarantee:
| Item | Detail (verify before booking) |
|---|---|
| Format | Online, remote-proctored, multiple-choice — a knowledge exam. No live cluster, no terminal |
| Duration | 90 minutes |
| Question count | Not published by either official page. Plan against the 90 minutes, not against a number you saw on a forum |
| Pass mark | 75% — published in the Linux Foundation's Multiple Choice Exam FAQ, which applies to every LF multiple-choice exam including this one, even though it isn't restated on the KCA product page itself |
| Validity | 2 years from the date you pass |
| Retake | One free retake included, alongside a 12-month eligibility window to schedule and sit the exam — confirm both are in the SKU you actually buy |
| Prerequisites | None. Listed at beginner level; working Kubernetes knowledge is assumed in practice, not formally required |
| Price | Listed around US$250 for the exam alone at the time of writing, higher when bundled with a subscription. Pricing moves with region, promotion and bundle — treat this as a signpost, not a quote |
| Domains & weights | The six above — 32 / 18 / 18 / 12 / 10 / 10, summing to 100% |
This is an independent, unofficial study resource, not affiliated with or endorsed by the CNCF or The Linux Foundation. Format, duration, pass mark, price, validity and even the curriculum version change without much notice, and third-party study pages — including this one — go stale between edits. The domains and weights above are transcribed from the official CNCF curriculum and sum to 100%; the rows marked "not published" are deliberately left blank rather than filled with a plausible guess. Confirm every detail on the official Linux Foundation KCA page before you register or pay for anything.
Foxy: Forty policies installed. That means we're governed, right?
Timmy: Run kubectl get polr -A -o wide and read the FAIL column out loud.
Nutty: …six hundred and twelve failures. And nothing has ever actually been blocked. Every rule is sitting in audit.
Gizmo: Which is perfect, obviously. I set them all to audit in March because a demo deploy broke. Nobody noticed for four months. 🤑
Timmy: That's the number-one policy-engine failure mode everywhere, and it's on the exam in spirit: failureAction: Enforce is what makes a rule a rule. Audit is a measurement, not a control.
Benny: So — enforce the two rules with zero current failures today, publish the report for the rest, and give teams a PolicyException path with an expiry date. Guardrails rolled out angrily get rolled back angrily.
1. Which domain is the largest, at what weight, and name four of its competencies. 2. Name the four rule types and say in one clause what each does. 3. What's the difference between Policy and ClusterPolicy, and which can match a Namespace? 4. A validate rule is installed and nothing is ever blocked — name two things to check. 5. Which three kyverno CLI subcommands does the curriculum name, and what does each answer? 6. Why does verifyImages run in the mutating phase rather than the validating phase? 7. What does a PolicyException give you that editing the policy directly does not?
Check your answers
- Writing Policies, at 32%. Any four of: Validation Rules · Preconditions · Background Scans · Mutation Rules · Generation Rules · VerifyImage Rules · Variables & API Calls · JSON Patches · Autogen Rules · Cleanup Policies · CEL.
validate— allow or reject the resource;mutate— rewrite it, via a strategic merge or JSON patch;generate— create a companion resource when a trigger appears;verifyImages— require a valid signature or attestation, and pin the tag to a digest.- Identical schema;
Policyis namespaced and applies only inside its own namespace,ClusterPolicyapplies cluster-wide. OnlyClusterPolicycan match cluster-scoped resources such asNamespace. - Any two of: the rule is still in audit —
failureAction: Enforceis not set; thematchblock doesn't actually select the kind, or the namespace is caught byexclude; the rule matchesPodbut the user creates a Deployment and autogen has been disabled; the admission controller is unhealthy or the webhook isn't registered. apply— "what would these policies do to these resources?";test— run declarative unit tests and assert each rule's expected result;jp— evaluate a JMESPath expression against a manifest to debug it before pasting it into a rule.- Because a successful verification rewrites the image tag to the digest that was just verified — pinning the reference closed the tag-mutation race — and only a mutating webhook is allowed to change the object on its way through.
- A separate, reviewable resource: one named workload skips one named rule, through Git and code review, while the policy stays strict for everyone else — instead of permanently weakening the rule for the whole fleet.