Back to blog

Kyverno v1.19.2: a practical roadmap for evaluating and upgrading clusters

Upgrading the component that decides which resources may enter Kubernetes requires more than checking whether its new Pods are ready. Approval should demonstrate two outcomes: legitimate workloads still work, and prohibited resources are still rejected.

Kyverno v1.19.2 was released on October 20, 2026. When checked for this article on October 24, 2026, it was the latest stable release. Its release notes list fixes for 24 security advisories: nine Critical, 14 High, and one Moderate. Actual exposure depends on affected versions and enabled features; this total does not mean every cluster is vulnerable to every issue. (github.com)

This roadmap proposes a staged upgrade backed by security, compatibility, and recovery evidence. Examples assume an existing Helm installation whose release and namespace are both named kyverno. Adjust those names and start in staging.

1. Understand what you are upgrading

Kyverno is a policy engine for Kubernetes. It supports resource validation and mutation, resource generation, and image verification. Some processing runs in the admission path: the API server calls webhooks before persisting an operation. Kyverno is not a proxy in the application's HTTP request path. (kyverno.io)

A simplified flow is:

CI/CD or kubectl → API server → admission and policy evaluation → persistence → application controllers

CI/CD stands for continuous integration and continuous delivery. The operational impact primarily concerns Kubernetes API operations and reconciliation, rather than traffic between users and an application already running. (kubernetes.io)

The installation separates responsibilities:

  • Admission controller: handles webhooks and admission-time checks.
  • Background controller: processes generation and mutation of existing resources.
  • Reports controller: produces and reconciles policy reports.
  • Cleanup controller: handles cleanup capabilities.
  • CRDs: Custom Resource Definitions, which register custom resource types.
  • ServiceAccounts and RBAC: controller-specific identities and role-based access control. (kyverno.io)

The operating model proposed here treats these components as critical platform infrastructure, with explicit owners, tests, and availability requirements.

2. Separate the security patch from the 1.19 migration

The chart associated with application version v1.19.2 is `3.9.2`. Chart versions and application versions are different identifiers. Do not use --version 1.19.2 expecting to select this chart; the mapping is recorded in the tagged Chart.yaml. (raw.githubusercontent.com)

For an installation already running 1.19.1, focus on the patch and its effects on existing policies. Earlier installations also face a release-line migration: in 1.19, ClusterPolicy, Policy, legacy cleanup policies, and the legacy PolicyException are deprecated, with removal announced for 1.20. CEL, or Common Expression Language, policy types are the forward path. Deprecation does not mean those legacy types were immediately removed in 1.19.2. (kyverno.io)

Build a risk-based regression matrix

Select tests according to the capabilities your organization actually uses:

AreaProposed staging test
Image verificationValid images pass; invalid signatures or attestations fail; workload-supplied metadata cannot bypass verification.
Namespaced policiesA tenant policy cannot modify resources in another namespace.
ExceptionsApproved exceptions work only within their authorized scope, including generated native admission policies where applicable.
CELRepresentative expressions work; excessive evaluation cost is handled without compromising availability.
GenerationPolicy-author authorization and generated-resource scope are checked.

These tests follow the areas covered by the official advisories. A patch release should not be assumed behaviorally invisible. Run negative tests in an isolated environment rather than reproducing abusive workloads in production. (github.com)

3. Establish a compatibility gate

As checked on October 24, 2026, the documentation lists Kubernetes 1.33–1.35 as supported for Kyverno 1.19. Other versions may work but do not carry the same tested compatibility assurance. The chart's minimum kubeVersion requirement is not a replacement for that matrix. Community support for the release line is estimated to end when 1.20 arrives, currently projected for November 2026; that projection is not a guaranteed release date. (kyverno.io)

My proposed gate blocks promotion when any of these conditions remains unresolved:

  • Kubernetes is outside the supported matrix without explicit validation and acceptance.
  • Intermediate upgrade requirements have not been reviewed.
  • CRD ownership is unclear.
  • Negative policy tests are missing.
  • Recovery has not been rehearsed.
  • Existing saturation or availability problems remain unexplained.

Do not upgrade by changing image tags alone: supporting resources and CRDs may change as well. Review intervening release notes for older installations. This Helm procedure should not be applied automatically to deployments managed through standalone YAML manifests. (kyverno.io)

4. Inventory and back up the current installation

Start by confirming the cluster context, versions, and current state. These commands inspect resources:

kubectl config current-context
kubectl version
helm version
helm list -n kyverno
helm history kyverno -n kyverno
kubectl get deployments,pods,services -n kyverno -o wide
kubectl get validatingwebhookconfigurations,mutatingwebhookconfigurations
kubectl api-resources --api-group=kyverno.io
kubectl api-resources --api-group=policies.kyverno.io

Use API discovery to identify installed resource types. Where resource names are ambiguous, qualify them with their API group. (kubernetes.io)

Capture operator-supplied values separately from computed values, which include defaults:

umask 077
mkdir -p backup-kyverno
helm get values kyverno -n kyverno -o yaml > backup-kyverno/values-user.yaml
helm get values kyverno -n kyverno --all -o yaml > backup-kyverno/values-effective.yaml
helm get manifest kyverno -n kyverno > backup-kyverno/release.yaml
kubectl get crd -o yaml > backup-kyverno/crds.yaml

--all captures computed values. Treat that output as comparison evidence, not an automatic input to the upgrade: old defaults should not be preserved without review. (helm.sh)

For recovery, I recommend also retaining policies, exceptions, configuration, relevant generated resources, the Git revision, and previous release artifacts. Export the resource types discovered during inventory; the commands above are not a complete backup.

Encrypt the backup and restrict access. Do not commit Secrets or sensitive manifests to a public repository. Define the recovery time objective, RTO, and recovery point objective, RPO, and rehearse restoration in a disposable cluster.

Assign explicit ownership of CRDs

Release line 1.19 introduces the kyverno-api dependency for CRD management, controlled by crds.install. Review workflows that manage CRDs separately. The documentation also distinguishes served APIs from storage versions: in 1.19, policies.kyverno.io types retain v1beta1 as their storage version even though manifests use v1. (kyverno.io)

Inspect spec.versions and status.storedVersions on relevant CRDs. My recommendation is not to edit storedVersions manually merely to silence an error. Avoid combining storage migration, policy conversion, and the security patch unless the upgrade path requires it.

5. Prepare reviewed values and availability settings

The following is an illustrative overlay, not a complete production configuration. It uses keys available in chart 3.9.2:

admissionController:
  replicas: 3
  podDisruptionBudget:
    enabled: true
    minAvailable: 2
  container:
    resources:
      requests:
        cpu: 250m
        memory: 256Mi
      limits:
        memory: 768Mi
backgroundController:
  replicas: 2
cleanupController:
  replicas: 2
reportsController:
  replicas: 2

replicas configures controller redundancy, container.resources sizes the admission controller, and podDisruptionBudget configures disruption protection. These numbers are test inputs, not universal sizing recommendations. Merge the overlay into reviewed existing values and save the result as values-reviewed.yaml, preserving required network, certificate, and registry settings. (raw.githubusercontent.com)

Availability does not imply linear throughput gains: controllers differ in leadership and work distribution. Spread replicas across nodes and zones, and test the loss of a failure domain. (kyverno.io)

A PodDisruptionBudget constrains certain voluntary disruptions. It does not cover every failure or replace the Deployment's rolling-update strategy. Check that the cluster has capacity for additional replicas during rollout. (kubernetes.io)

For capacity planning, reproduce admission bursts, matching-policy volume, and external dependencies. The scaling documentation recommends local measurement, warns about broad resource matching, and recommends avoiding CPU limits. If organizational policy requires CPU limits, explicitly test throttling. (kyverno.io)

A single replica may be acceptable for development experiments. For production, my acceptance checklist requires redundancy, verified probes, measured resource allocations, failure-domain distribution, alerting, and recovery. Do not enable autoscaling merely to complete a checklist: first validate minimum capacity and burst response.

6. Run an isolated policy smoke test

This complete example creates a test namespace and a ValidatingPolicy requiring an owner label on ConfigMaps within that namespace. It starts in Audit mode:

apiVersion: v1
kind: Namespace
metadata:
  name: policy-upgrade-test
---
apiVersion: policies.kyverno.io/v1
kind: ValidatingPolicy
metadata:
  name: upgrade-require-configmap-owner
spec:
  validationActions:
    - Audit
  matchConstraints:
    namespaceSelector:
      matchLabels:
        kubernetes.io/metadata.name: policy-upgrade-test
    resourceRules:
      - apiGroups: [""]
        apiVersions: [v1]
        operations: [CREATE, UPDATE]
        resources: [configmaps]
  validations:
    - expression: "has(object.metadata.labels) && 'owner' in object.metadata.labels"
      message: "ConfigMaps must declare an owner label."
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: upgrade-valid
  namespace: policy-upgrade-test
  labels:
    owner: platform-engineering
data:
  purpose: upgrade-smoke-test

matchConstraints limits scope, and the CEL expression checks label presence. Audit does not block violations; Deny enables rejection testing. Adapt the namespace and rule. This is a teaching example, not a complete enterprise policy. (kyverno.io)

Proposed procedure:

  1. Apply the file to the upgraded staging cluster.
  2. Wait for the policy and its admission configuration to reconcile.
  3. Confirm that the valid ConfigMap is accepted.
  4. Prepare a copy named upgrade-invalid without metadata.labels.
  5. Change only this test policy from Audit to Deny.
  6. Confirm that the valid object remains accepted and the invalid object is rejected by the expected rule.

Do not switch all production policies to audit mode to simplify the upgrade. The isolated test supplements existing controls rather than weakening them.

Run the existing suite with the target command-line interface, or CLI, version as well:

kyverno version
kyverno test ./tests

./tests must contain valid Kyverno tests, including resources and expected results. Local tests do not replace integrated testing of webhooks, permissions, and cluster dependencies. (kyverno.io)

7. Render, review, and deploy in waves

The following examples use Helm 3 syntax. If your environment uses Helm 4, validate the commands and its waiting and recovery semantics before execution. (helm.sh)

helm repo add kyverno https://kyverno.github.io/kyverno/
helm repo update
helm show chart kyverno/kyverno --version 3.9.2
helm show values kyverno/kyverno --version 3.9.2 > values-target-defaults.yaml
helm template kyverno kyverno/kyverno \
  --namespace kyverno \
  --version 3.9.2 \
  --is-upgrade \
  --include-crds \
  -f values-reviewed.yaml > rendered-kyverno.yaml

Compare the output with the current release: images, CRDs, RBAC, hooks, Services, webhooks, and scheduling settings. helm template renders locally; it does not prove API-server compatibility or execute hooks. (helm.sh)

After approval, upgrade one staging cluster:

helm upgrade kyverno kyverno/kyverno \
  --namespace kyverno \
  --version 3.9.2 \
  -f values-reviewed.yaml \
  --wait \
  --wait-for-jobs \
  --timeout 10m

The ten-minute timeout is illustrative. Waiting for resources and Jobs does not verify policy semantics. The example intentionally omits --atomic: enable automatic rollback only after validating the return path, particularly for CRDs. (helm.sh)

My recommended sequence is staging → production pilot cluster → small groups → remaining fleet. Do not install a second independent release in the same cluster as a canary without an explicit ownership and scoping design.

For GitOps environments, make the change through the repository and reconciler. Treat imperative commands as laboratory references or an authorized operational procedure, avoiding conflicting manual and declared states.

8. Define observability and promotion criteria

Record a baseline and track:

  • admission latency at the 95th and 99th percentiles;
  • operation volume and webhook errors;
  • expected versus unexpected rejections;
  • CPU, memory, restarts, and availability by controller;
  • reconciliation delay and report freshness.

Kyverno provides monitoring integration. Use Prometheus and Grafana according to your existing architecture, and inspect the actual exported metric names and labels before writing queries or alerts. (kyverno.io)

Centralize logs and correlate the upgrade window with API-server errors. When enabled, tracing can help investigate processing paths; keep sampling and retention controlled. Do not assume tracing is enabled by default. (kyverno.io)

Reports provide complementary evaluation evidence, not a replacement for admission rejection tests. Check that reports are updating rather than interpreting missing results as automatic success. (kyverno.io)

My proposed promotion criteria require all critical tests to pass, no policy bypass, healthy dependencies, and compliance with the team's service-level objective, or SLO. Agree on the observation window beforehand; do not invent an acceptable latency threshold during an incident.

9. Security and cost-aware operation

Review who can create policies, grant exceptions, and change Kyverno configuration. Preserve separate ServiceAccounts, least-privilege RBAC, and Transport Layer Security, or TLS. Limit additional permissions to required resources; do not resolve a Forbidden error by granting cluster-admin. (kyverno.io)

For production, I recommend validating control-plane connectivity to webhooks before tightening NetworkPolicies, keeping endpoints internal, and testing registry and external-service outages. Exceptions should have an owner, justification, approved scope, and expiration process.

For FinOps planning, establish explicit budgets for redundancy, log storage, and metric retention. Prefer stable capacity for the operational minimum. Consider Spot capacity only after testing interruption and replacement behavior. Review cross-zone traffic and external-dependency costs without sacrificing availability solely to reduce spending.

Avoid sizing every controller identically. Right-size from representative measurements, preserve rollout and recovery headroom, and reduce unnecessary observability cardinality and retention.

10. Troubleshooting and recovery

Start with the following commands, substituting the Pod name:

kubectl get pods -n kyverno -o wide
kubectl get deployments -n kyverno
kubectl get services,endpointslices -n kyverno
kubectl describe pod <pod> -n kyverno
kubectl logs <pod> -n kyverno --all-containers=true --tail=200
kubectl logs <pod> -n kyverno --all-containers=true --previous
kubectl get events -n kyverno --sort-by=.metadata.creationTimestamp

Containers that have not restarted have no previous logs to retrieve. The troubleshooting documentation recommends investigating component state, logs, and webhook communication. (kyverno.io)

SymptomPossible causeInvestigationProposed correction
Admission timeoutUnavailable endpoint or network restrictionPods, EndpointSlices, and connectivityRestore readiness or networking before changing policies.
ForbiddenMissing permissionIdentify ServiceAccount, verb, and resourceGrant only the required permission.
Unrecognized resource typeMissing CRD or unserved API versionAPI discovery and CRD versionsCorrect installation and reconciliation order.
Unexpected rejectionChanged rule, exception, or behaviorRejection message and controller logsReproduce and fix the specific configuration.

These are diagnostic hypotheses, not automatic conclusions. Distinguish policy denials from transport failures. A webhook's failurePolicy: Ignore handles certain invocation failures; it does not mean every explicit policy denial is ignored. During failures, it may allow operations to proceed without evaluation. (kubernetes.io)

Rollback is more than restoring an image

If the return path has been rehearsed, select a known-good revision:

helm history kyverno -n kyverno
REVISION=7
helm rollback kyverno "$REVISION" \
  --namespace kyverno \
  --wait \
  --wait-for-jobs \
  --timeout 10m

7 is an example; substitute the approved revision. This restores a Helm revision, not a guaranteed reversal of every migration or external side effect. (helm.sh)

I recommend checking CRD compatibility, persisted objects, generated resources, and any generated native policies separately. If downgrade is unsafe, prefer a targeted fix or a rehearsed recovery procedure. Returning to an affected version requires explicit security-risk acceptance.

Never delete CRDs or all webhooks indiscriminately as the default recovery action. Emergency access should be narrow, auditable, and followed by restoration of normal controls.

11. When to use Kyverno and what to consider instead

Kyverno fits platforms that need reusable policies, image verification, resource automation, and evaluation integrated into delivery workflows. For a small environment with only a few validations, I recommend evaluating a simpler option before adding controllers.

Kubernetes ValidatingAdmissionPolicy evaluates CEL validations inside the API server without an external webhook for that evaluation. It can reduce operational components when its capabilities meet the requirement. (kubernetes.io)

OPA Gatekeeper is another option, particularly for teams already maintaining Open Policy Agent and Rego policies. Its architecture uses constraints and templates. Evaluate existing skills, policy libraries, and operating costs rather than selecting solely by syntax preference. (open-policy-agent.github.io)

Avoid overlapping controls without clear ownership. Cloud portability does not eliminate the effort of migrating engine-specific policies.

Practical checklist

  • Confirm the mapping between application v1.19.2 and chart 3.9.2.
  • Make compatibility, CRD ownership, and recovery explicit gates.
  • Test both allowed and prohibited behavior.
  • Roll out across clusters with observation between waves.
  • Preserve security controls throughout the change.
  • Record recovery evidence, decisions, and owners.

Conclusion

Approve the upgrade based on preserved platform guarantees, not merely on Pods reaching Ready. The intended outcome is a verifiable set of policies, recovery paths, and operational signals that makes the next upgrade less uncertain.

This approach connects DevSecOps, SRE, and Platform Engineering: security defines the invariants, reliability engineering defines behavior under failure, and the platform turns both into a repeatable delivery process.

Want to apply this to your environment?

Book a free 30-minute call. I will look at your setup and tell you where to start.

Book a call

Get new articles by email

One email when a new article on infrastructure, backend and AI is published. No spam, unsubscribe anytime.