|
| 1 | +# Add support for `ExistingResourcePolicy` to restore API |
| 2 | +## Abstract |
| 3 | +Velero currently does not support any restore policy on kubernetes resources that are already present in-cluster. Velero skips over the restore of the resource if it already exists in the namespace/cluster irrespective of whether the resource present in the restore is the same or different than the one present on the cluster. It is desired that Velero gives the option to the user to decide whether or not the resource in backup should overwrite the one present in the cluster. |
| 4 | + |
| 5 | +## Background |
| 6 | +As of Today, Velero will skip over the restoration of resources that already exist in the cluster. The current workflow followed by Velero is (Using a `service` that is backed up for example): |
| 7 | +- Velero tries to attempt restore of the `service` |
| 8 | +- Fetches the `service` from the cluster |
| 9 | +- If the `service` exists then: |
| 10 | + - Checks whether the `service` instance in the cluster is equal to the `service` instance present in backup |
| 11 | + - If not equal then skips the restore of the `service` and adds a restore warning (except for [SeviceAccount objects](https://github.com/vmware-tanzu/velero/blob/574baeb3c920f97b47985ec3957debdc70bcd5f8/pkg/restore/restore.go#L1246)) |
| 12 | + - If equal then skips the restore of the `service` and mentions that the restore of resource `service` is skipped in logs |
| 13 | + |
| 14 | +It is desired to add the functionality to specify whether or not to overwrite the instance of resource `service` in cluster with the one present in backup during the restore process. |
| 15 | + |
| 16 | +Related issue: https://github.com/vmware-tanzu/velero/issues/4066 |
| 17 | + |
| 18 | +## Goals |
| 19 | +- Add support for `ExistingResourcePolicy` to restore API for Kubernetes resources. |
| 20 | + |
| 21 | +## Non Goals |
| 22 | +- Add support for `ExistingResourcePolicy` to restore API for Non-Kubernetes resources. |
| 23 | +- Change existing restore workflow for `ServiceAccount` objects |
| 24 | +- Add support for `ExistingResourcePolicy` as `recreate` for Kubernetes resources. (Future scope feature) |
| 25 | + |
| 26 | +## High-Level Design |
| 27 | +### Approach 1: Add a new spec field `existingResourcePolicy` to the Restore API |
| 28 | +In this approach we do *not* change existing velero behavior. If the resource to restore in cluster is equal to the one backed up then do nothing following current Velero behavior. For resources that already exist in the cluster that are not equal to the resource in the backup (other than Service Accounts). We add a new optional spec field `existingResourcePolicy` which can have the following values: |
| 29 | +1. `none`: This is the existing behavior, if Velero encounters a resource that already exists in the cluster, we simply skip restoration. |
| 30 | +2. `merge` or `patch`: In this behaviour Velero will try an attempt to patch the resource with the backed up version, if the patch fails log it as a warning and continue the restore process, user may wish specify the merge type. |
| 31 | +3. `recreate`: If resource already exists, then Velero will delete it and recreate the resource. |
| 32 | + |
| 33 | +*Note:* The `recreate` option is a non-goal for this enhancement proposal but it is considered as a future scope. |
| 34 | + |
| 35 | +Example: |
| 36 | +A. The following Restore will execute the `existingResourcePolicy` restore type `none` for the `services` and `deployments` present in the `velero-protection` namespace. |
| 37 | + |
| 38 | +``` |
| 39 | +Kind: Restore |
| 40 | +
|
| 41 | +… |
| 42 | +
|
| 43 | +includeNamespaces: velero-protection |
| 44 | +includeResources: |
| 45 | + - services |
| 46 | + - deployments |
| 47 | +existingResourcePolicy: none |
| 48 | +
|
| 49 | +``` |
| 50 | + |
| 51 | +B. The following Restore will execute the `existingResourcePolicy` restore type `patch` for the `secrets` and `daemonsets` present in the `gdpr-application` namespace. |
| 52 | +``` |
| 53 | +Kind: Restore |
| 54 | +
|
| 55 | +… |
| 56 | +includeNamespaces: gdpr-application |
| 57 | +includeResources: |
| 58 | + - secrets |
| 59 | + - daemonsets |
| 60 | +existingResourcePolicy: patch |
| 61 | +``` |
| 62 | + |
| 63 | +### Approach 2: Add a new spec field `existingResourcePolicyConfig` to the Restore API |
| 64 | +In this approach we give user the ability to specify which resources are to be included for a particular kind of force update behaviour, essentially a more granualar approach where in the user is able to specify a resource:behaviour mapping. It be would look like: |
| 65 | +`existingResourcePolicyConfig`: |
| 66 | +- `patch:` |
| 67 | + - `includedResources:` [ ]string |
| 68 | +- `recreate:` [ ]string |
| 69 | + - `includedResources:` [ ]string |
| 70 | + |
| 71 | +*Note:* |
| 72 | +- There is no `none` behaviour in this approach as that would conform to the current/default Velero restore behaviour. |
| 73 | +- The `recreate` option is a non-goal for this enhancement proposal but it is considered as a future scope. |
| 74 | + |
| 75 | + |
| 76 | +Example: |
| 77 | +A. The following Restore will execute the restore type `patch` and apply the `existingResourcePolicyConfig` for `secrets` and `daemonsets` present in the `inventory-app` namespace. |
| 78 | +``` |
| 79 | +Kind: Restore |
| 80 | +… |
| 81 | +includeNamespaces: inventory-app |
| 82 | +existingResourcePolicyConfig: |
| 83 | + patch: |
| 84 | + includedResources |
| 85 | + - secrets |
| 86 | + - daemonsets |
| 87 | +
|
| 88 | +``` |
| 89 | + |
| 90 | + |
| 91 | +### Approach 3: Combination of Approach 1 and Approach 2 |
| 92 | + |
| 93 | +Now, this approach is somewhat a combination of the aforementioned approaches. Here we propose addition of two spec fields to the Restore API - `existingResourceDefaultPolicy` and `existingResourcePolicyOverrides`. As the names suggest ,the idea being that `existingResourceDefaultPolicy` would describe the default velero behaviour for this restore and `existingResourcePolicyOverrides` would override the default policy explictly for some resources. |
| 94 | + |
| 95 | +Example: |
| 96 | +A. The following Restore will execute the restore type `patch` as the `existingResourceDefaultPolicy` but will override the default policy for `secrets` using the `existingResourcePolicyOverrides` spec as `none`. |
| 97 | +``` |
| 98 | +Kind: Restore |
| 99 | +… |
| 100 | +includeNamespaces: inventory-app |
| 101 | +existingResourceDefaultPolicy: patch |
| 102 | +existingResourcePolicyOverrides: |
| 103 | + none: |
| 104 | + includedResources |
| 105 | + - secrets |
| 106 | +
|
| 107 | +``` |
| 108 | + |
| 109 | +## Detailed Design |
| 110 | +### Approach 1: Add a new spec field `existingResourcePolicy` to the Restore API |
| 111 | +The `existingResourcePolicy` spec field will be an `PolicyType` type field. |
| 112 | + |
| 113 | +Restore API: |
| 114 | +``` |
| 115 | +type RestoreSpec struct { |
| 116 | +. |
| 117 | +. |
| 118 | +. |
| 119 | +// ExistingResourcePolicy specifies the restore behaviour for the kubernetes resource to be restored |
| 120 | +// +optional |
| 121 | +ExistingResourcePolicy PolicyType |
| 122 | +
|
| 123 | +} |
| 124 | +``` |
| 125 | +PolicyType: |
| 126 | +``` |
| 127 | +type PolicyType string |
| 128 | +const PolicyTypeNone PolicyType = "none" |
| 129 | +const PolicyTypePatch PolicyType = "patch" |
| 130 | +const PolicyTypeRecreate PolicyType = "recreate" |
| 131 | +``` |
| 132 | + |
| 133 | +### Approach 2: Add a new spec field `existingResourcePolicyConfig` to the Restore API |
| 134 | +The `existingResourcePolicyConfig` will be a spec of type `PolicyConfiguration` which gets added to the Restore API. |
| 135 | + |
| 136 | +Restore API: |
| 137 | +``` |
| 138 | +type RestoreSpec struct { |
| 139 | +. |
| 140 | +. |
| 141 | +. |
| 142 | +// ExistingResourcePolicyConfig specifies the restore behaviour for a particular/list of kubernetes resource(s) to be restored |
| 143 | +// +optional |
| 144 | +ExistingResourcePolicyConfig []PolicyConfiguration |
| 145 | +
|
| 146 | +} |
| 147 | +``` |
| 148 | + |
| 149 | +PolicyConfiguration: |
| 150 | +``` |
| 151 | +type PolicyConfiguration struct { |
| 152 | +
|
| 153 | +PolicyTypeMapping map[PolicyType]ResourceList |
| 154 | +
|
| 155 | +} |
| 156 | +``` |
| 157 | + |
| 158 | +PolicyType: |
| 159 | +``` |
| 160 | +type PolicyType string |
| 161 | +const PolicyTypePatch PolicyType = "patch" |
| 162 | +const PolicyTypeRecreate PolicyType = "recreate" |
| 163 | +``` |
| 164 | + |
| 165 | +ResourceList: |
| 166 | +``` |
| 167 | +type ResourceList struct { |
| 168 | +IncludedResources []string |
| 169 | +} |
| 170 | +``` |
| 171 | + |
| 172 | +### Approach 3: Combination of Approach 1 and Approach 2 |
| 173 | + |
| 174 | +Restore API: |
| 175 | +``` |
| 176 | +type RestoreSpec struct { |
| 177 | +. |
| 178 | +. |
| 179 | +. |
| 180 | +// ExistingResourceDefaultPolicy specifies the default restore behaviour for the kubernetes resource to be restored |
| 181 | +// +optional |
| 182 | +existingResourceDefaultPolicy PolicyType |
| 183 | +
|
| 184 | +// ExistingResourcePolicyOverrides specifies the restore behaviour for a particular/list of kubernetes resource(s) to be restored |
| 185 | +// +optional |
| 186 | +existingResourcePolicyOverrides []PolicyConfiguration |
| 187 | +
|
| 188 | +} |
| 189 | +``` |
| 190 | + |
| 191 | +PolicyType: |
| 192 | +``` |
| 193 | +type PolicyType string |
| 194 | +const PolicyTypeNone PolicyType = "none" |
| 195 | +const PolicyTypePatch PolicyType = "patch" |
| 196 | +const PolicyTypeRecreate PolicyType = "recreate" |
| 197 | +``` |
| 198 | +PolicyConfiguration: |
| 199 | +``` |
| 200 | +type PolicyConfiguration struct { |
| 201 | +
|
| 202 | +PolicyTypeMapping map[PolicyType]ResourceList |
| 203 | +
|
| 204 | +} |
| 205 | +``` |
| 206 | +ResourceList: |
| 207 | +``` |
| 208 | +type ResourceList struct { |
| 209 | +IncludedResources []string |
| 210 | +} |
| 211 | +``` |
| 212 | + |
| 213 | +The restore worklow changes will be done [here](https://github.com/vmware-tanzu/velero/blob/b40bbda2d62af2f35d1406b9af4d387d4b396839/pkg/restore/restore.go#L1245) |
0 commit comments