Skip to content
Yuvraj ๐Ÿงข

Generate polices ! Make Kubernetes life hassle free with Kyverno

โ€” kubernetes, kyverno โ€” 1 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

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
1apiVersion: kyverno.io/v1
2kind: ClusterPolicy
3metadata:
4 name: basic-policy
5spec:
6 rules:
7 - name: "Generate ConfigMap"
8 match:
9 resources:
10 kinds:
11 - Namespace
12 generate:
13 kind: ConfigMap # Kind of resource
14 name: default-config # Name of the new Resource
15 namespace: "{{request.object.metadata.name}}" # namespace that triggers this rule
16 synchronize : true
17 clone:
18 namespace: default
19 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.
1apiVersion: kyverno.io/v1
2kind: ClusterPolicy
3metadata:
4 name: basic-policy
5spec:
6 rules:
7 - name: "Generate Configmap"
8 match:
9 resources:
10 kinds:
11 - Namespace
12 generate:
13 kind: ConfigMap
14 name: config-app
15 namespace: "{{request.object.metadata.name}}" # namespace that triggers this rule
16 data:
17 data:
18 USERNAME: evalsocket=
19 DATABASE: blog
20 metadata:
21 labels:
22 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.

1# Create a configmap in default namespace (We need this configmap for generating resources)
2โžœ evalsocket โœ— kubectl create configmap config-template -n default --from-literal=special.how=very
3configmap/config-template created
4โžœ evalsocket โœ— kubectl apply -f namespace-configmap.yaml
5clusterpolicy.kyverno.io/basic-policy created
6# Trigger the policy by creating a namespace
7โžœ evalsocket โœ— kubectl create namespace kyverno-example
8namespace/kyverno-example created
9#Verify the resources
10โžœ evalsocket โœ— kubectl get configmap -n kyverno-example
11NAME DATA AGE
12config-app 2 5s
13default-config 1 6s
14
15# 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.

1# Let's try to delete configmap generated from default namespace. It should block your request basecause synchronize : true in case of generated configmap
2โžœ evalsocket โœ— kubectl delete configmap default-config -n kyverno-example
3Error 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.
4
5#Now let's try to delete generated resource configmap that doesn't have synchronize : true and synchronize has default value false.
6โžœ evalsocket โœ— kubectl delete configmap config-app -n kyverno-example
7configmap "config-app" deleted
8
9# Update Your configmap in default namespace and check your update to see synchronize. Set special.how=why
10โžœ evalsocket โœ— kubectl edit configmap config-template -n default
11configmap/config-template edited
12# Wait 5-6 sec and check
13โžœ evalsocket โœ— kubectl get configmap default-config -n kyverno-example -oyaml
14apiVersion: v1
15data:
16 special.how: why
17kind: ConfigMap
18metadata:
19 creationTimestamp: "2020-07-28T00:13:58Z"
20 labels:
21 app.kubernetes.io/managed-by: kyverno
22 app.kubernetes.io/synchronize: enable
23 kyverno.io/generated-by: Namespace--kyverno-example
24 name: default-config
25 namespace: kyverno-example
26 resourceVersion: "1682"
27 selfLink: /api/v1/namespaces/kyverno-example/configmaps/default-config
28 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

1apiVersion: rbac.authorization.k8s.io/v1
2kind: ClusterRole
3metadata:
4 name: kyverno:policycontroller
5rules:
6 - apiGroups:
7 - '*'
8 resources:
9 - '*'
10 verbs:
11 - create
12 - delete
13 - get
14 - list
15 - patch
16 - update
17 - watch
18---
19apiVersion: rbac.authorization.k8s.io/v1
20kind: ClusterRole
21metadata:
22 name: kyverno:userinfo
23rules:
24 - apiGroups:
25 - '*'
26 resources:
27 - roles
28 - clusterroles
29 - rolebindings
30 - clusterrolebindings
31 - configmaps
32 verbs:
33 - create
34 - delete
35 - get
36 - list
37 - patch
38 - update
39 - watch
40---
41kind: ClusterRoleBinding
42apiVersion: rbac.authorization.k8s.io/v1beta1
43metadata:
44 name: kyverno-admin-generate
45roleRef:
46 apiGroup: rbac.authorization.k8s.io
47 kind: ClusterRole
48 name: kyverno:generatecontroller # clusterRole defined above, to manage generated resources
49subjects:
50 - kind: ServiceAccount
51 name: kyverno-service-account # default Kyverno serviceAccount
52 namespace: kyverno

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

1apiVersion: kyverno.io/v1
2kind: ClusterPolicy
3metadata:
4 name: "gen-role-policy"
5spec:
6 background: false
7 rules:
8 - name: "gen-role"
9 match:
10 resources:
11 kinds:
12 - Namespace
13 generate:
14 kind: Role
15 name: "ns-role"
16 namespace: "{{request.object.metadata.name}}" # namespace that triggers this rule
17 synchronize: true
18 data:
19 rules:
20 - apiGroups: [""]
21 resources: ["pods"]
22 verbs: ["get", "watch", "list"]

Follow the steps to generate roles

1โžœ evalsocket โœ— kubectl apply -f gen-role-policy.yaml
2clusterpolicy.kyverno.io/gen-role-policy created
3
4โžœ evalsocket โœ— kubectl create ns new
5namespace/new created
6
7โžœ evalsocket โœ— kubectl get Role -n new
8NAME AGE
9ns-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..

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