All Policies

Backup All Volumes

In order for Velero to backup volumes in a Pod using an opt-in approach, it requires an annotation on the Pod called `backup.velero.io/backup-volumes` with the value being a comma-separated list of the volumes mounted to that Pod. This policy automatically annotates Pods (and Pod controllers) which refer to a PVC so that all volumes are listed in the aforementioned annotation if a Namespace with the label `velero-backup-pvc=true`.

Policy Definition

/velero-mpol/backup-all-volumes/backup-all-volumes.yaml

  1apiVersion: policies.kyverno.io/v1alpha1
  2kind: MutatingPolicy
  3metadata:
  4  name: backup-all-volumes
  5  annotations:
  6    policies.kyverno.io/title: Backup All Volumes
  7    policies.kyverno.io/category: Velero
  8    policies.kyverno.io/severity: medium
  9    policies.kyverno.io/subject: Pod, Deployment, CronJob, Annotation
 10    policies.kyverno.io/description: >-
 11      In order for Velero to backup volumes in a Pod using an opt-in approach, it
 12      requires an annotation on the Pod called `backup.velero.io/backup-volumes` with the
 13      value being a comma-separated list of the volumes mounted to that Pod. This policy
 14      automatically annotates Pods (and Pod controllers) which refer to a PVC so that
 15      all volumes are listed in the aforementioned annotation if a Namespace with the label
 16      `velero-backup-pvc=true`.
 17spec:
 18  evaluation:
 19    admission:
 20      enabled: true
 21  matchConstraints:
 22    resourceRules:
 23    - apiGroups: [""]
 24      apiVersions: ["v1"]
 25      operations: ["CREATE", "UPDATE"]
 26      resources: ["pods"]
 27    - apiGroups: ["apps"]
 28      apiVersions: ["v1"]
 29      operations: ["CREATE", "UPDATE"]
 30      resources: ["deployments", "daemonsets", "statefulsets"]
 31    - apiGroups: ["batch"]
 32      apiVersions: ["v1"]
 33      operations: ["CREATE", "UPDATE"]
 34      resources: ["jobs", "cronjobs"]
 35    namespaceSelector:
 36      matchLabels:
 37        velero-backup-pvc: "true"
 38  variables:
 39    # For Pods
 40    - name: podPvcVolumes
 41      expression: >-
 42        object.kind == "Pod" && has(object.spec.volumes) ? 
 43        object.spec.volumes.filter(v, has(v.persistentVolumeClaim)).map(v, v.name) : 
 44        []
 45    - name: podVolumesList
 46      expression: >-
 47        variables.podPvcVolumes.size() > 0 ? variables.podPvcVolumes.join(',') : ''
 48    # For Deployments, DaemonSets, StatefulSets
 49    - name: deploymentPvcVolumes
 50      expression: >-
 51        (object.kind == "Deployment" || object.kind == "DaemonSet" || object.kind == "StatefulSet") && 
 52        has(object.spec.template.spec.volumes) ? 
 53        object.spec.template.spec.volumes.filter(v, has(v.persistentVolumeClaim)).map(v, v.name) : 
 54        []
 55    - name: deploymentVolumesList
 56      expression: >-
 57        variables.deploymentPvcVolumes.size() > 0 ? variables.deploymentPvcVolumes.join(',') : ''
 58    # For Jobs
 59    - name: jobPvcVolumes
 60      expression: >-
 61        object.kind == "Job" && has(object.spec.template.spec.volumes) ? 
 62        object.spec.template.spec.volumes.filter(v, has(v.persistentVolumeClaim)).map(v, v.name) : 
 63        []
 64    - name: jobVolumesList
 65      expression: >-
 66        variables.jobPvcVolumes.size() > 0 ? variables.jobPvcVolumes.join(',') : ''
 67    # For CronJobs
 68    - name: cronjobPvcVolumes
 69      expression: >-
 70        object.kind == "CronJob" && has(object.spec.jobTemplate.spec.template.spec.volumes) ? 
 71        object.spec.jobTemplate.spec.template.spec.volumes.filter(v, has(v.persistentVolumeClaim)).map(v, v.name) : 
 72        []
 73    - name: cronjobVolumesList
 74      expression: >-
 75        variables.cronjobPvcVolumes.size() > 0 ? variables.cronjobPvcVolumes.join(',') : ''
 76  mutations:
 77  # Mutation for Pods
 78  - patchType: JSONPatch
 79    jsonPatch:
 80      expression: |
 81        object.kind == "Pod" && variables.podVolumesList != '' ?
 82        (
 83          !has(object.metadata.annotations) ?
 84          [
 85            JSONPatch{
 86              op: "add",
 87              path: "/metadata/annotations",
 88              value: {"backup.velero.io/backup-volumes": variables.podVolumesList}
 89            }
 90          ] :
 91          [
 92            JSONPatch{
 93              op: "add",
 94              path: "/metadata/annotations/" + jsonpatch.escapeKey("backup.velero.io/backup-volumes"),
 95              value: variables.podVolumesList
 96            }
 97          ]
 98        ) : []
 99  # Mutation for Deployments, DaemonSets, StatefulSets
100  - patchType: JSONPatch
101    jsonPatch:
102      expression: |
103        (object.kind == "Deployment" || object.kind == "DaemonSet" || object.kind == "StatefulSet") && 
104        variables.deploymentVolumesList != '' ?
105        (
106          !has(object.spec.template.metadata.annotations) ?
107          [
108            JSONPatch{
109              op: "add",
110              path: "/spec/template/metadata/annotations",
111              value: {"backup.velero.io/backup-volumes": variables.deploymentVolumesList}
112            }
113          ] :
114          [
115            JSONPatch{
116              op: "add",
117              path: "/spec/template/metadata/annotations/" + jsonpatch.escapeKey("backup.velero.io/backup-volumes"),
118              value: variables.deploymentVolumesList
119            }
120          ]
121        ) : []
122  # Mutation for Jobs
123  - patchType: JSONPatch
124    jsonPatch:
125      expression: |
126        object.kind == "Job" && variables.jobVolumesList != '' ?
127        (
128          !has(object.spec.template.metadata.annotations) ?
129          [
130            JSONPatch{
131              op: "add",
132              path: "/spec/template/metadata/annotations",
133              value: {"backup.velero.io/backup-volumes": variables.jobVolumesList}
134            }
135          ] :
136          [
137            JSONPatch{
138              op: "add",
139              path: "/spec/template/metadata/annotations/" + jsonpatch.escapeKey("backup.velero.io/backup-volumes"),
140              value: variables.jobVolumesList
141            }
142          ]
143        ) : []
144  # Mutation for CronJobs
145  - patchType: JSONPatch
146    jsonPatch:
147      expression: |
148        object.kind == "CronJob" && variables.cronjobVolumesList != '' ?
149        (
150          !has(object.spec.jobTemplate.spec.template.metadata.annotations) ?
151          [
152            JSONPatch{
153              op: "add",
154              path: "/spec/jobTemplate/spec/template/metadata/annotations",
155              value: {"backup.velero.io/backup-volumes": variables.cronjobVolumesList}
156            }
157          ] :
158          [
159            JSONPatch{
160              op: "add",
161              path: "/spec/jobTemplate/spec/template/metadata/annotations/" + jsonpatch.escapeKey("backup.velero.io/backup-volumes"),
162              value: variables.cronjobVolumesList
163            }
164          ]
165        ) : []