|
| 1 | +# KEP-1693: Warning mechanism for use of deprecated APIs |
| 2 | + |
| 3 | +<!-- toc --> |
| 4 | +- [Release Signoff Checklist](#release-signoff-checklist) |
| 5 | +- [Summary](#summary) |
| 6 | +- [Motivation](#motivation) |
| 7 | + - [Goals](#goals) |
| 8 | + - [Non-Goals](#non-goals) |
| 9 | +- [Proposal](#proposal) |
| 10 | + - [Server-side changes](#server-side-changes) |
| 11 | + - [Client-side changes](#client-side-changes) |
| 12 | +- [Design Details](#design-details) |
| 13 | + - [Test Plan](#test-plan) |
| 14 | + - [Risks and Mitigations](#risks-and-mitigations) |
| 15 | + - [Graduation Criteria](#graduation-criteria) |
| 16 | + - [Beta graduation](#beta-graduation) |
| 17 | + - [GA graduation](#ga-graduation) |
| 18 | + - [Upgrade / Downgrade Strategy](#upgrade--downgrade-strategy) |
| 19 | + - [Version Skew Strategy](#version-skew-strategy) |
| 20 | +- [Implementation History](#implementation-history) |
| 21 | +<!-- /toc --> |
| 22 | + |
| 23 | +## Release Signoff Checklist |
| 24 | + |
| 25 | +<!-- |
| 26 | +**ACTION REQUIRED:** In order to merge code into a release, there must be an |
| 27 | +issue in [kubernetes/enhancements] referencing this KEP and targeting a release |
| 28 | +milestone **before the [Enhancement Freeze](https://git.k8s.io/sig-release/releases) |
| 29 | +of the targeted release**. |
| 30 | +
|
| 31 | +For enhancements that make changes to code or processes/procedures in core |
| 32 | +Kubernetes i.e., [kubernetes/kubernetes], we require the following Release |
| 33 | +Signoff checklist to be completed. |
| 34 | +
|
| 35 | +Check these off as they are completed for the Release Team to track. These |
| 36 | +checklist items _must_ be updated for the enhancement to be released. |
| 37 | +--> |
| 38 | + |
| 39 | +- [x] Enhancement issue in release milestone, which links to KEP dir in [kubernetes/enhancements] (not the initial KEP PR) |
| 40 | +- [x] Design details are appropriately documented |
| 41 | +- [x] Test plan is in place, giving consideration to SIG Architecture and SIG Testing input |
| 42 | +- [x] Graduation criteria is in place |
| 43 | +- [ ] KEP approvers have approved the KEP status as `implementable` |
| 44 | +- [ ] "Implementation History" section is up-to-date for milestone |
| 45 | +- [ ] User-facing documentation has been created in [kubernetes/website], for publication to [kubernetes.io] |
| 46 | +- [ ] Supporting documentation e.g., additional design documents, links to mailing list discussions/SIG meetings, relevant PRs/issues, release notes |
| 47 | + |
| 48 | +<!-- |
| 49 | +**Note:** This checklist is iterative and should be reviewed and updated every time this enhancement is being considered for a milestone. |
| 50 | +--> |
| 51 | + |
| 52 | +[kubernetes.io]: https://kubernetes.io/ |
| 53 | +[kubernetes/enhancements]: https://git.k8s.io/enhancements |
| 54 | +[kubernetes/kubernetes]: https://git.k8s.io/kubernetes |
| 55 | +[kubernetes/website]: https://git.k8s.io/website |
| 56 | + |
| 57 | +## Summary |
| 58 | + |
| 59 | +This enhancement makes it easier for users and cluster administrators |
| 60 | +to recognize and remedy use of deprecated APIs. |
| 61 | +Users are presented with informative warnings at time of use. |
| 62 | +Administrators are given metrics that show deprecated API use, |
| 63 | +and audit annotations that can be used to identify particular API clients. |
| 64 | + |
| 65 | +## Motivation |
| 66 | + |
| 67 | +Kubernetes has many deprecations in flight at any given moment, in various stages, with various time horizons. |
| 68 | +Keeping track of all of them is difficult, and has historically required careful reading of release notes, |
| 69 | +and manually sweeping for use of deprecated features. |
| 70 | + |
| 71 | +### Goals |
| 72 | + |
| 73 | +* When a user makes a request to a deprecated API, present them with a warning |
| 74 | + that includes the target removal release and any replacement API |
| 75 | +* Allow a cluster administrator to programatically determine if deprecated APIs are being used: |
| 76 | + * Filtered to particular APIs |
| 77 | + * Filtered to particular operations (e.g. get, list, create, update) |
| 78 | + * Filtered to APIs targeting removal in particular releases |
| 79 | +* Allow a cluster administrator to programatically identify particular clients using deprecated APIs |
| 80 | + |
| 81 | +### Non-Goals |
| 82 | + |
| 83 | +While the proposed warning mechanism is generic enough to carry arbitrary warnings, |
| 84 | +the following items are out of scope for the first iteration of this feature: |
| 85 | + |
| 86 | +* Allowing extensions mechanisms like admission webhooks to contribute warnings |
| 87 | +* Surfacing warnings about other non-fatal problems |
| 88 | + (for example, [problematic API requests](http://issue.k8s.io/64841#issuecomment-395141013) |
| 89 | + that cannot be rejected for compatibility reasons) |
| 90 | + |
| 91 | +## Proposal |
| 92 | + |
| 93 | +### Server-side changes |
| 94 | + |
| 95 | +When a deprecated API is used: |
| 96 | + |
| 97 | +1. Add a `Warning` header to the response |
| 98 | +2. Increment a counter metric with labels for the API group, version, resource, API verb, and target removal major/minor version |
| 99 | +3. Record an audit annotation indicating the request used a deprecated API |
| 100 | + |
| 101 | +### Client-side changes |
| 102 | + |
| 103 | +In client-go: |
| 104 | + |
| 105 | +1. Parse `Warning` headers from server responses |
| 106 | +2. Provide default warning handler implementations, e.g.: |
| 107 | + 1. ignore warnings |
| 108 | + 2. dedupe warnings |
| 109 | + 3. log warnings with klog.Warn |
| 110 | +3. Add a process-wide warning handler (defaulting to the klog.Warn handler) |
| 111 | +4. Add a per-client warning handler (defaulting to the process-wide warning handler) |
| 112 | + |
| 113 | +In kubectl, configure the per-process handler to: |
| 114 | + |
| 115 | +1. dedupe warnings (only print a given warning once per invocation) |
| 116 | +2. log to stderr with a `Warning:` prefix |
| 117 | +3. color the `Warning:` prefix if stderr is a terminal and `$TERM != "dumb"` and `$NO_COLOR` is unset |
| 118 | + |
| 119 | +In kube-apiserver and kube-controller-manager, configure the process-wide handler to ignore warnings |
| 120 | + |
| 121 | +## Design Details |
| 122 | + |
| 123 | +Server-side: |
| 124 | + |
| 125 | +* Add a handler chain filter that attaches a WarningRecorder implementation to the request context |
| 126 | +* Add a WarningRecord implementation that deduplicates the warning message per request and writes a `Warning` header |
| 127 | + * the header structure is defined in [RFC2616#14.46](https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.46) |
| 128 | + * warnings would be written with code `299` and warn-agent of `-` |
| 129 | +* In the endpoint installer, decorate handlers for deprecated APIs: |
| 130 | + * add the warning header |
| 131 | + * increment the counter for the deprecated use metric |
| 132 | + * add an audit annotation indicating the request was to a deprecated API |
| 133 | + |
| 134 | +Client-side: |
| 135 | + |
| 136 | +* Parse `Warning` headers in server responses |
| 137 | +* Ignore malformed warning headers and warnings with codes other than `299`, |
| 138 | + ensuring that this enhancement will not cause any previously successful API request to fail |
| 139 | +* Add the parsed warning headers to the `rest.Result` struct |
| 140 | +* Pass parsed warnings through the per-client or per-process warning handler |
| 141 | + |
| 142 | +### Test Plan |
| 143 | + |
| 144 | +- Unit tests |
| 145 | + - `Warning` header generation |
| 146 | + - `Warning` header parsing (including tolerating/ignoreing malformed headers) |
| 147 | + - per-process / per-client warning handler precedence is honored |
| 148 | +- Integration tests |
| 149 | + - warning headers are returned when making requests to deprecated APIs |
| 150 | + - deprecated metrics are incremented when making requests to deprecated APIs |
| 151 | + - audit annotations are added when making requests to deprecated APIs |
| 152 | + |
| 153 | +### Risks and Mitigations |
| 154 | + |
| 155 | +**Metric cardinality** |
| 156 | + |
| 157 | +In the past, we have had problems with unbounded metric labels increasing cardinality of |
| 158 | +metrics and causing significant memory/storage use. Limiting these metrics to bounded values |
| 159 | +(API group, version, resource, API verb, target removal release) and omitting unbounded values |
| 160 | +(resource instance name, client username, etc), metric cardinality is controlled. |
| 161 | + |
| 162 | +Annotating audit events for the deprecated API requests allows an administrator to locate |
| 163 | +the particular client making deprecated requests when metrics indicate an investigation is needed. |
| 164 | + |
| 165 | +**Additional stderr / warning output** |
| 166 | + |
| 167 | +Additional warning messages may be unexpected by kubectl or client-go consumers. |
| 168 | +However, kubectl and client-go already output warning messages to stderr or via `klog.Warn`. |
| 169 | +client-go consumers can programmatically modify or suppress the warning output at a per-process or per-client level. |
| 170 | + |
| 171 | +### Graduation Criteria |
| 172 | + |
| 173 | +The structure of the `Warning` header is RFC-defined and unversioned. |
| 174 | +The RFC defines the behavior of the `299` warning code as follows: |
| 175 | + |
| 176 | +> The warning text can include arbitrary information to be presented to a human user or logged. |
| 177 | +> A system receiving this warning MUST NOT take any automated action. |
| 178 | +
|
| 179 | +Because the server -> client warning format is fixed, and the warnings do not |
| 180 | +drive automated action in clients, graduation criteria is primarily oriented |
| 181 | +toward the stability level of the administrator metrics, and the ability to |
| 182 | +disable the server sending warnings during the beta period. |
| 183 | + |
| 184 | +#### Beta graduation |
| 185 | + |
| 186 | +* Test plan is implemented |
| 187 | +* API server output of `Warning` headers for deprecated API use is feature-gated and enabled by default |
| 188 | +* The metric for deprecated API use is registered at [stability level `ALPHA`](https://github.com/kubernetes/enhancements/blob/master/keps/sig-instrumentation/20190404-kubernetes-control-plane-metrics-stability.md#stability-classes) |
| 189 | +* client-go logs warnings by default |
| 190 | +* kubectl outputs warnings to stderr |
| 191 | + |
| 192 | +#### GA graduation |
| 193 | + |
| 194 | +* At least two releases after Beta |
| 195 | +* Gathered feedback on metric structure and use from multi-cluster admins |
| 196 | +* API server output of `Warning` headers for deprecated API use is unconditionally enabled |
| 197 | +* Server metric for deprecated API use is registered at [stability level `STABLE`](https://github.com/kubernetes/enhancements/blob/master/keps/sig-instrumentation/20190404-kubernetes-control-plane-metrics-stability.md#stability-classes) |
| 198 | + |
| 199 | +### Upgrade / Downgrade Strategy |
| 200 | + |
| 201 | +client-go consumers wanting to suppress default warning messages would need to override the per-process warning handler. |
| 202 | +Note that client-go already [logs warning messages](https://grep.app/search?q=klog.Warn&filter[repo][0]=kubernetes/client-go). |
| 203 | + |
| 204 | +### Version Skew Strategy |
| 205 | + |
| 206 | +Old clients making requests to a new API server ignore `Warning` headers. |
| 207 | + |
| 208 | +New clients making requests to old API servers handle requests without `Warning` headers normally. |
| 209 | + |
| 210 | +## Implementation History |
| 211 | + |
| 212 | +- 2020-04-16: KEP introduced |
0 commit comments