创建 Docker 镜像并将其推送到仓库,然后在 Kubernetes pod 中引用它。
容器的 image
属性支持与 docker
命令相同的语法,包括私有仓库和标签。
默认的镜像拉取策略是 IfNotPresent
,在镜像已经存在的情况下,kubelet 将不再去拉取镜像。如果总是想要拉取镜像,您可以执行以下操作:
imagePullPolicy
为 Always
。imagePullPolicy
,并使用 :latest
作为要使用的镜像的标签。imagePullPolicy
和要使用的镜像标签。注意应避免使用 :latest
标签,参见配置镜像最佳实践 获取更多信息。
Docker CLI 现在支持以下命令 docker manifest
以及 create
、annotate
、push
等子命令。这些命令可用于构建和推送清单。您可以使用 docker manifest inspect
来查看清单。
请在此处查看 docker 清单文档: https://docs.docker.com/edge/engine/reference/commandline/manifest/
查看有关如何在构建工具中使用清单的示例: https://cs.k8s.io/?q=docker%20manifest%20(create%7Cpush%7Cannotate)&i=nope&files=&repos=
这些命令依赖于 Docker CLI 并仅在 Docker CLI 上实现。需要编辑 $HOME/.docker/config.json
并将 experimental
设置为 enabled
,或者仅在调用 CLI 命令时将 DOCKER_CLI_EXPERIMENTAL
环境变量设置为 enabled
。
注意:请使用 Docker *18.06 或更高版本*,低版本存在错误或不支持实验性命令行选项。导致容器问题示例 https://github.com/docker/cli/issues/1135。
如果在上传旧清单时遇到麻烦,只需删除 $HOME/.docker/manifests
中旧的清单即可重新开始。
对于 Kubernetes,通常使用带有后缀 -$(ARCH)
的镜像。为了向后兼容,请生成带有后缀的旧镜像。想法是生成具有所有 arch(es) 清单的 pause
镜像,并生成 pause-amd64
镜像,该镜像向后兼容较早的配置或者可能已对带有后缀的镜像进行硬编码的 YAML 文件。
从私有仓库读取镜像时可能需要密钥。 凭证可以用以下方式提供:
- 使用 Google Container Registry - 每个集群 - 在 Google Compute Engine 或 Google Kubernetes Engine 上自动配置 - 所有 Pod 均可读取项目的私有仓库 - 使用 Amazon Elastic Container Registry(ECR) - 使用 IAM 角色和策略来控制对 ECR 仓库的访问 - 自动刷新 ECR 登录凭据 - 使用 Oracle Cloud Infrastructure Registry(OCIR) - 使用 IAM 角色和策略来控制对 OCIR 仓库的访问 - 使用 Azure Container Registry (ACR) - 使用 IBM Cloud Container Registry - 配置节点用于私有仓库进行身份验证 - 所有 Pod 均可读取任何已配置的私有仓库 - 需要集群管理员配置节点 - 预拉镜像 - 所有 Pod 都可以使用节点上缓存的任何镜像 - 需要所有节点的 root 访问权限才能进行设置 - 在 Pod 上指定 ImagePullSecrets - 只有提供自己密钥的 Pod 才能访问私有仓库
下面将详细描述每一项。
Kuberetes 运行在 Google Compute Engine (GCE) 时原生支持 Google Container Registry (GCR)。如果 kubernetes 集群运行在 GCE 或者 Google Kubernetes Engine,使用镜像全名(例如 gcr.io/my_project/image:tag) 即可。
集群中所有 pod 都会有读取这个仓库镜像的权限。
kubelet 将使用实例的 Google service account 向 GCR 认证。实例的 Google service account 拥有 https://www.googleapis.com/auth/devstorage.read_only
,所以它可以从项目的 GCR 拉取,但不能推送。
当 Node 是 AWS EC2 实例时,Kubernetes 原生支持 Amazon Elastic Container Registry。
在 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
要求:
v1.2.0
及以上版本。(例如 运行 /usr/bin/kubelet --version=true
)。v1.3.0
及以上版本。故障排除:
us-west-2
) 凭证,使用凭证 SSH 到主机手动运行 Docker。它行得通吗?--cloud-provider=aws
运行。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 时,可以使用管理员用户或者 service principal 进行身份验证。任何一种情况,认证都通过标准的 Docker 授权完成。本指南假设使用 azure-cli 命令行工具。
首先,需要创建仓库并获取凭证,完整的文档请参考 Azure container registry 文档。
创建好容器仓库后,可以使用以下凭证登录:
DOCKER_USER
: service principal,或管理员用户名称DOCKER_PASSWORD
: service principal 密码,或管理员用户密码DOCKER_REGISTRY_SERVER
: ${some-registry-name}.azurecr.io
DOCKER_EMAIL
: ${some-email-address}
填写以上变量后,就可以 配置 Kubernetes Secret 并使用它来部署 Pod。
IBM Cloud Container Registry 提供了一个多租户私有镜像仓库,可以使用它来安全地存储和共享 Docker 仓库。默认情况下,集成的 Vulnerability Advisor 会扫描私有仓库中的镜像,以检测安全问题和潜在的漏洞。IBM Cloud 帐户中的用户可以访问您的镜像,也可以创建令牌来授予对仓库命名空间的访问权限。
要安装 IBM Cloud Container Registry CLI 插件并为镜像创建命名空间,请参阅 IBM Cloud Container Registry 入门。
可以使用 IBM Cloud Container Registry 将容器从 IBM Cloud 公共镜像 和私有镜像部署到 IBM Cloud Kubernetes Service 集群的默认命名空间。要将容器部署到其他命名空间,或使用来自其他 IBM Cloud Container 的仓库区域或 IBM Cloud 帐户的镜像,请创建 Kubernetes imagePullSecret
。有关更多信息,请参阅从镜像构建容器。
注意:如果在 Google Kubernetes Engine 上运行集群,每个节点上都会有
.dockercfg
文件,它包含 Google Container Registry 的凭证。不需要使用以下方法。
注意:如果在 AWS EC2 上运行集群且准备使用 EC2 Container Registry (ECR),每个 node 上的 kubelet 会管理和更新 ECR 的登录凭证。不需要使用以下方法。
注意:该方法适用于能够对节点进行配置的情况。该方法在 GCE 及在其它能自动配置节点的云平台上并不适合。
注意:截至目前,Kubernetes 仅支持 docker config 的
auths
和HttpHeaders
部分。这意味着不支持凭据助手(credHelpers
或credsStore
)。
Docker 将私有仓库的密钥存放在 $HOME/.dockercfg
或 $HOME/.docker/config.json
文件中。Kubelet 上,docker 会使用 root 用户 $HOME
路径下的密钥。
{--root-dir:-/var/lib/kubelet}/config.json
{cwd of kubelet}/config.json
${HOME}/.docker/config.json
/.docker/config.json
{--root-dir:-/var/lib/kubelet}/.dockercfg
{cwd of kubelet}/.dockercfg
${HOME}/.dockercfg
/.dockercfg
注意:可能必须在环境变量文件中为 kubelet 显式设置
HOME=/root
。
推荐如下步骤来为 node 配置私有仓库。以下示例在 PC 或笔记本电脑中操作:
docker login [server]
,它会更新 $HOME/.docker/config.json
。$HOME/.docker/config.json
,保证文件中包含了想要使用的凭证。nodes=$(kubectl get nodes -o jsonpath='{range.items[*].metadata}{.name} {end}')
nodes=$(kubectl get nodes -o jsonpath='{range .items[*].status.addresses[?(@.type=="ExternalIP")]}{.address} {end}')
.docker/config.json
拷贝到每个节点 root 用户目录下
for n in $nodes; do scp ~/.docker/config.json root@$n:/root/.docker/config.json; done
创建使用私有仓库的 pod 来验证,例如:
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: private-image-test-1
spec:
containers:
- name: uses-private-image
image: $PRIVATE_IMAGE_NAME
imagePullPolicy: Always
command: [ "echo", "SUCCESS" ]
EOF
pod/private-image-test-1 created
如果一切正常,一段时间后,可以看到:
kubectl logs private-image-test-1
SUCCESS
如果失败,则可以看到:
kubectl describe pods/private-image-test-1 | grep "Failed"
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 都会能读取私有仓库中的镜像。
注意:如果在 Google Kubernetes Engine 上运行集群,每个节点上都会有
.dockercfg
文件,它包含 Google Container Registry 的凭证。不需要使用以下方法。
注意:该方法适用于能够对节点进行配置的情况。该方法在 GCE 及在其它能自动配置节点的云平台上并不适合。
默认情况下,kubelet 会尝试从指定的仓库拉取每一个镜像。但是,如果容器属性 imagePullPolicy
设置为 IfNotPresent
或者 Never
,则会使用本地镜像(优先、唯一、分别)。
如果依赖提前拉取镜像代替仓库认证,必须保证集群所有的节点提前拉取的镜像是相同的。
可以用于提前载入指定的镜像以提高速度,或者作为私有仓库认证的一种替代方案。
所有的 pod 都可以使用 node 上缓存的镜像。
注意:Google Kubernetes Engine、GCE 及其他自动创建 node 的云平台上,推荐使用本方法。
Kubernetes 支持在 pod 中指定仓库密钥。
运行以下命令,将大写字母代替为合适的值:
kubectl create secret docker-registry <name> --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
如果已经有 Docker 凭证文件,则可以将凭证文件作为 Kubernetes secret 导入而不是使用上面的命令。根据现有 Docker 凭证创建 Secret 解释了如何安装。如果使用多个私有容器仓库,这将特别有用,因为 kubectl create secret docker-registry
创建了一个仅适用于单个私有仓库的 Secret。
注意:Pod 只能引用和它相同命名空间的 ImagePullSecrets,所以需要为每一个命名空间做配置。
现在,在创建 pod 时,可以在 pod 定义中增加 imagePullSecrets
部分来引用 secret。
cat <<EOF > pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: foo
namespace: awesomeapps
spec:
containers:
- name: foo
image: janedoe/awesomeapp:v1
imagePullSecrets:
- name: myregistrykey
EOF
cat <<EOF >> ./kustomization.yaml
resources:
- pod.yaml
EOF
对每一个使用私有仓库的 pod,都需要做以上操作。
但是,可以通过在 serviceAccount 资源中设置 imagePullSecrets 来自动设置 imagePullSecrets
。检查 将 ImagePullSecrets 添加 Service Account 以获取详细说明。
可以将其与每个节点 .docker/config.json
结合使用。凭据将被合并。这种方法适用于 Google Kubernetes Engine。
配置私有仓库有多种方案,以下是一些常用场景和建议的解决方案。
imagePullSecrets
。如果需要访问多个仓库,则可以为每个仓库创建一个 secret。Kubelet 将任何 imagePullSecrets
合并为单个虚拟 .docker/config.json
文件。
此页是否对您有帮助?
感谢反馈。如果您有一个关于如何使用 Kubernetes 的特定的、需要答案的问题,可以访问 Stack Overflow. 在 GitHub 仓库上登记新的问题 报告问题 或者 提出改进建议.