cloud-init: fix k8s node bootstrap snippet (multi-line interp + containerd v2 quotes)

Two bugs found while rebuilding k8s-node4 (2026-05-26):

1. **runcmd YAML breakage**: `- $${containerd_config_update_command}`
   interpolated a multi-line heredoc as bare list-item content. The
   trailing lines lost their list-item prefix, breaking cloud-config
   parsing. Cloud-init silently fell back to the minimal default
   (hostname + package_upgrade only) — kubeadm join, containerd config,
   kubelet tuning, iSCSI hardening, swap, ALL skipped. No error visible
   in `cloud-init status`.

   Fix: wrap the interpolation in `- |` literal block with `indent(4, ...)`.

2. **containerd v2 single-quote mismatch**: `containerd config default`
   in v2 writes `config_path = ''` (single quotes), v1 writes `""` (double).
   The sed pattern matched only double quotes → silent no-op on fresh
   containerd 2.x nodes → registry-mirror hosts.toml ignored → all image
   pulls hit upstream registries → DNS-to-MetalLB chicken-and-egg loop.

   Fix: match any value with `config_path = .*`.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Viktor Barzin 2026-05-26 07:06:50 +00:00
parent 445feb118f
commit 9b75b2817b
2 changed files with 12 additions and 3 deletions

View file

@ -107,7 +107,12 @@ runcmd:
- apt-mark hold containerd containerd.io runc 2>/dev/null || true
- systemctl stop kubelet
- containerd config default | sudo tee /etc/containerd/config.toml
- ${containerd_config_update_command}
# Multi-line containerd config update — wrapped in `- |` literal block so the
# heredoc content survives YAML rendering. Without this, the multi-line var
# gets inserted as bare top-level lines and breaks the cloud-config parser
# (silent fallback to default — observed 2026-05-26 during node4 rebuild).
- |
${indent(4, containerd_config_update_command)}
- systemctl restart containerd
- systemctl enable --now iscsid
# Harden iSCSI: increase recovery timeout (300s vs 120s default) and enable