aliyun-acr-credential-helper是一个可以在ACK集群中免密拉取ACR企业版私有镜像的组件。本文通过列举常用场景介绍如何使用免密组件拉取私有镜像。

前提条件

背景信息

免密组件通过读取ACK集群内的kube-system命名空间中的acr-configuration的配置,进行私有镜像拉取。当前支持针对私有镜像仓库使用以下四种权限之一的策略进行配置:
  • 使用默认的RAM角色进行拉取(默认策略,同账号场景下推荐使用)。
  • 通过配置子账号的AccessKey ID和AccessKey Secret进行拉取(支持跨账号)。
  • 通过配置RAM AssumeRole进行拉取(支持跨账号)。
  • 通过配置RRSA进行拉取(支持跨账号,跨账号场景下推荐使用)。

实现机制

根据升级并配置免密组件的要求配置免密组件后,免密组件会在集群中创建Secrets并关联到配置中指定的ServiceAccount上,任何使用这个ServiceAccount的Pod都会默认使用免密组件生成的Secrets进行镜像拉取,从而达到免密拉取镜像的效果。
重要 针对新创建ServiceAccount部署应用的场景(如部署Helm Chart),免密组件ServiceAccount关联Secrets可能存在延迟,建议使用Webhook功能,更多内容,请参见其他功能

使用限制

使用免密组件涉及的镜像及集群限制如下:

  • 镜像
    • 支持拉取集群当前用户容器镜像服务中的私有镜像,通过跨账号授权或AccessKey ID和AccessKey Secret配置可以拉取其他用户的私有镜像。
    • 支持拉取容器镜像服务企业版实例和个人版实例(兼容场景)中的私有镜像。
  • 集群
    • 支持集群多命名空间免密拉取。
    • 支持的集群类型:
      • 专有版Kubernetes集群。
      • 托管版Kubernetes集群。
    • 支持的集群版本:
      • 专有版Kubernetes集群:高于或等于1.11.2的版本默认支持免密拉取镜像。低于1.11.2版本请您手动升级,请参见升级ACK集群K8s版本
      • 托管版Kubernetes集群:所有版本。

注意事项

导致免密组件未生效的动作

  • 在Kubernetes资源(例如无状态应用Deployment)模板中配置拉取凭证(imagePullSecret)会导致免密组件失效,如果需使用免密组件,请避免手工配置拉取凭证(imagePullSecret)。
  • 如果部署的Kubernetes资源(例如无状态应用Deployment)使用了自定义的ServiceAccount,需先调整免密组件配置文件中Service-Account字段,使其作用于自定义的ServiceAccount,再进行部署资源操作。
  • 确认Kubernetes集群所属地域与要拉取的镜像所在的地域是否一致,默认配置只可以拉取本地域的镜像。如果需要跨地域拉取镜像,请参见下面的场景二。
  • 在集群中创建新的ServiceAccount一段时间后,免密组件生成的凭证才会更新到应用使用到的ServiceAccount中, 使用ServiceAccount的应用才能使用凭证拉取镜像。如果创建完ServiceAccount之后立即创建应用可能会出现因鉴权失败无法拉取的情况。
  • 免密组件默认覆盖ACK中所有命名空间中默认的ServiceAccount中的imagePullSecrets字段。被覆盖的ServiceAccount会随着对应kube-system命名空间中acr-configuration配置项中的service-account字段变动而变动。
  • 在修改kube-system命名空间中的acr-configuration配置项时,请确认缩进是否与给出的场景的例子相同。建议直接复制对应场景的YAML内容到编辑器中,修改对应的值然后直接应用到集群,以保证YAML格式的正确性。

安全注意事项

使用子账号的AccessKey ID和AccessKey Secret进行镜像拉取的情况下,需要把访问密钥写入configMap,这样存在一定的密钥泄露风险。请确定AccessKey ID和AccessKey Secret所属的RAM角色只拥有拉取容器镜像的相关权限。推荐使用其他几种方式。

升级并配置免密组件

在使用免密组件拉取镜像前,您可能需要升级组件并对组件进行配置,操作步骤如下。

  1. 升级aliyun-acr-credential-helper组件。
    关于aliyun-acr-credential-helper组件更多信息,请参见aliyun-acr-credential-helper。此组件升级不会对业务造成影响。
    1. 登录容器服务管理控制台,在左侧导航栏选择集群
    2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择运维管理 > 组件管理
    3. 组件管理页面,单击安全页签,找到aliyun-acr-credential-helper,单击升级
  2. 设置acr-configuration配置项。
    方式一:通过控制台方式设置acr-configuration配置项。
    1. 登录容器服务管理控制台,在左侧导航栏选择集群
    2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择配置管理 > 配置项
    3. 配置项页面的上方命名空间下拉框中,选择kube-system,然后找到配置项acr-configuration,然后通过以下两种方式配置acr-configuration。
      • 方式一:单击其右侧的编辑,设置配置项键和值。

        如果您没有acr-configuration配置项,请参见创建配置项。关于如何更新配置项,请参见修改配置项

      • 方式二:单击其右侧的YAML编辑,设置配置项键和值。
    方式二:通过kubectl命令行的方式设置acr-configuration配置项。
    1. 执行以下命令打开acr-configuration配置项的编辑页。
      kubectl edit cm acr-configuration -n kube-system
    2. 根据实际情况设置acr-configuration配置项的值。
    acr-configuration配置项的键和值说明如下。
    配置项键配置项键说明配置项值
    service-account使免密组件作用于指定的服务账号。默认为default
    说明 如果要配置多个请以英文半角逗号(,)分隔, 如果设置为“*”, 表示支持所有命名空间下的所有ServiceAccount。
    acr-registry-info容器镜像的实例信息数组,YAML多行字符串格式,每个实例以三元组方式配置。
    说明 实例信息三元组:
    • instanceId:实例ID,企业版实例必须配置此项。
    • regionId:可选,默认为本地地域。
    • domains:可选,默认为相应实例的所有域名。若要指定个别域名,多个以英文半角逗号(,)分隔。
    默认值为空,表示免密拉取同地域的个人版实例镜像(兼容场景)。
    针对企业版容器镜像实例,配置示例如下:
    - instanceId: "cri-instanceId"  
      regionId: "cn-hangzhou"
      domains: "xxx.com,yyy.com"
    watch-namespace期望能免密拉取镜像的Namespace。默认值为default
    说明
    • 当取值为all时,表示期望所有Namespace都能免密拉取。如果需要配置多个Namespace时,以英文半角逗号(,)分隔。
    • 推荐配置生效Namespace为客户业务Namespace,尽量避免配置all或者集群系统组件相关Namespace,使集群系统组件镜像无法拉取。
    expiring-threshold本地缓存凭证过期阈值。默认值为15m
    说明 建议使用15min。即在缓存过期15分钟前进行凭证更新。

场景一:配置同账号拉取镜像

您需要检查当前账号ACR拉取的权限。

  1. 登录容器服务管理控制台,在左侧导航栏选择集群
  2. 集群管理页面,单击目标集群名称或者目标集群右侧操作列下的详情
  3. 集群信息页面,选择集群资源,单击Worker RAM角色右侧链接。
  4. 在RAM角色基本信息的权限管理页面,单击目标权限策略名称。
  5. 请确认权限策略有如下内容,若没有,单击修改策略内容,在策略内容区域,增加如下字段,单击确定
    {
      "Action": [
         "cr:GetAuthorizationToken",
         "cr:ListInstanceEndpoint",
         "cr:PullRepository"
      ],
      "Resource": "*",
      "Effect": "Allow"
    }
    按照以下方式修改配置项acr-configuration中的configMap配置拉取企业版的私有镜像。配置步骤,请参见2
    data:
        service-account: "default"
        watch-namespace: "all"
        expiring-threshold: "15m"
        notify-email: "cs@aliyuncs.com"
        acr-registry-info:|
          - instanceId: "cri-instanceId"
            regionId: "cn-hangzhou"
            domains: "instance.default.domain.com,instance.custom.domain.com"

场景二:配置跨地域拉取镜像权限

如果需要拉取的镜像与当前ACK集群不属于同一地域的时候,需要修改配置项acr-configuration中的configMap

例如,默认仓库同时拉取北京地域与杭州地域的镜像,配置如下。配置步骤请参见上述配置组件
重要 开启跨地域拉取镜像后,组件将通过公网调用目标地域的OpenAPI,集群须具有出公网能力。
data:
    service-account: "default"
    watch-namespace: "all"
    expiring-threshold: "15m"
    notify-email: "cs@aliyuncs.com"
    acr-registry-info: |
      - instanceId: "cri-instanceId"
        regionId: "cn-beijing"
      - instanceId: "cri-instanceId"
        regionId: "cn-hangzhou"            

场景三:配置跨账号拉取权限

跨账号拉取权限分为:
  • 使用RRSA模式进行跨账号拉取:A用户扮演B用户的角色拉取B用户的私有镜像。
  • 使用角色扮演进行跨账号拉取:A用户扮演B用户的角色拉取B用户的私有镜像。
  • 使用子账号的AK及SK进行跨账号拉取:A用户使用B用户的子账号拉取B用户的私有镜像。

使用RRSA进行跨账号拉取

基于适用于服务账户的RAM角色(RAM Roles for Service Accounts,简称RRSA)功能,可以在集群内为组件实现Pod维度的权限隔离。

前提条件

RRSA功能目前仅支持在1.22及以上版本的集群(即ACK标准版、ACK Pro版、ASK标准版和ASK Pro版)中拉取ACR企业版实例(基础版,标准版,高级版)的镜像。
重要
  • 开启RRSA功能需要将组件升级到v23.02.06.1-74e2172-aliyun或以上版本。
  • 当开启RRSA功能后,由组件生成的凭证将不支持个人版非公开镜像拉取,同时也不支持本文中提到的其他的鉴权方式。
  • 启用免密插件的RRSA功能首先需要在集群基本信息中启用RRSA,再进行免密插件RRSA的相关配置。若顺序掉转,配置完成后,需要删除免密插件的Pod,RRSA功能才会生效。

启用集群的RRSA功能

  • 方式一:通过容器服务控制台开启
    1. 登录容器服务管理控制台,在左侧导航栏单击集群
    2. 集群列表页面中,单击目标集群名称或者右侧操作列下的详情
    3. 集群详情页面,选择基本信息页签,单击RRSA OIDC提供商URL右侧的启用RRSA
    4. 启用RRSA对话框,单击确定

      当集群状态由更新中变为运行中时,说明该集群的RRSA特性已变更完成,RRSA OIDC提供商URL右侧会显示OIDC提供商的URL链接。

  • 方式二:通过命令行工具ack-ram-tool开启
    您也可以使用命令行工具ack-ram-tool来启用RRSA功能,对应命令行示例如下,请替换<cluster_id>为您的集群ID。
    ack-ram-tool rrsa enable -c <cluster_id>

启用组件的RRSA功能

集群开启RRSA功能后,需要按照以下步骤进行配置。假设A用户为集群所有者,B用户为容器镜像服务实例所有者,现在需要授权A用户的集群具备访问B用户容器镜像服务资源的权限。

  1. 配置A用户的RAM角色
    在A用户中创建一个角色,并修改其信任策略。
    • 将示例中的<oidc_issuer_url>替换为当前集群中OIDC提供商的URL。该URL可在容器服务管理控制台集群信息页面的基本信息页签获取。
    • 将示例中的<oidc_provider_arn>替换为当前集群OIDC提供商的ARN。该ARN可在容器服务管理控制台集群信息页面的基本信息页签获取。
    {
      "Statement": [
        {
          "Action": "sts:AssumeRole",
          "Condition": {
            "StringEquals": {
              "oidc:aud": "sts.aliyuncs.com",
              "oidc:iss": "<oidc_issuer_url>",
              "oidc:sub": "system:serviceaccount:kube-system:aliyun-acr-credential-helper"
            }
          },
          "Effect": "Allow",
          "Principal": {
            "Federated": [
              "<oidc_provider_arn>"
            ]
          }
        }
      ],
      "Version": "1"
    }
  2. 配置B用户的RAM角色
    在B用户中创建一个角色,对角色添加如下权限策略,授予这个角色具有获取实例信息及拉取镜像权限。
    {
        "Version": "1",
        "Statement": [
            {
                "Action": [
                    "cr:GetAuthorizationToken",
                    "cr:ListInstanceEndpoint",
                    "cr:PullRepository"
                ],
                "Resource": "*",
                "Effect": "Allow"
            }
        ]
    }

    该RAM角色可以设置角色最大会话时间,可设置时间范围为3600秒到43200秒,而角色会话时间在下文的配置项中的expireDuration也需要设置。推荐这里的设置和配置项的expireDuration的值一致。允许expireDuration小于等于角色最大会话时间。

  3. 授权A用户可扮演B用户角色

    在B用户创建的拥有ACR相关权限的角色中,选择信任策略管理,添加A用户角色ARN。

    在创建的A角色中添加AliyunSTSAssumeRoleAccess权限策略,授予这个角色具有角色扮演的权限。

调整组件配置项

按照如下配置内容修改免密组件的配置项。
data:
  rrsa: |
    enable: true
  acr-registry-info: |
    - instanceId: cri-xxx
      regionId: cn-hangzhou
      rrsaRoleARN: aUserRoleARN
      rrsaOIDCProviderRoleARN: aUserClusterOIDCProviderRoleARN
      assumeRoleARN: bUserRoleARN
      expireDuration: 3600
配置项键配置项说明配置项值
rrsaRoleARN上文中A用户创建的角色的ARN。acs:ram::aaa
rrsaOIDCProviderRoleARN上文中A用户ACK控制台集群基本信息中的提供商ARN。acs:ram::bbb
assumeRoleARN上文中B用户创建的角色的ARN。acs:ram::ccc
expireDuration上文中B用户创建的角色的会话时间,等同于免密组件生成的临时凭证的有效期。
重要 expireDuration的值不应大于B用户创建角色的最大会话时间。
默认3600,最大支持43200,同时需要将B用户创建角色的最大会话时间调整为43200。

使用角色扮演进行跨账号拉取

使用角色扮演进行跨账号拉取
说明
配置原则如下:
  1. B用户(RAM角色)可以拉取指定私有仓库下的私有镜像(B用户RAM角色有cr.*相关的权限)。
  2. B用户(RAM角色)允许让A用户下的ACK Worker RAM角色扮演(信任策略)。
  3. A用户下的ACK集群的Worker RAM角色有扮演B用户(RAM角色)的权限(AliyunAssumeRoleAccess)。
  4. 设置A用户下的Worker RAM角色扮演B用户(configMap中的assumeRoleARN)。
  1. 创建B用户的受信实体为阿里云账号类型的RAM角色,并确保该RAM角色拥有拉取B用户私有镜像的权限。
    1. 创建RAM角色。

      具体操作请参见创建可信实体为阿里云账号的RAM角色

    2. 自定义RAM角色权限策略内容,确保该RAM角色拥有拉取B用户私有镜像的权限。
      具体操作请参见修改自定义权限策略内容和备注
      重要 请确保该RAM角色有cr.*的相关权限。
      ```
      {
      "Action": [
       "cr:GetAuthorizationToken",
       "cr:ListInstanceEndpoint",
       "cr:PullRepository"
      ],
      "Resource": [
      "*"
      ],
      "Effect": "Allow"
      }
      
      ```
      添加字段位置如下图所示。RAM有CR的相关权限
  2. 在创建的B用户的RAM角色上配置信任策略,允许A用户(需要拉取B用户下的私有镜像)的ACK集群的Worker RAM角色来扮演B用户。
    查看A用户的ACK集群的Worker RAM角色的ARN信息。
    1. 查看ARN信息具体步骤,请参见如何查看RAM角色的ARN?
    2. 配置信任策略。
      1. RAM控制台左侧导航栏,单击RAM角色管理,找到目标RAM角色并单击RAM角色名称。
      2. 在RAM角色基本信息页,单击信任策略管理页签,然后使用A用户的Worker RAM角色的ARN修改信任策略。RamRoleARN
  3. 确认A用户的Worker RAM角色拥有AssumeRole权限。AssumeRule权限

    具体操作步骤,请参见查看权限策略基本信息

  4. 调整组件配置,新增assumeRoleARN配置。
    配置内容为B用户Worker RAM角色的ARN。查看ARN信息具体步骤,请参见如何查看RAM角色的ARN?YAML配置示例如下。配置步骤,请参见上述配置组件
    data:
        service-account: "default"
        watch-namespace: "all"
        expiring-threshold: "15m"
        notify-email: "cs@aliyuncs.com"
        acr-registry-info: |
          - instanceId: ""
            regionId: "cn-beijing"
            domains: "registry.cn-beijing.aliyuncs.com"
            assumeRoleARN: "acs:ram::.*:role/kubernetesworkerrole-test"
            expireDuration: 3600

使用子账号的AK及SK进行跨账号拉取

使用子账号的AK及SK进行跨账号拉取
  1. 创建一个RAM用户并为该用户添加cr镜像拉取权限。有关配置cr镜像拉取权限的具体操作步骤,请参见场景三:配置跨账号拉取权限
  2. 配置kube-system命名空间中的配置项acr-configuration,并填入创建的RAM用户的访问密钥AccessKey ID和AccessKey Secret。

    此种方式可以使免密组件直接使用创建的RAM用户拉取私有镜像。查看访问密钥的具体步骤,请参见查看RAM用户的AccessKey信息

    配置示例如下。配置步骤请参见上述配置组件
    data:
        service-account: "default"
        watch-namespace: "all"
        expiring-threshold: "15m"
        notify-email: "cs@aliyuncs.com"
        acr-registry-info: |
          - instanceId: ""
            customAccessKey: "xxxxx" // 此处填写刚创建的RAM用户的AccessKey ID。
            customAccessKeySecret: "xxxxxx" // 此处填写刚创建的RAM用户的AccessKey Secret。

其他功能

拉取个人版实例中的私有镜像

针对个人版迁移到企业版过程中需要在过渡阶段同时拉取企业版实例及个人版实例私有镜像的场景,按照如下方式修改acr-configuration中configMap的配置项。关于配置的更多信息,请参见2
data:
    service-account: "default"
    watch-namespace: "all"
    expiring-threshold: "15m"
    notify-email: "cs@aliyuncs.com"
    acr-registry-info: |
      - instanceId: ""
      - instanceId: "cri-xxxx"

ServiceAccount创建即时使用支持

启用该功能后,ServiceAccount在创建时会即时注入Secret,满足特定场景下ServiceAccount无延迟注入Secret的需求,比如通过Helm Chart同时创建ServiceAccount和Deployment的场景,其他场景不推荐开启该功能。
重要 开启ServiceAccount创建即时使用功能需要将组件升级到v23.02.06.1-74e2172-aliyun或以上版本。

配置方法

更新组件为最新版本后,按照如下方式修改acr-configuration中configMap的配置项。配置步骤请参见上述配置组件
data:
  webhook-configuration: |
    enable: true
    failure-policy: Ignore
    timeout-seconds: 10
表 1. 配置项说明
配置项键配置项键说明配置项值
enable是否开启本功能。可选true或false。默认为false,即不开启。
failure-policy当本功能出现异常时的失败处理策略。可选Ignore或Fail。Ignore即忽略异常,使ServiceAccount正常创建完成(但可能不会附上可拉取镜像的Secret);Fail即异常时中断创建ServiceAccount(不推荐,可能导致业务部署失败)。受集群APIServer的限制,当timeout-seconds设置为15,failure-policy设置为Fail,持续每秒创建10个ServiceAccount时,会出现超时创建ServiceAccount失败。
timeout-seconds本功能的单个ServiceAccount创建请求处理超时时长,超出这个时长则按照failure-policy配置进行反馈。默认为 10,单位为秒(配置项值不用填写单位)。

相关文档