CodeMaster 2026-04-15 10:25 采纳率: 99%
浏览 2
已采纳

国内安装nginx-ingress时镜像拉取失败如何解决?

国内安装 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/controllerregistry.aliyuncs.com/google_containers/ingress-nginx-controller≤15分钟对比 docker pull ... && docker inspect --format='{{.RepoDigests}}'
    ghcr.io/kubernetes/ingress-nginx/controllerghcr.m.daocloud.io/kubernetes/ingress-nginx/controller实时镜像验证 sha256 digest 与 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 环境的原子化交付方案

    1. 在有网环境执行:docker pull registry.aliyuncs.com/google_containers/ingress-nginx-controller:v1.10.2
    2. 导出为 tar:docker save -o ingress-nginx-v1.10.2.tar registry.aliyuncs.com/google_containers/ingress-nginx-controller:v1.10.2
    3. 离线节点导入:ctr -n k8s.io images import ingress-nginx-v1.10.2.tar(containerd)或 podman load -i ...(CRI-O)
    4. 部署时强制使用本地镜像:imagePullPolicy: IfNotPresent 并确保 image.repository 与导入名称完全一致

    七、验证层:五步闭环检测法

    1. 检查节点是否可解析替代域名:nslookup registry.aliyuncs.com
    2. 确认 containerd 配置已生效:crictl info | jq '.config.registry'
    3. 手动触发拉取测试:crictl pull registry.aliyuncs.com/google_containers/ingress-nginx-controller:v1.10.2
    4. 观察 Pod 事件:kubectl get events -n ingress-nginx --field-selector reason=Pulling
    5. 最终验证就绪:kubectl wait --for=condition=ready pod -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx --timeout=120s
    ```
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 已采纳回答 4月16日
  • 创建了问题 4月15日