KCA — Kyverno Certified Associate
Watch a Policy Actually Block
This lab runs on real Kyverno
k3s + Kyverno is actually running inside the VM. The admission webhooks are registered, so when you attach a policy, things really get rejected, values really get injected, and other objects really get created.
The early policy-writing labs run on a fake cluster with only the CRDs loaded. There, no matter how well you write a policy, nothing happens — yet kubectl apply succeeds, so it looks normal on the screen.
It takes 4–5 minutes to come up the first time. It installs Kyverno and waits for the webhooks to be registered.
The expected study time is 70 minutes. The session starts at 60 minutes, so check the remaining time and extend it before it expires. This lab is pinned to k3s 1.35.8 and Kyverno 1.19.1. It uses ClusterPolicy to practice reading existing policies, but this API was deprecated in Kyverno 1.19, and the official documentation says it will be removed in 1.20. Do not copy it as is into a new project; check the supported versions and the new policy API.
Goal
Check for yourself when and how each of the policy's three actions (validate, mutate, and generate) happens, and see the difference between Enforce and Audit, and what happens when you leave out an exception.
Why it matters
The most dangerous state in a policy engine is not "the policy is wrong" but "the policy is applied nowhere." The latter is dangerous because it is quiet.
And the three actions happen at different times.
| Action | When | What |
|---|---|---|
mutate |
Admission, before validate | Modifies the object |
validate |
Admission | Rejects or lets it pass |
generate |
After admission, by a separate controller | Creates other objects |
If you do not know this order, the policies neutralize each other. If mutate puts in a label and validate requires that label, it passes thanks to the order. Conversely, generate happens outside admission, so it needs separate permissions.
Steps
Create the Pods in the kca namespace.
- Check how Kyverno is called and put it in
/root/kca/install.txt. The webhook configuration must be registered. - With the
require-teamClusterPolicy (Enforce), require theteamlabel, and put in/root/kca/validate.txtthat a Pod without the label is rejected and thatok-pod, which has it, comes up. - With the
add-defaultspolicy, inject theownerlabel into Pods, and put in/root/kca/mutate.txtwhat actually went into themutatedPod. Also write down the order of mutate and validate. - With the
gen-baselinepolicy, have it create abaselineConfigMap in a new namespace, createtenant-xto check, and put it in/root/kca/generate.txt. - Apply the
warn-onlypolicy asAudit, and put in/root/kca/audit.txtthat the violatingviolatorPod gets created and that it is recorded in thePolicyReport. - Add an exception to
require-teamto exclude the system namespaces, and put in/root/kca/exclude.txtwhy it has to be so. - Create
/root/kca/test-pod.yaml, test it with thekyvernoCLI before putting it on the cluster, and put the result in/root/kca/cli.txt. - In
/root/kca/report.md, write the three linesenforce_blocks=yes,audit_blocks=no, andpolicies=along with an explanation.
Notes
- A policy's behavior mode is
spec.validationFailureAction(the old version) orvalidate.failureActioninside a rule (the new version). Use whichever matches the cluster's Kyverno version — you can check withkubectl explain clusterpolicy.spec. - Right after you attach a policy, it may not take effect yet. It takes a few seconds for the webhook configuration to be updated. Wait a moment before testing.
generateis done not by admission but by the background controller. So that controller's service account must have permissions. If not, the policy looks fine but nothing gets created.- The CLI is
kyverno apply <정책> --resource <매니페스트>(the placeholders are the policy and the manifest). It does not need a cluster, so it is used in CI. - Common mistake 1: widening the target scope without checking the labels and recovery paths of system workloads. The recreation of a system Pod that violates this policy may be blocked. A rule's
excludeand a webhook'snamespaceSelectorare filters at different stages. - Common mistake 2: applying it as
Auditand thinking that policy blocks. An Audit policy allows and reports violations, and other Enforce policies can still reject.
How the policy gets called
Check how Kyverno is called and put it in /root/kca/install.txt. The webhook configuration must be registered.
The API server asks Kyverno only when a ValidatingWebhookConfiguration is registered.
Reject
With the require-team ClusterPolicy (Enforce), require the team label, and put in /root/kca/validate.txt that a Pod without the label is rejected and that ok-pod, which has it, comes up.
It blocks only if it is Enforce. Test both a Pod without the label and a Pod that has it.
Modify — and there is an order
With the add-defaults policy, inject the owner label into Pods, and put in /root/kca/mutate.txt what actually went into the mutated Pod. Also write down the order of mutate and validate.
mutate runs before validate. That is why validate can require a value that mutate inserted.
Create something else
With the gen-baseline policy, have it create a baseline ConfigMap in a new namespace, create tenant-x to check, and put it in /root/kca/generate.txt.
generate is done by the background controller. So that controller must have permissions, and the resource is not created immediately.
Only record, without blocking
Apply the warn-only policy as Audit, and put in /root/kca/audit.txt that the violating violator Pod gets created and that it is recorded in the PolicyReport.
An Audit policy creates the object even if it is violated. The results accumulate in the PolicyReport.
When you widen the policy scope, check the exceptions and recovery
Add an exception to require-team to exclude the system namespaces, and put in /root/kca/exclude.txt why it has to be so.
The earlier steps targeted only kca. This time you widen the target but exclude the system namespaces. Do not judge that webhook calls are also excluded just because of a policy exception.
Test before putting it up
Create /root/kca/test-pod.yaml, test it with the kyverno CLI before putting it on the cluster, and put the result in /root/kca/cli.txt.
kyverno apply <정책> --resource <매니페스트> tests a policy without a cluster (the placeholders are the policy and the manifest). It is used in CI.
What did you learn
In /root/kca/report.md, write the three lines enforce_blocks=yes, audit_blocks=no, and policies= along with an explanation.
Along with the three lines enforce_blocks=, audit_blocks=, and policies=, write about the timing of the three actions and the exception story.