Kubernetes 无法从私有 Docker 镜像仓库拉取镜像。

50

我在使用kubernetes(minikube)时遇到了问题,无法从Docker的本地镜像仓库中拉取镜像。 已经创建了Docker仓库:

I have problem with kubernetes (minikube) and pull images from local image repository on docker. Docker repository was created:

docker run --entrypoint htpasswd registry:2 -Bbn zordon examplePassword > /mnt/LINUX/auth/htpasswd

docker run -d \
  -p 5000:5000 \
  --restart=always \
  --name registry \
  -v /mnt/LINUX/dockerreg:/var/lib/registry \
  -v /mnt/LINUX/auth:/auth \
  -e "REGISTRY_AUTH=htpasswd" \
  -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
  -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
  registry:2

然后我想使用已成功上传到本地仓库的镜像创建简单的 pod:

curl localhost:5000/v2/_catalog
{"repositories":["car/configuration"]}

我也在minikube集群上创建了一个秘密:

kubectl create secret docker-registry docregkey --docker-server=localhost:5000 --docker-username=zordon --docker-password=examplePassword --docker-email=test@dock.mail

并定义简单 Pod:

    apiVersion: v1
kind: Pod
metadata:
  name: private-reg
spec:
  containers:
  - name: private-reg-container
    image: car/configuration:latest
    imagePullPolicy: Always
  restartPolicy: Always
  imagePullSecrets:
  - name: docregkey

不幸的是,我还是遇到了这个问题:

无法拉取镜像"car/configuration:latest": rpc错误:代码= Unknown desc =守护程序的错误响应:拉取被拒绝,因为可能需要'docker login'登录。

我该如何解决这个问题?


1
这个问题在官方文档中已经被完整正确地回答了,以下是它的深入链接地址:https://kubernetes.io/docs/tutorials/hello-minikube/#create-a-docker-container-image。 - VeRo
@vero 虽然那是一篇非常好的教程,但它并没有解决这个问题。 - conjectures
10个回答

22
  • 在 minikube 中部署时,本地镜像的拉取策略应为 IfNotPresentNever
  • 在云主机(如 AWS)中部署时,公共镜像的拉取策略应该与公共镜像相同(见下文)
  • 对于那些使用类似 "latest" 或 "stable" 标签的公共镜像,其拉取策略应该是 Always(因为标签指向的镜像会随时间变化),对于总是指向同一镜像的标签,其拉取策略应该是 IfNotPresent(避免不必要的拉取)
  • 这意味着,如果避免使用类似 latest 和 stable 的标签,只有一个规则需要遵循:

    对于 minikube 从您自己的本地 docker registry 拉取镜像时,标签影响拉取策略。根据 Images docs,默认情况下,拉取策略是 IfNotPresent,除非:

    1. 您使用 :latest 作为所使用镜像的标签
    2. 或者您省略了所使用镜像的标签

    在这些情况下,拉取策略将有效地默认为 Always,将尝试从 docker hub 拉取。这将导致 minikube 无法获取没有标签或 "latest" 标签的本地镜像。

    故事的道德是,不要依赖默认值,因为它太令人困惑了 :)

    因此,始终明确指定拉取策略:

  • 在您的规范中明确设置imagePullPolicy(或在运行命令行中设置)为IfNotPresent,因为这将始终首先在本地查找它,如果在本地未找到,则查找公共注册表。无论您是否部署到minikube或云中,这都可以正常工作。

  • 2
    谢谢你,Oliver。这让我开始使用minikube、docker和本地镜像。docker run image_name --image-pull-policy=IfNotPresent - Paul Watson

    19
    问题出在镜像拉取策略上 - 你将其设置为Always(默认设置)。这意味着Docker守护程序始终尝试从外部Docker注册表拉取镜像 - 你想使用本地的注册表。
    尝试创建deployment时添加--image-pull-policy=Never
    这里有一个很好的使用本地创建镜像的教程(对我很有帮助):

    https://kubernetes.io/docs/tutorials/hello-minikube/#create-a-docker-container-image


    14

    因为Minikube是一台虚拟机而不是你的本地主机。 你可以尝试运行这段代码 eval $(minikube docker-env) https://kubernetes.io/docs/getting-started-guides/minikube/

    1. 打开终端
    2. eval $(minikube docker-env)
    3. 构建Docker镜像
    4. 使用kubectl创建deployment.yaml文件

    请确保在终端中执行。如果关闭了终端,请重新打开终端并输入eval $(minikube docker-env)

    eval $(minikube docker-env) 这段代码将在Minikube中构建镜像。


    如果Docker镜像是由Maven插件和Jenkins构建的呢? - lukisp
    有两种可能的方式, 第一种是在Minikube中注册运行, 第二种是远程私有注册表。 - onuryartasi
    非常感谢,终于成功了,在调试了几个小时之后! - Jose Mhlanga

    12

    我遇到的同样问题是,当我使用本地Docker构建一个镜像时,它没有被添加到minikube镜像列表中。

    解决方法是手动添加镜像:

    minikube image load image-name:tag
    

    对我来说它是有效的,但在调试时需要频繁重建图像仍然不太方便。 - nguyenhoai890

    7

    我希望找到一行命令可以在终端中执行。其他尝试过的方法都对于使用minikube授权ecr来说过于复杂。

    这是我每天运行的aws ecr登录命令,因为令牌会过期。下面的示例适用于Debian 9与AWS ECR。

    shell

    kubectl create secret docker-registry aws-ecr-credentials \
    --docker-server=$ECR_REGISTRY \
    --docker-username=AWS \
    --docker-password=$(aws ecr get-login | awk '{print $6}') \
    --docker-email=$IAM_EMAIL \
    --namespace=$KUBE_NAMESPACE
    

    template.yml

    spec:
      imagePullSecrets:
        - name: aws-ecr-credentials
    

    6
    问题出在您在POD yaml文件中提到的图像名称。
    image: car/configuration:latest
    

    这将尝试从全局注册表中获取,而不是本地注册表。将镜像名称更改为包括仓库即可。
    image: localhost:5000/car/configuration:latest
    

    如果您的注册表未受保护,请确保在docker守护程序配置中包含不安全的注册表。


    对我不起作用。相同的 eval $(minikube docker-env)。 - lukisp
    注册表是否在与Minikube相同的节点上运行? - Pramod V
    两个都运行在同一主机上(也是PC)。Docker镜像是由Maven插件构建的,并且我可以在_catalog中看到该镜像。 - lukisp
    2
    此外,在 pod 的描述中,我得到了以下信息:Failed to pull image "localhost:5000/car/configuration:latest": rpc error: code = Unknown desc = Error response from daemon: Get http://localhost:5000/v2/: dial tcp 127.0.0.1:5000: getsockopt: connection refused,但是当尝试使用 curl (curl --user zordon:4a5b-9cd7 http://localhost:5000/v2/) 时,可以获得 {} 有效响应。 - lukisp
    好的,从这些错误中我能怀疑的一件事情是,当你运行minikube时,它理想情况下应该在虚拟化主机上运行...所以它将尝试联系那个localhost...你可以尝试使用主机IP公开注册表,并使用该主机IP代替kubernetes中的localhost。 - Pramod V

    4
    在Docker桌面版上运行Kubernetes时,您的应用程序将在Docker和Kubernetes之间共享同一图像注册表。所有图像列表:
    docker images --all
    

    选择其中一个并使用已更改的属性--image-pull-policy=Never运行它。例如:

    kubectl run ContainerName --image=myimage/server --port=8080 --image-pull-policy=Never 
    

    默认情况下,kubelet将尝试从指定的注册表中拉取每个镜像。但是,如果容器的imagePullPolicy属性设置为IfNotPresentNever,则使用本地镜像(分别优先或排他性地)。这意味着Kubernetes从本地注册表中拉取镜像,而不是远程云端。 链接

    1

    在Minikube中使用私有注册表

    运行命令:kubectl create -f kube-registry.yaml

    (从github的这个gist中获取kube-registry.yaml.)

    您需要将Minikube端口转发到本地主机(仅限于镜像构建时间)

    kubectl port-forward --namespace kube-system \
    $(kubectl get po -n kube-system | grep kube-registry-v0 | \
    awk '{print $1;}') 5000:5000
    

    接下来,从主机curl localhost:5000应该返回一个有效的响应,该响应来自运行在minikube上的docker注册表。

    仓库:http://localhost:5000/v2/_catalog

    拉取镜像:localhost:5000/image_name:image_tag

    参考资料:https://blog.hasura.io/sharing-a-local-registry-for-minikube-37c7240d0615


    0

    我发现使用本地注册表与minikube的最佳方法在这里:

    Minikube Registry Handbook

    基本上,您将向minikube添加一个注册表插件,并进行一些端口转发和重定向,以便从kubernetes集群内部和主机机器上都可以访问它。

    我尝试了另一种方法,在集群内部引用注册表:

    registry.kube-system.svc.cluster.local
    

    像这样:

    image: registry.kube-system.svc.cluster.local/postgres:latest
    

    但它没有起作用。

    为了使其工作,我将集群 IP 设置为注册表服务:

    kubectl get service --namespace kube-system
    

    enter image description here

    并且可以像这样引用:

    image: 10.99.112.119/postgres:latest
    

    0

    尝试在所有节点上登录Docker(如果是集群环境-在主节点和工作节点上登录Docker)。

    [root@****]# docker login

    使用您的Docker ID登录以从Docker Hub推送和拉取镜像。如果您没有Docker ID,请前往https://hub.docker.com创建一个。 用户名: 密码:

    登录成功!

    然后尝试在所有节点上手动加载镜像

    docker pull url


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接