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 of the admission request.
A Kyverno generates resources based on a given set of conditions or triggers (read more about match/exclude). Kyverno generates a policy that supports two types of generate rules.
Here is an example of a generated policy
- 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 isconfig-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
- 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 Secret (insecure)"
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 configmap and secrets 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-secret.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,secret -n kyverno-example
NAME DATA AGE
configmap/default-config 1 42s
configmap/config-app 1 42s
NAME TYPE DATA AGE
secret/default-token-rq4dx kubernetes.io/service-account-token 3 42s
# 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 action 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
โ 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: test
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
Some use cases for the generate policy are
- Create default Network policies for each namespace
- Create default resource quotas for each namespace
- 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..
Top comments (0)