• 镜像
    • 升级镜像
    • 使用私有仓库
      • 使用 Google Container Registry
      • 使用 AWS EC2 Container Registry
      • 使用 Azure Container Registry (ACR)
      • 配置Nodes对私有仓库认证
      • 提前拉取镜像
      • 在pod上指定ImagePullSecrets
        • 使用Docker Config创建Secret
        • 通过kubectl创建secret
        • 在pod中引用imagePullSecrets
      • 使用场景
    • 反馈

    镜像

    在Kubernetes pod中引用镜像前,请创建Docker镜像,并将之推送到镜像仓库中。容器的“image”属性支持和Docker命令行相同的语法,包括私有仓库和标签。

    升级镜像

    默认的镜像拉取策略是“IfNotPresent”,在镜像已经存在的情况下,kubelet将不在去拉取镜像。如果总是想要拉取镜像,必须设置拉取策略为“Always”或者设置镜像标签为“:latest”。

    如果没有指定镜像的标签,它会被假定为“:latest”,同时拉取策略为“Always”。

    注意应避免使用“:latest”标签,参见 Best Practices for Configuration 获取更多信息。

    使用私有仓库

    从私有仓库读取镜像时可能需要密钥。凭证可以用以下方式提供:

    • 使用Google Container Registry
      • 每个集群分别配置
      • 在Google Compute Engine 或者 Google Kubernetes Engine上自动配置
      • 所有的pod都能读取项目的私有仓库
    • 使用 AWS EC2 Container Registry (ECR)
      • 使用IAM角色和策略来控制对ECR仓库的访问
      • 自动刷新ECR的登录凭证
    • 使用 Azure Container Registry (ACR)
    • 配置节点对私有仓库认证
      • 所有的pod都可以读取已配置的私有仓库
      • 需要集群管理员提供node的配置
    • 提前拉取镜像
      • 所有的pod都可以使用node上缓存的镜像
      • 需要以root进入node操作
    • pod上指定 ImagePullSecrets
      • 只有提供了密钥的pod才能接入私有仓库下面将详细描述每一项

    使用 Google Container Registry

    Kuberetes运行在Google Compute Engine (GCE)时原生支持Google ContainerRegistry (GCR)。如果kubernetes集群运行在GCE或者Google Kubernetes Engine 上,使用镜像全名(e.g. gcr.io/my_project/image:tag)即可。

    集群中的所有pod都会有读取这个仓库中镜像的权限。

    Kubelet将使用实例的Google service account向GCR认证。实例的service account拥有https://www.googleapis.com/auth/devstorage.read_only,所以它可以从项目的GCR拉取,但不能推送。

    使用 AWS EC2 Container Registry

    当Node是AWS EC2实例时,Kubernetes原生支持AWS EC2 ContainerRegistry。

    在pod定义中,使用镜像全名即可 (例如 ACCOUNT.dkr.ecr.REGION.amazonaws.com/imagename:tag)

    集群中可以创建pod的用户都可以使用ECR中的任意镜像运行pod。

    Kubelet会获取并且定期刷新ECR的凭证。它需要以下权限

    • ecr:GetAuthorizationToken
    • ecr:BatchCheckLayerAvailability
    • ecr:GetDownloadUrlForLayer
    • ecr:GetRepositoryPolicy
    • ecr:DescribeRepositories
    • ecr:ListImages
    • ecr:BatchGetImage

    要求:

    • 必须使用kubelet 1.2.0及以上版本
    • 如果node在区域A,而镜像仓库在另一个区域B,需要1.3.0及以上版本
    • 区域中必须提供ECR

    诊断

    • 验证是否满足以上要求
    • 获取工作站的$REGION (例如 us-west-2)凭证,使用凭证SSH到主机手动运行docker,检查是否运行
    • 验证kubelet是否使用参数—cloud-provider=aws运行
    • 检查kubelet日志(例如 journalctl -u kubelet),是否有类似的行
      • plugins.go:56] Registering credential provider: aws-ecr-key
      • provider.go:91] Refreshing cache for provider: *aws_credentials.ecrProvider

    使用 Azure Container Registry (ACR)

    当使用Azure Container Registry时,可以使用admin user或者service principal认证。任何一种情况,认证都通过标准的Docker authentication完成。本指南假设使用azure-cli命令行工具。

    首先,需要创建仓库并获取凭证,完整的文档请参考Azure container registry documentation。

    创建好容器仓库后,可以使用以下凭证登录:

    • DOCKER_USER : service principal, or admin username
    • DOCKER_PASSWORD: service principal password, or admin user password
    • DOCKER_REGISTRY_SERVER: ${some-registry-name}.azurecr.io
    • DOCKER_EMAIL: ${some-email-address}

    填写以上变量后,就可以configure a Kubernetes Secret and use it to deploy a Pod。

    配置Nodes对私有仓库认证

    注意: 如果在Google Kubernetes Engine 上运行集群,每个节点上都会有.dockercfg文件,它包含对Google Container Registry的凭证。不需要使用以下方法。

    注意: 如果在AWS EC2上运行集群且准备使用EC2 Container Registry (ECR),每个node上的kubelet会管理和更新ECR的登录凭证。不需要使用以下方法。

    注意: 该方法适用于能够对节点进行配置的情况。该方法在GCE及在其它能自动配置节点的云平台上并不适合。

    Docker将私有仓库的密钥存放在$HOME/.dockercfg$HOME/.docker/config.json文件中。Kubelet上,docker会使用root用户$HOME路径下的密钥。

    推荐如下步骤来为node配置私有仓库。以下示例在PC或笔记本电脑中操作

    1.对于想要使用的每一种凭证,运行 docker login [server],它会更新$HOME/.docker/config.json。1.使用编辑器查看$HOME/.docker/config.json,保证文件中包含了想要使用的凭证1.获取node列表,例如- 如果使用node名称,nodes=$(kubectl get nodes -o jsonpath='{range.items[].metadata}{.name} {end}')- 如果使用node IP ,nodes=$(kubectl get nodes -o jsonpath='{range .items[].status.addresses[?(@.type=="ExternalIP")]}{.address} {end}')1.将本地的.docker/config.json拷贝到每个节点root用户目录下- 例如: for n in $nodes; do scp ~/.docker/config.json root@$n:/root/.docker/config.json; done

    创建使用私有仓库的pod来验证,例如:

    1. $ cat <<EOF > /tmp/private-image-test-1.yaml
    2. apiVersion: v1
    3. kind: Pod
    4. metadata:
    5. name: private-image-test-1
    6. spec:
    7. containers:
    8. - name: uses-private-image
    9. image: $PRIVATE_IMAGE_NAME
    10. imagePullPolicy: Always
    11. command: [ "echo", "SUCCESS" ]
    12. EOF
    13. $ kubectl create -f /tmp/private-image-test-1.yaml
    14. pod "private-image-test-1" created
    15. $

    如果一切正常,一段时间后,可以看到:

    1. $ kubectl logs private-image-test-1
    2. SUCCESS

    如果失败,则可以看到:

    1. $ kubectl describe pods/private-image-test-1 | grep "Failed"
    2. Fri, 26 Jun 2015 15:36:13 -0700 Fri, 26 Jun 2015 15:39:13 -0700 19 {kubelet node-i2hq} spec.containers{uses-private-image} failed Failed to pull image "user/privaterepo:v1": Error: image user/privaterepo:v1 not found

    必须保证集群中所有的节点都有相同的.docker/config.json文件。否则,pod会在一些节点上正常运行而在另一些节点上无法启动例如,如果使用node自动弹缩,那么每个实例模板都需要包含.docker/config.json,或者挂载一个包含这个文件的驱动器。

    .docker/config.json中配置了私有仓库密钥后,所有pod都会能读取私有仓库中的镜像。

    该方法已在6月26日的docker私有仓库和kubernetes v0.19.3上测试通过,其他私有仓库,如quay.io应该也可以运行,但未测试过。

    提前拉取镜像

    注意: 如果在Google Kubernetes Engine 上运行集群,每个节点上都会有.dockercfg文件,它包含对Google Container Registry的凭证。不需要使用以下方法。

    注意: 该方法适用于能够对节点进行配置的情况。该方法在GCE及在其它能自动配置节点的云平台上并不适合。

    默认情况下,kubelet会尝试从指定的仓库拉取每一个镜像但是,如果容器属性imagePullPolicy设置为IfNotPresent或者Never,则会使用本地镜像(优先、唯一、分别)。

    如果依赖提前拉取镜像代替仓库认证,必须保证集群所有的节点提前拉取的镜像是相同的。

    可以用于提前载入指定的镜像以提高速度,或者作为私有仓库认证的一种替代方案

    所有的pod都可以使用node上缓存的镜像

    在pod上指定ImagePullSecrets

    注意: Google Kubernetes Engine,GCE及其他自动创建node的云平台上,推荐使用本方法。

    Kubernetes支持在pod中指定仓库密钥。

    使用Docker Config创建Secret

    运行以下命令,将大写字母代替为合适的值

    1. $ kubectl create secret docker-registry myregistrykey --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
    2. secret "myregistrykey" created.

    如果需要接入多个仓库,可以为每个仓库创建一个secret。当为pod拉取镜像时,kubelet会将imagePullSecrets合入一个独立虚拟的.docker/config.json

    Pod只能引用和它相同namespace的ImagePullSecrets,所以需要为每一个namespace做配置

    通过kubectl创建secret

    由于某种原因在一个.docker/config.json中需要多个项或者需要非上述命令给出的secret,可以create a secret usingjson or yaml。

    请保证:

    • 设置data项的名称为.dockerconfigjson
    • 使用base64对docker文件编码,并将字符准确黏贴到data[".dockerconfigjson"]
    • 设置typekubernetes.io/dockerconfigjson

    示例:

    1. apiVersion: v1
    2. kind: Secret
    3. metadata:
    4. name: myregistrykey
    5. namespace: awesomeapps
    6. data:
    7. .dockerconfigjson: UmVhbGx5IHJlYWxseSByZWVlZWVlZWVlZWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGx5eXl5eXl5eXl5eXl5eXl5eXl5eSBsbGxsbGxsbGxsbGxsbG9vb29vb29vb29vb29vb29vb29vb29vb29vb25ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubmdnZ2dnZ2dnZ2dnZ2dnZ2dnZ2cgYXV0aCBrZXlzCg==
    8. type: kubernetes.io/dockerconfigjson

    如果收到错误消息error: no objects passed to create,可能是 base64 编码后的字符串非法。如果收到错误消息类似Secret "myregistrykey" is invalid: data[.dockerconfigjson]: invalid value …,说明数据已经解码成功,但是不满足.docker/config.json文件的语法。

    在pod中引用imagePullSecrets

    现在,在创建pod时,可以在pod定义中增加imagePullSecrets小节来引用secret

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: foo
    5. namespace: awesomeapps
    6. spec:
    7. containers:
    8. - name: foo
    9. image: janedoe/awesomeapp:v1
    10. imagePullSecrets:
    11. - name: myregistrykey

    对每一个使用私有仓库的pod,都需要做以上操作。

    也可以在serviceAccount 资源中设置imagePullSecrets自动设置imagePullSecrets

    imagePullSecrets可以和每个node上的.docker/config.json一起使用,他们将共同生效。本方法在Google Kubernetes Engine也能正常工作。

    使用场景

    配置私有仓库有多种方案,以下是一些常用场景和建议的解决方案。

    • 集群运行非专有(例如 开源镜像)镜像。镜像不需要隐藏。
      • 使用Docker hub上的公有镜像
      • 无需配置
      • 在GCE/GKE上会自动使用高稳定性和高速的Docker hub的本地mirror
    • 集群运行一些专有镜像,这些镜像对外部公司需要隐藏,对集群用户可见
      • 使用自主的私有Docker registry.
        • 可以放置在Docker Hub,或者其他地方。
        • 按照上面的描述,在每个节点手动配置.docker/config.json
      • 或者,在防火墙内运行一个内置的私有仓库,并开放读取权限
        • 不需要配置Kubenretes
      • 或者,在GCE/GKE上时,使用项目的Google Container Registry
        • 使用集群自动伸缩比手动配置node工作的更好
      • 或者,在更改集群node配置不方便时,使用imagePullSecrets
    • 使用专有镜像的集群,有更严格的访问控制
      • 保证AlwaysPullImages admission controller开启。否则,所有的pod都可以使用镜像
      • 将敏感数据存储在”Secret”资源中,而不是打包在镜像里
    • 多租户集群下,每个租户需要自己的私有仓库
      • 保证AlwaysPullImages admission controller开启。否则,所有租户的所有的pod都可以使用镜像
      • 私有仓库开启认证
      • 为每个租户获取仓库凭证,放置在secret中,并发布到每个租户的namespace下
      • 租户将secret增加到每个namespace下的imagePullSecrets中

    反馈

    此页是否对您有帮助?

    感谢反馈。如果您有一个关于如何使用 Kubernetes 的特定的、需要答案的问题,可以访问Stack Overflow.在 GitHub 仓库上登记新的问题报告问题或者提出改进建议.