Workshops

Policy Management in Kubernetes

Learn how Kyverno enforces policies in Kubernetes clusters

Introduction to Kyverno

  • Declarative Kubernetes policy in yaml
  • Kubernetes admission controller and CLI
  • Validate, mutate, generate or remove any Kubernetes resources
  • Verify container images and metadata

How It Works

  • Kyverno runs as a dynamic admission controller in a Kubernetes cluster.
  • Kyverno receives validating and mutating admission webhook HTTP callbacks from the Kubernetes API server.
  • Kyverno applies matching policies to return results that enforce admission policies or reject requests.
  • Policy enforcement is captured using Kubernetes events.
  • For existing resources, Kyverno creates Policy Reports in the cluster.
  • The Webhook is the server which handles incoming AdmissionReview requests from the Kubernetes API server and sends them to the Engine for processing.

Enable Kyverno in Kuberise.io

  1. Set enabled: true in app-of-apps values file.
app-of-apps/values-platformName.yaml
ArgocdApplications:
  kyverno:
    enabled: true
  1. Add your Kyverno policy yaml files
    • Add your policies in values/defaults/platform/raw/kyverno directories, to apply to all platforms. (Adding policies in templates/kyverno/templates directory will not work as some of them contains similar syntax to Helm templating)
    • Add your policies in values/platformName/raw/kyverno directory, to apply to a specific platform.

How to Validate Resources

  1. Create a policy to require labels:
values/platformName/raw/kyverno/required-labels.yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-labels
spec:
  rules:
  - name: check-team
    match:
      any:
      - resources:
          kinds:
          - Pod
          namespaces:
          - default
    skipBackgroundRequests: true
    validate:
      allowExistingViolations: true
      failureAction: Enforce
      message: "label 'team' is required"
      pattern:
        metadata:
          labels:
            team: "?*"
  1. Test the policy:
Terminal
kubectl run nginx --image nginx                            # should fail
kubectl run nginx --image nginx --labels='team=alpha'      # should pass
  1. Check the policy report:
Terminal
kubectl get policyreport -o wide

How to Mutate Resources

  1. Create a policy to add labels:
values/platformName/raw/kyverno/add-labels.yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: add-labels
spec:
  rules:
  - name: add-project
    skipBackgroundRequests: true
    match:
      any:
      - resources:
          kinds:
          - Pod
          namespaces:
          - default
    mutate:
      patchStrategicMerge:
        metadata:
          labels:
            +(project): bravo
  1. Test the policy:
Terminal
kubectl run nginx --image nginx --labels='team=alpha'   # should add label 'project=bravo'
  1. Check the policy report:
Terminal
kubectl get policyreport -o wide

How to Generate Resources

  1. Add these ClusterRoles to enable Kyverno to have access to secrets:
values/platformName/raw/kyverno/clusterrol.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: kyverno:secrets:view
  labels:
    rbac.kyverno.io/aggregate-to-admission-controller: "true"
    rbac.kyverno.io/aggregate-to-reports-controller: "true"
    rbac.kyverno.io/aggregate-to-background-controller: "true"
rules:
- apiGroups:
  - ''
  resources:
  - secrets
  verbs:
  - get
  - list
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: kyverno:secrets:manage
  labels:
    rbac.kyverno.io/aggregate-to-background-controller: "true"
rules:
- apiGroups:
  - ''
  resources:
  - secrets
  verbs:
  - create
  - update
  - delete
  1. Generate an Image Pull Secret
kubectl -n default create secret docker-registry regcred \
  --docker-server=myinternalreg.corp.com \
  --docker-username=john.doe \
  --docker-password=Passw0rd123! \
  [email protected]
  1. Create a policy to generate that image pull secret to any new namespace:
values/platformName/raw/kyverno/generate-secret.yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: sync-secrets
spec:
  rules:
  - name: sync-image-pull-secret
    match:
      any:
      - resources:
          kinds:
          - Namespace
    generate:
      apiVersion: v1
      kind: Secret
      name: regcred
      namespace: "{{request.object.metadata.name}}"
      synchronize: true
      clone:
        namespace: default
        name: regcred
  1. Test the policy:
Terminal
kubectl create ns test            # should create secret 'regcred' in namespace 'test'

Copyright © 2025. All rights reserved.