refactor(kubernetes): extract wait-for-kubeconfig init into shared helper

The three control-plane-side Deployments (cluster-autoscaler, kccm,
kcsi-controller) carried three copies of the same 20-line init
container. That already drifted: the CSI copy used 4-space nesting
while the other two used 2-space. Any future update to the image,
the deadline, or the poll script had to land in three places or
silently diverge.

Extract the block into a new kubernetes.waitForAdminKubeconfig helper
in templates/_helpers.tpl and include it at each call site. Tighten
the deadline from 20m to 10m so it stays strictly below the 15m
HelmRelease Install.Timeout and the CrashLoopBackOff surfaces in
dashboards before flux remediation can fire. Also clarify the wait
message so operators debugging a stuck init container do not chase
Kamaji for what is actually kubelet's optional-Secret refresh cadence.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
This commit is contained in:
Aleksei Sviridkin 2026-04-16 21:06:47 +03:00
parent b38ae60549
commit 1757567218
No known key found for this signature in database
GPG key ID: 7988329FDF395282
4 changed files with 43 additions and 60 deletions

View file

@ -49,3 +49,43 @@ Selector labels
app.kubernetes.io/name: {{ include "kubernetes.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
wait-for-kubeconfig init container shared by the control-plane-side
Deployments (cluster-autoscaler, kccm, kcsi-controller) that mount the
*-admin-kubeconfig Secret provisioned asynchronously by Kamaji. The
Secret volume is declared optional so kubelet does not FailedMount while
Kamaji is still bootstrapping; this container polls the mounted path and
exits only when super-admin.svc appears, which happens after kubelet's
optional-Secret refresh cycle.
The 10m deadline stays strictly below the 15m HelmRelease
Install.Timeout scoped to the Kubernetes Application kind so the
CrashLoopBackOff surfaces before flux remediation fires and uninstalls
the Cluster CR.
Call site owns the surrounding volumes block; the kubeconfig volume
must exist on the pod and mount at /etc/kubernetes/kubeconfig.
*/}}
{{- define "kubernetes.waitForAdminKubeconfig" -}}
- name: wait-for-kubeconfig
image: "{{ .Files.Get "images/busybox.tag" | trim }}"
command:
- sh
- -c
- |
set -eu
deadline=$(( $(date +%s) + 600 ))
until [ -s /etc/kubernetes/kubeconfig/super-admin.svc ]; do
if [ "$(date +%s)" -ge "$deadline" ]; then
echo "admin kubeconfig was not provisioned within 10m; exiting so the pod goes CrashLoopBackOff and surfaces in dashboards" >&2
exit 1
fi
echo "waiting for admin kubeconfig (provisioned by Kamaji, visible after kubelet Secret refresh)..."
sleep 5
done
volumeMounts:
- name: kubeconfig
mountPath: /etc/kubernetes/kubeconfig
readOnly: true
{{- end }}

View file

@ -24,26 +24,7 @@ spec:
operator: Exists
effect: "NoSchedule"
initContainers:
- name: wait-for-kubeconfig
image: "{{ $.Files.Get "images/busybox.tag" | trim }}"
command:
- sh
- -c
- |
set -eu
deadline=$(( $(date +%s) + 1200 ))
until [ -s /etc/kubernetes/kubeconfig/super-admin.svc ]; do
if [ "$(date +%s)" -ge "$deadline" ]; then
echo "admin kubeconfig was not provisioned within 20m; exiting so the pod goes CrashLoopBackOff and surfaces in dashboards" >&2
exit 1
fi
echo "waiting for admin kubeconfig to be provisioned by Kamaji..."
sleep 5
done
volumeMounts:
- name: kubeconfig
mountPath: /etc/kubernetes/kubeconfig
readOnly: true
{{- include "kubernetes.waitForAdminKubeconfig" $ | nindent 6 }}
containers:
- image: "{{ $.Files.Get "images/cluster-autoscaler.tag" | trim }}"
name: cluster-autoscaler

View file

@ -25,26 +25,7 @@ spec:
operator: Exists
effect: "NoSchedule"
initContainers:
- name: wait-for-kubeconfig
image: "{{ $.Files.Get "images/busybox.tag" | trim }}"
command:
- sh
- -c
- |
set -eu
deadline=$(( $(date +%s) + 1200 ))
until [ -s /etc/kubernetes/kubeconfig/super-admin.svc ]; do
if [ "$(date +%s)" -ge "$deadline" ]; then
echo "admin kubeconfig was not provisioned within 20m; exiting so the pod goes CrashLoopBackOff and surfaces in dashboards" >&2
exit 1
fi
echo "waiting for admin kubeconfig to be provisioned by Kamaji..."
sleep 5
done
volumeMounts:
- name: kubeconfig
mountPath: /etc/kubernetes/kubeconfig
readOnly: true
{{- include "kubernetes.waitForAdminKubeconfig" $ | nindent 6 }}
containers:
- name: csi-driver
imagePullPolicy: Always

View file

@ -23,26 +23,7 @@ spec:
operator: Exists
effect: "NoSchedule"
initContainers:
- name: wait-for-kubeconfig
image: "{{ $.Files.Get "images/busybox.tag" | trim }}"
command:
- sh
- -c
- |
set -eu
deadline=$(( $(date +%s) + 1200 ))
until [ -s /etc/kubernetes/kubeconfig/super-admin.svc ]; do
if [ "$(date +%s)" -ge "$deadline" ]; then
echo "admin kubeconfig was not provisioned within 20m; exiting so the pod goes CrashLoopBackOff and surfaces in dashboards" >&2
exit 1
fi
echo "waiting for admin kubeconfig to be provisioned by Kamaji..."
sleep 5
done
volumeMounts:
- name: kubeconfig
mountPath: /etc/kubernetes/kubeconfig
readOnly: true
{{- include "kubernetes.waitForAdminKubeconfig" $ | nindent 6 }}
containers:
- name: kubevirt-cloud-controller-manager
args: