Claude Platform Docs
Managed Agents自行託管的 Managed Agents

在 Kubernetes 上部署

使用版本封存檔中的兩個 Helm chart,在 Kubernetes 叢集上安裝自行託管的 Claude Managed Agents 伺服器及其沙箱,然後在沙箱 pod 中執行第一個工作階段。

本頁面將帶您從一個空的 Google Kubernetes Engine (GKE) 叢集開始,一路到在沙箱 pod 中執行工具的工作階段。它使用「release archive」(版本封存檔)中的兩個 Helm chart,可在叢集上執行整個堆疊:

  • cma-server: 套用資料庫結構描述,並在命名空間 cma-server 中,於一個 Service 後方執行兩個伺服器。
  • cma-sandboxes: 在命名空間 cma 中,執行一個 dispatcher 與沙箱 pod。dispatcher 會向伺服器輪詢工作,並為每個工作階段提供專屬的沙箱 pod,由 worker 在其中執行代理的 shell 與檔案工具。

您的 PostgreSQL 資料庫位於這兩者之外。在其他類型的叢集上,步驟相同,但叢集先決條件和部分 chart 值有所不同。請參閱其他叢集。

先決條件

  • 叢集: Kubernetes 1.30 或更新版本,需具備:
    • Agent Sandbox 控制器(在 GKE 上,即為 Agent Sandbox 附加元件)
    • 執行 gVisor 的節點(在 GKE 上,即為 GKE Sandbox 節點集區)
    • 會強制執行 NetworkPolicy 的網路外掛程式(在 GKE 上,即為 Dataplane V2 或 Calico)
  • 資料庫: 叢集可連線的 PostgreSQL 16 或更新版本。
  • 登錄庫: 叢集可從中提取映像的登錄庫。映像需由您自行建置。
  • Claude API 金鑰: 伺服器會使用它進行模型呼叫。若要使用其他提供者,請參閱推論提供者。
  • 權限: Cluster-admin 權限或同等權限。安裝過程會建立命名空間、Roles 和一個 ClusterRoleBinding。
  • 您機器上的工具: helm、kubectl、docker buildx、openssl,以及 ant CLI。
  • 版本封存檔: 若要申請下載權限,請聯絡您的 Anthropic 客戶團隊。解壓縮封存檔。本頁面上的每個指令都請從其頂層目錄執行。

安裝堆疊

  1. 建置並推送映像

    將這些變數設定為您自己的值。PLATFORM 是您節點的架構。TAG 是該版本的版本號,位於封存檔名稱中的 v 之後。兩個 chart 都預期映像以此版本號作為標籤。

    REGISTRY=us-docker.pkg.dev/my-project/cma
    TAG=1.2.3
    PLATFORM=linux/amd64

    接著建置並推送這三個映像:

    docker buildx build --platform "$PLATFORM" -f kubernetes/server/Dockerfile -t "$REGISTRY/cma-server-image:$TAG" --push .
    docker buildx build --platform "$PLATFORM" -f kubernetes/dispatcher/Dockerfile -t "$REGISTRY/cma-dispatcher:$TAG" --push .
    docker buildx build --platform "$PLATFORM" -t "$REGISTRY/cma-sandbox:$TAG" --push kubernetes/sandbox
  2. 建立密鑰檔案和資料庫

    建立一個檔案,其中包含產生的資料庫密碼,以及您的 Claude API 金鑰的預留位置:

    cat > secrets.env <<EOF
    PG_PASSWORD=$(openssl rand -hex 32)
    UPSTREAM_KEY=sk-ant-...
    EOF
    chmod 600 secrets.env

    請在編輯器中開啟 secrets.env,並將 sk-ant-... 替換為您的 Claude API 金鑰。接著以管理員身分連線至您的資料庫伺服器,例如使用 psql。執行此 SQL,並以 PG_PASSWORD 的值取代 ...:

    CREATE ROLE cma_server LOGIN PASSWORD '...';
    GRANT cma_server TO CURRENT_USER;
    CREATE DATABASE cma_server OWNER cma_server;
  3. 建立伺服器的命名空間和 Secrets

    建立伺服器的命名空間及其 Secrets:

    source secrets.env
    ENCRYPTION_KEY=$(openssl rand -base64 32)
    kubectl create namespace cma-server
    kubectl label namespace cma-server pod-security.kubernetes.io/enforce=restricted pod-security.kubernetes.io/enforce-version=latest
    kubectl -n cma-server create secret generic cma-server-db \
      --from-literal=PGPASSWORD="$PG_PASSWORD"
    kubectl -n cma-server create secret generic cma-server-keys \
      --from-literal=CMA_SERVER__API_KEY="$(openssl rand -hex 32)" \
      --from-literal=CMA_STORE__CREDENTIALS_ENCRYPTION_KEY="$ENCRYPTION_KEY"
    kubectl -n cma-server create secret generic cma-server-upstream \
      --from-literal=ANTHROPIC_API_KEY="$UPSTREAM_KEY"

    使用 echo "$ENCRYPTION_KEY" 印出加密金鑰,並在叢集之外保留一份副本。伺服器會使用此金鑰來加密其所儲存的憑證,而還原的資料庫也需要它。接著刪除 secrets.env。cma-server-db Secret 會保存資料庫密碼。

  4. 建立沙箱的命名空間和憑證

    建立沙箱的命名空間,以及一個由 dispatcher 提供、並由沙箱信任的憑證:

    kubectl create namespace cma
    kubectl label namespace cma pod-security.kubernetes.io/enforce=restricted pod-security.kubernetes.io/enforce-version=latest
    openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes -days 825 \
      -subj "/CN=cma-dispatcher.cma.svc" \
      -addext "subjectAltName=DNS:cma-dispatcher.cma.svc,DNS:cma-dispatcher.cma.svc.cluster.local" \
      -keyout tls.key -out tls.crt
    kubectl -n cma create secret tls cma-dispatcher-tls --cert=tls.crt --key=tls.key --dry-run=client -o yaml | kubectl apply -f -
    kubectl -n cma create configmap cma-dispatcher-ca --from-file=ca.crt=tls.crt --dry-run=client -o yaml | kubectl apply -f -
  5. 安裝伺服器

    將以下內容儲存為 cma-server-values.yaml,並填入您的登錄庫和資料庫位址:

    earlierNames: false   # a new install
    image:
      registry: us-docker.pkg.dev/my-project/cma   # REGISTRY in the build commands
    database:
      url: host=10.20.0.5 port=5432 user=cma_server dbname=cma_server sslmode=require   # your database's address
    environments:
      - name: default
        namespace: cma

    接著安裝 chart:

    helm install cma-server kubernetes/server/chart --namespace cma-server -f cma-server-values.yaml --wait
    kubectl -n cma-server logs job/cma-server-environment-default

    安裝過程會建立環境 default,並將其金鑰儲存在命名空間 cma 中的 Secret cma-environment。第二個指令會印出一行以 filled Secret cma/cma-environment 開頭的內容。如果第一次 helm install 失敗,請在重新安裝之前,先對該 Helm release 執行 helm uninstall。

  6. 找出要封鎖的叢集位址

    此安裝會讓沙箱能連線至公用網際網路。叢集的 API 端點通常具有公用位址,因此沙箱也可能連線至該端點。若要封鎖它,請在下一個步驟中將其位址列於 egress.clusterCIDRs 之下。

    若要印出該位址,請以您叢集的名稱執行 gcloud container clusters describe my-cluster --format 'value(endpoint)'。

    chart 本身會封鎖私人範圍 10.0.0.0/8、172.16.0.0/12、192.168.0.0/16 和 100.64.0.0/10。如果您的叢集有位於這四個範圍之外的 pod、服務或節點範圍,也請列出該範圍。

  7. 安裝沙箱

    將以下內容儲存為 cma-values.yaml,並填入您的登錄庫和上一個步驟中的位址:

    platform: gke
    image:
      registry: us-docker.pkg.dev/my-project/cma   # REGISTRY in the build commands
    egress:
      mode: publicInternet
      clusterCIDRs:
        - 203.0.113.10/32                          # the cluster's API endpoint
      cmaServer:
        pods:
          namespace: cma-server
          matchLabels:
            anthropic.com/role: server
        port: 8400

    egress.cmaServer 會開放通往您伺服器的路徑。若要將 publicInternet 與另外兩種模式進行比較,請參閱沙箱可連線的位置。

    如果您的叢集使用下列其中一種 DNS 設定,請在檔案中加入一行:

    • Cloud DNS for GKE(Autopilot 叢集即使用此功能): gke: {dns: cloudDns}
    • NodeLocal DNSCache: gke: {dns: nodeLocalCache, kubeDnsUpstreamIP: <address>}。若要印出該位址,請執行 kubectl -n kube-system get svc kube-dns-upstream -o jsonpath='{.spec.clusterIP}'。

    接著安裝 chart:

    helm install cma kubernetes/chart --namespace cma -f cma-values.yaml --wait

執行工作階段

這些步驟使用新安裝的名稱。如果您的伺服器 values 檔案包含 earlierNames: true,請在Kubernetes:您的物件名稱中找出應改用的名稱。

  1. 轉送伺服器的連接埠

    在一個終端機中,將伺服器的連接埠轉送到您的電腦:

    kubectl -n cma-server port-forward svc/cma-server 8400:8400
  2. 將 CLI 指向您的伺服器

    在第二個終端機中,將 ant CLI 指向轉送的連接埠,並從 cma-server-keys Secret 讀取伺服器 API 金鑰:

    export ANTHROPIC_BASE_URL=http://127.0.0.1:8400
    export ANTHROPIC_API_KEY=$(kubectl -n cma-server get secret cma-server-keys -o jsonpath='{.data.CMA_SERVER__API_KEY}' | base64 -d)
  3. 建立代理並要求它執行指令

    依照快速入門中執行您的第一個工作階段的三個步驟操作:建立代理、啟動工作階段,以及要求代理執行指令。在「啟動工作階段」中,請將 compose-sandbox 替換為 default,也就是 chart 所建立之環境的名稱。

  4. 找出沙箱 pod

    代理會回覆執行該指令之 pod 的主機名稱。在第三個終端機中,kubectl -n cma get pods 會在 dispatcher 的 pod 旁列出該名稱的 pod。根據預設,該 pod 會在代理的回合結束後約 5 分鐘消失。如果清單中沒有它,請要求代理再次執行 hostname。

    若要離開聊天,請按 Ctrl+C。

在伺服器前方加上 TLS

伺服器在連接埠 8400 上使用純 HTTP,而來自您應用程式的請求會攜帶伺服器 API 金鑰。在叢集外的用戶端連線之前,請在 cma-server Service 前方加上一個終止 TLS 的負載平衡器或 ingress。它必須:

  • 原封不動地傳遞請求路徑。
  • 接受最大 32 MiB 的請求主體。
  • 以不緩衝的方式傳遞回應。
  • 設定預設 2 分鐘的讀取逾時。對於 Git 請求,請為符合 ^/cma-[a-z]+/git/ 的路徑設定 10 分鐘的讀取逾時。
  • 僅將流量傳送至已就緒的伺服器。cma-server Service 已經會這樣做。直接連線至 pod 的負載平衡器必須在每個 pod 上探測 /cma-server/readyz,並略過回傳 503 的 pod。
  • 絕不重新傳送伺服器已接受的 POST。
  • 絕不快取回應。

若要從叢集外檢查,請執行 curl -s https://<host>/cma-server/healthz。回應為 {"status":"ok"}。

沙箱可連線的位置

在 cma-values.yaml 中,egress.mode: publicInternet 可讓沙箱連線至公用網際網路。

此表格將它與另外兩種模式進行比較:

egress.mode沙箱可連線的位置
closed,預設值您的伺服器和 dispatcher,且無法連線至任何 DNS 伺服器
publicInternet您的伺服器、dispatcher、DNS 伺服器,以及公用網際網路
gateway您的伺服器、dispatcher,以及透過「egress gateway」(輸出閘道)連線的您所列出的主機。請參閱在 Kubernetes 上開啟閘道。

其他叢集

在 cma-values.yaml 中,將 platform 設定為 eks(適用於 Amazon EKS)、aks(適用於 Azure Kubernetes Service (AKS))或 generic(適用於任何其他叢集)。三者都需要上游的 Agent Sandbox 控制器及其擴充功能,以及強制執行 NetworkPolicy 的網路外掛程式。它們還需要:

  • Amazon EKS: 一個已將 gVisor 的 runsc 註冊為名為 runsc 之 containerd 處理常式的節點群組。為節點加上標籤 cma.anthropic.com/sandbox-node=true,並加上 taint cma.anthropic.com/sandbox-node=true:NoSchedule。chart 會針對該處理常式註冊 gvisor RuntimeClass。
  • AKS: 一個啟用 Pod Sandboxing 的節點集區,其標籤和 taint 與 Amazon EKS 上相同。將叢集網路政策引擎的名稱(cilium、calico 或 azure)填入 aks.networkPolicy。請保留 egress.mode: publicInternet,這是 chart 在 AKS 上唯一接受的模式。在代理於其上執行實際工作之前,請先在您的叢集上測試此 chart。
  • 任何其他叢集: 適用於 gVisor 或其他沙箱化執行環境的 RuntimeClass。將其名稱填入 runtimeClass.name。

封存檔中的資料夾 kubernetes/chart/examples/ 為每種叢集提供了完整的 values 檔案。

釋放工作階段的磁碟區

根據 chart 的預設值,每個工作階段都有一個用於 /workspace 的 10 GiB 磁碟區。工作階段的 pod 消失後,該磁碟區仍會保留,因此工作階段的下一則訊息可以找到其檔案。

要釋放的對象執行的操作
單一工作階段的磁碟區在工作階段的回合結束後將其封存。dispatcher 通常會在約 5 分鐘內刪除該磁碟區。
無人封存之工作階段的磁碟區在 cma-values.yaml 中設定 dispatcher.retentionDays。之後,當工作階段閒置達該天數時,dispatcher 會刪除其磁碟區,而該工作階段的下一則訊息會以空的 /workspace 開始。chart 的預設值 0 會保留所有磁碟區。

本節中的指令適用於 GKE。在其他叢集上,請使用 sandboxclaims 取代 sandboxes。

刪除工作階段並不會釋放其磁碟區。請先封存工作階段。只有在 kubectl -n cma get sandboxes -l anthropic.com/session-id=<session-id> 未列出任何項目之後,才刪除它。

如果您在未封存的情況下刪除了工作階段,請自行釋放其磁碟區:

  1. 在 dispatcher 的記錄中找出工作階段的 ID。此指令會為每個看似已刪除但仍有磁碟區的工作階段印出一行,其 ID 位於 session_id 之後:

    kubectl -n cma logs deployment/cma-dispatcher --since=6m \
      | grep "could not check the claim's session" | grep "403 Forbidden"

    dispatcher 每 5 分鐘寫入一次這些行。如果未列出該工作階段,請等待 5 分鐘後再次執行指令。

  2. 確認工作階段已刪除。在依照執行工作階段轉送連接埠並設定 ANTHROPIC_API_KEY 的情況下,執行 ant --base-url http://127.0.0.1:8400 beta:sessions retrieve --session-id <session-id>。只有在回應為 404 Not Found 且帶有 Session not found 時,才繼續進行。如果指令印出了工作階段,請停止:該工作階段尚未刪除。

  3. 刪除擁有該磁碟區的 Kubernetes 物件。工作階段的檔案會隨之刪除:

    kubectl -n cma delete sandboxes -l anthropic.com/session-id=<session-id>

更新金鑰和憑證

環境金鑰的有效期為 365 天,dispatcher 的憑證有效期為 825 天。請在各自到期之前進行更新。

在環境金鑰的最後 30 天內,伺服器會在每個使用該金鑰的請求上記錄一則警告。該警告以 environment key is within 30 days of expiry 開頭。

更新 chart 所建立的環境金鑰

若要查看金鑰的到期時間,請執行 kubectl -n cma describe secret cma-environment。

請在金鑰的最後 60 天內,從目前已安裝版本之封存檔的頂層目錄,至少執行一次這兩個指令:

helm upgrade cma-server kubernetes/server/chart --namespace cma-server -f cma-server-values.yaml --wait
kubectl -n cma rollout restart deployment/cma-dispatcher

每次執行伺服器 chart 的 helm upgrade 指令時,如果金鑰將在 60 天內到期,它都會將新的金鑰儲存在 Secret 中。除此之外,沒有其他任何機制會更新金鑰。第二個指令會重新啟動 dispatcher,使其讀取新的金鑰。

更新 dispatcher 的憑證

請回到「建立沙箱的命名空間和憑證」步驟。再次執行其中的 openssl 指令及其後的兩個 kubectl 指令。然後使用 kubectl -n cma rollout restart deployment/cma-dispatcher 重新啟動 dispatcher。

為您自己的 worker 替換環境金鑰

chart 只會更新自己的金鑰。如果您自行建立了金鑰(如建立環境及其金鑰中所述),請使用管理 CLI 替換它。該 CLI 位於版本封存檔的頂層。

請在執行工作階段中的第二個終端機執行這些指令,其中 ANTHROPIC_API_KEY 存放著伺服器 API 金鑰。請讓連接埠轉送在第一個終端機中持續執行。如果您透過其他位址連線到您的伺服器,請將該位址作為 -base-url 傳入,此時就不需要連接埠轉送。

  1. 為相同環境建立新金鑰

    對於 -env,請傳入環境的 ID:

    echo "$ANTHROPIC_API_KEY" | ./cma-server-admin mint-key \
      -base-url http://127.0.0.1:8400 -env env_01595EKxaaTTGwwY3kyXdtbs -key-file -

    此指令會印出新金鑰,並在標準錯誤輸出上印出金鑰的 ID 和到期時間。

  2. 將您的 worker 移至新金鑰

    為每個進行輪詢的處理程序將新金鑰設定為 ANTHROPIC_ENVIRONMENT_KEY,並重新啟動該處理程序。

  3. 撤銷舊金鑰

    仍使用已撤銷金鑰的 worker 會收到 401 錯誤,並放棄其正在服務的工作階段。若要找出舊金鑰的 ID,請使用相同的 -base-url、-env 和 -key-file 旗標執行 list-keys。當不再有任何 worker 使用舊金鑰時,請依該 ID 撤銷它:

    echo "$ANTHROPIC_API_KEY" | ./cma-server-admin revoke-key \
      -base-url http://127.0.0.1:8400 -env env_01595EKxaaTTGwwY3kyXdtbs \
      -key-id etok_01AbCdEfGhIjKlMnOpQrStUv -key-file -

解除安裝堆疊

請先刪除沙箱。helm uninstall 會刪除限制沙箱的網路政策,但 dispatcher 為工作階段建立的沙箱會持續執行。

這些步驟不會影響您的資料庫,但會刪除 Secrets。若要再次使用該資料庫,您需要您保留的加密金鑰副本。

  1. 停止 dispatcher 並刪除沙箱

    kubectl -n cma scale deployment/cma-dispatcher --replicas=0
    kubectl -n cma delete sandboxwarmpool cma-sandbox
    kubectl -n cma delete sandboxclaims --all

    在 GKE 上,也請執行此指令:

    kubectl -n cma delete sandboxes --all
  2. 等待沙箱消失

    重複執行此指令,直到沙箱、其 pod 和其磁碟區都消失為止:

    kubectl -n cma get sandboxes,pods,pvc
  3. 解除安裝 chart 並刪除命名空間

    helm uninstall cma --namespace cma
    helm uninstall cma-server --namespace cma-server
    kubectl delete namespace cma cma-server

後續步驟

這個頁面有幫助嗎?