使用拉取机密将映像从 Azure 容器注册表拉取到 Kubernetes 群集

你可以将 Azure 容器注册表用作容器映像的来源,并将其用于任何 Kubernetes 群集,包括“本地”Kubernetes 群集,例如 minikubekind。 本文演示如何使用 Azure 容器注册表的凭据创建 Kubernetes 拉取机密。 然后,在 Pod 部署中使用该机密从 Azure 容器注册表中拉取映像。

此示例使用 Azure Active Directory 服务主体凭据创建拉取机密。 还可以使用其他 Azure 容器注册表凭据(例如存储库范围访问令牌)配置拉取机密。

备注

虽然会经常用到拉取机密,但会带来额外的管理开销。 如果使用的是 Azure Kubernetes 服务,建议使用其他选项(例如,使用群集的托管标识或服务主体)来安全地拉取映像,而无需在每个 Pod 上额外设置 imagePullSecrets

先决条件

本文假设你已创建了一个专用 Azure 容器注册表。 你还需要确保 Kubernetes 群集正在运行并可通过 kubectl 命令行工具访问。

创建服务主体

若要创建可以访问容器注册表的服务主体,请在本地安装的 Azure CLI 中运行以下脚本。 此脚本已针对 Bash Shell 格式化。

运行脚本之前,请将 ACR_NAME 变量更新为容器注册表的名称。 SERVICE_PRINCIPAL_NAME 值必须在 Azure Active Directory 租户中唯一。 如果收到“'http://acr-service-principal' already exists.”错误,请为服务主体指定另一名称。

如果需要授予其他权限,可以选择修改 az ad sp create-for-rbac 命令中的 --role 值。

运行脚本后,请记下服务主体的 ID密码。 获得其凭据后,可以配置应用程序和服务使其作为服务主体对容器注册表进行身份验证。

#!/bin/bash

# Modify for your environment.
# ACR_NAME: The name of your Azure Container Registry
# SERVICE_PRINCIPAL_NAME: Must be unique within your AD tenant
ACR_NAME=<container-registry-name>
SERVICE_PRINCIPAL_NAME=acr-service-principal

# Obtain the full registry ID for subsequent command args
ACR_REGISTRY_ID=$(az acr show --name $ACR_NAME --query id --output tsv)

# Create the service principal with rights scoped to the registry.
# Default permissions are for docker pull access. Modify the '--role'
# argument value as desired:
# reader:      pull only
# contributor: push and pull
# owner:       push, pull, and assign roles
SP_PASSWD=$(az ad sp create-for-rbac --name $SERVICE_PRINCIPAL_NAME --scopes $ACR_REGISTRY_ID --role reader --query password --output tsv)
SP_APP_ID=$(az ad sp show --id http://$SERVICE_PRINCIPAL_NAME --query appId --output tsv)

# Output the service principal's credentials; use these in your services and
# applications to authenticate to the container registry.
echo "Service principal ID: $SP_APP_ID"
echo "Service principal password: $SP_PASSWD"

使用现有的服务主体

若要向现有服务主体授予注册表访问权限,必须为服务主体分配新角色。 与创建新的服务主体一样,可以授予“拉取”、“推送和拉取”以及“所有者”访问权限。

以下脚本使用 az role assignment create 命令向 SERVICE_PRINCIPAL_ID 变量中指定的服务主体授予“拉取”权限。 如果要授予不同的访问级别,请调整 --role 值。

#!/bin/bash

# Modify for your environment. The ACR_NAME is the name of your Azure Container
# Registry, and the SERVICE_PRINCIPAL_ID is the service principal's 'appId' or
# one of its 'servicePrincipalNames' values.
ACR_NAME=mycontainerregistry
SERVICE_PRINCIPAL_ID=<service-principal-ID>

# Populate value required for subsequent command args
ACR_REGISTRY_ID=$(az acr show --name $ACR_NAME --query id --output tsv)

# Assign the desired role to the service principal. Modify the '--role' argument
# value as desired:
# reader:      pull only
# contributor: push and pull
# owner:       push, pull, and assign roles
az role assignment create --assignee $SERVICE_PRINCIPAL_ID --scope $ACR_REGISTRY_ID --role reader

如果你未保存或记住服务主体密码,则可以使用 az ad sp credential reset 命令重置密码:

az ad sp credential reset  --name http://<service-principal-name> --query password --output tsv

此命令为你的服务主体返回一个新的有效密码。

创建映像拉取机密

Kubernetes 使用“映像拉取机密” 来存储向注册表证明身份所需的信息。 若要为 Azure 容器注册表创建拉取机密,请提供服务主体 ID、密码和注册表 URL。

使用以下 kubectl 命令创建映像拉取机密:

kubectl create secret docker-registry <secret-name> \
    --namespace <namespace> \
    --docker-server=<container-registry-name>.azurecr.cn \
    --docker-username=<service-principal-ID> \
    --docker-password=<service-principal-password>

其中:

说明
secret-name 映像拉取机密的名称,例如 acr-secret
namespace 用来放置机密的 Kubernetes 命名空间
仅当要将机密置于默认命名空间之外的命名空间中时才需要此项
container-registry-name Azure 容器注册表的名称,例如 myregistry

--docker-server 是注册表登录服务器的完全限定名称
service-principal-ID Kubernetes 用来访问注册表的服务主体的 ID
service-principal-password 服务主体密码

使用映像拉取机密

创建映像拉取机密后,可以使用它来创建 Kubernetes Pod 和部署。 在部署文件中,在 imagePullSecrets 下提供机密名称。 例如:

apiVersion: v1
kind: Pod
metadata:
  name: my-awesome-app-pod
  namespace: awesomeapps
spec:
  containers:
    - name: main-app-container
      image: myregistry.azurecr.cn/my-awesome-app:v1
      imagePullPolicy: IfNotPresent
  imagePullSecrets:
    - name: acr-secret

在前面的示例中,my-awesome-app:v1 是要从 Azure 容器注册表中拉取的映像的名称,acr-secret 是你创建的用于访问注册表的拉取密钥的名称。 部署 Pod 时,如果群集上尚无映像,则 Kubernetes 会自动从注册表中拉取映像。

后续步骤