国内安装 nginx-ingress 时镜像拉取失败是高频问题,主因是官方镜像(如 `k8s.gcr.io/ingress-nginx/controller:v1.10.2`)托管在被屏蔽的 GCR 仓库,导致 `kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml` 等命令直接超时或报 `ImagePullBackOff`。此外,部分 Helm Chart 默认仍引用 gcr 或 GitHub Container Registry(ghcr.io)镜像,而国内网络对这些源访问不稳定。常见误操作包括仅配置 Docker 镜像加速器却忽略 Kubernetes 节点上的 containerd 或 CRI-O 的独立镜像仓库配置,或未同步更新 `image.repository` 和 `image.digest` 字段。该问题在离线环境、金融云或政企内网中尤为突出,需结合镜像代理、国内镜像源替换与离线导入三类方案综合解决。
1条回答 默认 最新
泰坦V 2026-04-15 10:26关注```html一、现象层:典型报错与可观测信号
ImagePullBackOff事件高频出现在kubectl describe pod -n ingress-nginx输出中- 节点级日志(
journalctl -u containerd -n 100)显示failed to resolve reference "k8s.gcr.io/ingress-nginx/controller:v1.10.2": failed to do request: Head "https://k8s.gcr.io/v2/..." - 使用
curl -v https://k8s.gcr.io在节点上直接测试,返回Connection timed out或 TLS 握手失败 - Helm install 后
helm get values ingress-nginx显示image.repository: ghcr.io/kubernetes/ingress-nginx/controller—— 未适配国内网络
二、根因层:镜像分发链路的三重断裂点
下图展示了从声明到拉取的完整链路及国内失效环节:
graph LR A[deploy.yaml/Helm Chart] -->|硬编码引用| B(k8s.gcr.io/...)
ghcr.io/...) B --> C{DNS解析} C -->|GFW拦截| D[连接超时] C -->|DNS污染| E[错误IP] A -->|未覆盖| F[containerd registry config] F -->|无mirror配置| G[直连失败]三、配置层:常被忽视的 CRI 级别镜像策略
仅配置 Docker daemon.json 的
registry-mirrors对 Kubernetes 无效——因 kubelet 调用的是 containerd/CRI-O。正确做法需编辑:# /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."k8s.gcr.io"]
endpoint = ["https://registry.aliyuncs.com/google_containers"]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."ghcr.io"]
endpoint = ["https://ghcr.m.daocloud.io"]修改后必须执行:
sudo systemctl restart containerd四、替代源层:经生产验证的国内可信镜像仓库矩阵
原始仓库 推荐替代源 同步时效 校验方式 k8s.gcr.io/ingress-nginx/controller registry.aliyuncs.com/google_containers/ingress-nginx-controller ≤15分钟 对比 docker pull ... && docker inspect --format='{{.RepoDigests}}'ghcr.io/kubernetes/ingress-nginx/controller ghcr.m.daocloud.io/kubernetes/ingress-nginx/controller 实时镜像 验证 sha256digest 与 upstream 一致五、Helm 层:参数化覆盖不可省略的字段组合
- 必须同时指定
--set image.repository=registry.aliyuncs.com/google_containers/ingress-nginx-controller - 必须显式设置
--set image.tag=v1.10.2(避免 chart 内置 default 覆盖) - 若启用 digest 验证,须同步提供
--set image.digest="sha256:abc123..."—— 否则 Helm 会忽略 digest 字段 - 金融云场景建议追加
--set controller.hostNetwork=true --set controller.dnsPolicy=ClusterFirstWithHostNet规避 DNS 策略冲突
六、离线层:Air-Gapped 环境的原子化交付方案
- 在有网环境执行:
docker pull registry.aliyuncs.com/google_containers/ingress-nginx-controller:v1.10.2 - 导出为 tar:
docker save -o ingress-nginx-v1.10.2.tar registry.aliyuncs.com/google_containers/ingress-nginx-controller:v1.10.2 - 离线节点导入:
ctr -n k8s.io images import ingress-nginx-v1.10.2.tar(containerd)或podman load -i ...(CRI-O) - 部署时强制使用本地镜像:
imagePullPolicy: IfNotPresent并确保image.repository与导入名称完全一致
七、验证层:五步闭环检测法
- 检查节点是否可解析替代域名:
nslookup registry.aliyuncs.com - 确认 containerd 配置已生效:
crictl info | jq '.config.registry' - 手动触发拉取测试:
crictl pull registry.aliyuncs.com/google_containers/ingress-nginx-controller:v1.10.2 - 观察 Pod 事件:
kubectl get events -n ingress-nginx --field-selector reason=Pulling - 最终验证就绪:
kubectl wait --for=condition=ready pod -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx --timeout=120s
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报