全部产品
Search
文档中心

密钥管理服务:ACK容器环境中部署KMS Agent获取凭据

更新时间:Jun 10, 2026

KMS支持您在ACK集群中以Sidecar形式部署KMS Agent,Agent通过RRSA机制向KMS获取凭据值,业务应用通过本地接口向Agent获取KMS凭据。该方式无需集成SDK,可以降低应用改造成本,确保统一的集成标准,适用于大规模应用访问KMS的场景。本文介绍如何在ACK容器环境中部署KMS Agent获取凭据。

前置概念

在您了解本最佳实践前,请先了解以下内容:

  • 什么是KMS Agent:KMS Agent是一个HTTP代理服务,负责获取KMS服务中的凭据值并缓存在内存中,应用通过HTTP请求向KMS Agent获取凭据值。

  • 通过RRSA配置ServiceAccount的RAM权限实现Pod权限隔离:如果您的应用程序部署在阿里云ACK容器集群上,则可以基于RRSA(RAM Roles for Service Accounts)功能,在容器集群内实现应用隔离的RAM角色功能,各个应用可以扮演独立的RAM角色,访问阿里云OpenAPI。

应用场景

在ACK容器环境中部署KMS Agent获取凭据,使用RRSA作为访问凭证,适用于以下业务场景。

  • 企业需要解决last key问题。

    企业将敏感凭证托管至阿里云KMS以提升安全性,但由于访问KMS本身仍需进行身份认证,若长期依赖固定AccessKey访问云服务,会导致KMS的访问凭证成为新的潜在安全隐患。

    通过在阿里云ACK集群上开启RRSA功能,基于RRSA可以为不同Pod关联不同的RAM角色,不同Pod内的各个应用可以扮演独立的RAM角色并使用获取的临时凭证访问云资源,从而实现应用RAM权限最小化以及无AccessKey访问阿里云OpenAPI,避免AccessKey泄露。

  • 企业需要隔离不同应用对凭据的访问权限。

    例如同一应用的测试与正式环境以及不同应用间,都需要进行权限隔离,避免访问权限扩大,凭据被非法获取。

    RRSA基于RAM策略,不同的应用运行在不同的namespace和service account,绑定不同的ramrole,通过为ramrole授予不同的权限,实现不同应用对KMS凭据的访问权限控制。

  • 降低应用与KMS的集成的研发成本。

    如果只有少数几个应用需要访问KMS,应用可以集成SDK,但对于大中型企业来说,面对成百上千的应用,让每个应用改造去集成SDK,并且都按照一致的标准去设计容灾和缓存是非常困难的。同时由于一般中国内地企业的安全、运维、开发分属不同团队,已经存在的开源external secret方式在中国内地企业也不太适用,其更适合于集开发运维一体的devops模式。

    此时您可以通过KMS Agent来获取凭据。在ACK容器集群环境中,KMS Agent作为Sidecar容器运行在与业务容器相同的Pod里。当ACK集群启动RRSA后,KMS Agent会自动以RRSA RamRole的身份访问KMS,不需要再设置任何访问凭证。Agent从远端KMS获取凭证并缓存到内存,业务应用再从Agent获取凭据。

解决方案架构

下图以用户拥有两个应用dev和prod为例,通过ACK容器环境中部署KMS Agent获取凭据,不同环境的应用只能访问各自对应的KMS凭据。

image

使用限制

  • ACK集群支持ACK托管集群、ACK专有集群、ACK注册集群、ACK Serverless集群。

  • ACK集群与KMS实例需要在同一地域。

操作步骤

以下流程演示了ACK、RAM、KMS如何配置,以实现业务应用通过KMS Agent获取凭据。研发只需要在KMS创建凭据,然后在应用里从本地检索即可,其余配置由运维和安全团队提前配置。整个过程中,研发不需要在业务代码里集成SDK,也不需要关心应用访问KMS的认证鉴权以及缓存容灾等。

image

步骤一:构建KMS Agent可执行文件

  1. 安装Golang环境。具体操作,请参见Go安装指南

  2. 下载源码和依赖。

    1. 请访问Git官网,下载并安装Git工具。

    2. 执行以下命令下载源码和依赖。

      git clone https://github.com/aliyun/alibabacloud-kms-agent
      go mod download
  3. 在项目根目录下,执行go build .命令编译可执行文件。文件默认名称alibabacloud-kms-agent,默认保存在项目根目录下 。

    编译环境与部署环境一致,执行go build .命令即可。如果编译环境和部署环境不一致,请参考以下命令进行跨平台编译,生成64位可执行文件。

    编译环境

    部署环境为Mac

    部署环境为Linux

    部署环境为Windows

    Mac

    go build .

    CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build .

    CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build .

    Linux

    CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build .

    go build .

    CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build .

    Windows

    SET CGO_ENABLED=0 SET GOOS=darwin SET GOARCH=amd64 go build .

    SET CGO_ENABLED=0 SET GOOS=linux SET GOARCH=amd64 go build .

    go build .

  4. 在项目根目录下,查看是否存在可执行文件alibabacloud-kms-agent。

步骤二:启用ACK RRSA并授权其访问特定的凭据

  1. 启用ACK RRSA功能。

    创建集群时开启

    创建ACK托管集群ACK Edge集群时,您可以在集群配置的高级选项(选填)区域,选中开启RRSA功能。

    image

    在集群信息页面开启

    1. 登录容器服务管理控制台,在左侧导航栏选择集群列表

    2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择集群信息

    3. 基本信息页签的安全与审计区域,单击RRSA OIDC右侧的开启image

    4. 在弹出的启用 RRSA对话框,单击确定

      基本信息区域,当集群状态由更新中变为运行中后,表明该集群的RRSA特性已变更完成。

  2. 打开集群详情页,在基本信息页签的安全与审计区域,将鼠标悬浮至RRSA OIDC右侧已开启上面,查看提供商的URL链接和ARN信息。开启 RRSA 后,该区域将显示 RRSA OIDC提供商 URL提供商 ARN,后续配置 RAM 角色信任策略时需要使用这两项信息。

  3. 创建一个可信实体为身份提供商的RAM角色。

    1. 使用RAM管理员登录RAM控制台,在身份管理 > 角色页面。

    2. 单击创建角色,在创建页面右上角,单击切换编辑器

    3. 在编辑器中指定具体的OIDC身份提供商。选择可视化编辑模式,并参考如下说明,完成配置。

      说明

      更多模式,请参见创建OIDC身份提供商的RAM角色

      1. 主体中选择身份提供商后,单击下方编辑。

      2. 添加主体弹窗中,参考如下说明,完成配置。

        • 身份提供商类型:选择OIDC。

        • 身份提供商:开启RRSA后,ACK集群会默认创建身份提供商,命名格式为ack-rrsa-<cluster_id>。其中,<cluster_id>为集群ID。

        • 操作:保持默认。即勾选sts:AssumeRole。

        • 条件:在默认的oidc:issoidc:aud限制条件基础上,新增一个限制条件:

          • 条件键:选择oidc:sub

          • 运算符:选择StringEquals

          • 条件值:system:serviceaccount:<namespace>:<serviceAccountName>

            • <namespace>:应用所在的命名空间。

            • <serviceAccountName>:服务账户名称。

            本文以system:serviceaccount:rrsa-dev:dev-sa为例, 其中 rsa-dev 是下一步需要创建 k8s namespace,dev-sa 是下一步需要创建的 k8s service account。

    4. 创建角色对话框中,设置角色名称,然后单击确定。本文角色名称以dev-role-for-rrsa为例。

    5. 查看并确认dev-role-for-rrsa 的信任策略:该策略表示允许特定的服务账户通过阿里云RRSA(RAM Roles for Service Accounts) ,在满足 OIDC 身份验证条件后,担任某个RAM角色。

      {
        "Statement": [
          {
            "Action": "sts:AssumeRole",
            "Condition": {
              "StringEquals": {
                "oidc:aud": [
                  "sts.aliyuncs.com"
                ],
                "oidc:iss": [
                  "https://oidc-ack-cn-hongkong.oss-cn-hongkong.aliyuncs.com/cf01******"
                ],
                "oidc:sub": [
                  "system:serviceaccount:rrsa-dev:dev-sa"
                ]
              }
            },
            "Effect": "Allow",
            "Principal": {
              "Federated": [
                "acs:ram::5269************:oidc-provider/ack-rrsa-cf01******"
              ]
            }
          }
        ],
        "Version": "1"
      }
  4. 创建权限策略并授权给RAM角色。

    1. 权限策略名称以dev-role-for-rrsa-kms-policy为例,策略内容以仅允许访问带有env:dev 标签的凭据为例。在RAM 访问控制控制台左侧导航栏选择权限策略,单击创建权限策略,选择脚本编辑页签,在策略编辑器中输入以下策略内容。

      权限策略内容如下所示:

      {
          "Version": "1",
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": [
                      "kms:Decrypt",
                      "kms:GetSecretValue"
                  ],
                  "Resource": "*",
                  "Condition": {
                      "StringEqualsIgnoreCase": {
                          "kms:tag/env": [
                              "dev"
                          ]
                      }
                  }
              }
          ]
      }
    2. 将dev-role-for-rrsa-kms-policy权限策略,授权给dev-role-for-rrsa角色。在RAM访问控制的角色列表中找到角色 dev-role-for-rrsa,为其新增授权资源范围选择账号级别授权主体选择 dev-role-for-rrsa,在权限策略中搜索并选中自定义策略 dev-role-for-rrsa-kms-policy,单击确认新增授权

步骤三:在ACK中创建Namespace和Service Account

Namespace将ACK集群划分为逻辑隔离的虚拟空间,用于区分开发、测试、生产等环境,不同Namespace中的应用默认无法互访资源,为RAM角色绑定提供物理边界。Service Account为Pod提供身份标识,通过RRSA机制与RAM角色动态绑定。

  1. 通过YAML文件创建Namespace。

    Namespace名称以rrsa-dev为例,YAML文件名称以namespace.yaml为例。

    apiVersion: v1
    kind: Namespace
    metadata:
      name: rrsa-dev
  2. 执行如下命令在ACK集群中创建名为 rrsa-dev 的 Namespace。

    kubectl apply -f namespace.yaml

    查看Namespace是否创建成功:

    kubectl get namespaces

    若输出包含rrsa-dev,即代表创建成功。

  3. 通过YAML文件创建Service Account。

    Service Account名称以dev-sa为例,YAML文件名称以serviceaccount.yaml为例。

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: dev-sa
      namespace: rrsa-dev
  4. 执行如下命令在 rrsa-dev 中创建一个名为 dev-sa 的ServiceAccount。

    kubectl apply -f serviceaccount.yaml

    查看 ServiceAccount 是否创建成功:

    kubectl get serviceaccount -n rrsa-dev

    若输出包含 dev-sa,即代表创建成功。

步骤四:制作sidecar容器镜像

将KMS Agent作为sidecar容器与应用程序容器一起部署到阿里云的ACK容器服务。

  1. 在config.toml中配置KMS Agent的运行参数。

    说明

    config.toml是Agent的配置文件,您可以在步骤一获取的alibabacloud-kms-agent源码的configs目录下查看到该文件。

    [Server]
    HttpPort = 2025
    [KMS]
    Region = "cn-hangzhou"
    [Cache]
    CacheType = "InMemory"
    CacheSize = 1000
    TtlSeconds = 300
    [Log]
    LogLevel = "Debug"
    LogPath = "./logs/"
    MaxSize = 100
    MaxBackups = 2

  2. 创建Dockerfile文件。

    以Agent部署在deploy/ack/agent路径下为例,在该路径下创建Dockerfile。文件内容,请参考agent_Dockerfile

    # Use the centos image as the base
    FROM centos:centos7
    # Set the working directory inside the container
    WORKDIR /usr/local/alibabacloudkmsagent
    # Copy the binary and config to the container
    COPY alibabacloud-kms-agent .
    COPY config.toml .
    # Set the entry point to run the kms agent
    ENTRYPOINT ["./alibabacloud-kms-agent", "agent", "./config.toml"]

  3. 将步骤1和步骤2创建的文件拷贝到deploy/ack/agent目录下。

    deploy/ack/agent
    ├── alibabacloud-kms-agent
    ├── config.toml
    ├── Dockerfile.agent
  4. 编译sidecar容器镜像并上传到阿里云镜像服务。

    # 编译
    docker build -t registry.cn-hangzhou.aliyuncs.com/<ns>/<repo>:kmsagent-v1.0 .
    # 上传
    docker push registry.cn-hangzhou.aliyuncs.com/<ns>/<repo>:kmsagent-v1.0

步骤五:制作业务容器镜像

  1. 以业务应用部署在deploy/ack/app路径下为例,在该路径下编写应用容器镜像的Dockerfile。

    # Use the centos image as the base
    FROM centos:centos7
    # Set the working directory inside the container
    WORKDIR /
    # Set the entry point to run the kms agent
    ENTRYPOINT ["sleep", "360000"]

  2. 编译应用容器镜像,并将镜像上传到阿里云镜像仓库。

    # 编译
    docker build -t registry.cn-hangzhou.aliyuncs.com/<ns>/<repo>:app-v1.0 .
    # 上传
    docker push registry.cn-hangzhou.aliyuncs.com/<ns>/<repo>:app-v1.0

步骤六:发布应用

方法一:自定义Deployment模板

编写一个自定义的deployment模板,将KMS Agent与应用容器部署在同一个Pod中作为附加容器,将app与sidecar容器放到同一个Pod或者Deployment里一起部署。如何运行您的容器应用,请参见创建无状态工作负载Deployment

  • KMS_TOKEN:指定Agent启动时生成的SSRF Token文件的存储路径。

  • ALIBABA_CLOUD_ROLE_ARN:RAM角色的ARN。

  • ALIBABA_CLOUD_OIDC_PROVIDER_ARN :OIDC身份提供商的ARN,此处为ACK集群ARN。

  • ALIBABA_CLOUD_OIDC_TOKEN_FILE:包含OIDC Token的文件路径。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: rrsa-dev
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      serviceAccountName: dev-sa
      containers:
      - name: kmsagent
        image: registry-vpc.cn-hangzhou.aliyuncs.com/<ns>/<repo>:kmsagent-v1.0
        env:
        - name: ALIBABA_CLOUD_ROLE_ARN
          value: acs:ram::<uid>:role/dev-role-for-rrsa
        - name: ALIBABA_CLOUD_OIDC_PROVIDER_ARN
          value: acs:ram::<uid>:oidc-provider/ack-rrsa-<ackClusterId>
        - name: ALIBABA_CLOUD_OIDC_TOKEN_FILE
          value: /var/run/secrets/ack.alibabacloud.com/rrsa-tokens/token
        - name: KMS_TOKEN
          value: file:///var/run/kmstoken/token
        volumeMounts:
          - name: shared-volume
            mountPath: /var/run/kmstoken
          - name: rrsa-oidc-token
            mountPath: /var/run/secrets/ack.alibabacloud.com/rrsa-tokens
            readOnly: true
        command: ["/bin/sh", "-c", "./alibabacloud-kms-agent token /var/run/kmstoken/token && ./alibabacloud-kms-agent agent config.toml"]
      - name: my-app
        image: registry-vpc.cn-hangzhou.aliyuncs.com/<ns/<repo>:app-v1.0
        volumeMounts:
          - name: shared-volume
            mountPath: /var/run/kmstoken
      volumes:
        - name: shared-volume
          emptyDir: {}
        - name: rrsa-oidc-token
          projected:
            defaultMode: 420
            sources:
            - serviceAccountToken:
               audience: sts.aliyuncs.com
               expirationSeconds: 3600
               path: token

方法二:安装OpenKruise,配置注入规则

OpenKruise是基于Kubernetes的一个标准扩展组件,可以配合原生Kubernetes使用,高效管理应用容器、Sidecar容器及镜像分发。详细介绍,请参见使用OpenKruise部署云原生应用

  1. 安装OpenKruise。

    1. 登录容器服务管理控制台,在左侧导航栏选择集群列表

    2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,单击组件管理

    3. 组件管理页面,单击应用管理页签。在ack-kruise区域,单击安装

      安装ack-cruise对话框确认组件信息后,单击确认

  2. 设置Sidecar注入规则。

    设置Sidecar容器注入规则,为带有标签label: app的Pod注入Sidecar容器。

    • 环境变量定义:

      • KMS_TOKEN:指定Agent启动时生成的SSRF Token文件的存储路径。

      • ALIBABA_CLOUD_ROLE_ARN:RAM角色的ARN。

      • ALIBABA_CLOUD_OIDC_PROVIDER_ARN :OIDC身份提供商的ARN,此处为ACK集群ARN。

      • ALIBABA_CLOUD_OIDC_TOKEN_FILE:包含OIDC Token的文件路径。

    • selector 定义:选择需要注入sidecar的Pod,可以根据实际情况修改,本文以对带有标签app的Pod注入sidecar容器为例。

    apiVersion: apps.kruise.io/v1alpha1
    kind: SidecarSet
    metadata:
      name: kms-agent-sidecarset
      namespace: rrsa-dev
    spec:
      serviceAccountName: dev-sa
      containers:
      - name: kms-agent
        image: registry-vpc.cn-hangzhou.aliyuncs.com/<ns>/<repo>:kmsagent-v1.0
        env:
        - name: ALIBABA_CLOUD_ROLE_ARN
          value: acs:ram::<uid>:role/dev-role-for-rrsa
        - name: ALIBABA_CLOUD_OIDC_PROVIDER_ARN
          value: acs:ram::<uid>:oidc-provider/ack-rrsa-<ackClusterId>
        - name: ALIBABA_CLOUD_OIDC_TOKEN_FILE
          value: /var/run/secrets/ack.alibabacloud.com/rrsa-tokens/token
        - name: KMS_TOKEN
          value: file:///var/run/kmstoken/token
        volumeMounts:
           - name: shared-volume
             mountPath: /var/run/kmstoken
           - name: rrsa-oidc-token
             mountPath: /var/run/secrets/ack.alibabacloud.com/rrsa-tokens
             readOnly: true
        command: ["/bin/sh", "-c", "./alibabacloud-kms-agent token /var/run/kmstoken/token && ./alibabacloud-kms-agent agent config.toml"]
      # 用于选择需要注入 sidecar 的 Pod,可以根据实际情况修改
      selector:
        matchLabels:
          app: app
      volumes:
         - name: shared-volume
           emptyDir: {}
         - name: rrsa-oidc-token
           projected:
             defaultMode: 420
             sources:
             - serviceAccountToken:
                 audience: sts.aliyuncs.com
                 expirationSeconds: 3600
                 path: token
  3. 自动注入KMS Agent。

    编写Deployment文件,在ACK上发布应用,labels标注上app: app,才能被注入Sidecar容器。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: app-with-kmsagent
      namespace: rrsa-dev
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: app
      template:
        metadata:
          labels:
            app: app
        spec:
          serviceAccountName: dev-sa
          containers:
          - name: my-app
            image: registry-vpc.cn-hangzhou.aliyuncs.com/<ns>/<repo>:app-v1.0
            volumeMounts:
              - name: shared-volume
                mountPath: /var/run/kmstoken
          volumes:
            - name: shared-volume
              emptyDir: {}
  4. 运行您的容器应用。具体操作,请参见创建无状态工作负载Deployment

    应用启动,可以看到在应用所在Pod里,已经被注入了kms agent代理容器。

    无状态页面,可以查看到名称以 ack-kms-agent 开头的 Deployment,其容器组数量为 2/2,表示代理容器已成功注入并正常运行。

步骤七:创建并获取凭据值

  1. 在KMS创建凭据。

    本文示例中创建凭据时需要加上标签 env:dev,应用容器只能获取到有这个标签的凭据,没有权限获取其他凭据。

    1. 登录密钥管理服务控制台,在顶部菜单栏选择地域后,在左侧导航栏单击资源 > 凭据管理

    2. 单击通用凭据页签,选择实例ID后,单击创建凭据,完成各项配置后单击确定

      配置项

      说明

      凭据名称

      自定义凭据名称,需确保名称在当前地域内唯一。

      设置凭据值

      选择凭据键/值纯文本,输入要托管的敏感数据。长度不超过 30720 字节(30 KB)。

      初始版本号

      初始版本号,默认为 v1,支持自定义。

      加密主密钥

      选择用于加密凭据值的对称密钥。密钥和凭据必须属于同一个 KMS 实例。

      重要
      • 密钥和凭据需要属于同一个 KMS 实例,且密钥必须为对称密钥。关于 KMS 支持哪些对称密钥,请参见密钥管理类型和密钥规格

      • 如果是 RAM 用户、RAM 角色,需要具备使用加密主密钥执行 GenerateDataKey 操作的权限。

      标签

      为凭据添加标签,便于分类管理。每个标签由键值对(Key:Value)组成。

      说明
      • 标签键和标签值的格式:最多支持 128 个字符,可以包含英文大小写字母、数字、正斜线(/)、反斜线(\)、下划线(_)、短划线(-)、半角句号(.)、加号(+)、等于号(=)、半角冒号(:)、字符 at(@)、空格。

      • 标签键不能以 aliyun 或 acs:开头。

      • 每个凭据最多可以设置 20 个标签键值对。

      描述信息

      填写凭据的补充描述信息,便于后续识别和管理。

      高级设置 > 策略配置

      设置凭据的访问权限策略,可控制哪些 RAM 用户或角色可以读取或修改此凭据。

      可先选择默认策略,创建后根据业务需要修改。

  2. 获取凭据值。

    • 使用curl命令。

      curl -v -H "X-Vault-Token:$(</var/run/kmstoken/token)" 'http://localhost:2025/secretsmanager/get?secretId=app/dev/secret-1'
    • 在业务代码里使用HTTP GET请求获取凭据。

      package main
      import (
      	"fmt"
      	"io/ioutil"
      	"net/http"
      )
      func main() {
      	url := fmt.Sprintf("http://localhost:2025/secretsmanager/get?secretId=%s", "app/dev/secret-1")
      	token, err := ioutil.ReadFile("/var/run/kmstoken/token")
      	if err != nil {
      		fmt.Printf("error reading token file: %v\n", err)
      	}
      	req, err := http.NewRequest("GET", url, nil)
      	if err != nil {
      		fmt.Printf("error creating request: %v\n", err)
      	}
      	req.Header.Add("X-KMS-Token", string(token))
      	client := &http.Client{}
      	resp, err := client.Do(req)
      	if err != nil {
      		fmt.Printf("error sending request: %v \n", err)
      	}
      	defer resp.Body.Close()
      	body, _ := ioutil.ReadAll(resp.Body)
      	fmt.Printf("status code %d - %s \n", resp.StatusCode, string(body))
      }