Kubernetes拉取私有镜像不读取服务器/etc/hosts问题求助
问题背景
在Ubuntu Server 22.04上用kubeadm搭建3节点Kubernetes集群(Flannel网络插件),部署Deployment时无法从内部GitLab私有镜像仓库拉取镜像。节点/etc/hosts已配置192.168.1.30 registry.example.com,服务器命令行docker pull可正常拉取,但Kubernetes部署时解析到公网IP导致超时。尝试过hostAliases(仅Pod内部生效)、修改CoreDNS配置均无效。
Deployment配置:
apiVersion: apps/v1 kind: Deployment metadata: name: platform-deployment spec: replicas: 1 selector: matchLabels: app: platform-service template: metadata: labels: app: platform-service spec: containers: - name: platform-service image: registry.example.com/demo/platform-service:latest
报错信息:
Failed to pull image "registry.example.com/demo/platform-service:latest": rpc error: code = Unknown desc = failed to pull and unpack image "registry.example.com/deni/platform-service:latest": failed to resolve reference "registry.example.com/demo/platform-service:latest": failed to do request: Head "https://registry.example.com/v2/demo/platform-service/manifests/latest": dial tcp xxx.xxx.xxx.xxx:443: i/o timeout
问题根源
Kubernetes拉取镜像由kubelet调用容器运行时(kubeadm默认用containerd)执行,这个阶段不依赖Pod的CoreDNS配置,且containerd的DNS解析逻辑不会直接读取节点/etc/hosts。而docker pull能成功是因为Docker的解析逻辑与containerd不同。
可行解决方法
方法一:配置containerd私有仓库映射(推荐)
直接给containerd添加私有仓库的IP映射,确保拉取时解析到内部地址:
- 编辑每个K8s节点的containerd配置文件:
sudo nano /etc/containerd/config.toml - 找到或新增
[plugins."io.containerd.grpc.v1.cri".registry]区块,添加以下配置:[plugins."io.containerd.grpc.v1.cri".registry.configs] [plugins."io.containerd.grpc.v1.cri".registry.configs."registry.example.com".hosts] [plugins."io.containerd.grpc.v1.cri".registry.configs."registry.example.com".hosts."http://192.168.1.30"] capabilities = ["pull"] skip_verify = true # 私有仓库用自签证书时需添加,可信证书可删除此行提示:如果仓库用HTTPS且证书可信,将
http://改为https://并移除skip_verify。 - 重启containerd服务:
sudo systemctl restart containerd - 删除失败Pod,触发重新拉取:
kubectl delete pod -l app=platform-service
方法二:用dnsmasq配置节点本地DNS解析
通过本地DNS服务强制私有域名解析到内部IP,让containerd继承正确解析:
- 安装dnsmasq:
sudo apt install dnsmasq -y - 添加私有域名解析规则:
echo "address=/registry.example.com/192.168.1.30" | sudo tee /etc/dnsmasq.d/registry.conf - 修改节点
resolv.conf,优先使用本地dnsmasq:sudo sed -i '1s/^/nameserver 127.0.0.1\n/' /etc/resolv.conf - 重启服务:
sudo systemctl restart dnsmasq sudo systemctl restart containerd - 重新创建Pod验证结果。
方法三:临时方案——直接使用IP拉取镜像
若上述方法暂时无法生效,可直接用仓库IP替换域名,同时配置拉取凭证(如需认证):
- 修改Deployment YAML:
apiVersion: apps/v1 kind: Deployment metadata: name: platform-deployment spec: replicas: 1 selector: matchLabels: app: platform-service template: metadata: labels: app: platform-service spec: containers: - name: platform-service image: 192.168.1.30/demo/platform-service:latest imagePullSecrets: # 仓库需认证时添加此部分 - name: registry-secret - 创建镜像拉取凭证(如需):
kubectl create secret docker-registry registry-secret \ --docker-server=192.168.1.30 \ --docker-username=你的用户名 \ --docker-password=你的密码 - 重新部署:
kubectl apply -f deployment.yaml
内容的提问来源于stack exchange,提问作者Aaron Murray
相关产品推荐
相关产品推荐

