Skip to content
Yuvraj ๐Ÿงข
GithubDatasherlockContact

Generate polices ! Make Kubernetes life hassle free with Kyverno

โ€” kubernetes, kyverno โ€” 5 min read

Briefly, Kyverno is a policy engine built for Kubernetes. It runs as an admission controller that can mutate and validate incoming resources. Also, Kyverno can generate any type of resource-based on various triggers from an admission request.

Kyverno generates resources based on a given set of conditions or triggers (read more about match/exclude). Kyverno generate a policy that support two types of rules.

Here is an example of a generated policy

  1. Copy a resource from one namespace to another namespace. It's similar to copy command in a shell. The user has to define the clone block for providing the source resource path. In the below example source is config-template configmap in the default namespace
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: basic-policy
spec:
rules:
- name: "Generate ConfigMap"
match:
resources:
kinds:
- Namespace
generate:
kind: ConfigMap # Kind of resource
name: default-config # Name of the new Resource
namespace: "{{request.object.metadata.name}}" # namespace that triggers this rule
synchronize: true
clone:
namespace: default
name: config-template
  1. Generate a resource from inline data. In this type of generating policy users can define a defined data block directly in the policy.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: basic-policy
spec:
rules:
- name: "Generate Configmap"
match:
resources:
kinds:
- Namespace
generate:
kind: ConfigMap
name: config-app
namespace: "{{request.object.metadata.name}}" # namespace that triggers this rule
data:
data:
USERNAME: evalsocket=
DATABASE: blog
metadata:
labels:
purpose: config

Both examples above will trigger when a new namespace is created then Kyverno will automatically generate the configmaps in the newly created namespace.

# Create a configmap in default namespace (We need this configmap for generating resources)
โžœ evalsocket โœ— kubectl create configmap config-template -n default --from-literal=special.how=very
configmap/config-template created
โžœ evalsocket โœ— kubectl apply -f namespace-configmap.yaml
clusterpolicy.kyverno.io/basic-policy created
# Trigger the policy by creating a namespace
โžœ evalsocket โœ— kubectl create namespace kyverno-example
namespace/kyverno-example created
#Verify the resources
โžœ evalsocket โœ— kubectl get configmap -n kyverno-example
NAME DATA AGE
config-app 2 5s
default-config 1 6s
# We did it

Now let's discuss the behavior of the field synchronize: true. If you enable synchronization that means that Kyverno will manage your generated resources and administrators can only update/delete a resource from the policy. All direct actions on generated resources will be blocked by the kyverno. And in case of clone rule, the cluster-admin can update/delete generated resources from the source resources.

# Let's try to delete configmap generated from default namespace. It should block your request basecause synchronize : true in case of generated configmap
โžœ evalsocket โœ— kubectl delete configmap default-config -n kyverno-example
Error from server: admission webhook "nirmata.kyverno.resource.validating-webhook" denied the request: Resource is managed by a Kyverno policy and cannot be update manually. You can edit the generate policy to update this resource.
#Now let's try to delete generated resource configmap that doesn't have synchronize : true and synchronize has default value false.
โžœ evalsocket โœ— kubectl delete configmap config-app -n kyverno-example
configmap "config-app" deleted
# Update Your configmap in default namespace and check your update to see synchronize. Set special.how=why
โžœ evalsocket โœ— kubectl edit configmap config-template -n default
configmap/config-template edited
# Wait 5-6 sec and check
โžœ evalsocket โœ— kubectl get configmap default-config -n kyverno-example -oyaml
apiVersion: v1
data:
special.how: why
kind: ConfigMap
metadata:
creationTimestamp: "2020-07-28T00:13:58Z"
labels:
app.kubernetes.io/managed-by: kyverno
app.kubernetes.io/synchronize: enable
kyverno.io/generated-by: Namespace--kyverno-example
name: default-config
namespace: kyverno-example
resourceVersion: "1682"
selfLink: /api/v1/namespaces/kyverno-example/configmaps/default-config
uid: b683b4c1-c498-4c25-b018-aa0c63cbcf7f

Let's try one more example. This time we will try to generate RBAC from generate policy. By default Kyverno service account doesn't have that permission, Admin has to manually provide access to Kyverno service account. Please read more about Kyverno role

Add admin privilege to Kyverno for creating the role

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: kyverno:policycontroller
rules:
- apiGroups:
- "*"
resources:
- "*"
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: kyverno:userinfo
rules:
- apiGroups:
- "*"
resources:
- roles
- clusterroles
- rolebindings
- clusterrolebindings
- configmaps
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: kyverno-admin-generate
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: kyverno:generatecontroller # clusterRole defined above, to manage generated resources
subjects:
- kind: ServiceAccount
name: kyverno-service-account # default Kyverno serviceAccount
namespace: kyverno

Now we are ready for generating role and cluster role. let's take an example policy for generating role

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: "gen-role-policy"
spec:
background: false
rules:
- name: "gen-role"
match:
resources:
kinds:
- Namespace
generate:
kind: Role
name: "ns-role"
namespace: "{{request.object.metadata.name}}" # namespace that triggers this rule
synchronize: true
data:
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]

Follow the steps to generate roles

โžœ evalsocket โœ— kubectl apply -f gen-role-policy.yaml
clusterpolicy.kyverno.io/gen-role-policy created
โžœ evalsocket โœ— kubectl create ns new
namespace/new created
โžœ evalsocket โœ— kubectl get Role -n new
NAME AGE
ns-role 8s

via GIPHY

Some use cases for the generate policy are:

  1. Create default Network policies for each namespace
  2. Create default resource quotas for each namespace
  3. For more example please check best practices

Check out the Kyverno GitHub page to learn more about the generate policy and several other features, like validating and deny rule. Find more about kyverno in the previous post Kubernetes Policy Management with Kyverno..

ยฉ 2024 by Yuvraj ๐Ÿงข. All rights reserved.
Theme by LekoArts