diff --git a/modules/create-template-vm/cloud_init.yaml b/modules/create-template-vm/cloud_init.yaml index 1dc683f6..751b04ec 100644 --- a/modules/create-template-vm/cloud_init.yaml +++ b/modules/create-template-vm/cloud_init.yaml @@ -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 diff --git a/stacks/infra/main.tf b/stacks/infra/main.tf index d78f86de..fabca8bd 100644 --- a/stacks/infra/main.tf +++ b/stacks/infra/main.tf @@ -64,8 +64,12 @@ module "k8s-node-template" { snippet_name = local.k8s_cloud_init_snippet_name # Add mirror registry containerd_config_update_command = <<-EOF - # Set up config_path for per-registry mirror configuration - sed -i 's|config_path = ""|config_path = "/etc/containerd/certs.d"|' /etc/containerd/config.toml + # Set up config_path for per-registry mirror configuration. + # NOTE: containerd v2 writes `config_path = ''` (single quotes) on + # `config default`; v1 writes `config_path = ""`. Match both forms so this + # is idempotent across versions. Without the v2 match, hosts.toml mirror + # config is silently ignored — observed 2026-05-26 on node4 (containerd v2.2.4). + sed -i 's|config_path = .*|config_path = "/etc/containerd/certs.d"|' /etc/containerd/config.toml # Create hosts.toml for docker.io (Docker Hub) — high traffic, rate-limited mkdir -p /etc/containerd/certs.d/docker.io