Salta ai contenuti

Kyverno

Kyverno is a policy engine designed specifically for Kubernetes. Policies are defined as Kubernetes resources — no new language to learn. Kyverno can validate, mutate, generate, and verify images for workloads in your cluster.

Installation

Install via Helm

# Add Helm repository
helm repo add kyverno https://kyverno.github.io/kyverno/
helm repo update

# Install Kyverno (standalone mode — 1 replica)
helm install kyverno kyverno/kyverno \
  --namespace kyverno \
  --create-namespace

# Install in HA mode (production — 3 replicas)
helm install kyverno kyverno/kyverno \
  --namespace kyverno \
  --create-namespace \
  --set replicaCount=3 \
  --set admissionController.replicas=3 \
  --set backgroundController.replicas=2 \
  --set cleanupController.replicas=2 \
  --set reportsController.replicas=2

# Install Kyverno CLI
brew install kyverno
# Or download from GitHub releases

Install via Manifest

kubectl create -f \
  https://github.com/kyverno/kyverno/releases/latest/download/install.yaml

# Verify
kubectl get pods -n kyverno
kubectl get crds | grep kyverno

Install Kyverno CLI

# macOS
brew install kyverno

# Linux
curl -LO https://github.com/kyverno/kyverno/releases/latest/download/kyverno-cli_linux_x86_64.tar.gz
tar -xzf kyverno-cli_linux_x86_64.tar.gz
sudo mv kyverno /usr/local/bin/

# Verify
kyverno version

Configuration

ClusterPolicy vs Policy

# ClusterPolicy — cluster-scoped, applies across all namespaces
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: my-cluster-policy
spec:
  # ...

# Policy — namespace-scoped
apiVersion: kyverno.io/v1
kind: Policy
metadata:
  name: my-namespace-policy
  namespace: production
spec:
  # ...

Policy Spec Structure

spec:
  validationFailureAction: Enforce    # Enforce | Audit
  background: true                    # Apply to existing resources
  rules:
    - name: rule-name
      match:
        any:
          - resources:
              kinds:
                - Pod
              namespaces:
                - production
      exclude:
        any:
          - resources:
              namespaceSelector:
                matchLabels:
                  kyverno.io/exclude: "true"
      validate:
        message: "Validation failed message"
        pattern:
          # ...

Core Commands

CommandDescription
kubectl get clusterpolicyList all ClusterPolicies
kubectl get policy -AList all namespace-scoped Policies
kubectl get policyreport -AList PolicyReports per namespace
kubectl get clusterpolicyreportList cluster-level PolicyReports
kubectl describe clusterpolicy <name>Show policy details and status
kyverno apply <policy> -r <resource>Test policy against a resource file
kyverno test .Run all test cases in current directory
kyverno test --detailed-results .Show per-rule test results
kyverno jp query -i <json> '<expr>'Test JMESPath expressions
kyverno jp parse '<pattern>'Parse and validate a Kyverno pattern
kubectl get admissionreports -AList admission-time reports
kubectl get backgroundscanreports -AList background scan reports
kubectl logs -n kyverno -l app=kyvernoView Kyverno controller logs

Advanced Usage

Validation Policy — Require Labels

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-labels
spec:
  validationFailureAction: Audit
  background: true
  rules:
    - name: check-team-label
      match:
        any:
          - resources:
              kinds:
                - Deployment
                - StatefulSet
                - DaemonSet
      validate:
        message: "Deployment must have a 'team' label"
        pattern:
          metadata:
            labels:
              team: "?*"

Mutation Policy — Add Default Labels

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: add-default-labels
spec:
  rules:
    - name: add-managed-by
      match:
        any:
          - resources:
              kinds:
                - Deployment
      mutate:
        patchStrategicMerge:
          metadata:
            labels:
              managed-by: kyverno
          spec:
            template:
              metadata:
                labels:
                  managed-by: kyverno

Generation Policy — Create NetworkPolicy

# Auto-generate a default-deny NetworkPolicy in every new namespace
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: generate-default-networkpolicy
spec:
  rules:
    - name: default-deny
      match:
        any:
          - resources:
              kinds:
                - Namespace
      generate:
        apiVersion: networking.k8s.io/v1
        kind: NetworkPolicy
        name: default-deny-all
        namespace: "{{request.object.metadata.name}}"
        synchronize: true
        data:
          spec:
            podSelector: {}
            policyTypes:
              - Ingress
              - Egress

Image Verification with Cosign

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-image-signature
spec:
  validationFailureAction: Enforce
  background: false
  rules:
    - name: check-image
      match:
        any:
          - resources:
              kinds:
                - Pod
      verifyImages:
        - imageReferences:
            - "ghcr.io/my-org/*"
          attestors:
            - count: 1
              entries:
                - keys:
                    publicKeys: |-
                      -----BEGIN PUBLIC KEY-----
                      MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
                      -----END PUBLIC KEY-----
                    signatureAlgorithm: sha256

Enforce Resource Limits

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-resource-limits
spec:
  validationFailureAction: Enforce
  background: true
  rules:
    - name: validate-limits
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: "All containers must have resource limits"
        foreach:
          - list: "request.object.spec.containers"
            deny:
              conditions:
                any:
                  - key: "{{ element.resources.limits.cpu }}"
                    operator: Equals
                    value: ""
                  - key: "{{ element.resources.limits.memory }}"
                    operator: Equals
                    value: ""

Policy Exception

# Allow a specific workload to bypass a policy
apiVersion: kyverno.io/v2
kind: PolicyException
metadata:
  name: delta-exception
  namespace: delta
spec:
  exceptions:
    - policyName: require-labels
      ruleNames:
        - check-team-label
  match:
    any:
      - resources:
          kinds:
            - Deployment
          names:
            - legacy-app
          namespaces:
            - delta

Common Workflows

Test Policies Before Enforcing

# Create a test directory structure:
# tests/
#   kyverno-test.yaml       — test manifest
#   policy.yaml             — the policy
#   resource-pass.yaml      — resource that should pass
#   resource-fail.yaml      — resource that should fail

# kyverno-test.yaml example:
cat <<EOF > tests/kyverno-test.yaml
name: require-labels-test
policies:
  - policy.yaml
resources:
  - resource-pass.yaml
  - resource-fail.yaml
results:
  - policy: require-labels
    rule: check-team-label
    resource: passing-deployment
    result: pass
  - policy: require-labels
    rule: check-team-label
    resource: failing-deployment
    result: fail
EOF

# Run tests
kyverno test tests/

Audit Existing Resources

# Switch policy to Audit mode (doesn't block, just reports)
kubectl patch clusterpolicy require-labels \
  --type=json \
  -p='[{"op":"replace","path":"/spec/validationFailureAction","value":"Audit"}]'

# Check audit results
kubectl get clusterpolicyreport -o wide

# View detailed failures
kubectl get clusterpolicyreport -o json | \
  jq '.items[].results[] | select(.result == "fail")'

Generate Policy Reports in CI

# Apply policy against resource manifests (no cluster needed)
kyverno apply ./policies/ \
  --resource ./manifests/ \
  --detailed-results

# Exit code 0 = all pass, non-zero = failures found
# Use in CI pipelines to gate PRs

Monitor Policy Violations

# Watch for new violations
kubectl get policyreport -A --watch

# Count violations per policy
kubectl get policyreport -A -o json | \
  jq '[.items[].results[] | select(.result == "fail")] | 
      group_by(.policy) | 
      map({policy: .[0].policy, count: length})'

Tips and Best Practices

  • Start with Audit mode before switching to Enforce — audit mode reports violations without blocking deployments, letting you fix resources first.
  • Use background: true to scan existing resources — without this, Kyverno only evaluates new/updated resources, leaving existing violations undetected.
  • Set synchronize: true on generation rules — Kyverno will keep generated resources in sync if the source policy changes.
  • Write tests before policies — use kyverno test in CI to validate that policies match the correct resources and allow intended exceptions.
  • Scope policies with exclude — always exclude the kyverno namespace and any system namespaces to prevent the policy engine from blocking itself.
  • Use PolicyExceptions instead of disabling policies — exceptions are tracked in Git and auditable; disabling policies leaves no trace.
  • Pin image verification keys in policies — rotating signing keys requires updating policies; use key references or OCI keyless with OIDC for easier rotation.
  • Enable podSecurityStandards — Kyverno’s built-in Pod Security Standard policies are a quick win for baseline security posture.
  • Monitor the kyverno namespace — check controller logs for admission webhook timeouts; a failing webhook can block all admissions if failurePolicy: Fail.
  • Use kyverno jp query to test JMESPath expressions interactively before embedding them in policies.