从私有镜像仓库在Kubernetes中拉取镜像

48

我已经建立了一个运行在CoreOS上的4节点Kubernetes集群,其中包含多个容器的Pod。这些镜像来自公有和私有仓库。目前每次更新时,我都需要登录到每个节点并手动下载镜像。我希望能够自动拉取它们。

  1. 我尝试在每个服务器上运行docker login,然后将.dockercfg文件放置在/root和/core目录下。
  2. 我也使用了.docker/config.json文件进行了如上操作。
  3. 我向kube master添加了secret,并在Pod配置文件中添加了imagePullSecrets:
    • name:docker.io

当我创建Pod时,会收到错误消息Error:

image <user/image>:latest not found
如果我登录并运行docker pull命令,它会拉取镜像。我尝试过使用docker.io和quay.io。

如果我登录并运行docker pull命令,它会拉取镜像。我尝试过使用docker.io和quay.io。

7个回答

86

除了 @rob 提到的,从 docker 1.7 开始,使用 .dockercfg 已被弃用,现在使用 ~/.docker/config.json 文件。kube 1.1 支持此类密钥,但您必须在 yaml 中使用不同的键/类型配置来创建它:

首先,将您的 ~/.docker/config.json 进行 base64 编码:

cat ~/.docker/config.json | base64 -w0   

请注意,base64编码应出现在单行上,因此使用-w0禁用了换行。

接下来,创建一个yaml文件:my-secret.yaml

apiVersion: v1
kind: Secret
metadata:
  name: registrypullsecret
data:
  .dockerconfigjson: <base-64-encoded-json-here>
type: kubernetes.io/dockerconfigjson
$ kubectl create -f my-secret.yaml && kubectl get secrets

NAME                  TYPE                                  DATA
default-token-olob7   kubernetes.io/service-account-token   2
registrypullsecret    kubernetes.io/dockerconfigjson        1

然后,在您的Pod的yaml文件中,您需要引用registrypullsecret或创建一个副本控制器:

apiVersion: v1
kind: Pod
metadata:
  name: my-private-pod
spec:
  containers:
    - name: private
      image: yourusername/privateimage:version
  imagePullSecrets:
    - name: registrypullsecret

1
感谢您详细的回复。我还发现我需要升级我使用的k8s版本。一旦我升级了,一切都按照文档正常工作了。 - KSB
1
现在应该接受这个答案。此外,根据先前答案中@MrE的评论,在对config.json进行编码之前,请确保您的私有存储库上有https://。如果没有,我将无法拉取我的容器。 - Ian Belcher
4
Base64 编码的 docker 配置需要全部在一行上。最好使用带有 "-w 0" 标志的 base64 命令。 - Chris Jones

32

如果您需要从私有的Docker Hub存储库中拉取图像,则可以使用以下方法。

创建您的密钥

kubectl create secret docker-registry myregistrykey --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL

密钥 "myregistrykey" 已创建。

然后将新创建的密钥添加到您的Kubernetes服务账户中。

检索当前服务账户

kubectl get serviceaccounts default -o yaml > ./sa.yaml

编辑sa.yaml,在Secrets后添加ImagePullSecret。

imagePullSecrets:
- name: myregistrykey

更新服务帐户

kubectl replace serviceaccount default -f ./sa.yaml

这是最新的答案,更多细节请参见 https://kubernetes.io/docs/user-guide/service-accounts/#adding-imagepullsecrets-to-a-service-account - Max Vorobjev
如果您想从Azure容器注册表(ACR)中拉取,您可以使用此方法进行测试,其中您在ACR上启用管理员用户并创建包含管理员用户信息的密钥。对于生产目的,您需要创建一个服务主体(或服务连接,它会像我所理解的那样创建主体),然后将Principal的信息放入密钥中,如此处所示:https://github.com/MicrosoftDocs/azure-docs/blob/master/articles/container-registry/container-registry-auth-aks.md 我还没有尝试过Principals,但这个管理员用户大约也适用于OpenShift。 - straville
1
最详细的答案并且它是有效的,只需补充一点,如果您正在使用docker.io,请设置-docker-server=docker.io。 - Prash

11

我可以确认,使用deployment时imagePullSecrets无效,但你可以

kubectl create secret docker-registry myregistrykey --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
kubectl edit serviceaccounts default

添加

imagePullSecrets:
- name: myregistrykey

Secrets后面到末尾处,保存并退出。经过测试,这个方法已经可以在Kubernetes 1.6.7上使用。


8

Kubernetes支持一种特殊的机密类型,您可以创建该机密类型以用于获取Pod的镜像。更多细节请参见此处


你需要创建一个服务账户吗?我按照用户指南中的步骤操作了,但它仍然没有拉取图像。有日志可以查看发生了什么吗? - KSB
你需要将该秘密挂载到 pod 中以便使用。 - Rob
1
请注意: 1)URL 必须为 https:// 2)整个内容必须在一行上。 3)经过 base64 编码后,仍然必须在一行上。 - MrE
7
把英语翻译成中文。仅返回翻译后的文本:回答不应该只是一个链接和一句话的摘要。 - 333kenshin
文档的URL已更改为https://kubernetes.io/docs/concepts/containers/images/#using-a-private-registry。 - Lucy Llewellyn
如果你花更多的时间解释为什么新的“特殊”秘密类型会帮助解决问题,那么今天我就可以解决我所面临的问题了。链接已经过期,而且我不知道“特殊秘密”是什么意思... - Rikki

3

在CentOS 7中,Docker配置文件位于/root/.dockercfg。

  1. echo $(cat /root/.dockercfg) | base64 -w 0
  2. Copy and paste result to secret YAML based on the old format:

    apiVersion:  v1
    kind: Secret
    metadata:
      name: docker-secret
      type: kubernetes.io/dockercfg
    data:
      .dockercfg: <YOUR_BASE64_JSON_HERE> 
    

对我很有效,希望也能帮到你。


0

使用相同的凭据创建与您的Docker配置相同的密钥的最简单方法是:

kubectl create secret generic myregistry --from-file=.dockerconfigjson=$HOME/.docker/config.json

这已经将数据编码为base64。

如果您可以使用docker下载图像,那么kubernetes也应该能够下载它们。但是需要将此添加到您的kubernetes对象中:

spec:
  template:
    spec:
      imagePullSecrets:
      - name: myregistry
      containers:
      # ...

其中myregistry是上一个命令中给定的名称。


0

走捷径,别忘了定义--type并将其添加到正确的命名空间中

kubectl create secret generic YOURS-SECRET-NAME \
--from-file=.dockerconfigjson=$HOME/.docker/config.json \
--type=kubernetes.io/dockerconfigjson

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