目录
2026-09-11。三台节点 k8s-10-1-16-21(10.1.16.21)、k8s-10-1-16-22、k8s-10-1-16-23。GitLab Operator chart 10.3.2,升到 19.3.2。gitlab-toolbox / gitlab-migrations 长时间 PodInitializing,主容器一直 Pulling,既没有 Pulled 也没有 Failed。当时看起来像 Harbor 下不动大层。下面按当天怎么查的写;命令和数字可以原样复现。节点 PATH 带 /opt/kube/bin。SSH:ssh root@10.1.16.21、22、23。
目录
- 现象
- 时间线
- 先别用 docker pull 当证据
- 这张镜像在 Harbor 里什么样
- Harbor 这一层能不能下完
- 节点:对端不是 Harbor,ingest 卡在这一层
- 根因
- 处理
- 验证
- 防再发
- 附录:排查链路和最短路径
- 附录:amd64 30 层
现象
当时:
gitlab-migrations-a3aba68-e90-9-pre-96skt PodInitializing k8s-10-1-16-21gitlab-toolbox-76f597b7f6-bmvmm PodInitializing k8s-10-1-16-22gitlab-migrations-f354d9f-e90-7-dbpxk Completed k8s-10-1-16-21kubectl -n gitlab get pods,jobs -o wide | grep -E 'toolbox|migrat'kubectl -n gitlab get events --sort-by=.lastTimestamp \ | grep -iE 'toolbox-ce|Pulling|Pulled|Failed|ErrImage'kubectl -n gitlab describe pod <卡着的 pod> | tail -40describe:init 的 certificates / gitlab-base 已经 already present,主容器:
Pulling image "harbor.cyxc.club/gitlab/gitlab-org/build/cng/gitlab-toolbox-ce:v19.3.2"十几分钟既没有 Pulled 也没有 Failed。kubelet 卡在一次 CRI pull 上。journalctl -u kubelet --since "30 min ago" 几乎没有 Pulling,以 events / describe 为准。
事件里同时有两个仓库(已删除的 Pod 只出现在 events):
Pulling image "registry.gitlab.com/gitlab-org/build/cng/gitlab-toolbox-ce:v19.3.2"Pulling image "harbor.cyxc.club/gitlab/gitlab-org/build/cng/gitlab-toolbox-ce:v19.3.2"| 对象 | 镜像 | 节点 |
|---|---|---|
Job gitlab-migrations-300ebb3-e90-8-pre Pod …-clqgl |
GitLab.com v19.3.2 | 16.21 |
同一 Job Pod …-qm644 |
GitLab.com v19.3.2 | 16.22 |
gitlab-migrations-a3aba68-e90-9-pre |
Harbor v19.3.2 | 16.21 |
gitlab-toolbox-76f597b7f6-bmvmm |
Harbor v19.3.2 | 16.22 |
gitlab-migrations-f354d9f-e90-7 Completed |
GitLab.com v19.3.0 | 16.21 |
300ebb3 在 21、22 各有一个 Pod。已删除的对象只出现在 events 里,只看当前 Pod 会漏掉 GitLab.com 那一行。
时间线(CST,UTC+8)
| 时间 | 发生了什么 |
|---|---|
| 21:08–21:45 | 从 Harbor 预拉一遍 19.3.2 CNG(urllib 走 /v2/)。toolbox:31 层、1032.5 MiB、169.9s,amd64 digest sha256:4cc3659714b1…。脚本 13:08:02–13:45:25 UTC,结束码 0 |
| 21:46:15 | Job gitlab-migrations-300ebb3-e90-8-pre 创建(2026-09-11 13:46:15 UTC,UID e77696f3-a9bc-4cde-85b4-194d7fea165f),镜像 registry.gitlab.com/.../gitlab-toolbox-ce:v19.3.2 |
| 21:46:16 | ReplicaSet gitlab-toolbox-76f597b7f6 创建(13:46:16Z,rev 4),镜像已是 Harbor …/gitlab-toolbox-ce:v19.3.2 |
| 21:46 | 16.22 ingest 开始,ref 已是 layer-sha256:bf390218420b…(与 Job 创建同一分钟) |
| 22:00:35 | 16.21 同一层 ingest 开始 |
| ~22:07 | Job gitlab-migrations-a3aba68-e90-9-pre 在拉 Harbor(values 哈希 e90-8 → e90-9;Successfully pulled 14:22:57Z,含等待 16m19s,倒推拉取约 14:06:38Z) |
| 22:14 | 有人问 Harbor 上这张镜像能不能拉 |
| ~22:15 | 16.23 上 crictl pull Harbor 成功(本机,不是 21/22) |
| 22:17 | 指出 bf390218420b 这层会卡住 download |
| 22:18 | 16.21 timeout 60 crictl pull 失败;ss 里 containerd 钉在 34.149.22.116:443 |
| 22:20 | 16.21 ingest data ≈ 366 MiB / 733 MiB;16.22 ≈ 445 MiB。Recv-Q/Send-Q 都是 0 |
| 22:22 | 21、22 上 ss -K dst 34.149.22.116 dport 443(没带 sport)。300ebb3 两 Pod ErrImagePull / connection abort(14:21:58Z / 14:22:00Z) |
| 22:23 | crictl pull Harbor:Image is up to date。a3aba68-e90-9-pre、toolbox 变成 Running |
| 22:24 | a3aba68-e90-9-pre Job completed(14:24:11Z) |
| 22:27:06 | post-migrations Job gitlab-migrations-a3aba68-e90-9 创建(14:27:06Z),22:28:32 完成 |
| 22:31 | GitLab CR generation=9,Initialized / Available(14:31:18Z / 14:31:19Z) |
预拉脚本 toolbox 那一行:
==> harbor.cyxc.club/gitlab/gitlab-org/build/cng/gitlab-toolbox-ce:v19.3.2 index 685B -> amd64 sha256:4cc3659714b1... OK layers=31 blobs=1032.5MiB 169.9s预拉 21:45 结束,toolbox 的 blob 已经在 Harbor 里。21:46 起节点仍在 Pulling。
先别用 docker pull 当证据
本机(当时是 16.23)docker pull harbor.cyxc.club/gitlab/gitlab-org/build/cng/gitlab-toolbox-ce:v19.3.2 立刻失败:
Error response from daemon: Get "https://harbor.cyxc.club/v2/": EOFdocker manifest inspect 却能返回清单。Docker daemon 配了:
HTTP Proxy: http://10.1.10.11:7890HTTPS Proxy: http://10.1.10.11:7890No Proxy: localhost,127.0.0.1,easzlab.io.local,10.0.0.0/8,10.1.0.0/16,.localNO_PROXY 没有 .cyxc.club。harbor.cyxc.club 解析到 10.1.10.3,但 daemon 仍把 HTTPS 送进代理,/v2/ 直接 EOF。~/.docker/config.json 的 auths 里只有 ghcr.io、registry.cyxc.club、registry.gitlab.cyxc.club,没有 Harbor;这次也不需要登录。
节点排查用 curl / crictl。K8s 的 containerd 不走这条 Docker 代理。TLS 正常:证书 CN harbor.cyxc.club,Let’s Encrypt YR1,2026-08-23 到 2026-11-21。
匿名探测 Harbor:
curl -sS -o /dev/null -w 'http:%{http_code}\n' https://harbor.cyxc.club/v2/# 401,WWW-Authenticate: Bearer realm="https://harbor.cyxc.club/service/token",service="harbor-registry"项目 gitlab 是 public,token 接口匿名就能发 pull token(这次 token 长度 786)。不要把 401 当成镜像不存在。
curl -sS 'https://harbor.cyxc.club/service/token?service=harbor-registry&scope=repository:gitlab/gitlab-org/build/cng/gitlab-toolbox-ce:pull'这张镜像在 Harbor 里什么样
清单是 fat manifest:linux/arm64 + linux/amd64。
| 项 | 值 |
|---|---|
| 镜像 | harbor.cyxc.club/gitlab/gitlab-org/build/cng/gitlab-toolbox-ce:v19.3.2 |
| 清单 digest | sha256:37a75ea1cf23a17b6fb3c60dbc1409caaf466e5664565b53cf95f08495ca27fc |
| arm64 manifest | sha256:367032bf84a6e063e0076d797990054a3527ad5d96ff973ae120fe560f3dadff size 6217 |
| amd64 manifest | sha256:4cc3659714b133908f024617cac3a32288ce5d7a83e87f443e75d6cb2ce59ca0 size 6217 |
| amd64 config | sha256:de9db0f2559c3ccfa4690b2ca4bea58ab76a6cfaf5516766b3ed9c58be43709a size 11775 |
| amd64 层数 | 30(加上 config 预拉脚本数成 31) |
| 层压缩合计 | 1082618030 B(1032.5 MiB) |
| 落地 | crictl images:de9db0f2559c3,约 1.08GB |
| Harbor 制品 | sha256:80cb989de853ac27ec9940dbc70259ad8ac687471a1c8c18b06f40b1199b41ef size 1082636456(制品元数据);events 里 Image size: 1082636707;层压缩合计 1082618030。三个数口径不同,差的是 config/元数据,不是下错了 |
docker manifest inspect / 带 token 的 GET /manifests/v19.3.2 都能拿到这份 list。
Harbor 项目 gitlab:project_id=7,registry_id=5,public=true,repo_count=16。上游 registry id=5 name=gitlab url=https://registry.gitlab.com status=healthy。这只说明层可以从 GitLab.com 进仓。Ingress 把 /v2/ 指到 harbor-core,不是 registry Pod;registry 的 S3 配了 disableredirect: true,blob 不会 307 到 RGW。这些和「节点连 34.149」不是同一条路径。
卡住的层是 amd64 第 18 条(下标 17),比其它层大一个数量级:
sha256:bf390218420b5dcdeed2d425c9594b46bc91e2885f6beca227fb9147b55a2887 768735388完整 30 层见文末附录。HEAD 第一层和最后一层都是 200,Accept-Ranges: bytes。Range bytes=0-1048575 和 bytes=536870912-537919487(512 MiB 附近)都是 206,RGW 对象没有在半截挖空。
16.23 上 ctr -n k8s.io images pull 17.9s 下完约 1005.6 MiB(56.2 MiB/s),随后 unpacking linux/amd64 sha256:37a75ea1…,被 timeout 30 打断。接着 crictl pull 成功:
Image is up to date for sha256:de9db0f2559c3ccfa4690b2ca4bea58ab76a6cfaf5516766b3ed9c58be43709aharbor.cyxc.club/gitlab/gitlab-org/build/cng/gitlab-toolbox-ce v19.3.2 de9db0f2559c3 1.08GB必须用 crictl 或 ctr -n k8s.io。ctr 默认 namespace kubelet 看不见。这就是「16.23 对照」的来源:本机先从 Harbor 拉完,不是这台节点天生没事。
Harbor 这一层能不能下完
在能解析 harbor.cyxc.club 的机器上跑,卡住节点上也跑一遍。getent hosts harbor.cyxc.club 必须是 10.1.10.3。
TOKEN=$(python3 -c 'import json,urllib.request;print(json.load(urllib.request.urlopen( "https://harbor.cyxc.club/service/token?service=harbor-registry&scope=repository:gitlab/gitlab-org/build/cng/gitlab-toolbox-ce:pull"))["token"])')DIGEST=sha256:bf390218420b5dcdeed2d425c9594b46bc91e2885f6beca227fb9147b55a2887URL=https://harbor.cyxc.club/v2/gitlab/gitlab-org/build/cng/gitlab-toolbox-ce/blobs/$DIGEST
# 必须 --max-redirs 0,才能看见有没有 307curl -sS -D - -o /dev/null --max-redirs 0 -H "Authorization: Bearer $TOKEN" "$URL" | head -20
curl -sS --http1.1 -r 0-16777215 \ -w 'code=%{http_code} size=%{size_download} speed=%{speed_download} time=%{time_total} url=%{url_effective}\n' \ -o /dev/null -H "Authorization: Bearer $TOKEN" "$URL"
# 整层 HTTP/2 / HTTP/1.1curl -sS --http2 -w 'http=%{http_code} ver=%{http_version} size=%{size_download} speed=%{speed_download} time=%{time_total}\n' \ -o /dev/null -H "Authorization: Bearer $TOKEN" "$URL"curl -sS --http1.1 -w 'http=%{http_code} ver=%{http_version} size=%{size_download} speed=%{speed_download} time=%{time_total}\n' \ -o /dev/null -H "Authorization: Bearer $TOKEN" "$URL"没有 python3 时,token 用前面的 curl 打 /service/token。urllib 默认会 follow 307,要用 --max-redirs 0 或自己关 redirect。
| 探测 | 结果 |
|---|---|
| HEAD / GET 不跟随 | 200,无 Location,Content-Length: 768735388,Accept-Ranges: bytes |
| 16.21 抽 16 MiB | 206,0.535s,约 31.4 MiB/s,url_effective 仍是 Harbor |
| urllib HTTP/1.1 整层 | 768735388 B,9.5s,77.53 MiB/s |
| curl HTTP/2 整层 | 9.026s,约 81.2 MiB/s |
| curl HTTP/1.1 整层 | 8.887s,约 82.5 MiB/s |
Traefik readTimeout/writeTimeout |
已是 600s,不是默认 60s |
| Harbor 结果 | 含义 |
|---|---|
200/206,URL 仍是 harbor.cyxc.club,至少十几 MiB/s |
仓、Traefik、RGW、HTTP/2 都排除 |
307 + Location: registry.gitlab.com |
才是 proxy cache 回源(这次不是) |
| 超时 / EOF / 极慢 | 才查 Traefik / registry / RGW(这次不是) |
Harbor core 当时有:
Artifact: gitlab/gitlab-org/build/cng/gitlab-toolbox-ce:, digest:sha256:367032bf… is not found in proxy cache, fetch it from remote repo那是 arm64 manifest,和 bf390218420b 无关。registry 还有 blob unknown sha256:9c1e19b054454ab3f04fd08b8f9fa7cdd69d83f4e46908c4c4ea7e24edeee515,也不是这层。不要把 proxy cache 日志绑到卡住的 digest 上。
节点:对端不是 Harbor,ingest 卡在这一层
三台都看。ss 里 Process 必须是 containerd,节点上还有 kube-apiserver、speaker 等 443,不要看错。
export PATH=/opt/kube/bin:$PATHgetent hosts harbor.cyxc.club # 必须是 10.1.10.3ss -tnp | grep containerd | grep -E '443|10.1.10.3|34.149'# 挂死时 ESTAB,Recv-Q/Send-Q 往往都是 0# 对端 IP 下次可能不是 34.149:凡是 containerd 的 443 且不是 10.1.10.3,都反查# getent hosts <对端IP># getent hosts registry.gitlab.com
ING=/var/lib/containerd/io.containerd.content.v1.content/ingestls -la "$ING"for d in "$ING"/*; do [ -d "$d" ] || continue echo "==== $(basename "$d") ====" echo -n "ref="; cat "$d/ref"; echo echo -n "total="; cat "$d/total"; echo echo -n "startedat="; cat "$d/startedat"; echo echo -n "updatedat="; cat "$d/updatedat"; echo stat -c "data=%s mtime=%y" "$d/data"donels -l /proc/$(pidof containerd)/fd | grep ingest || truecrictl images | grep toolbox这次 ingest 目录名两边一样:b69bb7584d7ceeec51b9f1acf557c7cc62bbec595d676035a7a9c570b1f558d7(按 ref/digest 派生,不是随机到无法对照)。
ref=k8s.io/1/layer-sha256:bf390218420b5dcdeed2d425c9594b46bc91e2885f6beca227fb9147b55a2887total=768735388| 节点 | ss |
ingest | data / total |
|---|---|---|---|
| 16.21 | 10.1.16.21:51968 → 34.149.22.116:443,containerd pid 3712737 fd 1343;ingest data 的 fd 也开着 |
上述 ref | 383778816 B(366 MiB)/ 733 MiB,startedat=2026-09-11T22:00:35+08:00,下了 20+ 分钟 |
| 16.22 | :57916 → 34.149.22.116:443,containerd pid 723673 fd 1357 |
同一 digest | 466616320 B(445 MiB);ingest 约 21:46 开始 |
| 16.23 | 无此连接 | 空 | 已有 Harbor v19.3.2 de9db0f2559c3 |
34.149.22.116 反查 116.22.149.34.bc.googleusercontent.com,GitLab GCP。下次 GitLab.com 可能换 IP,不要把 34.149 写成永恒特征。
过 15 秒再 stat 一次 data。几乎不涨或只有几百 KB/s = 挂死(20 分钟下 366 MiB ≈ 0.3 MB/s)。Harbor 本地下完这层大约 10 秒。updatedat 这次从一开始就等于 startedat,不要用它判断是否在下,看 data 的 size / mtime。
不要 rm -rf ingest/...:containerd 还开着 data 的 fd,删目录只会更脏。
16.21 的 containerd:max_concurrent_downloads = 3。registry.mirrors 覆盖了 registry.k8s.io、docker.io、gcr.io、quay.io、ghcr.io 等,没有 harbor.cyxc.club,也没有把 Harbor 指到 GitLab。不是 mirror 把拉取拐走。
判定四条同时成立,就是这次这个问题:
- Harbor 对该 blob
200、快、没有 307 - 这台节点 ingest
ref是layer-sha256:bf390218420b…(别的节点有镜像不能代替) - TCP 对端不是
10.1.10.3,反查是 GitLab/GCP - 旧 Job 的 image 字段 是
registry.gitlab.com/...,新 Pod 是 Harbor,同一 tag / 同一层 digest
不是这次的分支:
- ingest 对端已经是
10.1.10.3仍不涨 → 查 Harbor / RGW,不要掐 GitLab - 没有 ingest、镜像也没有 → kubelet 还没开始拉,或 CRI 挂了
- 只有 Harbor 在 Pulling、events 和活对象里都没有
registry.gitlab.com→ 另查(包括 Harbor307) - Harbor
curl也慢或 307 → 不要走节点ss -K
根因
Harbor 对 bf390218420b 能 200、大约 80 MiB/s 出层,没有 307。卡住的是节点上的 containerd:按 digest 存层,不按仓库名。同一层 digest 的 ingest 锁在每个节点自己的 content store里。旧 Job 先从 registry.gitlab.com 半截下载占住之后,同一节点上 Harbor 的拉取只能等。16.23 没有这条 GitLab.com ingest,所以能从 Harbor 拉完。不是全集群一把锁。
节点连 34.149.22.116:443,是因为 kubelet 的镜像引用就是 registry.gitlab.com/...,不是 Harbor proxy cache 把 GET 307 出去。项目 gitlab 作为 registry.gitlab.com 的 proxy cache,只负责层可以进仓。
Job 300ebb3 是哪一次写出来的
不是「CR 早就改成 Harbor、残留了一个很久以前的 Job」。它和 Harbor 的 toolbox ReplicaSet 是同一秒写出来的:
| 对象 | 创建时间 | 镜像 |
|---|---|---|
Job gitlab-migrations-300ebb3-e90-8-pre,UID e77696f3-a9bc-4cde-85b4-194d7fea165f |
2026-09-11 13:46:15 UTC(21:46:15 CST) |
registry.gitlab.com/gitlab-org/build/cng/gitlab-toolbox-ce:v19.3.2 |
ReplicaSet gitlab-toolbox-76f597b7f6(rev 4) |
13:46:16Z(21:46:16) |
Harbor …/gitlab-toolbox-ce:v19.3.2 |
values 哈希 e90-8 写进 Job 名。大约 20 分钟后变成 e90-9,operator 另建 Job gitlab-migrations-a3aba68-e90-9-pre(Harbor),不会改已经存在的 300ebb3。Job 规格不可变:300ebb3 按 13:46:15 写入的 image 一直重试。Pod …-clqgl 在 16.21、…-qm644 在 16.22,所以两台都卡住。
活着的 CR 后来已经是 Harbor;generation=9 到 14:31:18Z / 14:31:19Z 才 Initialized / Available。查当时写了什么:
kubectl -n gitlab get gitlab gitlab \ -o jsonpath='{.spec.chart.values.global.image.registry}{"\n"}'kubectl -n gitlab get gitlab gitlab \ -o jsonpath='{.spec.chart.values.gitlab.migrations.image.repository}{"\n"}{.spec.chart.values.gitlab.toolbox.image.repository}{"\n"}'kubectl -n gitlab get pods,jobs,deploy -o json \ | grep -oE 'image": "[^"]*toolbox-ce[^"]*"'global.image.registry=harbor.cyxc.club/gitlab 不够。CNG Chart 的 repository 自带 registry.gitlab.com,只改 registry 前缀不会改掉已经写死的主机名。每个组件都要写完整 Harbor repository。见 gitlab.yaml 注释。
更早的 Job f354d9f(e90-7)已经是 GitLab.com 的 v19.3.0,说明升级前节点本来就会直连 GitLab.com。16.21 本地还留着 registry.gitlab.com/.../gitlab-toolbox-ce:v19.3.0(bc501b784b671,1.08GB),16.22 有 Harbor 的 v19.3.0。那是上一版,digest 不是 bf390218420b。
CNG 层会共享,不限 toolbox:任何还在拉 registry.gitlab.com/gitlab-org/build/cng/... 的对象,都可能在所在节点锁住同一 digest。
处理
更稳妥:先删还在拉 GitLab.com 的 Job,再掐连接。否则 ImagePullBackOff 会立刻再连 GitLab,该节点同一 digest 又被占住。operator 可能把 Job 再建出来,删完再扫一遍。
当天实操是先 ss -K、没先删 Job。GitLab.com 拉取变成 connection abort,Job 随后自己没了。
kubectl -n gitlab get pods,jobs -o wide | grep -E '300ebb3|toolbox-ce'kubectl -n gitlab get pods,jobs -o json | grep -F registry.gitlab.comkubectl -n gitlab delete job gitlab-migrations-300ebb3-e90-8-pre --ignore-not-foundkubectl -n gitlab get pods,jobs -o json | grep -F registry.gitlab.com然后每个卡住节点各掐一次,用该节点自己的 sport。不要整段 dst <gitlab-ip>,以免误杀同 IP 上其它 Google 连接。
当天用的是不带 sport 的:
ss -K dst 34.149.22.116 dport 44321、22 各一次,能解开,但更粗。更稳:
ss -tnp | grep containerd | grep 34.149.22.116# 这次 16.21 sport=51968,16.22 sport=57916ss -K dst 34.149.22.116 dport 443 sport 51968预期:
- ingest 消失,或
data不再涨 - events:
read tcp 10.1.16.21:51968->34.149.22.116:443: read: software caused connection abort(22 同理,sport57916) - containerd 改连
10.1.10.3:443
掐完后立刻看:16.21 ingest 已空,containerd 连着 10.1.10.3:443;16.22 仍有同一 ingest,但对端已经是 Harbor,data 涨到 613293248(585 MiB)。再过几十秒两边 ingest 都空了,可是 crictl images 还没列出 v19.3.2——kubelet 仍停在旧的 Pulling RPC 上。两台都补:
crictl pull harbor.cyxc.club/gitlab/gitlab-org/build/cng/gitlab-toolbox-ce:v19.3.216.21 22:22:59 开始,2 秒后 Image is up to date;16.22 约 12 秒。后台其实已经拉完。
ss -K 后 ingest 仍不放、containerd 无响应,再重启 containerd。控制面代价大,也去不掉根:GitLab.com 的 Job 还在,起来后可能再占 digest。
掐连接时其它 Pod 可能一次性 ErrImagePull。这次 gitlab-toolbox-76f597b7f6-9mwdz:
Get "https://harbor.cyxc.club/v2/.../blobs/sha256:bf390218420b…": net/http: TLS handshake timeout随后 Harbor 拉取应是 Successfully pulled / already present,不要当成仓坏了。
验证
crictl images | grep gitlab-toolbox-ce# harbor.cyxc.club ... v19.3.2 de9db0f2559c3 1.08GB
ls /var/lib/containerd/io.containerd.content.v1.content/ingest # 空ss -tnp | grep containerd | grep 34.149 # 无kubectl -n gitlab get pods | grep -E 'toolbox|migrat' # Running / Completedevents:
Successfully pulled image "harbor.cyxc.club/.../gitlab-toolbox-ce:v19.3.2" in 16m19.616s (16m19.616s including waiting). Image size: 1082636707 bytes.Successfully pulled image "...toolbox-ce:v19.3.2" in 22m31.002s (22m31.002s including waiting). Image size: 1082636707 bytes.等待时间几乎全是 GitLab 那条连接。镜像本身从 Harbor 下只要十几秒。migrations / toolbox 从 PodInitializing 变成 1/1 Running。
防再发
kubectl -n gitlab get events --sort-by=.lastTimestamp | grep -F registry.gitlab.comkubectl -n gitlab get pods,jobs,deploy,sts -o json | grep -F registry.gitlab.com活对象应全部是 Harbor。看到 GitLab.com 的 CNG 就删对应 Job,并确认 operator 没有立刻重建。gitlab.yaml 里每个组件都要写完整 Harbor 路径,toolbox / migrations 现在是:
harbor.cyxc.club/gitlab/gitlab-org/build/cng/gitlab-toolbox-ce附录:排查链路和最短路径
现象:toolbox / migrations 长时间 PodInitializing,events 只有 Pulling │ ├─ 1. 拉的是哪个仓库? events / describe / Pod .image │ 两个仓库同时 Pulling 同一 tag → 可能抢 digest(按节点) │ ├─ 2. Harbor 这层还能不能出? curl blob,禁止 follow 307 │ 200 且快 → 仓、Traefik、RGW、HTTP/2 都排除 │ 307 到 gitlab.com → 才是 proxy cache 回源 │ 超时/EOF → 才查 Traefik / registry / RGW │ ├─ 3. 节点在跟谁传、卡哪一层? ss + ingest/ref + ingest/data │ 对端不是 10.1.10.3 + ref=bf390218420b + data 几乎不涨 │ → 这台节点上的半截 GitLab 下载 │ 对端已是 10.1.10.3 仍不涨 → 才回头查 Harbor │ ├─ 4. 为何会去 GitLab.com? 旧 Job 的 image 字段和创建时间,不是 ss 猜的 │ 300ebb3 13:46:15Z = registry.gitlab.com;1 秒后 toolbox RS = Harbor │ 同一层 digest → 这台节点 ingest 一把锁 │ └─ 5. 处理并验证 先删 GitLab.com Job,再 ss -K,再 crictl pull查过但排除:
| 查了什么 | 结果 | 排除 |
|---|---|---|
本机 docker pull |
Get https://harbor.cyxc.club/v2/: EOF |
Docker daemon 代理 |
Harbor HEAD/GET/Range(含 512MiB 附近) |
200/206,无 Location |
层缺失、RGW 空洞、Harbor 307 |
| HTTP/1.1 与 HTTP/2 整层 | 约 9s、~80 MiB/s | Traefik/HTTP/2 卡大层 |
| 卡住节点抽 16MiB | ~0.5s、~30 MiB/s | 「节点到 Harbor 不通」 |
| Traefik timeout | 600s |
默认 60s 切连接 |
core proxy cache 打 arm64 manifest |
和这层无关 | 不要绑到 bf390218420b |
registry blob unknown 9c1e19b0… |
另一块 digest | 不是这层 |
registry.mirrors |
没有 Harbor | 不是 mirror 到 GitLab |
max_concurrent_downloads=3 |
默认值 | 不是原因 |
| 重启 containerd | 未做;ss -K 已解开 |
不是必须 |
最短路径:
describe/ events:主容器长时间只有 Pulling;有没有registry.gitlab.com和 Harbor 同时拉 toolbox(含已删除 Pod);GitLab.com 的 Pod 落在哪几台;Job 的creationTimestamp- 卡住节点:
getent hosts harbor.cyxc.club是10.1.10.3;ss里 containerd 的 443 对端是不是 Harbor(这次是34.149.22.116,Recv-Q/Send-Q 是否为 0;IP 会变,要反查) ingest/*/ref是不是bf390218420b,看data的 size 是否几乎不涨(不要看updatedat)- 卡住节点上
curl --max-redirs 0Harbor 该 blob:200、快、无 307 - 还在的 GitLab.com Job/Pod 先删掉,再确认没被 operator 重建
- 每个卡住节点:
ss -K dst <对端IP> dport 443 sport <该节点 sport> crictl pull harbor.cyxc.club/gitlab/gitlab-org/build/cng/gitlab-toolbox-ce:v19.3.2- Pod Running,ingest 空,不再连 GitLab GCP
附录:amd64 30 层
config sha256:de9db0f2559c3ccfa4690b2ca4bea58ab76a6cfaf5516766b3ed9c58be43709a。层压缩合计 1082618030 B。卡的是 17。
00 sha256:a8ac7f6c67abc236e4c745052c404112b8fab6fe8ac3a329d1ef3b867ad67c71 2823265501 sha256:a29cbbf324724d8211418aac5b65fc07f5db5543af72ff82687007a3948bcc63 715624802 sha256:188663d35da33221b599e7b3235bedd857161ecdb0e98ce3531c1acbaa38193d 126803 sha256:4f4fb700ef54461cfa02571ae0db9a0dc1e0cdb5577484a6d75e68dc38e8acc1 3204 sha256:1f1060c1e3b2c4bdd378b309265c4abcd9e5115bf55364ab9a1884a41b71f16f 2905556005 sha256:fda767dcea1b8975a95916b2a8228f06f4d9ad62e86ef6c86621511e2957ba93 195348506 sha256:9bd288a93092ae1002f0897df086f3444ab87116e5568230cb15dea7aa7f78ee 1272035407 sha256:55914a128bbf3e434d6e158eb7861a370855724d452b0d0dd30406392ceb5b8a 506008 sha256:77ce5c68db320603b1e94646350cb9ea02d4ac5095e0aa1d29cb8447610a05e1 3920975509 sha256:c626ceac14b7e679dec0825c595fca7e7dd8a63567a6847281a9754d9d991fbb 2803105710 sha256:33014e15442a13d5cf531b4a2b17e31ec11a5d4f09d453bc25f9cf82aa0be1c5 152032811 sha256:6588bb78f1c6a8cdec17b0bae901785adafab86cc7e15e7a6614cdca25d7291f 31805812 sha256:1c63f8c5fb002c0c366a080d746ab921519e2efb67fd7b7f9f8bc6f8e915c0fb 52671913 sha256:a2ad6535aeab354bac48304dc630c0100e2247e2052b929af78626dfcfa2a472 359565814 sha256:a4a2264495378446a5bd77749d7c26633e33791fa8d14ebf04f41a16be5164f2 550905315 sha256:60880a3b740ee5b0df223b0e773795a734592149d2afbec31f48d7b4d3b8e51b 2150869116 sha256:ac05878049d35074c8f8f6a8765b0befecccd71e9ada559ada045ea89116edfa 335917 sha256:bf390218420b5dcdeed2d425c9594b46bc91e2885f6beca227fb9147b55a2887 76873538818 sha256:4b2390aba4b7e61e0942baa45280b5feecae8c764b164d117547be5fbe881da7 22519 sha256:4f4fb700ef54461cfa02571ae0db9a0dc1e0cdb5577484a6d75e68dc38e8acc1 3220 sha256:74777c880bc08df616187fedc77d1dff3576c6603d67afcec436d2ad9e267d7f 123021 sha256:01ddbc40c96e17b284c39e0d5a590506ddc47f0b337ea953f08a41a4860c1c39 841122 sha256:94874a0070a508da42eb59e278f9ce743e9e5b93441b68306825bd04738a94f9 8653523 sha256:0868632af4ecff87675447a349fb5e2b617f8c2ae01e713edce7bff75958fad3 7480493424 sha256:6c60b87d0dbb0fcfe49957a77126550f67e1a7b77c9c73cde2f47eb8e1f33e4a 27554425 sha256:f467a892639e164e1bf95d7e4e59d4936ea4826437b6775d35ad24a486ece345 368774826 sha256:96fdc535a1aee88164b0034c20e124ed171b5d110efa37a2a36e3ef23fbe7fad 3179073327 sha256:9679f988225583408626eb598e75311c12a441146e020dcef5b594b419d01b45 2386934328 sha256:66f36859f0cfd2ec19e69ad7045092d21ab4a15e3798b831a8f9a11a7222d736 723029 sha256:f4dbd993078ebaecd22a908cd0d0b5d1822161fe29cf31e47f39633cc10b90c9 3337预拉其它镜像(同一脚本,仅作对照):operator 54.9 MiB / 37.2s;certificates 63.3 MiB / 163.9s;gitaly 456.5 MiB / 102.4s;workhorse 540.4 MiB / 540.8s;webservice 950.9 MiB / 519.0s;sidekiq 1022.4 MiB / 562.0s。sidekiq 也接近 1 GiB,当天没有逐层核对是否与 toolbox 共享 bf390218420b。仍应假定:任何 GitLab.com 的 CNG 拉取都可能在所在节点锁住大层。