Skip to content

Commit 90a81bc

Browse files
authored
Merge pull request kubernetes#2189 from pacoxu/default-kubectl-container
add KEP-2227 for default container used by kubectl
2 parents e0d8795 + 0ae8e51 commit 90a81bc

File tree

3 files changed

+369
-0
lines changed

3 files changed

+369
-0
lines changed

keps/prod-readiness/sig-cli/2227.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
kep-number: 2227
2+
alpha:
3+
approver: "@deads2k"
Lines changed: 321 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,321 @@
1+
# KEP-2227: default container behavior
2+
3+
## Table of Contents
4+
5+
<!-- toc -->
6+
- [Release Signoff Checklist](#release-signoff-checklist)
7+
- [Summary](#summary)
8+
- [Motivation](#motivation)
9+
- [Goals](#goals)
10+
- [Non-Goals](#non-goals)
11+
- [Proposal](#proposal)
12+
- [Current CLI Behaviors](#current-cli-behaviors)
13+
- [User Stories](#user-stories)
14+
- [Proposal Details](#proposal-details)
15+
- [Notes/Constraints/Caveats](#notesconstraintscaveats)
16+
- [Risks and Mitigations](#risks-and-mitigations)
17+
- [Design Details](#design-details)
18+
- [Test Plan](#test-plan)
19+
- [Graduation Criteria](#graduation-criteria)
20+
- [Alpha -&gt; Beta Graduation](#alpha---beta-graduation)
21+
- [Beta -&gt; GA Graduation](#beta---ga-graduation)
22+
- [Upgrade / Downgrade Strategy](#upgrade--downgrade-strategy)
23+
- [Version Skew Strategy](#version-skew-strategy)
24+
- [Production Readiness Review Questionnaire](#production-readiness-review-questionnaire)
25+
- [Feature Enablement and Rollback](#feature-enablement-and-rollback)
26+
- [Rollout, Upgrade and Rollback Planning](#rollout-upgrade-and-rollback-planning)
27+
- [Monitoring Requirements](#monitoring-requirements)
28+
- [Dependencies](#dependencies)
29+
- [Scalability](#scalability)
30+
- [Troubleshooting](#troubleshooting)
31+
- [Implementation History](#implementation-history)
32+
- [Drawbacks](#drawbacks)
33+
- [Alternatives](#alternatives)
34+
<!-- /toc -->
35+
36+
## Release Signoff Checklist
37+
38+
Items marked with (R) are required *prior to targeting to a milestone / release*.
39+
40+
- [X] (R) Enhancement issue in release milestone, which links to KEP dir in [kubernetes/enhancements] (not the initial KEP PR)
41+
- [X] (R) KEP approvers have approved the KEP status as `implementable`
42+
- [X] (R) Design details are appropriately documented
43+
- [X] (R) Test plan is in place, giving consideration to SIG Architecture and SIG Testing input
44+
- [X] (R) Graduation criteria is in place
45+
- [X] (R) Production readiness review completed
46+
- [X] (R) Production readiness review approved
47+
- [ ] "Implementation History" section is up-to-date for milestone
48+
- [ ] User-facing documentation has been created in [kubernetes/website], for publication to [kubernetes.io]
49+
- [ ] Supporting documentation—e.g., additional design documents, links to mailing list discussions/SIG meetings, relevant PRs/issues, release notes
50+
51+
<!--
52+
**Note:** This checklist is iterative and should be reviewed and updated every time this enhancement is being considered for a milestone.
53+
-->
54+
55+
[kubernetes.io]: https://kubernetes.io/
56+
[kubernetes/enhancements]: https://git.k8s.io/enhancements
57+
[kubernetes/kubernetes]: https://git.k8s.io/kubernetes
58+
[kubernetes/website]: https://git.k8s.io/website
59+
60+
## Summary
61+
62+
Introduce an optional annotation for consumption by certain kubectl commands which will allow picking a default container.
63+
64+
## Motivation
65+
66+
Pods are composed of one or more containers. This leads to an extra effort by the operators when they need to run a command on a Pod that needs to target a specific container.
67+
68+
It gets worse because aside from a warning, this couples the default exec container to the container order.
69+
70+
As an example, with Service Mesh now a Pod can always have two containers: the main application and the sidecar. The container startup order impacts on which is the "default" container nowadays, leading to command executions against wrong containers.
71+
72+
We don't have a general default container name attribute for pod, and this would change pod spec and is not acceptable.
73+
74+
Having a well-known annotation that specifies what's the default container of that Pod reduces operation efforts and improves the user experience.
75+
76+
> However, it gets worse because aside from a warning, this couples the default exec container to the container order.
77+
> The container ordering also happens to have an impact on container startup order. We have started offering an option
78+
> to inject our sidecar as the first container (previously, it was the last one), which has resulted in users running
79+
> kubectl exec and getting the "wrong" container.
80+
81+
Quoted from [kubernetes #96986](https://github.com/kubernetes/kubernetes/issues/96986) opened by @howardjohn
82+
83+
### Goals
84+
85+
- Provide a way for consumers (CLI, operators) to know which is the default Container of a Pod
86+
- Deprecate the already in use annotation `kubectl.kubernetes.io/default-logs-container`
87+
88+
### Non-Goals
89+
90+
- If the cli is not kubectl, we don't determine which is the default container.
91+
- Automatically define/create the default container annotation. This is an user operation.
92+
93+
## Proposal
94+
95+
Define a default well-known annotation for Pods called `kubectl.kubernetes.io/default-container` which points to Kubectl (and other commands) what's the default container to be used when the command needs this information.
96+
97+
Also this KEP proposes the change of behavior of kubectl commands that relies on the --container flag to read and make use of this annotation when the flag is not provided.
98+
99+
### Current CLI Behaviors
100+
101+
The following is the behavior of kubectl commands that can specify a container with --container:
102+
103+
- `kubectl attach`, `kubectl cp` and `kubectl exec`
104+
The three above have similar behavior: if --container flag is omitted, the first container of the Pod will be chosen.
105+
106+
- `kubectl logs`
107+
There's no default value. If a Pod have multiple containers, the operator needs to select which container to show the logs, or use the flag `--all-containers`
108+
Also, there's support for the annotation kubectl.kubernetes.io/default-logs-container in the Pod, that specified the default container to show the log. It will be deprecated with a warning message and be removed in 1.25.
109+
110+
- `kubectl debug`
111+
Use this option to specify container name for debug container.
112+
113+
### User Stories
114+
115+
User story 1: Julia, the operator of a deployment called "backend" that generates some stack traces locally. Her environment uses Service Mesh, and because of this, every time she tries to copy those stack traces she gets an error because the file does not exist, and this happens because kubectl cp points to the service mesh sidecar as the first container.
116+
117+
Story 2: John, a developer of a PHP application always needs to run a command inside the application Pod. Because of the way John structured the Pod (a Container with NGINX and the other with php_fpm) every time he wants to execute this command on the php_fpm but he forgets to use the flag --container, and this way the command gets executed in the wrong container.
118+
119+
### Proposal Details
120+
121+
A single, generic and well known annotation for all above commands like `kubectl.kubernetes.io/default-container` is a good choice to avoid needing many new annotations in the future.
122+
123+
There are currently 3 commands that consume this annotation if `--container` is not specified.
124+
- `kubectl exec`
125+
- `kubectl attach`
126+
- `kubectl cp`
127+
- `kubectl logs`
128+
129+
However, there is an exception that `kubectl logs` will consume this annotation only if no `--all-containers` option is specified. If `--all-containers` is specified, all pods logs should be returned.
130+
131+
`kubectl debug` will not consume this annotation, as `--container` for `kubectl debug` is to speicify new debug container name to use. It is quite differenet with the annotation meaning here.
132+
133+
If `kubectl.kubernetes.io/default-logs-container` is specified, we should use this annotation instead of the general one for `kubectl log` and use general annotation for other commands. We need add a deprecation warn message for users with default-logs-container annotation and keep the old annotation working until 1.25.
134+
135+
### Notes/Constraints/Caveats
136+
137+
As the annotation `kubectl.kubernetes.io/default-container` will not be automatically added, users and Pod owners will need to be aware of this new annotation.
138+
139+
### Risks and Mitigations
140+
**Note:** No server-side changes are required for this, all Request and Response template expansion is performed on
141+
the client side.
142+
143+
- None
144+
145+
## Design Details
146+
147+
**Publishing Data:**
148+
149+
Alpha: default container annotation
150+
151+
- Define a well known annotation `kubectl.kubernetes.io/default-container` in a Pod to provide a way to consumers (CLI, operators) to know which is the default Container.
152+
- Define a global function GetDefaultContainerName for kubectl that uses this annotation like below
153+
-- 1. if the command is `logs` check `--all-containers` flag at first: if it is specified, ignore container flag or annotations; if not, next step.
154+
-- 2. check `-c`/`--container` flag: if it is specified, use it; if not, next step.
155+
-- 3. check containers number in pod: if only one container, use its name; if more than one, next step.
156+
-- 4. check annotations:
157+
-- 4.1 if command is `log` and pod has `kubectl.kubernetes.io/default-logs-container` annotation, then use the annotation value and print a warning message for deprecation(removing this step when GA);
158+
-- 4.2 check `kubectl.kubernetes.io/default-container` annotation: if specified, use it; if not, next step
159+
-- 5. use the first container name as the default. Print a notice message before it.
160+
- Add test cases to make sure that the command is running with the right container. When `--container` is specified, the annotation will be ignored.
161+
- Validate the annotation value before using it, as the container name should follow RFC 1123. If the annotation value is invalid or not found in the pod, a warning message is needed before exiting.
162+
- By default, this feature should be enabled as this feature is opt-in, and it only works once user adds the specified annotation to their pods.
163+
- Ensure that when `kubectl.kubernetes.io/default-logs-container` is specified, we should use this annotation instead of the general one for `kubectl log` and use general annotation for other commands.
164+
165+
**Data Command Structure:**
166+
167+
168+
**Example Command:**
169+
Users might specify the `kubectl.kubernetes.io/default-container` annotation in a Pod to preselect container for kubectl exec and all kubectl commands.
170+
171+
An example Pod yaml is like below:
172+
173+
```
174+
apiVersion: v1
175+
kind: Pod
176+
metadata:
177+
annotations:
178+
kubectl.kubernetes.io/default-container: sidecar-container
179+
```
180+
181+
### Test Plan
182+
Add a unit test for each command, testing the behavior with the annotation, without the annotation, and with the --container flag
183+
184+
### Graduation Criteria
185+
186+
#### Alpha -> Beta Graduation
187+
188+
As this is an opt-in feature, no gate is expected.
189+
- At least 2 release cycles pass to gather feedback and bug reports during
190+
- Documentations, add it to [well-known annotations docs](https://kubernetes.io/docs/reference/kubernetes-api/labels-annotations-taints/)
191+
- Add a warning deprecation message when using the annotation `kubectl.kubernetes.io/default-logs-container`
192+
193+
#### Beta -> GA Graduation
194+
195+
- Gather feedback from developers and surveys
196+
- At least 2 release cycles pass to gather feedback and bug reports during
197+
- The deprecation message of the annotation `kubectl.kubernetes.io/default-logs-container` will be removed and this annotation will stop working.
198+
199+
### Upgrade / Downgrade Strategy
200+
201+
If kubectl is upgraded and no annotation is found, nothing happens.
202+
If there's an annotation and kubectl is downgraded, the old behavior of using the first container will come back to the users.
203+
204+
### Version Skew Strategy
205+
None
206+
207+
## Production Readiness Review Questionnaire
208+
209+
210+
### Feature Enablement and Rollback
211+
212+
* **How can this feature be enabled / disabled in a live cluster?**
213+
- [ ] Feature gate (also fill in values in `kep.yaml`)
214+
- Feature gate name:
215+
- Components depending on the feature gate:
216+
- [x] Other
217+
- Describe the mechanism:
218+
- This feature is explicitly opt-in since it need user to add specified
219+
annotation in pod.
220+
- Will enabling / disabling the feature require downtime of the control
221+
plane?
222+
- No. Disabling the feature would be a client behaviour.
223+
- Will enabling / disabling the feature require downtime or reprovisioning
224+
of a node?
225+
- No. It is a client behaviour only.
226+
227+
* **Does enabling the feature change any default behavior?**
228+
- No. The old behavior is notification when no default container is specified.
229+
Current behavior is cover that once specified annotation is in the pod spec.
230+
231+
* **Can the feature be disabled once it has been enabled (i.e. can we rollback
232+
the enablement)?**
233+
- Yes. When `--container` flag is specified, we will ignore
234+
the specified annotation.
235+
236+
* **What happens if we reenable the feature if it was previously rolled back?**
237+
- Nothing. It uses the first container as default in old behivior. It uses the
238+
annotation with this feature implemented, the first container will be used
239+
if the annotation is not defined.
240+
241+
* **Are there any tests for feature enablement/disablement?**
242+
- There are unit tests in `staging/src/k8s.io/kubectl/pkg/cmd/exec/` and
243+
`staging/src/k8s.io/kubectl/pkg/polymorphichelpers/` that
244+
verify the behaviour.
245+
246+
### Rollout, Upgrade and Rollback Planning
247+
248+
* **How can a rollout fail? Can it impact already running workloads?**
249+
- None
250+
* **What specific metrics should inform a rollback?**
251+
- None
252+
* **Were upgrade and rollback tested?**
253+
- None, or with adding and deleting the annotation from a pod to test it.
254+
* **Is the rollout accompanied by any deprecations and/or removals of features, APIs, fields of API types, flags, etc.?** Even if applying deprecation policies, they may still surprise some users. No.
255+
- None
256+
257+
### Monitoring Requirements
258+
259+
* **How can an operator determine if the feature is in use by workloads?**
260+
- A cluster-admin can checking which pods have the annotation.
261+
262+
* **What are the SLIs (Service Level Indicators) an operator can use to determine
263+
the health of the service?**
264+
- N/A, since it's just an annotation used for client-side hint.
265+
266+
* **What are the reasonable SLOs (Service Level Objectives) for the above SLIs?**
267+
- N/A.
268+
269+
* **Are there any missing metrics that would be useful to have to improve observability of this feature? **
270+
- No.
271+
272+
273+
### Dependencies
274+
* **Does this feature depend on any specific services running in the cluster? **
275+
- No, since it's just an annotation used for client-side hint.
276+
277+
### Scalability
278+
* **Will enabling / using this feature result in any new API calls?**
279+
- No, since it's just an annotation used for client-side hint.
280+
281+
* **Will enabling / using this feature result in introducing new API types?**
282+
- No.
283+
284+
* **Will enabling / using this feature result in any new calls to the cloud
285+
provider?**
286+
- No.
287+
288+
* **Will enabling / using this feature result in increasing size or count of
289+
the existing API objects?**
290+
- No.
291+
292+
* **Will enabling / using this feature result in increasing time taken by any
293+
operations covered by [existing SLIs/SLOs]?**
294+
- No.
295+
296+
* **Will enabling / using this feature result in non-negligible increase of
297+
resource usage (CPU, RAM, disk, IO, ...) in any components?**
298+
- No.
299+
300+
### Troubleshooting
301+
302+
* **How does this feature react if the API server and/or etcd is unavailable?**
303+
- Same with original behavior.
304+
305+
* **What are other known failure modes?**
306+
- Same with original behavior.
307+
308+
* **What steps should be taken if SLOs are not being met to determine the problem?**
309+
- Use `-c`/`--container` flag to skip this feature.
310+
311+
## Implementation History
312+
313+
WIP in https://github.com/kubernetes/kubernetes/pull/97099 in 1.21.
314+
315+
## Drawbacks
316+
317+
It is not generic for other clients like go-client for kubernetes.
318+
319+
## Alternatives
320+
321+
Use `-c` or `--container` option in kubectl commands.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
title: kubectl default container
2+
kep-number: 2227
3+
authors:
4+
- "@pacoxu"
5+
owning-sig: sig-cli
6+
participating-sigs:
7+
status: implementable
8+
creation-date: 2020-12-16
9+
reviewers:
10+
- "@dougsland"
11+
- "@eddiezane"
12+
- "@soltysh"
13+
- "@howardjohn"
14+
- "@rikatz"
15+
approvers:
16+
- "@soltysh"
17+
- "@rikatz"
18+
prr-approvers:
19+
- "@johnbelamaric"
20+
- "@deads2k"
21+
see-also:
22+
23+
# The target maturity stage in the current dev cycle for this KEP.
24+
stage: alpha
25+
26+
# The most recent milestone for which work toward delivery of this KEP has been
27+
# done. This can be the current (upcoming) milestone, if it is being actively
28+
# worked on.
29+
latest-milestone: "v1.21"
30+
31+
# The milestone at which this feature was, or is targeted to be, at each stage.
32+
milestone:
33+
alpha: "v1.21"
34+
beta: "v1.23"
35+
stable: "v1.25"
36+
37+
# The following PRR answers are required at alpha release
38+
# List the feature gate name and the components for which it must be enabled
39+
#
40+
# kubectl does not use feature-gates
41+
feature-gates: []
42+
disable-supported: true
43+
44+
# The following PRR answers are required at beta release
45+
metrics: []

0 commit comments

Comments
 (0)