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
- 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/v1kind: ClusterPolicymetadata: name: basic-policyspec: 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/v1kind: ClusterPolicymetadata: name: basic-policyspec: 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=veryconfigmap/config-template createdโ evalsocket โ kubectl apply -f namespace-configmap.yamlclusterpolicy.kyverno.io/basic-policy created# Trigger the policy by creating a namespaceโ evalsocket โ kubectl create namespace kyverno-examplenamespace/kyverno-example created#Verify the resourcesโ evalsocket โ kubectl get configmap -n kyverno-exampleNAME DATA AGEconfig-app 2 5sdefault-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-exampleError 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-exampleconfigmap "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 defaultconfigmap/config-template edited# Wait 5-6 sec and checkโ evalsocket โ kubectl get configmap default-config -n kyverno-example -oyamlapiVersion: v1data: special.how: whykind: ConfigMapmetadata: 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/v1kind: ClusterRolemetadata: name: kyverno:policycontrollerrules: - apiGroups: - "*" resources: - "*" verbs: - create - delete - get - list - patch - update - watch---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: kyverno:userinforules: - apiGroups: - "*" resources: - roles - clusterroles - rolebindings - clusterrolebindings - configmaps verbs: - create - delete - get - list - patch - update - watch---kind: ClusterRoleBindingapiVersion: rbac.authorization.k8s.io/v1beta1metadata: name: kyverno-admin-generateroleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: kyverno:generatecontroller # clusterRole defined above, to manage generated resourcessubjects: - 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/v1kind: ClusterPolicymetadata: 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.yamlclusterpolicy.kyverno.io/gen-role-policy created
โ evalsocket โ kubectl create ns newnamespace/new created
โ evalsocket โ kubectl get Role -n newNAME AGEns-role 8s
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..