全部產品
Search
文件中心

Key Management Service:ACK容器環境中部署KMS Agent擷取憑據

更新時間:Jun 11, 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憑據。

使用限制

  • ACK叢集支援ACK託管叢集、ACK專有叢集、ACK註冊叢集、ACK Serverless叢集。

  • ACK叢集與KMS執行個體需要在同一地區。

操作步驟

以下流程示範了ACK、RAM、KMS如何配置,以實現業務應用通過KMS Agent擷取憑據。研發只需要在KMS建立憑據,然後在應用裡從本地檢索即可,其餘配置由營運和安全團隊提前配置。整個過程中,研發不需要在業務代碼裡整合SDK,也不需要關心應用訪問KMS的認證鑒權以及緩衝容災等。

步驟一:構建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. 登入Container Service管理主控台,在左側導覽列選擇叢集列表

    2. 叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇叢集資訊

    3. 基本資料頁簽的安全與審計地區,單擊RRSA OIDC右側的開啟image

    4. 在彈出的啟用 RRSA對話方塊,單擊確定

      基本資料地區,當叢集狀態由更新中變為運行中後,表明該叢集的RRSA特性已變更完成。

  2. 開啟叢集詳情頁,在基本資料頁簽的安全與審計地區,將滑鼠懸浮至RRSA OIDC右側已開啟上面,查看供應商的URL連結和ARN資訊。開啟 RRSA 後,該地區將顯示 RRSA OIDC供應商 URL供應商 ARN,後續配置 RAM 角色信任策略時需要使用這兩項資訊。

  3. 建立一個可信實體為身份供應商的RAM角色。

    1. 使用Resource Access Management員登入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容器與應用程式容器一起部署到阿里雲的ACKContainer Service。

  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. 登入Container Service管理主控台,在左側導覽列選擇叢集列表

    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. 登入Key Management Service控制台,在頂部功能表列選擇地區後,在左側導覽列單擊资源 > 凭据管理

    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))
      }