KEP-2558: Publish versioning information in OpenAPI
KEP-2558: Publish versioning information in OpenAPI
- Release Signoff Checklist
- Summary
- Motivation
- Proposal
- Production Readiness Review Questionnaire
- Implementation History
- Alternatives
Release Signoff Checklist
Items marked with (R) are required prior to targeting to a milestone / release.
- (R) Enhancement issue in release milestone, which links to KEP dir in kubernetes/enhancements (not the initial KEP PR)
- (R) KEP approvers have approved the KEP status as
implementable - (R) Design details are appropriately documented
- (R) Test plan is in place, giving consideration to SIG Architecture and SIG Testing input (including test refactors)
- (R) Graduation criteria is in place
- (R) Production readiness review completed
- (R) Production readiness review approved
- “Implementation History” section is up-to-date for milestone
- User-facing documentation has been created in kubernetes/website , for publication to kubernetes.io
- Supporting documentation—e.g., additional design documents, links to mailing list discussions/SIG meetings, relevant PRs/issues, release notes
Summary
This KEP proposes a way for publishing field-level versioning information in OpenAPI using comment tags on API fields for built-in types.
Specifically, the field-level versioning information would include the prerelease status, minimum Kubernetes version for the prerelease status and the feature gate associated with field.
Motivation
Feature gate
When a new field is added to an existing API version, a feature gate
is added to control the enablement of the new field. Sometimes feature
gates are also used when a new Kind is added.
The feature gates are defined in kube_features.go
. The comments
for each of these feature gates in kube_features.go
lists
the prerelease status of the feature gate and the minimum Kubernetes
version for the particular prerelease. These comments do not follow
a pattern and are not parseable.
Currently, when a new field is added, there is no way to map and document the field with the feature gate that controls it. Some fields mention the feature gates in a comment but these comments are not parseable either.
Field version
Currently, when a new field is added to a stable API version, there is no way to expose the version of the new field in OpenAPI. One way to identify alpha API fields is by comparing the OpenAPI schema generated from an apiserver with all APIs enabled and the one generated from an apiserver with only stable and beta APIs enabled. However, this process is cumbersome and not always feasible because not all fields are gated at the API group level.
Since the OpenAPI definition is the source of truth for API documentation, this KEP proposes a way to publish versioning and feature gate information via OpenAPI.
As a follow-up, this information can also be used to:
- update the Kubernetes API reference documentation
- surface server-side warnings in client-go and kubectl when a deprecated field or alpha field is being used.
- surface warnings next to the field name in IDE when a deprecated field or alpha field is being used.
Goals
- Publish feature gate associated with an API field for built-in API types in OpenAPI to document the mapping of API fields with their feature gates.
- Document the current prerelease status of an API field by publishing the prerelease status of the field and the minimum Kubernetes version for the prerelease in OpenAPI.
- Validate that the feature gate mentioned in the API field comment is a valid feature gate.
Non-Goals
- Support publishing versioning information for built-in
Kinds. This may be added in the future but is not in scope in the alpha status of this KEP. - Support publishing field-level versioning for custom resources in OpenAPI.
- Publish the default status of a feature gate (enabled/disabled by default) in OpenAPI.
- Allow parsing comment tags on feature gates in
kube_features.go. - Update the Kubernetes API reference docs to include the field-level versioning information (out of scope of this KEP, can be done in a follow up).
Proposal
This KEP proposes changes to the kube-openapi generator to add a new
vendor extension field x-kubernetes-api-lifecycle in OpenAPI.
This extension specifies the prerelease status of an API field,
the minimum Kubernetes version for the prerelease and the
feature gate associated with the field.
This information is derived from comment tag on API fields with the format:
// +lifecycle:kubernetes:minVersion=<k8s-version>,status=<prelease-status>,featureGate=<featuregate-name>
The following Kubernetes-specific constraints are validated by a linter:
- The
+lifecycle:kubernetes:minVersion=<k8s-version>tag denotes that the field is in the prerelease since the specified Kubernetes version. It must map to a Kubernetes release (e.g.v1.20). - The
statusvalue must be one ofalpha,beta, ordeprecated. - The
featureGatevalue must be a valid feature gate as defined inkube_features.go.
When an API field moves to GA, the feature gate and the comment tag for the API field
are removed. This will also remove the x-kubernetes-api-lifecycle vendor extension for
the field in OpenAPI.
This method also provides us the extensibility to support CRDs in the future.
For CRDs, multiple // +lifecycle comment lines may be added for custom types
to denote the project’s specific version.
For example, an additional line // +lifecycle:istio:minVersion=v3.0.0 may be added.
This allows capturing both the Kubernetes and the project’s (istio) versions accurately.
The specific syntax for CRDs will be defined later.
Note: This KEP does not propose changing what API fields are published in the OpenAPI schema. It only adds extensions to fields for which the comment tag is specified.
Example
Consider adding a new alpha API field Width to the stable API Frobber
in v1.20.
type Frobber struct {
Height *int32 `json:"height"
Param string `json:"param"
// width indicates how wide the object is.
// This field is alpha-level and is only honored by servers that enable the Frobber2D feature.
// +optional
Width *int32 `json:"width,omitempty"
}
The field Width is controlled by the Frobber2D feature gate defined
in kube_features.go
.
// owner: @you
// alpha: v1.20
//
// Add multiple dimensions to frobbers.
Frobber2D utilfeature.Feature = "Frobber2D"
var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureSpec{
...
Frobber2D: {Default: false, PreRelease: utilfeature.Alpha},
}
To link the feature gate with the API field, the following comment line
is added for the Width field:
type Frobber struct {
Height *int32 `json:"height"
Param string `json:"param"
// width indicates how wide the object is.
// +optional
// +lifecycle:kubernetes:minVersion=v1.20,status=alpha,featureGate=Frobber2D
Width *int32 `json:"width,omitempty"
}
This will generate an OpenAPI schema with an additional vendor extension field:
"width": {
VendorExtensible: spec.VendorExtensible{
Extensions: spec.Extensions{
"x-kubernetes-api-lifecycle": map[string]interface{}{
"kubernetes": map[string]interface{
"minVersion": "v1.20",
"status": "alpha",
"featureGate": "Frobber2D",
},
},
},
},
This shows that the field is alpha from Kubernetes version v1.20 and
is controlled by the Frobber2D feature gate.
Constraints and Caveats
Constraints
The source of truth for versioning information for a feature gate will be the comment tags on the respective API fields because these comment tags are used for publishing to OpenAPI. A linter ensures that comments for feature gates defined in
kube_features.godo not diverge from the comment lines on API fields.Additionally, the following constraints are applied and validated for comment tags on API fields:
- The
+lifecycle:kubernetes:minVersionvalue must satisfy the regular expression^v[1-9][0-9]*\.(0|[1-9][0-9]*)$. - The
statusvalue must be one ofalpha,beta, ordeprecated. - The
featureGatevalue is a valid feature gate as defined inkube_features.go.
Test Plan
The constraints for the comment tags listed above are validated using a linter and relevant tests for introducing a new OpenAPI extension are added to kube-openapi.
Graduation Criteria
This feature is currently in the alpha status.
For the feature to move to the beta status, feedback will be collected
on usage of the x-kubernetes-api-lifecycle extension in OpenAPI in
various places like documentation, IDE support and server-side warnings
in client-go and kubectl.
Depending on the feedback, support for publishing versioning information
may be added to new Kinds as well.
Production Readiness Review Questionnaire
Feature Enablement and Rollback
How can this feature be enabled / disabled in a live cluster?
N/A
Does enabling the feature change any default behavior?
N/A
Can the feature be disabled once it has been enabled (i.e. can we roll back the enablement)?
N/A
What happens if we reenable the feature if it was previously rolled back?
N/A
Are there any tests for feature enablement/disablement?
N/A
Rollout, Upgrade and Rollback Planning
How can a rollout fail? Can it impact already running workloads?
N/A
What specific metrics should inform a rollback?
N/A
Were upgrade and rollback tested? Was the upgrade->downgrade->upgrade path tested?
N/A
Is the rollout accompanied by any deprecations and/or removals of features, APIs, fields of API types, flags, etc.?
No
Monitoring Requirements
How can an operator determine if the feature is in use by workloads?
N/A
What are the SLIs (Service Level Indicators) an operator can use to determine the health of the service?
N/A
What are the reasonable SLOs (Service Level Objectives) for the above SLIs?
N/A
Are there any missing metrics that would be useful to have to improve observability of this feature?
N/A
Dependencies
Does this feature depend on any specific services running in the cluster?
N/A
Scalability
Will enabling / using this feature result in any new API calls?
No
Will enabling / using this feature result in introducing new API types?
No
Will enabling / using this feature result in any new calls to the cloud provider?
No
Will enabling / using this feature result in increasing size or count of the existing API objects?
No
Will enabling / using this feature result in increasing time taken by any operations covered by existing SLIs/SLOs?
No
Will enabling / using this feature result in non-negligible increase of resource usage (CPU, RAM, disk, IO, …) in any components?
No
Troubleshooting
N/A
How does this feature react if the API server and/or etcd is unavailable?
N/A
What are other known failure modes?
N/A
What steps should be taken if SLOs are not being met to determine the problem?
N/A
Implementation History
- 2021-02-05: Initial discussion on the SIG Architecture mailing list
- 2021-03-07: KEP proposed
Alternatives
- The prerelease-lifecycle-gen
generator allows specifying metadata about
the prerelease status for packages (e.g.
cronjobs.v1beta1.batch).
Field-level versioning information support is added in the kube-openapi generator and not added to the prerelease-lifecycle-gen generator because:
- prerelease-lifecycle-gen only generates and documents metadata about when each package was introduced, deprecated or removed. It is not meant to work for individual API types or fields.
- Additionally, even if field-level support was added to it, this information would not be surfaced in OpenAPI which makes it harder to be consumed by other tools (e.g. for conformance and documentation).
- An alternative was considered to define the prerelease status, minVersion and featureGate value on a single comment line:
// +k8s:openapi-gen:prerelease=alpha,minVersion=v1.20,featureGate=Frobber2D
This approach was not used because +k8s:openapi-gen would limit the field metadata
to only be used by the openapi generator. Additionally, splitting into multiple comment
lines keeps the syntax simpler and makes it easier to debug.
- The initial draft of this KEP allowed specifying multiple prerelease statuses in comment tags for an API field. For example:
// +k8s:openapi-gen:prerelease=alpha,minVersion=v1.20,featureGate=Frobber2D
// +k8s:openapi-gen:prerelease=beta,minVersion=v1.21,featureGate=Frobber2D
However, this introduces risk of vastly increasing the size of the OpenAPI schema.
CRDs with multiple embedded PodTemplateSpecs can easily blow past the 1MB etcd limit with
this approach.
- An alternative was considered to add comment tags to all types that are not GA.
Existing and new GA types would be listed as exceptions
.
This ensures that
types.gofiles are not spammed with comment tags an tooling can interpret absence of a comment tag as an error instead of assuming the types to be GA.
Depending on the feedback of the initial proposal for fields, this option may be considered in the future.