Managing security and compliance in Kubernetes clusters can be challenging, especially when dealing with multiple teams and environments. Manual policy enforcement is error-prone and doesn’t scale. This is where Kyverno comes in - a Kubernetes-native policy engine that helps you enforce best practices automatically using simple YAML policies.

In this guide, we’ll walk through setting up Kyverno and implementing essential policies that every Kubernetes cluster should have.

What is Kyverno?

Kyverno is a policy engine designed for Kubernetes that allows you to:

  • Validate resources against security and operational standards
  • Mutate resources to automatically apply best practices
  • Generate additional resources like NetworkPolicies automatically
  • Clean up resources based on conditions

Unlike other policy engines, Kyverno uses YAML instead of domain-specific languages, making it accessible to any Kubernetes user.

How Kyverno Works

Kyverno operates as a Kubernetes admission controller, intercepting API requests before resources are created or modified in your cluster. Here’s the flow:

  1. User creates a Kubernetes resource (Pod, Deployment, etc.)
  2. Kubernetes API server sends the request to Kyverno
  3. Kyverno evaluates the resource against defined policies
  4. Based on policy rules, Kyverno allows, denies, or modifies the resource
  5. The final resource is created in the cluster

Installing Kyverno

The easiest way to install Kyverno is using Helm:

1
2
3
4
5
6
# Add Kyverno Helm repository
helm repo add kyverno https://kyverno.github.io/kyverno/
helm repo update

# Install Kyverno
helm install kyverno kyverno/kyverno -n kyverno --create-namespace

Verify the installation:

1
kubectl get pods -n kyverno

You should see the Kyverno pods running successfully.

Basic Policy Examples

Let’s start with practical policies that solve real-world problems.

1. Require Resource Limits (Validation Policy)

This policy ensures all containers have resource requests and limits defined:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-pod-resources
spec:
validationFailureAction: enforce
background: true
rules:
- name: validate-resources
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Resource requests and limits are required"
pattern:
spec:
containers:
- name: "*"
resources:
requests:
memory: "?*"
cpu: "?*"
limits:
memory: "?*"
cpu: "?*"

Apply this policy:

1
kubectl apply -f require-resources-policy.yaml

Now try creating a pod without resource limits:

1
2
3
4
5
6
7
8
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: nginx
image: nginx

This will be rejected with the message “Resource requests and limits are required”.

2. Add Default Labels (Mutation Policy)

This policy automatically adds standard labels to all resources:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: add-default-labels
spec:
background: true
rules:
- name: add-labels
match:
any:
- resources:
kinds:
- Pod
- Deployment
- Service
mutate:
patchStrategicMerge:
metadata:
labels:
managed-by: kyverno
app.kubernetes.io/managed-by: kyverno

With this policy, any new resource will automatically get these labels added.

3. Disallow Privileged Containers (Validation Policy)

Security policy to prevent privileged containers:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-privileged
spec:
validationFailureAction: enforce
background: true
rules:
- name: check-privileged
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Privileged containers are not allowed"
pattern:
spec:
=(securityContext):
=(privileged): "false"
containers:
- name: "*"
=(securityContext):
=(privileged): "false"

4. Generate Default NetworkPolicy (Generation Policy)

Automatically create a default-deny NetworkPolicy for new namespaces:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: generate-network-policy
spec:
background: true
rules:
- name: default-deny
match:
any:
- resources:
kinds:
- Namespace
exclude:
any:
- resources:
namespaces:
- kube-system
- kyverno
generate:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
name: default-deny-all
namespace: "{{request.object.metadata.name}}"
data:
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress

Testing Your Policies

Test with Valid Resources

Create a pod that complies with your policies:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: v1
kind: Pod
metadata:
name: compliant-pod
spec:
containers:
- name: nginx
image: nginx
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
securityContext:
privileged: false

This pod should be created successfully and will have the default labels added automatically.

View Policy Reports

Check policy violations and compliance:

1
2
3
4
5
6
7
8
# View cluster policy reports
kubectl get cpol

# View policy violations
kubectl get events --field-selector reason=PolicyViolation

# Get detailed policy report
kubectl describe cpol require-pod-resources

Common Use Cases

Enforce Security Standards

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: security-standards
spec:
validationFailureAction: enforce
rules:
- name: non-root-user
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Containers must run as non-root user"
pattern:
spec:
containers:
- name: "*"
securityContext:
runAsNonRoot: true

Standardize Resource Naming

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: naming-convention
spec:
validationFailureAction: enforce
rules:
- name: check-name
match:
any:
- resources:
kinds:
- Deployment
- Service
validate:
message: "Resource names must follow naming convention (lowercase, hyphens only)"
pattern:
metadata:
name: "^[a-z0-9-]+$"

Best Practices

Start with Audit Mode: Before enforcing policies, run them in audit mode to see their impact:

1
2
spec:
validationFailureAction: audit # Change to 'enforce' when ready

Test Policies: Always test policies in development environments before production.

Use Background Scanning: Enable background scanning to check existing resources:

1
2
spec:
background: true

Monitor Policy Performance: Keep policies simple and efficient to avoid impacting cluster performance.

Troubleshooting

Policy Not Working

Check if the policy is correctly applied:

1
2
kubectl get cpol
kubectl describe cpol <policy-name>

View Kyverno Logs

1
2
kubectl logs -n kyverno deployment/kyverno-admission-controller
kubectl logs -n kyverno deployment/kyverno-background-controller

Webhook Issues

Ensure webhooks are properly configured:

1
2
kubectl get validatingadmissionpolicies
kubectl get mutatingadmissionpolicies

Conclusion

Kyverno makes implementing Kubernetes best practices straightforward and automated. By using familiar YAML syntax, teams can quickly create policies that:

  • Enhance security by preventing misconfigurations
  • Standardize resource configurations across teams
  • Automate compliance and governance tasks
  • Reduce operational overhead

Start with basic validation policies, test them thoroughly, then gradually add more sophisticated mutation and generation policies as your team becomes comfortable with Kyverno.

The key to success with Kyverno is starting simple and iterating. Begin with one or two essential policies, validate their impact, and expand from there. Your Kubernetes clusters will be more secure, compliant, and easier to manage.

You can find the all the related scripts for this tutorial from here.

Happy Coding