8.3 KiB
8.3 KiB
快速修复镜像拉取问题
🚨 问题识别
当你看到这些错误时,使用本指南快速修复:
# Pod 状态
kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-xxx 0/1 ImagePullBackOff 0 5m
myapp-yyy 0/1 ErrImagePull 0 5m
# 错误详情
kubectl describe pod myapp-xxx
...
Events:
Warning Failed 2m kubelet Failed to pull image "nginx:alpine":
Error response from daemon:
Get "https://registry-1.docker.io/v2/":
context deadline exceeded
⚡ 快速修复方案
方案 1: 自动修复 Deployment(推荐)
一键修复:
cd /Users/brunogao/work/codes/tools/macos/k8s
./cache-image.sh --update-deployment <namespace>/<deployment-name>
示例:
# 修复 kubernetes-dashboard
./cache-image.sh --update-deployment kubernetes-dashboard/kubernetes-dashboard
# 修复 myapp
./cache-image.sh --update-deployment default/myapp
效果:
- ✅ 自动缓存所有镜像
- ✅ 自动更新 Deployment
- ✅ 自动触发 Pod 重启
- ✅ 使用本地 Harbor 镜像
方案 2: 手动缓存镜像
步骤 1: 查看失败的镜像
kubectl describe pod <pod-name> -n <namespace> | grep "Image:"
# 输出: Image: nginx:alpine
步骤 2: 缓存镜像
./cache-image.sh nginx:alpine
步骤 3: 更新 Deployment
# 获取容器名
kubectl get deployment <deploy-name> -n <namespace> -o jsonpath='{.spec.template.spec.containers[*].name}'
# 输出: nginx
# 更新镜像
kubectl set image deployment/<deploy-name> \
nginx=harbor.omniverseai.net:8080/library/nginx:alpine \
-n <namespace>
方案 3: 从失败 Pod 提取镜像
适用场景: Pod 已经失败,需要批量处理
./cache-image.sh --from-pod <namespace>/<pod-name>
示例:
./cache-image.sh --from-pod kubernetes-dashboard/dashboard-xxx
效果:
- ✅ 自动提取 Pod 所有镜像
- ✅ 批量缓存到本地 Harbor
- ⚠️ 需要手动更新 Deployment
📝 常见场景速查
场景 1: Dashboard 部署失败
# 错误
kubectl get pods -n kubernetes-dashboard
NAME READY STATUS RESTARTS AGE
kubernetes-dashboard-79cbcf9fb6-hwpxp 0/1 ImagePullBackOff 0 5m
dashboard-metrics-scraper-xxx 0/1 ImagePullBackOff 0 5m
# 修复
./cache-image.sh --update-deployment kubernetes-dashboard/kubernetes-dashboard
./cache-image.sh --update-deployment kubernetes-dashboard/dashboard-metrics-scraper
场景 2: Helm Chart 部署失败
# 查看 Helm Release 的 Pods
kubectl get pods -l app.kubernetes.io/instance=myrelease
# 获取镜像列表
helm get values myrelease | grep image
# 缓存镜像
./cache-image.sh <image1> <image2> <image3>
# 升级 Helm Release 使用本地镜像
helm upgrade myrelease ./mychart \
--set image.repository=harbor.omniverseai.net:8080/library/myapp \
--set image.tag=v1.0.0
场景 3: StatefulSet 失败
# 查看 StatefulSet
kubectl get statefulset <name> -n <namespace>
# 获取镜像
kubectl get statefulset <name> -n <namespace> -o jsonpath='{.spec.template.spec.containers[*].image}'
# 缓存镜像
./cache-image.sh <image>
# 更新 StatefulSet
kubectl set image statefulset/<name> \
<container-name>=harbor.omniverseai.net:8080/library/<image>:<tag> \
-n <namespace>
场景 4: DaemonSet 失败
# 查看 DaemonSet
kubectl get daemonset <name> -n <namespace>
# 缓存并更新(DaemonSet 需要手动处理)
./cache-image.sh <image>
kubectl set image daemonset/<name> \
<container-name>=harbor.omniverseai.net:8080/library/<image>:<tag> \
-n <namespace>
🔍 诊断命令
检查 Pod 状态
# 查看所有 ImagePull 失败的 Pods
kubectl get pods --all-namespaces | grep -E "ImagePull|ErrImage"
# 查看详细错误
kubectl describe pod <pod-name> -n <namespace> | grep -A 10 "Events:"
检查镜像是否已缓存
# 查询本地 Harbor
curl -u admin:admin123 \
"http://192.168.1.83:8080/api/v2.0/projects/library/repositories" | \
jq -r '.[].name'
验证 Deployment 使用的镜像
# 查看当前镜像
kubectl get deployment <deploy-name> -n <namespace> \
-o jsonpath='{.spec.template.spec.containers[*].image}'
# 查看是否使用本地 Harbor
kubectl get deployment <deploy-name> -n <namespace> \
-o jsonpath='{.spec.template.spec.containers[*].image}' | \
grep "harbor.omniverseai.net"
💡 预防措施
1. 部署前预缓存
创建镜像清单:
# 从 YAML 提取镜像
grep "image:" deployment.yaml | awk '{print $2}' > images.txt
# 批量缓存
./cache-image.sh -f images.txt
2. 修改 YAML 使用本地镜像
原始 YAML:
spec:
containers:
- name: app
image: nginx:alpine
修改后:
spec:
containers:
- name: app
image: harbor.omniverseai.net:8080/library/nginx:alpine
3. 使用 imagePullPolicy
spec:
containers:
- name: app
image: harbor.omniverseai.net:8080/library/nginx:alpine
imagePullPolicy: IfNotPresent # 优先使用本地缓存
🚀 批量修复脚本
修复整个命名空间
#!/bin/bash
# fix-namespace-images.sh
NAMESPACE="$1"
if [[ -z "$NAMESPACE" ]]; then
echo "用法: $0 <namespace>"
exit 1
fi
echo "=== 修复命名空间: $NAMESPACE ==="
# 获取所有 Deployment
DEPLOYMENTS=$(kubectl get deployment -n "$NAMESPACE" -o name)
for deploy in $DEPLOYMENTS; do
deploy_name="${deploy#deployment.apps/}"
echo "处理: $deploy_name"
./cache-image.sh --update-deployment "$NAMESPACE/$deploy_name"
done
echo "=== 完成 ==="
使用方式
chmod +x fix-namespace-images.sh
./fix-namespace-images.sh kubernetes-dashboard
📊 故障排查流程图
发现 ImagePullBackOff
↓
检查错误详情
kubectl describe pod <pod-name>
↓
判断错误类型
├─ context deadline exceeded → 网络超时
├─ unauthorized → 认证失败
└─ not found → 镜像不存在
↓
选择修复方案
├─ 自动修复(推荐)
│ └─ ./cache-image.sh --update-deployment ns/deploy
│
├─ 手动修复
│ ├─ ./cache-image.sh <image>
│ └─ kubectl set image ...
│
└─ 批量修复
└─ ./fix-namespace-images.sh <namespace>
↓
验证修复
├─ kubectl get pods -n <namespace>
├─ kubectl describe deployment <deploy>
└─ 检查 Pod 是否 Running
↓
✅ 完成
⏱️ 时间估算
| 操作 | 耗时 |
|---|---|
| 单个镜像缓存 | 30-60 秒 |
| Deployment 自动修复 | 1-2 分钟 |
| 批量缓存 10 个镜像 | 5-10 分钟 |
| 整个命名空间修复 | 取决于 Deployment 数量 |
🔗 相关文档
- 完整指南: CACHE-IMAGE-GUIDE.md
- 镜像缓存方案: HARBOR-IMAGE-CACHE-SOLUTION.md
- 主 README: README.md
📞 常见问题
Q: 脚本报错 "登录失败"
# 检查 Harbor 状态
curl http://192.168.1.83:8080/api/v2.0/health
# 检查 EU Harbor 连接
curl -I https://harbor.eu.lingjingwanxiang.cn
# 手动登录测试
docker login harbor.omniverseai.net:8080 -u admin -p admin123
Q: 镜像缓存成功但 Pod 仍然失败
# 检查 Deployment 是否已更新
kubectl describe deployment <deploy-name> -n <namespace> | grep Image
# 强制重启 Pod
kubectl rollout restart deployment/<deploy-name> -n <namespace>
Q: 需要缓存私有仓库的镜像怎么办?
# 脚本目前仅支持公共镜像
# 对于私有仓库,需要先配置 Docker 登录
docker login <private-registry>
# 然后手动拉取和推送
docker pull <private-registry>/<image>:<tag>
docker tag <private-registry>/<image>:<tag> \
harbor.omniverseai.net:8080/library/<image>:<tag>
docker push harbor.omniverseai.net:8080/library/<image>:<tag>
最后更新: 2025-12-24
脚本位置: /Users/brunogao/work/codes/tools/macos/k8s/cache-image.sh