Two of the three fields the post's second worked example changes are forbidden on the kind of container its first example creates, the default profile the task page names is not the one the reference page names, and the switch that made this beta has no record anywhere in the tree¶
Post — Kubernetes 1.31: Custom Profiling in Kubectl Debug Graduates to Beta, 2024-08-22.
3,549 bytes over 103 lines: the fifth-smallest of the fifty-four 2024 posts and the second-smallest
of the thirteen the year marks walk. One author, Arda Güçlü of Red Hat, and three people thanked
at :99-103. Five fenced blocks in a post of ten prose paragraphs — two shell, two YAML, one JSON —
which is an unusually high ratio of example to argument, and the reason this exercise is the
cheapest in the year to run: one node, one namespace, a busybox image and no reboots. Three lines
carry trailing whitespace (:11, :20, :43), one of the ten paragraphs is the two words and
execute:, and the file has no final newline — small evidence, but it is the only evidence, that
this one was typed rather than generated.
As written
:10-16 opens on the thing that already worked. kubectl debug ships a set of static profiles,
one per role, and the example given is a network administrator taking a node: kubectl debug
node/mynode -it --image=busybox --profile=netadmin. :18-20 names the cost of that design —
static profiles also bring about inherent rigidity — and :22-36 gives the case it breaks on: a
Pod whose container will not start healthy without an environment variable, shown as a twelve-line
manifest with image: customapp:latest and REQUIRED_ENV_VAR=value1.
:38-39 states the problem in one sentence and one rhetorical question: copying the Pod is the
sole mechanism that supports debugging this pod, and if you need the variable set to something else
for the debugging run, there is no mechanism to achieve this.
:41-57 is the answer. A new flag, --custom, taking a partial Container spec in YAML or JSON.
The first example is four lines of YAML setting one environment variable, applied with kubectl
debug example-pod -it --image=customapp --custom=partial_container.yaml, and :44 says what shape
of debugging it is doing: by creating an ephemeral container.
:59-85 is the second example, and it is the one this exercise is mostly about. Twenty-five lines
of JSON introduced as another example that modifies multiple fields at once, with the three fields
named in the prose: change port number, add resource limits, modify environment variable. The JSON
sets ports, resources with both limits and requests, and env.
:87-90 is a section called Constraints, and it lists what you may not customise: command,
image, lifecycle, volume devices and container name. It closes by predicting the list will grow —
in the future, more fields can be added to the disallowed list if required.
:92-95 is a section called Limitations, and it is a claim about shape rather than about a field.
kubectl debug has three aspects — ephemeral containers, pod copying, node debugging — and the
largest intersection set of these aspects is the container spec within a Pod, so custom profiling
supports container fields and not Pod fields. The sentence that says so is missing its full stop.
As it runs now
The post's second example cannot be applied to the container its first example creates.
pod-v1.md:1225 is the EphemeralContainer type, and it is a Container with holes cut in it.
:1274 against ports reads Ports are not allowed for ephemeral containers. :1286 against
resources reads Resources are not allowed for ephemeral containers. Ephemeral containers use
spare resources already allocated to the pod. Those are two of the three things the post says its
JSON changes. The third, env, is fine. So the example is two-thirds inadmissible in the aspect the
post had just demonstrated, and entirely admissible in the other two, where the container being
built is an ordinary one. The post does not say which aspect the JSON is for, and nothing in it
suggests the answer changes with the aspect. Steps 4 to 7 submit it three times and collect three
different outcomes.
The list of forbidden fields the documentation gives is not the list the API enforces.
debug-running-pod.md:767-772 carries a note with five names — name, image, command,
lifecycle, volumeDevices — and adds that the Pod spec is out of reach. Those five are kubectl's
list, refused client-side. The EphemeralContainer table refuses six more, and one of them
overlaps: lifecycle at :1262, ports at :1274, resources at :1286, probes at :1266,
:1278 and :1302, and subpath mounts at :1334. lifecycle appears on both lists; ports,
resources and the three probes appear only on the second, where the rejection arrives from the API
server after kubectl has already accepted the file. The post's Constraints section at :89
reproduces kubectl's five and nothing else.
The post predicted the forbidden list would grow, and it has not. :90 says in the future,
more fields can be added to the disallowed list if required. The note at debug-running-pod.md:769
at the pin names the same five, in a different order, with volumeDevices spelled as one word
rather than two. Step 8 submits all five and then submits four that ought still to be allowed.
The default profile the task page names is not the default the reference page gives.
debug-running-pod.md:702 says if you don't specify --profile, the legacy profile is used by
default, but it is planned to be deprecated in the near future, and the table at :691-698 lists
legacy as the first of six profiles. The generated flag reference at
kubectl_debug/_index.md:195-198 says Default: "general" and enumerates five options — general,
baseline, restricted, netadmin, sysadmin. legacy is not among them. Two pages in one
checkout, one flag, two different defaults and two different option sets. One command settles it,
and it is step 1.
legacy survives in exactly two places, both on the same page. Across all of content/en the
word appears as a debug profile only at debug-running-pod.md:693, in the table row whose
description is A set of properties backwards compatibility with 1.22 behavior, and at :702, in
the note that calls it the default. The generated reference dropped it; nothing else mentions it. A
profile named for compatibility with a release eleven behind the one this post announces is the only
entry in the table the reference does not know about.
There is no record of how this was ever a beta. The post's title says Graduates to Beta. There
is no file for it under the feature-gates directory, because it was never an API server feature; it
is client-side, and kubectl's switches are not gates in that sense. But the string KUBECTL_DEBUG
occurs zero times in the whole pinned checkout. This is not a general gap in the documentation of
kubectl switches: kubectl_debug/_index.md:366 prints, on the --kuberc flag, this can be
disabled by exporting KUBECTL_KUBERC=false feature gate or turning off the feature KUBERC=off, and
the same sentence is repeated on dozens of other generated pages. kubectl gating is documented at
the pin. It is documented for kuberc and not for this. Step 9 goes looking and comes back empty,
which is the finding.
The stable banner on this feature is hand-written. debug-running-pod.md:762 is {{<
feature-state for_k8s_version="v1.32" state="stable" >}} — the two-argument form that states a
version and a stage directly, rather than the feature_gate_name form that reads a gate record.
There is no record to read. Taken with the post, the shape is beta at v1.31 and stable at v1.32: one
release. That is worth holding beside the exercise on the pod failure policy GA
post from three days earlier in the same month, where
three banners on the same shortcode are keyed to gate records that have been deleted. The same
shortcode is doing two different jobs in the same tree, and only one of them can go stale on its
own.
The post's own worked example has never been runnable. :32 gives the target Pod image:
customapp:latest and :56 debugs it with --image=customapp, an image that exists in no registry.
The documentation's version of the same walkthrough at debug-running-pod.md:774-819 replaced both
with busybox:1.28, replaced the partial container with a different one — two environment variables
and NET_ADMIN plus SYS_TIME capabilities at :784-793 — and added --profile=general to a
command line the post left bare at :56. Step 2 runs the documentation's version, which works; step
3 runs the post's shape with a real image, which also works.
The Limitations claim is the wrong way round. :94-95 says the container spec is the largest
intersection set of the three aspects of kubectl debug. It is the intersection only if all three
take the same container spec, and they do not: two take a Container and one takes an
EphemeralContainer, which pod-v1.md:1225-1341 defines as a Container with ports,
resources, three probes, lifecycle, restartPolicy and subpath mounts removed. The intersection
is the smaller type, not the larger one, and the post's second example is written against the larger
one.
The flag itself is exactly what the post says it is. --custom takes a path to a JSON or YAML
file containing a partial container spec, composes with --profile, and is described at
kubectl_debug/_index.md:111-114 in one sentence that matches :43 of the post almost word for
word. Nothing about the mechanism drifted. Everything in this exercise is about the two examples
around it and the pages that describe it.
And the thing the documentation cannot settle with itself. pod-v1.md:1227 introduces ephemeral
containers with two sentences that sit awkwardly together: Ephemeral containers have no resource or
scheduling guarantees, and the kubelet may evict a Pod if an ephemeral container causes the Pod to
exceed its resource allocation. The whole premise of kubectl debug on a running Pod — the premise
debug-running-pod.md is built on, and the reason the post wants to reach into production Pods — is
that attaching a debugger is the safe move. The same paragraph says attaching one may get the Pod
killed. That is also why resources is refused at :1286: you cannot reserve headroom for the
debugger, so the post's add resource limits is asking for the one thing the design forbids.
Neither page gives a threshold, neither says how much room a debug container may take before the
eviction it warns about happens, and a one-node lab with no memory pressure cannot produce it on
demand. Both halves are quoted here and neither is picked.
What this exercise does not cover, and where it lives
What an ephemeral container is, and the first demonstration of putting one into a running Pod,
belong to the exercise on nine kubectl features and six
fates, which runs kubectl debug pod/redis
-it --image=busybox --target=redis and reads the target's filesystem through /proc/1/root. Node
debugging — kubectl debug node/, and what the debug Pod gets that an ordinary Pod does not —
belongs to the exercise on the security post the project marked partly
obsolete. Step 7 below uses node/
only as the third place to submit one JSON file. Why a container's resources cannot be changed after
it starts, and which container kinds are excluded from the mechanism that changes them, is the
exercise on the in-place resize alpha, which already
records that init and ephemeral containers cannot be resized. Pod Security Standards, which two of
the six static profiles are named after, are not touched here at all.
The diff, and why
Still right. The flag exists, takes what the post says it takes, composes with --profile, and
refuses the five fields the post's Constraints section names. Steps 2, 3 and 8 confirm all of it.
For a post this short that is most of the surface area, and it should be said before the rest.
Wrong when it was published. The JSON at :61-85 sets ports and resources on what :44 has
just established is an ephemeral container. pod-v1.md forbade both then and forbids both now; this
is not drift. The post did not test its second example against the aspect its first example
introduced, and the aspect it would be valid for — pod copying, node debugging — is mentioned only
two sections later, in Limitations, in a sentence that gets the containment backwards. Step 4 is
one command and it has been failing since the day the post went up.
Overtaken by stasis. The legacy profile is the clearest case. It is still tabled and still
called the default on the task page; the generated reference, which is regenerated from kubectl's
own flag help, has dropped it from both the default and the option list. The task page was not
edited when kubectl changed, and nothing links the two. The prose warning that legacy is planned
to be deprecated in the near future has outlived the deprecation it predicted.
Retired by being agreed with. Custom profiling went beta in v1.31 and stable in v1.32, and the only evidence of its beta period left in the tree is this post's title. The switch is gone, the env var is unmentioned, and the banner that marks the feature stable was typed by hand rather than read off a record. There is nothing left to turn off, which is why this exercise has no ladder.
Never absorbed. The post's prediction at :90 that more fields would join the disallowed list
did not happen, and neither did the natural fix for what this exercise finds: kubectl still does not
refuse ports or resources on an ephemeral-container debug, so the error still comes from the API
server, in the API server's words, about a field the user wrote into a file the client had already
accepted.
Topology
solo — one node, 4096MB, 4 cores, at 10.10.10.180,
running Kubernetes v1.35. Bring it up with the provision
steps and install Kubernetes with the node baseline
procedure. This is the cheapest exercise in
the year: everything below is busybox:1.28, one namespace called bw-dbg, and no step touches the
node's configuration or restarts anything. One node is enough because step 7 debugs a node and
there is only one to debug. Note that an ephemeral container cannot be removed from a Pod once added
— pod-v1.md:1229 says so — so each step that adds one uses a fresh Pod rather than reusing the
last. The offline reads are against the pinned checkout at /path/to/kubernetes/website/content/en;
W below is that path.
Do
- Settle the default. Read what kubectl says about
--profile, then ask for the profile the task page calls the default. Compare all three answers:debug-running-pod.md:702,kubectl_debug/_index.md:195-198, and the binary.
kubectl version -o json | grep -E '"gitVersion"'
kubectl debug --help | grep -A3 -- '--profile'
kubectl create namespace bw-dbg
kubectl -n bw-dbg run app1 --image=busybox:1.28 --restart=Never -- sleep 1d
kubectl -n bw-dbg wait --for=condition=Ready pod/app1 --timeout=180s
kubectl -n bw-dbg debug app1 --image=busybox:1.28 --target=app1 --profile=legacy -- true
kubectl -n bw-dbg get pod app1 -o jsonpath='{range .spec.ephemeralContainers[*]}{.name}{"\n"}{end}'
- Run the documentation's own custom-profile walkthrough, verbatim from
debug-running-pod.md:774-819. The file it asks for is at:784-793; this writes it out rather than retyping it, so any drift between what you read and what you run is impossible.
W=/path/to/kubernetes/website/content/en
sed -n '784,793p' $W/docs/tasks/debug/debug-application/debug-running-pod.md > /tmp/custom-profile.yaml
cat /tmp/custom-profile.yaml
kubectl -n bw-dbg run app2 --image=busybox:1.28 --restart=Never -- sleep 1d
kubectl -n bw-dbg wait --for=condition=Ready pod/app2 --timeout=180s
kubectl -n bw-dbg debug app2 --image=busybox:1.28 --target=app2 \
--profile=general --custom=/tmp/custom-profile.yaml -- true
kubectl -n bw-dbg get pod app2 -o jsonpath='{.spec.ephemeralContainers[0].env}{"\n"}'
kubectl -n bw-dbg get pod app2 -o jsonpath='{.spec.ephemeralContainers[0].securityContext}{"\n"}'
- Now the post's shape: one environment variable, no
--profileon the command line, against a Pod that actually carries the variable the post's example Pod carries. The image is the only thing changed, becausecustomapp:latestdoes not exist.
kubectl -n bw-dbg run app3 --image=busybox:1.28 --restart=Never \
--env=REQUIRED_ENV_VAR=value1 -- sleep 1d
kubectl -n bw-dbg wait --for=condition=Ready pod/app3 --timeout=180s
cat > /tmp/partial_container.yaml <<'YAML'
env:
- name: REQUIRED_ENV_VAR
value: value2
YAML
kubectl -n bw-dbg debug app3 --image=busybox:1.28 --target=app3 \
--custom=/tmp/partial_container.yaml -- true
kubectl -n bw-dbg get pod app3 -o jsonpath='{.spec.containers[0].env}{"\n"}'
kubectl -n bw-dbg get pod app3 -o jsonpath='{.spec.ephemeralContainers[0].env}{"\n"}'
- The post's second example, verbatim, against an ephemeral container — the aspect
:44introduced. This is the whole finding in one command.
cat > /tmp/post-json-profile.json <<'JSON'
{
"ports": [
{
"containerPort": 80
}
],
"resources": {
"limits": {
"cpu": "0.5",
"memory": "512Mi"
},
"requests": {
"cpu": "0.2",
"memory": "256Mi"
}
},
"env": [
{
"name": "REQUIRED_ENV_VAR",
"value": "value2"
}
]
}
JSON
kubectl -n bw-dbg run app4 --image=busybox:1.28 --restart=Never -- sleep 1d
kubectl -n bw-dbg wait --for=condition=Ready pod/app4 --timeout=180s
kubectl -n bw-dbg debug app4 --image=busybox:1.28 --target=app4 \
--custom=/tmp/post-json-profile.json -- true
- Bisect it. Three files, one field each, three fresh Pods, so you learn which of the three the post names is the one that is fine and which two are not — and, from the wording of each error, whether kubectl refused it or the API server did.
printf '{"ports":[{"containerPort":80}]}\n' > /tmp/only-ports.json
printf '{"resources":{"limits":{"memory":"512Mi"}}}\n' > /tmp/only-resources.json
printf '{"env":[{"name":"X","value":"y"}]}\n' > /tmp/only-env.json
for n in 5a 5b 5c; do
kubectl -n bw-dbg run app$n --image=busybox:1.28 --restart=Never -- sleep 1d
done
kubectl -n bw-dbg wait --for=condition=Ready pod/app5a pod/app5b pod/app5c --timeout=180s
for pair in "app5a only-ports" "app5b only-resources" "app5c only-env"; do
set -- $pair
echo "--- $2 ---"
kubectl -n bw-dbg debug "$1" --image=busybox:1.28 --target="$1" --custom=/tmp/$2.json -- true
done
- The same JSON against the second aspect: pod copying. Here the thing being built is an ordinary
container in a new Pod, so the
EphemeralContainerrestrictions do not apply.
kubectl -n bw-dbg run app6 --image=busybox:1.28 --restart=Never -- sleep 1d
kubectl -n bw-dbg wait --for=condition=Ready pod/app6 --timeout=180s
kubectl -n bw-dbg debug app6 --image=busybox:1.28 --copy-to=app6-copy \
--custom=/tmp/post-json-profile.json -- sleep 1d
kubectl -n bw-dbg get pod app6-copy \
-o jsonpath='{range .spec.containers[*]}{.name}{"\t"}{.ports}{"\t"}{.resources}{"\n"}{end}'
- And the third aspect: node debugging. Same file, a third kind of target. The debug Pod runs in
bw-dbgso teardown catches it.
NODE=$(kubectl get nodes -o jsonpath='{.items[0].metadata.name}')
kubectl -n bw-dbg debug node/"$NODE" --image=busybox:1.28 \
--profile=general --custom=/tmp/post-json-profile.json -- sleep 1d
kubectl -n bw-dbg get pods -o name | grep node-debugger
kubectl -n bw-dbg get pods -o json | grep -o '"containerPort":[0-9]*' | sort -u
- The five fields the post's
Constraintssection names, one at a time, and then four it does not, to test the prediction at:90that the list would have grown. Every one of these is refused or accepted by kubectl before the API server sees it, so a single Pod is enough — nothing that fails adds a container.
kubectl -n bw-dbg run app8 --image=busybox:1.28 --restart=Never -- sleep 1d
kubectl -n bw-dbg wait --for=condition=Ready pod/app8 --timeout=180s
for j in '{"name":"nope"}' \
'{"image":"busybox:1.36"}' \
'{"command":["sh"]}' \
'{"lifecycle":{"preStop":{"exec":{"command":["true"]}}}}' \
'{"volumeDevices":[{"name":"d","devicePath":"/dev/x"}]}' \
'{"workingDir":"/tmp"}' \
'{"tty":true}' \
'{"imagePullPolicy":"Never"}' \
'{"securityContext":{"runAsUser":1000}}'; do
echo "--- $j"
printf '%s\n' "$j" > /tmp/one-field.json
kubectl -n bw-dbg debug app8 --image=busybox:1.28 --target=app8 \
--custom=/tmp/one-field.json -- true 2>&1 | head -2
done
kubectl -n bw-dbg get pod app8 -o jsonpath='{range .spec.ephemeralContainers[*]}{.name}{"\n"}{end}'
- Go looking for the switch the post's title implies. Ask kubectl for anything gate-shaped on this command, ask it for the one client-side gate the tree does document, and ask the checkout for the string that would name this one.
W=/path/to/kubernetes/website/content/en
kubectl debug --help | grep -inE 'gate|alpha|beta|experiment|KUBECTL_' || echo 'nothing gate-shaped on kubectl debug'
kubectl options | grep -i kuberc
grep -rc 'KUBECTL_DEBUG' $W || echo 'KUBECTL_DEBUG: zero occurrences in the checkout'
grep -rln 'KUBECTL_KUBERC' $W/docs/reference/kubectl/generated | wc -l
ls $W/docs/reference/command-line-tools-reference/feature-gates/ | grep -icE 'debug|profile|kubectl' || true
-
Offline, against the pinned checkout. Four reads: the two profile lists side by side, the hand-written stable banner, the note that says which fields kubectl refuses, and the
EphemeralContainerrows that say which fields the API refuses.cd /path/to/kubernetes/website/content/en sed -n '686,704p' docs/tasks/debug/debug-application/debug-running-pod.md sed -n '195,199p' docs/reference/kubectl/generated/kubectl_debug/_index.md | sed -e 's/<[^>]*>//g' grep -rn '`legacy`\|^| legacy' --include='*.md' docs | grep -i 'profile\|1.22' sed -n '760,772p' docs/tasks/debug/debug-application/debug-running-pod.md sed -n '1225,1229p' docs/reference/kubernetes-api/core/pod-v1.md | sed -e 's/<[^>]*>//g' grep -n 'not allowed for ephemeral containers' docs/reference/kubernetes-api/core/pod-v1.md sed -n '111,115p;363,367p' docs/reference/kubectl/generated/kubectl_debug/_index.md | sed -e 's/<[^>]*>//g'
Expect
Step 1 prints v1.35. The help text for --profile gives general as the default and lists five
names with legacy absent — the generated reference at kubectl_debug/_index.md:195-198 is right
and debug-running-pod.md:702 is wrong. Asking for --profile=legacy therefore fails, and fails
client-side with a message about an unsupported profile rather than anything from the API server;
the ephemeral-container list on app1 stays empty. If instead the profile is accepted and a
container appears, note it and carry that forward, because every later step's default changes with
it.
Step 2 works cleanly, which is the point of running it first. The file extracted from the page is
ten lines: two environment variables and a securityContext adding NET_ADMIN and SYS_TIME. The
debug container is created, and the two read-backs print
[{"name":"ENV_VAR_1","value":"value_1"},{"name":"ENV_VAR_2","value":"value_2"}] and
{"capabilities":{"add":["NET_ADMIN","SYS_TIME"]}}, matching debug-running-pod.md:806-818
exactly. That is the documentation's walkthrough reproducing itself at v1.35 with nothing changed.
Step 3 is the post's own case with a real image. The target Pod's own container carries
REQUIRED_ENV_VAR=value1; the ephemeral container carries value2. Two containers in one Pod,
sharing the same target namespaces, disagreeing about one variable — which is precisely the thing
:38-39 said there was no mechanism to achieve. It also runs without --profile, so whatever step
1 found the default to be is what this container was built from.
Step 4 fails. The post's JSON is accepted by kubectl — the client checks only its own five names —
and refused by the API server, which is where the error text comes from. Expect it to name
spec.ephemeralContainers[0].ports and spec.ephemeralContainers[0].resources and to say they are
not allowed, the sentences at pod-v1.md:1274 and :1286 in their enforced form. No ephemeral
container is added to app4. This is the exercise's centre: a worked example from a GA-track
announcement that the API has never accepted for the aspect the post was demonstrating.
Step 5 separates the three. only-env.json succeeds. only-ports.json and only-resources.json
both fail, and both errors come from the API server rather than from kubectl — read the prefix of
each message and note which component is speaking. Two fields out of three, and the one the post's
prose puts last is the only one that works. If a message instead mentions kubectl's own validation,
the client-side list has grown since the pin and the post's prediction at :90 came true late;
record which field.
Step 6 succeeds where step 4 failed, with the same file. app6-copy is a new Pod holding an
ordinary container, so containerPort: 80 and the CPU and memory limits and requests are all
present in the read-back. Nothing about the JSON changed; only what kubectl was asked to build from
it. Hold this beside step 4 and the Limitations paragraph at :94-95 reads backwards: the
container spec is not the largest intersection of the three aspects, it is two supersets and one
subset.
Step 7 succeeds as well, and the node-debugger Pod carries the port. That is the third of three:
rejected once, accepted twice, from one file. The grep for containerPort is a coarse instrument
on purpose — it will match the debug Pod and nothing else in the namespace at this point.
Step 8 prints nine results. The first five — name, image, command, lifecycle,
volumeDevices — are refused by kubectl with a message naming the field, which is the Constraints
section at :89 and the note at debug-running-pod.md:769 both holding. The last four —
workingDir, tty, imagePullPolicy, securityContext — are accepted, and app8 ends with four
ephemeral containers on it, one per success. Four accepted fields is the answer to the post's more
fields can be added to the disallowed list: two years on, none were.
Step 9 comes back empty, and the emptiness is the finding. kubectl debug --help says nothing about
gates, alpha, beta or any KUBECTL_ variable. kubectl options does print the --kuberc line with
its KUBECTL_KUBERC=false feature gate sentence, so the mechanism exists and is documented — for a
different feature. The recursive grep for KUBECTL_DEBUG across the whole checkout returns nothing,
and the feature-gates directory has no file matching debug, profile or kubectl. A post whose
title is Graduates to Beta has left no trace of the switch that beta was behind.
Step 10 is all reading. The static-profile section prints six rows and a note calling legacy the
default; the reference stanza three lines later prints Default: "general" and five options. The
legacy census returns two hits, both on the task page. The custom-profile section shows {{<
feature-state for_k8s_version="v1.32" state="stable" >}} with no gate name in it, and the note
beneath it with its five field names. The EphemeralContainer header paragraph gives the two
sentences that cannot both be comfortable — no resource guarantees, and the kubelet may evict the
Pod — and the grep beneath it returns seven rows of not allowed for ephemeral containers, of which
only lifecycle also appears in kubectl's list. Finally the --custom flag's own description, one
sentence, still correct.
Read on
-
The exercise on nine kubectl features and six fates — where
kubectl debugfirst appears in this archive, as the thing that arrived to fill a gap a 2015 post could not have named. -
The exercise on the security post the project marked partly obsolete — it owns
kubectl debug node/, which step 7 above borrows for one submission and gives back. -
The exercise on the in-place pod resize alpha — for why container resources are not an ordinary mutable field, and for the limitation list that already records ephemeral containers as excluded.
-
The exercise on the pod failure policy GA post — three days earlier in the same month, and the other half of the
feature-statestory: banners keyed to gate records that no longer exist, against this one's banner with no record behind it at all. -
Stage 2 of the webhook lab — the one place in the repo where
kubectl debug --targetis not an exercise aboutkubectl debugbut the only way into ascratchimage that has no shell.
Teardown