

Achieving Policy as Code with Kyverno in Kubernetes
Kubernetes environments thrive on flexibility and scalability, but these benefits also present challenges in maintaining consistency in governance, security, and compliance.
Manual policy enforcement can be error-prone and inefficient, so policies must be automated- and Policy as Code is an effective solution.
This approach embeds policies directly into your workflows- transforming policies into versioned, auditable, and executable code that keeps pace with your infrastructure.
Kyverno, a policy engine designed specifically for Kubernetes, simplifies managing policies as code in your cluster management.
This blog explores how Kyverno enables effective policy management in Kubernetes through real-world examples. We will demonstrate its capabilities to automate governance tasks like enforcing naming conventions, validating resource labels, and more.
Why Use Kyverno for Policy as Code?
Kyverno is tailored for Kubernetes and offers several benefits:
- Native integration with Kubernetes: Seamlessly integrates with Kubernetes, simplifying policy enforcement directly in the cluster.
- Simple, YAML-based policy definitions: Policies are defined in YAML, which makes them easy for developers and Kubernetes administrators to write, read, and manage.
- Seamless application of policies at admission or runtime: Policies are enforced during resource admission to ensure compliance before deploying resources.
- Support for validation, mutation, and generation policies: Kyverno supports different types of policies that provide flexibility and control over resource management.
To learn more about Kyverno and how it works, refer to Kyverno's official documentation.
Prerequisites
To follow along with the examples in this blog, ensure you have the following:
- Kubernetes Cluster: A running Kubernetes cluster (local or cloud-based, such as AWS EKS).
- Helm Installed: Install Helm to manage and deploy Kubernetes applications.
- Kyverno Installed: Install Kyverno using the following command:
helm repo add kyverno https://kyverno.github.io/kyverno/
helm install my-kyverno kyverno/kyverno --version 3.3.4
- kubectl Access: Ensure you have
kubectl
installed and configured it to interact with your cluster. - Kyverno CLI: To test policies locally, download and install the Kyverno CLI.
- Namespace Preparation: Create namespaces or use existing ones to test scoped policies.
Common Knowledge for Using Kyverno
1. Types of Kyverno Policies
Kyverno supports three primary policy types:
- Validation Policies: Ensure that Kubernetes resources meet predefined conditions before they are created or updated.
- Mutation Policies: Modify resources dynamically during their admission process.
- Generation Policies: Automatically create additional resources to maintain consistency.
2. Policy Scoping
Policies can be defined at two levels:
- Cluster Policy: Applicable cluster-wide, targeting resources across all namespaces.
- Policy: Scoped to a specific namespace, targeting resources within that namespace only.
In addition to resource validation and policy enforcement, Kubernetes provides mechanisms like probes to ensure the health and resilience of your applications.
Learn more about the Role of Probes in Kubernetes.
3. Failure Action
Kyverno policies have two failure actions:
- Audit: Logs the violation without rejecting the resource.
- Enforce: Rejects the resource if it does not comply with the policy.
4. Policy Testing
Before applying policies to a live cluster, test them locally using the Kyverno CLI. This avoids potential disruptions caused by misconfigured policies.
kyverno test /path/with/manifests
5. Excluding Resources from Policies
Kyverno allows you to exclude specific resources from being evaluated by policies. This is particularly useful for excluding system-critical resources or third-party components. You can specify exclusions in the policy metadata under the match
or exclude
fields.
Example: Excluding a Namespace
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: exclude-dev-namespace
spec:
rules:
- name: exclude-dev
match:
any:
- resources:
kinds:
- Deployment
exclude:
any:
- resources:
namespaces:
- dev-namespace
validate:
failureAction: Audit
message: "Resource is excluded from policy enforcement."
pattern:
metadata:
labels:
excluded: "true"
This policy excludes deployments in the dev-namespace
from validation while still applying other cluster-wide rules.
Best Practices for Writing Kyverno Policies
- Keep Policies Modular: Break policies into smaller, manageable chunks to avoid unintended impacts.
- Use Descriptive Messages: Make violation messages clear and actionable.
- Review and Update Regularly: Align policies with evolving security and compliance requirements.
Tip: After implementing and testing your Kyverno policies, tracking their impacts in your Kubernetes environment is essential. Get real-time insights by streamlining ELK Stack deployment on Kubernetes.
Implementation Examples
Use Case 1: Restricting Resource Creation Based on Image Repositories
This policy enforces the use of approved container image registries, preventing resources from being created if unapproved image repositories are used.
Step 1: Defining the Policy
Save the following policy to a file (e.g., restrict-image-registries.yaml):
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: restrict-image-registries
spec:
rules:
- name: validate-image-registry
match:
any:
- resources:
kinds:
- Pod
validate:
failureAction: Enforce
message: "Images must be pulled from the approved registries: 'docker.io' or 'ghcr.io'."
pattern:
spec:
containers:
- image: ("docker.io/* | "ghcr.io/*"")
Step 2: Apply the Policy
Run the following command to apply the policy to your cluster:
kubectl apply -f <yaml-file-name-for-policy>
After applying the policy, you should see confirmation of successful policy creation.

Step 3: Test the Policy with a Deployment
Create a deployment YAML file (e.g., approved-registry-deployment.yaml) and include an image from an approved registry (docker.io or ghcr.io).
apiVersion: apps/v1
kind: Deployment
metadata:
name: approved-registry-deployment
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: docker.io/nginx:latest
# image: nginx:latest # Uncomment this section to know more about kyverno error
ports:
- containerPort: 80
Apply the deployment using the following command:
kubectl apply -f <deployment-file-name>
Observing Policy Enforcement
- Using an Approved Image: The deployment will succeed because
docker.io/nginx:latest
is from an approved registry.
- Using an Unapproved Image: To test policy enforcement, uncomment the
image: nginx:latest
line in the YAML file, save it and reapply the deployment.
The deployment will fail, and you will see an error message indicating that the image is not from an approved registry.

Flow of the Use Case: Restricting Container Image Registries
- Pod/Deployment Creation or Update: When a new
Pod
is created or updated in the cluster, the Kyverno policy triggers automatically. - Image Validation: Kyverno checks the image registry specified in the
containers
section of thePod
specification against the defined pattern. It ensures that the image is pulled from an approved registry (eitherdocker.io
orghcr.io
). - Policy Enforcement: If the image is not from the approved registries, the creation or update of the
Pod
is blocked, and an error message is returned. - Successful Validation: If the image is from an approved registry, the policy validation passes, and the
Pod
is successfully created or updated in the cluster. - Ongoing Enforcement: The Kyverno policy continues to enforce this validation for all future Pod creations or updates, ensuring that only images from the trusted registries are used throughout the cluster.
Use Case 2: Automating Resource Creation
Aside from enforcing policies, Kyverno can generate resources automatically, saving time and ensuring consistency across your Kubernetes clusters.
Step 1: Create the ClusterPolicy for NetworkPolicy Generation
The following ClusterPolicy
ensures that a default NetworkPolicy
is automatically generated whenever a new Namespace
is created.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: generate-network-policy
spec:
rules:
- name: generate-default-network-policy
match:
any:
- resources:
kinds:
- Namespace
generate:
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
name: default-deny-all
namespace: "{{request.object.metadata.name}}"
synchronize: true
data:
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Apply the policy using the following command:
kubectl apply -f <yaml-file-name-for-policy>

Flow of the Use Case:
- Namespace Creation: When a new
Namespace
is created, the Kyverno policy triggers automatically.
- NetworkPolicy Generation: Kyverno generates a default
NetworkPolicy
that denies all inbound (Ingress) and outbound (Egress) traffic for the newly createdNamespace
. - Automatic Enforcement: This policy automatically synchronizes with the
Namespace
, ensuring that all newly created namespaces have secure default network isolation.
Step 2: Example Namespace Creation
Create a new Namespace
to trigger the Kyverno policy and validate that it generates the expected NetworkPolicy
. Use the following YAML file:
apiVersion: v1
kind: Namespace
metadata:
name: dev
Apply the namespace creation:
kubectl apply -f <namespace-file-name>
Step 3: Reviewing the Generated Resource
Once the Namespace
is created, Kyverno will automatically generate the NetworkPolicy
for that namespace. The generated resource will look like this:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: dev-namespace
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress

Use Case 3: Conditional Logic with Dynamic Variables
Kyverno supports dynamic variables that allow policies to adapt based on contextual information such as user roles, namespaces, or service accounts.
Step 1: Creating a Role-Based Validation Policy
In this policy, we restrict Pod creation to users with the "admin" role. Save the following YAML as validate-admin-user.yaml
:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: validate-admin-user
spec:
rules:
- name: restrict-non-admin
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Only admin users can create Pods."
pattern:
metadata:
annotations:
user-role: "admin"
condition:
key: "{{request.userInfo.username}}"
operator: Equals
value: "admin"
Step 2: Applying the Policy
To apply the policy, run the following command:
kubectl apply -f validate-admin-user.yaml

Step 3: Testing the Policy with a Deployment Example
Now, let’s test the policy by creating a Deployment that tries to create a Pod.
Sample Deployment YAML (Without admin Role)
Save the following Deployment YAML as infix-nginx-deployment.yaml
. Initially, it does not include the user-role: "admin"
annotation.
apiVersion: apps/v1
kind: Deployment
metadata:
name: infix-nginx
namespace: default
labels:
app: nginx
team: devops
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: infix-nginx
image: docker.io/nginx:1.28
ports:
- containerPort: 80
Command to apply the Deployment:
kubectl apply -f infix-nginx-deployment.yaml
You will get the error in the picture below:

Step 4: Add the "admin" Role Annotation for Successful Deployment
Modify the Deployment YAML by adding the user-role: "admin"
annotation to bypass the policy enforcement error.
annotations:
user-role: "admin"
The deployment is created successfully when we add this annotation to the container section.
Flow of the Use Case:
1. Pod/Deployment Creation or Update:
When a new Pod is created or updated in the cluster, the Kyverno policy validate-admin-user
is automatically triggered.
2. Validation of User Role:
The Kyverno policy checks the annotations of the Pod's metadata to determine the user role. It ensures the user-role
annotation is set to "admin"
in the Pod's metadata.
3. Condition Check:
The policy further validates the username of the user creating the Pod ({{request.userInfo.username}}
) to ensure it matches the value "admin"
. This double-check ensures that only users with the role "admin" and who are authenticated as "admin" can create Pods.
4. Policy Enforcement:
If the conditions are not met—either the user-role annotation is missing or not set to "admin"
, or the username does not match "admin"
—the creation or update of the Pod is blocked. An error message is returned to the user:
"Only admin users can create Pods."
5. Successful Validation:
The policy validation passes if the annotation and username match the required values, and the Pod is created or updated successfully.
6. Ongoing Enforcement:
Kyverno will continue to enforce this policy for all future Pod creations or updates, ensuring that only users with the "admin"
role can create Pods in the cluster.
Related Topic: Dynamic NFS Provisioning For Persistence Storage in Kubernetes
Conclusion
Kyverno empowers Kubernetes administrators to efficiently define, enforce, and automate policies using simple YAML configurations. Administrators can ensure smooth and effective policy implementation across their clusters by mastering Kyverno policy types, scoping, exclusions, and debugging.
Whether it's enforcing naming conventions, validating labels, restricting container image registries, or automating resource generation, Kyverno, a powerful policy as code, provides a robust approach to Kubernetes security and compliance.
If you're looking to strengthen your Kubernetes policy enforcement, our DevOps services can guide you through a seamless implementation process.
Read More:
- DevOps Outsourcing: How it works, benefits & how to get started
- Mastering DevOps: Your Ultimate Guide to DevOps Managed Services
- Ensuring Data Security in Outsourced DevOps: Best Practices
- Budgeting for DevOps Outsourcing: Cost Analysis In 2025
- Easy Guide To Backup and Restore Kubernetes Clusters with Velero