CKS upgrade fails in air-gapped clusters when the new K8s version bumps the pause image (kubeadm upgrade health-check Job scheduled on worker without the image)

未關閉
#14,654 0 則留言 2 個 reaction 已指派 0 人 在 GitHub 檢視

維護者通常 1 天內回覆

還沒有人認領這個 Issue。

評估

難度
4/5
預估耗時
3-5 天
新手友好度
48/100
Issue 類型
缺陷
描述清晰度
描述清楚
活躍度
活躍
技術堆疊
bash, java, kubernetes

研究方向

Start with KubernetesClusterUpgradeWorker, upgradeKubernetesClusterNodes(), and upgrade-kubernetes.sh; trace how ISO images are imported and how the upgrade script’s output is handled. Reproduce the failure in an offline upgrade where the target pause image is missing on workers. Done means the health-check Job can run using images from the ISO and upgrade failures provide the script output in management-server.log.

由索引模型根據 Issue 內容生成。

描述

bug
problem

Since kubeadm runs a CreateJob health check during upgrade apply/upgrade plan,
it creates a Job upgrade-health-check-* in kube-system using the pause image of the
TARGET version (registry.k8s.io/pause:3.10.2 for 1.36.5).

CKS upgrades node 0 (control) first. The upgrade script imports ISO images only on the
node it runs on, so at this point the workers still only have pause:3.10.1.
The control node has also just been drained (cordoned), so the Job pod is scheduled on a
worker, tries to pull from registry.k8s.io, fails (air-gapped), the Job hits its deadline,
and kubeadm upgrade apply fails. The fallback retry only ignores
CoreDNSUnsupportedPlugins, so it fails again. The upgrade fails after all retries.

kubeadm-plan.log

versions
COMPONENT NAME

Kubernetes Service (CKS) – KubernetesClusterUpgradeWorker / upgrade-kubernetes.sh

CLOUDSTACK VERSION

4.23

ENVIRONMENT
  • Upgrade: v1.35.9 -> v1.36.5 (offline ISO, no internet on nodes)
  • containerd 1.7.12, 1 control + 2 workers, Cilium CNI
OS
  • Ubuntu 24.04
The steps to reproduce the bug
STEPS TO REPRODUCE
  1. Deploy an offline CKS cluster on a version whose pause tag differs from the target
    (1.35.x -> pause 3.10.1)
  2. Register the 1.36.5 ISO (contains pause 3.10.2) and upgrade the cluster
  3. kubectl -n kube-system get events | grep upgrade-health-check
EXPECTED RESULTS

Upgrade succeeds using only images from the ISO.

ACTUAL RESULTS

Failed to pull image "registry.k8s.io/pause:3.10.2": ... lookup registry.k8s.io ... i/o timeout
Job was active longer than specified deadline
(control node left cordoned, still v1.35.9; worker has only pause:3.10.1)
kubeadm upgrade plan v1.36.5 reproduces it (hangs on "Job ... is not yet complete").

LOGS

1. Health-check Job events (one full cycle, the same pattern repeated for 8 Jobs between 56m and 46m)

$ kubectl -n kube-system get events --sort-by=.lastTimestamp | grep -iE 'upgrade-health|pause|pull'
56m  Normal   SuccessfulCreate  job/upgrade-health-check-1794277494890       Created pod: upgrade-health-check-1794277494890-vbh5b
56m  Normal   Scheduled         pod/upgrade-health-check-1794277494890-vbh5b Successfully assigned kube-system/upgrade-health-check-1794277494890-vbh5b to k8s-upgrade-node-1a1c33de33f
56m  Warning  Failed            pod/upgrade-health-check-1794277494890-vbh5b Failed to pull image "registry.k8s.io/pause:3.10.2": failed to pull and unpack image "registry.k8s.io/pause:3.10.2": failed to resolve reference "registry.k8s.io/pause:3.10.2": failed to do request: Head "https://registry.k8s.io/v2/pause/manifests/3.10.2": dial tcp: lookup registry.k8s.io on 127.0.0.53:53: read udp 127.0.0.1:45086->127.0.0.53:53: i/o timeout
55m  Warning  Failed            pod/upgrade-health-check-1794277494890-vbh5b Error: ErrImagePull
55m  Normal   BackOff           pod/upgrade-health-check-1794277494890-vbh5b Back-off pulling image "registry.k8s.io/pause:3.10.2"
55m  Warning  Failed            pod/upgrade-health-check-1794277494890-vbh5b Error: ImagePullBackOff
55m  Normal   SuccessfulDelete  job/upgrade-health-check-1794277494890       Deleted pod: upgrade-health-check-1794277494890-vbh5b
55m  Warning  DeadlineExceeded  job/upgrade-health-check-1794277494890       Job was active longer than specified deadline

Jobs created: 1794277494890, 1794277555081, 1794277651281, 1794277711462,
1794277807947, 1794277868124, 1794277969440, 1794278029604. All were scheduled on the worker
k8s-upgrade-node-1a1c33de33f and all failed the same way. 8 Jobs = 4 script runs
(upgrade retries) x 2 kubeadm upgrade apply attempts per run.

2. Reproduce with kubeadm upgrade plan (control node)

$ kubeadm upgrade plan v1.36.5 --v=5
[upgrade] Running cluster health checks
I1110 03:21:49.429624 health.go:182] Creating a Job "upgrade-health-check-1794280909429" in the namespace "kube-system"
I1110 03:21:49.449846 health.go:210] Job "upgrade-health-check-1794280909429" in the namespace "kube-system" is not yet complete, retrying
... (repeats every 1s until deadline)

3. Image state: control has the image, worker does not

# control node (images imported from 1.36.5 ISO)
$ kubeadm config images list --kubernetes-version v1.36.5 | grep pause
registry.k8s.io/pause:3.10.2
$ crictl images | grep pause
registry.k8s.io/pause   3.10.1   cd073f4c5f6a8   320kB
registry.k8s.io/pause   3.10.2   4a83b15d3ecfe   321kB

# worker node (not yet upgraded)
$ crictl images | grep pause
registry.k8s.io/pause   3.10.1   cd073f4c5f6a8   320kB

4. Cluster state after failure

$ kubectl get node
NAME                              STATUS                     ROLES           AGE   VERSION
k8s-upgrade-control-1a1c33cc713   Ready,SchedulingDisabled   control-plane   57m   v1.35.9
k8s-upgrade-node-1a1c33d569a      Ready                      <none>          56m   v1.35.9
k8s-upgrade-node-1a1c33de33f      Ready                      <none>          56m   v1.35.9

kubeadm binary on control is already v1.36.5, but static pods and kubelet are still v1.35.9
(the script exits at kubeadm upgrade apply).
Environment: containerd 1.7.12, imageRepository: registry.k8s.io,
sandbox_image = "registry.k8s.io/pause:3.10.2" (control).

WORKAROUND

Export pause:3.10.2 from the control node, import it on all workers, then retry the upgrade.

What to do about it?
SUGGESTED FIX
  1. Pre-stage phase: after attachIsoKubernetesVMs, import ISO images on ALL cluster VMs
    before upgrading node 0 (e.g. split image import out of upgrade-kubernetes.sh into a
    separate script/flag run on every node first).
  2. Log result.second() (script stdout/stderr) on failure in
    upgradeKubernetesClusterNodes(). It is currently discarded, which makes the
    failure invisible in management-server.log.
  3. Minor: upgrade-kubernetes.sh checks $# -lt 4 but its usage text and the Java caller use 5 args;
    PAUSE_IMAGE selection via ctr images ls | grep pause | sort | tail -1 is fragile.
    Use kubeadm config images list | grep pause instead.
主要語言
Java
星號
3.1k
分支
1.4k
平均合併
7 天 16 小時
30 天內合併 PR
15

環境準備

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

apache/cloudstack 的其他 Issue

查看 apache/cloudstack 的全部 Issue

相似的 Issue

更多 Java Issue

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。