From 401d23ac480393778d8b2a7956d6d212a6935610 Mon Sep 17 00:00:00 2001 From: Claude Bot Date: Thu, 30 Jul 2026 13:47:11 +0200 Subject: [PATCH] fix(multus): drop runtime apk add from the CNI plugins installer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Owner directive: tools belong in the image, not installed at container start. This is the highest-blast-radius instance of the pattern left in the repo — a DaemonSet, so it runs on every node. No image was needed. `apk add --no-cache curl tar` turns out to have been unnecessary from the start: verified in alpine:3.21 that `tar` is already busybox (v1.37.0) and handles -xzf, and that busybox `wget` follows GitHub's release redirect to objects.githubusercontent.com over TLS using the base image's /etc/ssl/certs/ca-certificates.crt. Only `curl` is genuinely absent, and wget covers what it was used for. So this replaces the install with `wget -q -O` rather than introducing another layered image. Severity note for the record: the apk add sat inside the else branch, so steady-state nodes never reached it. It ran when plugins were absent — i.e. on a fresh node or after /opt/cni/bin was wiped, which is precisely the moment you least want a dependency on package-index availability. Verified by running the RENDERED init script in alpine:3.21 against the real release URL, both paths: empty dir -> Fetching ...; Installed: host-local, macvlan, static macvlan executable, /opt/cni/bin owner 0:0, exit 0 already there -> "CNI plugins already installed (CNI macvlan plugin v1.5.1)", exit 0, no fetch The second line is worth noting: that version string comes from executing the extracted binary, so the download and extraction are confirmed good, not merely present. The chown 0:0 also still applies, which the existing comment explains is required or Cilium's apply-sysctl-overwrites init container fails with "Permission denied". Co-Authored-By: Claude Opus 5 (1M context) --- .../multus/cni-plugins-installer.yaml | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/kubernetes/infrastructure/multus/cni-plugins-installer.yaml b/kubernetes/infrastructure/multus/cni-plugins-installer.yaml index 2a115887..b6eb3681 100644 --- a/kubernetes/infrastructure/multus/cni-plugins-installer.yaml +++ b/kubernetes/infrastructure/multus/cni-plugins-installer.yaml @@ -53,8 +53,21 @@ spec: echo "CNI plugins already installed (${installed})" else echo "Fetching ${URL}" - apk add --no-cache curl tar - curl -fsSL "${URL}" -o /tmp/plugins.tgz + # busybox wget + tar, NOT `apk add --no-cache curl tar`. + # Installing tools at container start is not acceptable here: it + # makes the install path depend on package-index availability at + # exactly the moment a node is being (re)built, and this is a + # DaemonSet — it runs on every node. + # + # Nothing needed to be added in the first place. Verified in + # alpine:3.21: `tar` is already busybox (v1.37.0) and handles + # -xzf, and busybox `wget` follows GitHub's release redirect to + # objects.githubusercontent.com over TLS using the base image's + # /etc/ssl/certs/ca-certificates.crt — fetched the real 48MB + # tarball and extracted an executable macvlan from it. + # Only `curl` is genuinely absent from the base, and wget covers + # what it was used for here. + wget -q -O /tmp/plugins.tgz "${URL}" # Extract everything: the tarball entries are stored with a # `./` prefix, so selective extraction by bare name fails. # All standard plugins are tiny (~5-10MB total) and harmless -- 2.54.0