---
title: KubernetesでWIFを使用する
url: https://platform.claude.com/docs/ja/manage-claude/wif-providers/kubernetes
description: 投影されたサービスアカウントトークンを使用して、セルフマネージドKubernetesクラスターからClaude APIに認証します。
---

セルフマネージドKubernetesクラスター（kubeadm、k3s、OpenShift、およびオンプレミスディストリビューション）は、[projected service account tokens](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#serviceaccount-token-volume-projection)（投影されたサービスアカウントトークン）を通じて、すべてのPodに対してOIDC「JSON Web Token」（JSON Webトークン）、すなわちJWTに署名します。クラスターのAPIサーバーがOIDC発行者（issuer）として機能し、各トークンの `sub` クレームは `system:serviceaccount:<namespace>:<service-account>` の形式に従います。クラスターの発行者URLは、ディスカバリードキュメントを読み取ることで確認できます。

```bash cURL
kubectl get --raw /.well-known/openid-configuration | jq -r .issuer
```

<Note>
  このページの仕組み（投影されたサービスアカウントトークン、OIDC発行者としてのクラスターAPIサーバー）はKubernetes自体にネイティブなものであるため、すべてのKubernetesディストリビューションの基盤となっています。マネージドKubernetesサービス上で実行している場合は、クラウドプロバイダーのガイドでプロバイダー管理の発行者URLの確認場所を説明しています：[AWS (EKS)](https://platform.claude.com/docs/ja/manage-claude/wif-providers/aws#use-eks-projected-service-account-tokens)、[Google Cloud (GKE)](https://platform.claude.com/docs/ja/manage-claude/wif-providers/gcp)、または[Azure (AKS)](https://platform.claude.com/docs/ja/manage-claude/wif-providers/azure)。クラスターでSPIREを実行している場合は、クラスターAPIサーバーではなくSPIRE OIDC Discovery Providerが発行者となります。[SPIFFE](https://platform.claude.com/docs/ja/manage-claude/wif-providers/spiffe)を参照してください。その他のディストリビューションや、そこに記載されていないマネージドプロバイダーの場合は、このガイドに従い、クラスターが報告する発行者URLを使用してください。
</Note>

## 前提条件

* [WIFの概念](https://platform.claude.com/docs/ja/manage-claude/workload-identity-federation#concepts)（サービスアカウント、フェデレーション発行者、フェデレーションルール）に精通していること。

* APIサーバーで[`--service-account-issuer`](https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/)フラグが設定されたKubernetesクラスター。ほとんどのディストリビューションではデフォルトで設定されています。kubeadmクラスターは通常 `https://kubernetes.default.svc.cluster.local` を使用します。APIサーバーの設定に直接アクセスできない場合は、プラットフォームチームが値を確認できます。

* Anthropicがトークン署名を検証できるように、次のいずれかを満たすこと：

  * 発行者のJWKSエンドポイントがパブリックインターネットからHTTPSのポート443で到達可能であること、または
  * クラスター内部からJWKSを取得し、`inline` モードで登録できること（[Anthropicを設定する](https://platform.claude.com/docs/ja/manage-claude/wif-providers/kubernetes#configure-anthropic)で説明します）。

* Anthropic組織のClaude Consoleでサービスアカウント、フェデレーション発行者、フェデレーションルールを作成する権限。

## Kubernetesを設定する

フェデレーションルールが期待するオーディエンスと有効期間を指定して、サービスアカウントトークンをPodに投影します。`serviceAccountToken` プロジェクションは新しいJWTをマウントパスに書き込み、`expirationSeconds` が経過する前にローテーションします。

```yaml Pod
apiVersion: v1
kind: Pod
metadata:
  name: inference-worker
  namespace: inference
spec:
  serviceAccountName: inference-worker
  volumes:
    - name: anthropic-token
      projected:
        sources:
          - serviceAccountToken:
              audience: https://api.anthropic.com
              expirationSeconds: 3600
              path: token
  containers:
    - name: app
      image: your-registry/inference-worker:latest
      env:
        - name: ANTHROPIC_IDENTITY_TOKEN_FILE
          value: /var/run/secrets/anthropic.com/token
        - name: ANTHROPIC_FEDERATION_RULE_ID
          value: fdrl_...
        - name: ANTHROPIC_ORGANIZATION_ID
          value: 00000000-0000-0000-0000-000000000000
        - name: ANTHROPIC_SERVICE_ACCOUNT_ID
          value: svac_...
        - name: ANTHROPIC_WORKSPACE_ID  # required when the rule covers multiple workspaces
          value: wrkspc_...
      volumeMounts:
        - name: anthropic-token
          mountPath: /var/run/secrets/anthropic.com
          readOnly: true
```

このPodに対して発行されるトークンには `sub: "system:serviceaccount:inference:inference-worker"` と `aud: ["https://api.anthropic.com"]` が含まれます。

## Anthropicを設定する

Claude Consoleで[Workload identity](https://platform.claude.com/settings/workload-identity-federation)ページ（`platform.claude.com/settings/workload-identity-federation`）に移動し、**Connect workload** をクリックして、**Kubernetes** タイルを選択します。ウィザードが発行者の登録、サービスアカウントの作成、フェデレーションルールの作成を順に案内します。

ウィザードがこれらのリソースを作成します。ウィザードに入力する場合でも、[Admin API](https://platform.claude.com/docs/ja/manage-claude/wif-admin-api)に送信する場合でも、以下の値を使用してください。

**フェデレーション発行者：** 多くのセルフマネージドクラスターは、`https://kubernetes.default.svc.cluster.local` のようなパブリックインターネットから到達できない発行者URLを使用しています。お使いのクラスターがこれに該当する場合は、**inline** JWKSソースを選択し、クラスターの鍵を貼り付けます。クラスター内部から取得してください。

```bash cURL
kubectl get --raw /openid/v1/jwks
```

次に、返された `keys` 配列の内容（外側の `{"keys": [...]}` ラッパーではなく）を使用して発行者を設定します。

```json
{
  "name": "onprem-k8s",
  "issuer_url": "https://kubernetes.default.svc.cluster.local",
  "jwks": {
    "type": "inline",
    "keys": [{ "kty": "RSA", "kid": "...", "n": "...", "e": "AQAB" }]
  }
}
```

`inline` モードでは、`issuer_url` はJWTの `iss` クレームと比較されるだけで、Anthropicがそこに到達を試みることはありません。発行者がパブリックに到達可能な場合は、代わりに `"jwks": {"type": "discovery"}` を使用してください。

<Warning>
  `inline` 鍵を使用する場合、クラスターがサービスアカウント署名鍵をローテーションした際に発行者を更新する責任はお客様にあります。ローテーションはまれ（通常はクラスターのアップグレード時のみ）ですが、新しいJWKSをプッシュするまでトークン交換は署名エラーで失敗します。
</Warning>

**フェデレーションルール：** サービスアカウントの `sub` クレームと、投影されたトークンに設定したオーディエンスに一致させます。

```json
{
  "name": "onprem-inference",
  "issuer_id": "fdis_...",
  "match": {
    "subject_prefix": "system:serviceaccount:inference:inference-worker",
    "audience": "https://api.anthropic.com"
  },
  "target": {
    "type": "service_account",
    "service_account_id": "svac_..."
  },
  "workspace_id": "wrkspc_...",
  "oauth_scope": "workspace:developer",
  "token_lifetime_seconds": 600
}
```

ワークロードが許す限り具体的に指定してください。名前空間内のすべてのサービスアカウントを同じAnthropicサービスアカウントにマッピングすべき場合にのみ、`subject_prefix` を `system:serviceaccount:inference:*` に緩めてください（末尾の `*` によりプレフィックス一致になります）。ルールの `fdrl_...` IDをPodの `ANTHROPIC_FEDERATION_RULE_ID` 環境変数に追加します。

## トークンを取得して使用する

[Kubernetesを設定する](https://platform.claude.com/docs/ja/manage-claude/wif-providers/kubernetes#configure-kubernetes)のPod仕様では、`ANTHROPIC_IDENTITY_TOKEN_FILE` を投影されたマウントパスに設定し、あわせて `ANTHROPIC_FEDERATION_RULE_ID`、`ANTHROPIC_ORGANIZATION_ID`、`ANTHROPIC_SERVICE_ACCOUNT_ID`、`ANTHROPIC_WORKSPACE_ID` も設定しています。これらが設定されていれば、SDKは交換のたびにディスクからトークンを読み取り、Anthropicアクセストークンを自動的に更新します。

<CodeGroup>
  ```bash cURL
  JWT=$(cat "$ANTHROPIC_IDENTITY_TOKEN_FILE")

  ACCESS_TOKEN=$(curl -sS https://api.anthropic.com/v1/oauth/token \
    -H "content-type: application/json" \
    --data @- <<JSON | jq -r .access_token
  {
    "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
    "assertion": "$JWT",
    "federation_rule_id": "$ANTHROPIC_FEDERATION_RULE_ID",
    "organization_id": "$ANTHROPIC_ORGANIZATION_ID",
    "service_account_id": "$ANTHROPIC_SERVICE_ACCOUNT_ID",
    "workspace_id": "$ANTHROPIC_WORKSPACE_ID"
  }
  JSON
  )

  curl https://api.anthropic.com/v1/messages \
    -H "authorization: Bearer $ACCESS_TOKEN" \
    -H "anthropic-version: 2023-06-01" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-opus-5-5",
      "max_tokens": 1024,
      "messages": [{"role": "user", "content": "Hello, Claude"}]
    }' | jq -r '.content[] | select(.type == "text") | .text'
  ```

  ```python Python
  import anthropic

  # ANTHROPIC_IDENTITY_TOKEN_FILE、ANTHROPIC_FEDERATION_RULE_ID、
  # ANTHROPIC_ORGANIZATION_ID、ANTHROPIC_SERVICE_ACCOUNT_ID、ANTHROPIC_WORKSPACE_ID を
  # Pod の環境変数から読み取ります。
  client = anthropic.Anthropic()

  message = client.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      messages=[{"role": "user", "content": "Hello, Claude"}],
  )
  print(next(block.text for block in message.content if block.type == "text"))
  ```

  ```typescript TypeScript
  import Anthropic from "@anthropic-ai/sdk";

  // ANTHROPIC_IDENTITY_TOKEN_FILE、ANTHROPIC_FEDERATION_RULE_ID、
  // ANTHROPIC_ORGANIZATION_ID、ANTHROPIC_SERVICE_ACCOUNT_ID、ANTHROPIC_WORKSPACE_ID を
  // Pod の環境変数から読み取ります。
  const client = new Anthropic();

  const message = await client.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    messages: [{ role: "user", content: "Hello, Claude" }]
  });
  for (const block of message.content) {
    if (block.type === "text") {
      console.log(block.text);
    }
  }
  ```

  ```go Go
  // ANTHROPIC_IDENTITY_TOKEN_FILE、ANTHROPIC_FEDERATION_RULE_ID、
  // ANTHROPIC_ORGANIZATION_ID、ANTHROPIC_SERVICE_ACCOUNT_ID、ANTHROPIC_WORKSPACE_ID を
  // Pod の環境変数から読み取ります。
  client := anthropic.NewClient()

  message, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 1024,
  	Messages: []anthropic.MessageParam{
  		anthropic.NewUserMessage(anthropic.NewTextBlock("Hello, Claude")),
  	},
  })
  if err != nil {
  	panic(err)
  }
  for _, block := range message.Content {
  	if textBlock, ok := block.AsAny().(anthropic.TextBlock); ok {
  		fmt.Println(textBlock.Text)
  		break
  	}
  }
  ```

  ```java Java
  AnthropicClient client = AnthropicOkHttpClient.fromEnv();

  var message = client.messages().create(MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(1024)
          .addUserMessage("Hello, Claude")
          .build());

  IO.println(message.content());
  ```

  ```csharp C#
  // ANTHROPIC_IDENTITY_TOKEN_FILE、ANTHROPIC_FEDERATION_RULE_ID、
  // ANTHROPIC_ORGANIZATION_ID、ANTHROPIC_SERVICE_ACCOUNT_ID、ANTHROPIC_WORKSPACE_ID を
  // Pod の環境変数から読み取ります。
  using var client = new AnthropicClient();

  var message = await client.Messages.Create(new()
  {
      Model = Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      Messages = [new() { Role = Role.User, Content = "Hello, Claude" }],
  });
  foreach (var block in message.Content)
  {
      if (block.Value is TextBlock textBlock)
      {
          Console.WriteLine(textBlock.Text);
      }
  }
  ```

  ```bash CLI
  # ANTHROPIC_FEDERATION_RULE_ID、ANTHROPIC_ORGANIZATION_ID、
  # ANTHROPIC_SERVICE_ACCOUNT_ID、ANTHROPIC_WORKSPACE_ID、ANTHROPIC_IDENTITY_TOKEN_FILE を読み取ります
  ant messages create \
    --model claude-opus-5-5 \
    --max-tokens 1024 \
    --message '{role: user, content: "Hello, Claude"}'
  ```

  ```php PHP
  use Anthropic\Client;

  // ANTHROPIC_FEDERATION_RULE_ID、ANTHROPIC_ORGANIZATION_ID、
  // ANTHROPIC_SERVICE_ACCOUNT_ID、ANTHROPIC_WORKSPACE_ID、ANTHROPIC_IDENTITY_TOKEN_FILE を読み取ります
  $client = new Client();

  $message = $client->messages->create(
      model: 'claude-opus-5-5',
      maxTokens: 1024,
      messages: [['role' => 'user', 'content' => 'Hello, Claude']],
  );
  $textBlock = array_find($message->content, static fn ($block): bool => $block->type === 'text');
  echo $textBlock->text, PHP_EOL;
  ```

  ```ruby Ruby
  require "anthropic"

  # ANTHROPIC_FEDERATION_RULE_ID、ANTHROPIC_ORGANIZATION_ID、
  # ANTHROPIC_SERVICE_ACCOUNT_ID、ANTHROPIC_WORKSPACE_ID、ANTHROPIC_IDENTITY_TOKEN_FILE を読み取ります
  client = Anthropic::Client.new

  message = client.messages.create(
    model: "claude-opus-5-5",
    max_tokens: 1024,
    messages: [{role: "user", content: "Hello, Claude"}]
  )
  puts message.content.find { it.type == :text }.text
  ```
</CodeGroup>

## セットアップを検証する

交換が成功すると、`sk-ant-oat01-` で始まる `access_token` と、秒単位の `expires_in` 値が返されます。交換が不透明な `401` `authentication_error` レスポンス（メッセージ `Authentication failed`）で失敗した場合は、Claude Consoleの[認証履歴ページ](https://platform.claude.com/settings/workload-identity-federation?tab=history)で拒否理由を確認し、[失敗した交換のトラブルシューティング](https://platform.claude.com/docs/ja/manage-claude/wif-reference#troubleshoot-a-failed-exchange)を参照してください。Kubernetes側で最も一般的な原因はJWKS鍵の不一致です（`inline` モードの場合は、`kubectl get --raw /openid/v1/jwks` で再取得して発行者を更新してください）。

## ルールのスコープを絞る

<Warning>
  `subject_prefix` が `system:serviceaccount:*` の場合、クラスター内のすべてのサービスアカウントに一致するため、どのPodでもフェデレーションされたAnthropicトークンを取得できてしまいます。`audience` マッチャーがない場合、ルールはクラスターのデフォルトオーディエンストークンにも一致します。これはすべてのPodにすでに投影されているものです。
</Warning>

ルールの `match` ブロックを、ユースケースに適合する最も狭いスコープに固定してください。

* **名前空間とサービスアカウント名を固定する：** 末尾の `*` を付けずに、完全な `system:serviceaccount:<namespace>:<name>` の値を使用します。
* **常にオーディエンスを設定する：** ルールで `audience` を必須とし、Podの `serviceAccountToken` プロジェクションにも同じ値を設定して、デフォルトオーディエンストークンが拒否されるようにします。
* **名前空間ごとに別のルールを使用する：** 1つのルールを広げるのではなく、名前空間ごとに個別のルールとAnthropicサービスアカウントを作成します。
* **inline JWKS発行者を1つのクラスターにスコープする：** 複数のクラスターが発行者URLを共有している場合は、各クラスターのJWKSをそれぞれ独自のフェデレーション発行者として登録し、ルールをその発行者のみにバインドします。

## 次のステップ

* [Workload Identity Federation](https://platform.claude.com/docs/ja/manage-claude/workload-identity-federation)：概念、トークン交換フロー、SDK設定オプション。
* [WIFリファレンス](https://platform.claude.com/docs/ja/manage-claude/wif-reference)：環境変数、JWKSソースモード、ルール一致モード。
