|
| 1 | +# VEP #NNNN: Your short, descriptive title |
| 2 | + |
| 3 | +## Release Signoff Checklist |
| 4 | + |
| 5 | +Items marked with (R) are required *prior to targeting to a milestone / release*. |
| 6 | + |
| 7 | +- [X] (R) Enhancement issue created, which links to VEP dir in [kubevirt/enhancements] (not the initial VEP PR) |
| 8 | +- [ ] (R) Target version is explicitly mentioned and approved |
| 9 | +- [ ] (R) Graduation criteria filled |
| 10 | + |
| 11 | +## Overview |
| 12 | + |
| 13 | +Today, Kubevirt's API for feature gate management is a `kv.spec.configuration.developerConfiguration.featureGates` |
| 14 | +which is a [list of strings](https://github.com/kubevirt/kubevirt/blob/18c78c0f4d5f4c155ff2b425d0a213b563ac720e/staging/src/kubevirt.io/api/core/v1/types.go#L2813-L2815), |
| 15 | +each string is an enabled feature gate. |
| 16 | + |
| 17 | +The API is defined as follows: |
| 18 | +```go |
| 19 | + type DeveloperConfiguration struct { |
| 20 | + // FeatureGates is the list of experimental features to enable. Defaults to none |
| 21 | + FeatureGates []string `json:"featureGates,omitempty" |
| 22 | +``` |
| 23 | + |
| 24 | +With this approach it is impossible to explicitly disable a feature gate. |
| 25 | +This VEP aims to make it possible. |
| 26 | + |
| 27 | +## Motivation |
| 28 | + |
| 29 | +Disabling a feature gate is very important for different reasons, the main one arguably being that it opens the door to |
| 30 | +enable beta feature gates by default. |
| 31 | +This capability is very important, because it allows widely testing a feature upstream |
| 32 | +(which will at least be tested by CI and developers, alongside small users) while possibly disabling it downstream. |
| 33 | + |
| 34 | +This approach enables to gain wider feedback and confidence before the feature becomes GA, |
| 35 | +which has the potential to ensure features are much more stable and get a much wider feedback before graduating. |
| 36 | + |
| 37 | +This VEP however is only scoped to allow disabling feature gates. |
| 38 | +Enabling Beta feature gates is out-of-scope for this VEP and should be addressed in a follow-up. |
| 39 | + |
| 40 | +## Goals |
| 41 | + |
| 42 | +* Allow to explicitly disable feature gates. |
| 43 | + |
| 44 | +## Non Goals |
| 45 | + |
| 46 | +* Enable feature gates by default. |
| 47 | + |
| 48 | +## Definition of Users |
| 49 | + |
| 50 | +* Feature developers. |
| 51 | +* Cluster admins. |
| 52 | + |
| 53 | +## User Stories |
| 54 | + |
| 55 | +* As a feature developer, I want my feature to be widely tested and used before graduating, |
| 56 | +so I can gain wide feedback and confidence in it. |
| 57 | +* As a cluster administrator, I want to be able to decide on whether to use Alpha/Beta features or not. |
| 58 | + |
| 59 | +## Repos |
| 60 | + |
| 61 | +kubevirt/kubevirt. |
| 62 | + |
| 63 | +## Design |
| 64 | + |
| 65 | +Kubevirt CR's API needs to change in order to allow disablement of feature gates. |
| 66 | +
|
| 67 | +See the different alternatives below. |
| 68 | +
|
| 69 | +## API Examples |
| 70 | +
|
| 71 | +See below. |
| 72 | +
|
| 73 | +## Alternatives |
| 74 | +
|
| 75 | +Before deciding to create a VEP, this change was re-implemented three times as part of PR [#14427](https://github.com/kubevirt/kubevirt/pull/14427). |
| 76 | +
|
| 77 | +In this section, I'll outline the three approaches so we can discuss which of them is the best moving forward. |
| 78 | +I'd be happy for more pros and cons from reviewers if you can think of any. |
| 79 | +
|
| 80 | +### Approach #1 - Use a `FeatureGateConfiguration` struct slice with an `Enabled` field |
| 81 | +
|
| 82 | +As part of this approach, a feature enablement is determined by its configuration in the new `kv.spec.configuration.featureGates` field. |
| 83 | +This field is a slice of `FeatureGateConfiguration` objects which currently contain two fields, `name` and `enabled`: |
| 84 | +```go |
| 85 | +type FeatureGateConfiguration struct { |
| 86 | + Name string `json:"name"` |
| 87 | + // Enabled indicates whether the feature gate is enabled or not. Defaults to true. |
| 88 | + // +optional |
| 89 | + Enabled *bool `json:"enabled,omitempty"` |
| 90 | +} |
| 91 | +``` |
| 92 | +
|
| 93 | +`kv.spec.configuration.featureGates` has precedence over `kv.spec.configuration.developerConfiguration.featureGates`. |
| 94 | +In addition, `kv.spec.configuration.developerConfiguration.featureGates` would be marked as deprecated and discouraged. |
| 95 | +However, if a feature gate exists only in the legacy feature gate slice, it would be considered enabled. |
| 96 | +This way we keep backward compatibility. |
| 97 | +
|
| 98 | +Usage Example: |
| 99 | +```go |
| 100 | +kind: KubeVirt |
| 101 | +spec: |
| 102 | + configuration: |
| 103 | + featureGates: |
| 104 | + - name: VMExport |
| 105 | + enabled: true |
| 106 | + - name: ImageVolume |
| 107 | + enabled: false |
| 108 | + - name: DownwardMetrics |
| 109 | + # defaults to true |
| 110 | + developerConfiguration: |
| 111 | + featureGates: |
| 112 | + - IncrementalBackup # This enables the FG |
| 113 | + - ImageVolume # Being ignored since the same FG is listed in the above config which takes precedence |
| 114 | +``` |
| 115 | +
|
| 116 | +Pros: |
| 117 | +* Extensible: a struct opens the door for further configuration moving forward. |
| 118 | +* Aligns with Kubernetes best practices: "the convention is to use a list of subobjects containing name fields ... |
| 119 | +This rule maintains the invariant that all JSON/YAML keys are fields in API objects". |
| 120 | +See [Kubernetes api conventions](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#lists-of-named-subobjects-preferred-over-maps) |
| 121 | +for more info. |
| 122 | +
|
| 123 | +Cons: |
| 124 | +* Verbose: when there is no desire to disable feature gates, the admin would now have to supply the `name: ` boilerplate |
| 125 | +which makes the manifest more verbose. |
| 126 | +
|
| 127 | +### Approach #2 - Use a new map structure from a string to bool |
| 128 | +
|
| 129 | +As part of this approach, a new `kv.spec.configuration.featureGateMap` will be added of type `map[string]bool`. |
| 130 | +That is a map from string to bool types, i.e. feature name to whether it's enabled or not. |
| 131 | + |
| 132 | +`kv.spec.configuration.featureGates` has precedence over `kv.spec.configuration.developerConfiguration.featureGates`. |
| 133 | +However, if a feature gate exists only in the legacy feature gate slice, it would be considered enabled. |
| 134 | +This way we keep backward compatibility. |
| 135 | + |
| 136 | +Usage Example: |
| 137 | +```go |
| 138 | +kind: KubeVirt |
| 139 | +spec: |
| 140 | + configuration: |
| 141 | + featureGateMap: |
| 142 | + VMExport: true |
| 143 | + ImageVolume: false |
| 144 | + DownwardMetrics: false |
| 145 | + developerConfiguration: |
| 146 | + featureGates: |
| 147 | + - IncrementalBackup # This enables the FG |
| 148 | + - ImageVolume # Being ignored since the same FG is listed in the above config which takes precedence |
| 149 | +``` |
| 150 | + |
| 151 | +Pros: |
| 152 | +* Simplicity (?): Easy to implement and understand. |
| 153 | + |
| 154 | +Cons: |
| 155 | +* Goes against Kubernetes best practices: "the convention is to use a list of subobjects containing name fields". |
| 156 | +The api conventions specifically mention using maps as an anti-pattern: |
| 157 | +"Lists of named subobjects preferred over maps ... There are no maps of subobjects in any API objects". |
| 158 | +See [Kubernetes api conventions](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#lists-of-named-subobjects-preferred-over-maps) |
| 159 | +for more info. |
| 160 | +* Maps are, by definition, unordered. This means that users/clients always have to sort it in a consistent manner |
| 161 | +to avoid entities mistakenly assuming that the state had changed because a change of ordering. |
| 162 | +* Non-extensible: If we'll need to add more configurations to feature gates in the future, we'll be in the same problem |
| 163 | +of having to extend the API. |
| 164 | + |
| 165 | +### Approach #3 - Use a complementary slice for disabled feature gates |
| 166 | + |
| 167 | +As part of this approach, a complementary `kv.spec.configuration.developerConfiguration.disabledFeatureGates` string slice will be added. |
| 168 | +The same feature gate cannot be provided to both slices, this should result with an error. |
| 169 | + |
| 170 | +Usage Example: |
| 171 | +```go |
| 172 | +kind: KubeVirt |
| 173 | +spec: |
| 174 | + configuration: |
| 175 | + developerConfiguration: |
| 176 | + featureGates: |
| 177 | + - IncrementalBackup |
| 178 | + - ImageVolume |
| 179 | + disabledFeatureGates: |
| 180 | + - VMExport |
| 181 | + - DownwardMetrics |
| 182 | + # - ImageVolume -> invalid, would result in an error since already provided above |
| 183 | +``` |
| 184 | + |
| 185 | +Pros: |
| 186 | +* No need to deprecate the old `kv.spec.configuration.developerConfiguration.featureGates` field. |
| 187 | +* Easy adoption: the API is very familiar to what we have to day. |
| 188 | + |
| 189 | +Cons: |
| 190 | +* Non-extensible: If we'll need to add more configurations to feature gates in the future, we'll be in the same problem |
| 191 | +of having to extend the API. |
| 192 | +* We keep both API fields under `kv.spec.configuration.developerConfiguration` instead of finding a new home under `kv.spec.configuration`. |
| 193 | + |
| 194 | +### Approach #4 - Reuse the current string slice, allow special syntax for disablement |
| 195 | + |
| 196 | +As part of this approach no new API fields will be added, but the current `kv.spec.configuration.developerConfiguration.featureGates` |
| 197 | +will be reused to allow disabling feature gates. |
| 198 | + |
| 199 | +This will be achieved by allowing the following special syntax: `<gate>=<true|false>`, |
| 200 | +or just `<gate>` that will be interpreted as `<gate>=true`. |
| 201 | + |
| 202 | +Usage Example: |
| 203 | +```go |
| 204 | +kind: KubeVirt |
| 205 | +spec: |
| 206 | + configuration: |
| 207 | + developerConfiguration: |
| 208 | + featureGates: |
| 209 | + - "IncrementalBackup: true" |
| 210 | + - "ImageVolume: false" |
| 211 | + - VMExport # defaults to true |
| 212 | +``` |
| 213 | + |
| 214 | +Pros: |
| 215 | +* Avoid adding / changing API fields. |
| 216 | +* Syntax is fairly simple and elegant. |
| 217 | + |
| 218 | +Cons: |
| 219 | +* Special parsing would be needed by any user/client. This means: |
| 220 | + * Kubevirt's code would need to include many parsing logic. |
| 221 | + * Standard tooling would have trouble working with that. |
| 222 | +* We keep the API field under `kv.spec.configuration.developerConfiguration` instead of finding a new home under `kv.spec.configuration`. |
| 223 | +
|
| 224 | +## Scalability |
| 225 | +
|
| 226 | +No scalability issues are expected. |
| 227 | +
|
| 228 | +## Update/Rollback Compatibility |
| 229 | +
|
| 230 | +In all of the approached above backward compatibility will be kept. |
| 231 | +
|
| 232 | +In some of the approaches above `kv.spec.configuration.developerConfiguration` will be deprecated, but will not be |
| 233 | +removed in the foreseen future. |
| 234 | +
|
| 235 | +## Functional Testing Approach |
| 236 | +
|
| 237 | +## Implementation History |
| 238 | +
|
| 239 | +<!-- |
| 240 | +For example: |
| 241 | +01-02-1921: Implemented mechanism for doing great stuff. PR: <LINK>. |
| 242 | +03-04-1922: Added support for doing even greater stuff. PR: <LINK>. |
| 243 | +--> |
| 244 | +
|
| 245 | +## Graduation Requirements |
| 246 | +
|
| 247 | +This VEP is intended to jump straight to GA, for the following reasons: |
| 248 | +* This VEP has an effect on all other feature-gates. |
| 249 | +* It is essential for enabling beta features by default. |
| 250 | +* It is not really a feature, more of a formal API review. The logic and implementation is straight forward. |
| 251 | +* It doesn't make sense to create a feature gate for feature gate management. |
| 252 | + |
| 253 | +I would ask for an approval from each SIG approver in order to ensure this approach is widely accepted. |
0 commit comments