fix: ensure kubelet and containerd in kube.slice via systemd drop-ins#8958
fix: ensure kubelet and containerd in kube.slice via systemd drop-ins#8958titilambert wants to merge 11 commits into
Conversation
|
This change is part of the following stack: Change managed by git-spice. |
There was a problem hiding this comment.
Pull request overview
This PR updates the Linux CSE helper responsible for Node Memory Hardening cgroup hierarchy setup so that both kubelet and containerd are configured to run under kubelet.slice, and adjusts ShellSpec coverage accordingly.
Changes:
- Extend
ensureKubeletCgroupHierarchyto setSlice=kubelet.sliceforkubelet.serviceand add a matching drop-in forcontainerd.service. - Update ShellSpec assertions to validate the additional systemd drop-in content for containerd.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
parts/linux/cloud-init/artifacts/cse_helpers.sh |
Adds systemd drop-ins to place kubelet and containerd into kubelet.slice when hardening cgroups are enabled. |
spec/parts/linux/cloud-init/artifacts/cse_helpers_spec.sh |
Updates tests to assert Slice= and validates the containerd drop-in is created. |
39476df to
4045739
Compare
SriHarsha001
left a comment
There was a problem hiding this comment.
We need to look into the AI's comments, apart from that changes look good to me.
|
### AgentBaker Linux gate detective
Run: https://msazure.visualstudio.com/CloudNativeCompute/_build/results?buildId=172575900 Failed job/stage/task: e2e / Run AgentBaker E2E / Run AgentBaker E2E Detective summary: The primary terminal failure is the known Ubuntu2204 HTTPSProxy PrivateDNS E2E proxy flake. CSE failed before kubelet startup while apt refreshed packages.microsoft.com through the scenario proxy. Likely cause/signature: vmssCSE exited 99 after apt-get update to packages.microsoft.com via proxy 10.14.1.120:8888 returned connection refused. Wiki signature: e2e-httpsproxy-privatedns-err-outbound-conn-fail. Confidence: High for E2E infra/proxy availability; low that this PR caused the failure. Recommended owner/action: E2E/test-infra owner should track this under repair item #38837639 and harden proxy readiness/diagnostics for the HTTPSProxy PrivateDNS scenario. No PR action is expected from this signal. Strongest alternative: PR CSE/helper changes broke provisioning. Less likely because the concrete failure is TCP connection refused to the scenario proxy during apt-get update, before kubelet/containerd slice behavior was reached. Evidence:
|
…de hardening is on
4da0d05 to
939cc03
Compare
| tee "/etc/systemd/system/kubelet.service.d/10-containerd-base-flag.conf" > /dev/null <<EOF | ||
| [Service] | ||
| Environment="KUBELET_CONTAINERD_FLAGS=--runtime-request-timeout=15m --container-runtime-endpoint=unix:///run/containerd/containerd.sock --runtime-cgroups=${containerd_runtime_cgroups}" | ||
| EOF | ||
|
|
| // ValidateServiceInSlice asserts that the given systemd service is running in the expected slice. | ||
| func ValidateServiceInSlice(ctx context.Context, s *Scenario, service, expectedSlice string) { | ||
| s.T.Helper() | ||
| result := execScriptOnVMForScenarioValidateExitCode(ctx, s, | ||
| fmt.Sprintf("systemctl show %s -p Slice --value", service), 0, | ||
| fmt.Sprintf("could not query Slice property of %s", service)) | ||
| actual := strings.TrimSpace(result.stdout) | ||
| require.Equal(s.T, expectedSlice, actual, | ||
| "expected %s to be in %s, but got %s", service, expectedSlice, actual) | ||
| } |
AgentBaker Linux gate detectiveRun: https://msazure.visualstudio.com/CloudNativeCompute/_build/results?buildId=172680420 Failed job/stage/task: e2e / Run AgentBaker E2E / Go package compile Detective summary: The E2E gate failed before running any tests because the e2e package did not compile. Likely cause/signature: scenario_test.go references SkipScriptlessNBC in a Config literal, but Config does not define that field. Wiki signature: e2e-compile-config-unknown-field-skip-scriptless-nbc. Confidence: Very high that this is PR/test-code caused; infra was not reached. Recommended owner/action: PR author should fix the Config field definition or use the correct config struct/field and run an E2E compile check before retrying the gate. Strongest alternative: stale generated source or checkout mismatch. Less likely because the compiler points at the PR-touched scenario_test.go and zero tests ran. Evidence:
|
|
The latest Buf updates on your PR. Results from workflow Buf CI / buf (pull_request).
|
|
The latest Buf updates on your PR. Results from workflow Buf CI / buf (pull_request).
|
| # Validate supported values: only /kube.slice (or bare kube.slice) is | ||
| # supported for KUBE_RESERVED_CGROUP, and only /system.slice for | ||
| # SYSTEM_RESERVED_CGROUP (a built-in systemd slice). Reject any other value | ||
| # explicitly so kubelet doesn't fail later with an opaque enforcement error. | ||
| case "${KUBE_RESERVED_CGROUP:-}" in | ||
| ""|"/kubelet.slice"|"kubelet.slice") ;; | ||
| ""|"/kube.slice"|"kube.slice") ;; | ||
| *) | ||
| echo "ensureKubeletCgroupHierarchy: unsupported KUBE_RESERVED_CGROUP=${KUBE_RESERVED_CGROUP}; only /kubelet.slice is supported" | ||
| echo "ensureKubeletCgroupHierarchy: unsupported KUBE_RESERVED_CGROUP=${KUBE_RESERVED_CGROUP}; only /kube.slice is supported" | ||
| return 1 |
| }) | ||
| } | ||
|
|
||
| func Test_Ubuntu2204_NodeHardening_KubeletSlice(t *testing.T) { |
| # Validate supported values: only /kube-reserved.slice (or bare kube-reserved.slice) is | ||
| # supported for KUBE_RESERVED_CGROUP, and only /system.slice for | ||
| # SYSTEM_RESERVED_CGROUP (a built-in systemd slice). Reject any other value | ||
| # explicitly so kubelet doesn't fail later with an opaque enforcement error. | ||
| case "${KUBE_RESERVED_CGROUP:-}" in | ||
| ""|"/kubelet.slice"|"kubelet.slice") ;; | ||
| ""|"/kube-reserved.slice"|"kube-reserved.slice") ;; | ||
| *) | ||
| echo "ensureKubeletCgroupHierarchy: unsupported KUBE_RESERVED_CGROUP=${KUBE_RESERVED_CGROUP}; only /kubelet.slice is supported" | ||
| echo "ensureKubeletCgroupHierarchy: unsupported KUBE_RESERVED_CGROUP=${KUBE_RESERVED_CGROUP}; only /kube-reserved.slice is supported" | ||
| return 1 |
| tee "/etc/systemd/system/kubelet.service.d/10-containerd-base-flag.conf" > /dev/null <<EOF | ||
| [Service] | ||
| Environment="KUBELET_CONTAINERD_FLAGS=--runtime-request-timeout=15m --container-runtime-endpoint=unix:///run/containerd/containerd.sock --runtime-cgroups=${containerd_runtime_cgroups}" | ||
| EOF | ||
|
|
| }) | ||
| } | ||
|
|
||
| func Test_Ubuntu2204_NodeHardening_KubeletSlice(t *testing.T) { |
What this PR does / why we need it:
When node hardening is enabled,
ensureKubeletCgroupHierarchy()creates a dedicatedkubelet.slicefor kube-reserved cgroup enforcement. However the existing drop-in forkubelet.serviceonly declaredWants=andAfter=ordering — it did not setSlice=kubelet.slice, so kubelet remained insystem.slice. Additionally,containerd.servicehad no drop-in at all and was never placed in the slice.This PR fixes both issues:
Slice=kubelet.sliceto the kubelet drop-in so kubelet actually runs inside the dedicated slice.containerd.service(10-kubelet-slice.conf) so containerd is co-located in the same slice.Without this fix, cgroup resource accounting under
kubelet.sliceis incomplete — node hardening'skube-reservedbudget doesn't capture the real resource usage ofkubeletandcontainerd, which blocks nodes to be ready since they are affected tosystem.slicewhich has a low max memory limitTesting:
correct
[Service] Slice=kubelet.slicedirective.Which issue(s) this PR fixes:
Fixes #