Merge pull request #8087 from Jefftree/feature-gate-compat-version
Update feature gate documentation for compatibility version
This commit is contained in:
commit
6977d1b926
|
@ -105,6 +105,33 @@ While some exceptions may happen, approvers should use the following guidance:
|
||||||
|
|
||||||
[API changes]: https://github.com/kubernetes/community/blob/master/sig-architecture/api-review-process.md#what-parts-of-a-pr-are-api-changes
|
[API changes]: https://github.com/kubernetes/community/blob/master/sig-architecture/api-review-process.md#what-parts-of-a-pr-are-api-changes
|
||||||
|
|
||||||
|
### Compatibility versions
|
||||||
|
|
||||||
|
The Kubernetes "compatibility version" feature promises that control-plane
|
||||||
|
components can be configured to behave as if they were any of the three previous
|
||||||
|
releases, which includes (non-alpha) feature gates and gate-controlled APIs and logic.
|
||||||
|
|
||||||
|
As a feature progresses through the lifecycle, we must preserve enough
|
||||||
|
information to allow such compatible configuration, including both the old and
|
||||||
|
new states, along with the version that the transition occurred.
|
||||||
|
|
||||||
|
```
|
||||||
|
RetryGenerateName: {
|
||||||
|
{Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Alpha},
|
||||||
|
{Version: version.MustParse("1.31"), Default: true, PreRelease: featuregate.Beta},
|
||||||
|
{Version: version.MustParse("1.32"), Default: true, LockToDefault: true, PreRelease: featuregate.GA},
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example, a component at v1.33 can be configured to behave as v1.32+ or
|
||||||
|
to be compatible with v1.31 (where the gate was disableable) or v1.30 (where the
|
||||||
|
gate was off by default). That component at v1.34 can be configured to behave as
|
||||||
|
v1.32+ or to be compatible with v1.31 (where the gate was disableable), but
|
||||||
|
v1.30 falls outside the "three releases" window.
|
||||||
|
|
||||||
|
At v1.35, the component can only be configured to be compatible as far back as
|
||||||
|
1.32 (where the gate was locked on), and so the lifecycle is complete.
|
||||||
|
|
||||||
### Alpha features
|
### Alpha features
|
||||||
|
|
||||||
* `PreRelease` is set to `featuregate.Alpha`
|
* `PreRelease` is set to `featuregate.Alpha`
|
||||||
|
@ -152,8 +179,17 @@ other action outside of Kubernetes to use it. This gives some grace period for
|
||||||
users to take action, but such feature gates will eventually set
|
users to take action, but such feature gates will eventually set
|
||||||
`LockToDefault` to `true` and then be retired, like normal.
|
`LockToDefault` to `true` and then be retired, like normal.
|
||||||
|
|
||||||
[After at least two releases post-GA and deprecation](https://kubernetes.io/docs/reference/using-api/deprecation-policy/#deprecation),
|
To achieve our [compatibility version](#compatibility-versions) promise, after
|
||||||
feature gates should be removed. Typically, we add a comment in
|
three releases where a feature has been locked to the default value (whether
|
||||||
|
that feature is GA or deprecated), feature gates and references should be
|
||||||
|
removed. We use three releases because it corresponds to roughly one year in the
|
||||||
|
Kubernetes development cycle which is our [support
|
||||||
|
period](https://kubernetes.io/releases/patch-releases/#support-period). For
|
||||||
|
example, if a gate was `LockToDefault: true` in kubernetes version `X`, it may
|
||||||
|
be removed in version `X+3` (which must be compatible with `X+2`, `X+1`, and
|
||||||
|
`X`, all of which were also locked).
|
||||||
|
|
||||||
|
Typically, we add a comment in
|
||||||
[the code](https://github.com/kubernetes/kubernetes/blob/master/pkg/features/kube_features.go)
|
[the code](https://github.com/kubernetes/kubernetes/blob/master/pkg/features/kube_features.go)
|
||||||
such as: `// remove in 1.23` to signal when we plan to remove the feature gate.
|
such as: `// remove in 1.23` to signal when we plan to remove the feature gate.
|
||||||
We provide this grace period to give users time to stop referencing "finished"
|
We provide this grace period to give users time to stop referencing "finished"
|
||||||
|
@ -161,8 +197,48 @@ gates. If a feature gate is removed and a user has forgotten to drop the
|
||||||
reference to it (e.g. in the CLI flags of `kube-apiserver`), then they will see
|
reference to it (e.g. in the CLI flags of `kube-apiserver`), then they will see
|
||||||
a hard failure.
|
a hard failure.
|
||||||
|
|
||||||
When we set `LockToDefault` to `true`, we also remove all references to the feature
|
#### Disablement Tests
|
||||||
gate from the codebase.
|
|
||||||
|
Typically for full coverage, unit and integration tests exist for both when a
|
||||||
|
feature is enabled and disabled. When a feature is promoted to GA, it is usually
|
||||||
|
locked to true by default and cannot be unset in testing. For integration with
|
||||||
|
compatibility version, feature disablement tests should be maintained until the
|
||||||
|
GA feature is fully removed three releases after promotion. To test scenarios
|
||||||
|
where the feature gate may still be disabled, emulation version should be set in
|
||||||
|
disablement tests. For these disablement tests, simply set emulation version to
|
||||||
|
the version before the GA promotion to support disablement. The emulation
|
||||||
|
version would be set the line before the feature gate is set.
|
||||||
|
|
||||||
|
For example, if the "CustomResourceFieldSelectors" becomes GA in version 1.32,
|
||||||
|
the emulation version is set to v1.31.
|
||||||
|
|
||||||
|
```go
|
||||||
|
featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultFeatureGate, version.MustParse("1.31"))
|
||||||
|
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceFieldSelectors, false)
|
||||||
|
```
|
||||||
|
|
||||||
|
When the feature gate is removed three releases later in v1.35, the disablement
|
||||||
|
feature gate test is then removed. For tests using a matrix, emulation version
|
||||||
|
should only be set on tests that disable the feature.
|
||||||
|
|
||||||
|
|
||||||
|
```go
|
||||||
|
testcases := []struct{
|
||||||
|
...
|
||||||
|
featureEnabled bool
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testcases {
|
||||||
|
if !tc.featureEnabled {
|
||||||
|
featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultFeatureGate, version.MustParse("1.31"))
|
||||||
|
}
|
||||||
|
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.MyFeature, tc.featureEnabled)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Disablement tests are only required to be preserved for components and libraries
|
||||||
|
that support compatibility version. Tests for node and kubelet are unaffected by
|
||||||
|
compatibility version.
|
||||||
|
|
||||||
### Deprecation
|
### Deprecation
|
||||||
|
|
||||||
|
@ -181,6 +257,24 @@ to unbreak themselves (and then file a bug). If this happens, we must
|
||||||
reconsider the deprecation and may choose to abandon it entirely by changing
|
reconsider the deprecation and may choose to abandon it entirely by changing
|
||||||
the gate back to `true` for a release or two and eventually removing it.
|
the gate back to `true` for a release or two and eventually removing it.
|
||||||
|
|
||||||
|
Once the [deprecation period](https://kubernetes.io/docs/reference/using-api/deprecation-policy/#deprecation)
|
||||||
|
has passed, the gate should be locked to the default value (`LockToDefault:
|
||||||
|
true`). As with GA features, all references to the feature gate must be kept for
|
||||||
|
a minimum of three releases after gate has been locked to the default value. the
|
||||||
|
gate, all references to it, and all gated logic may be removed after those three
|
||||||
|
releases. See [compatibility version](#compatibility-versions) for more details.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
DeprecatedFeature: {
|
||||||
|
{Version: version.MustParse("1.29"), Default: false, PreRelease: featuregate.Alpha}, // feature graduated to alpha.
|
||||||
|
{Version: version.MustParse("1.30"), Default: true, PreRelease: featuregate.Beta}, // feature graduated to beta.
|
||||||
|
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Deprecated}, // feature is deprecated and turned off. LockToDefault is unset to give users time to transition.
|
||||||
|
{Version: version.MustParse("1.34"), Default: false, LockToDefault: true, PreRelease: featuregate.Deprecated}, // feature is deprecated, off, and locked. remove in v1.37 once versions up to v1.34 cannot be emulated anymore.
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
NOTE: We do not remove GA fields from the API.
|
NOTE: We do not remove GA fields from the API.
|
||||||
|
|
||||||
### Other scenarios
|
### Other scenarios
|
||||||
|
|
Loading…
Reference in New Issue