Container Service for Kubernetes (ACK) 上でコンテナ化されたワークロードを実行する際、アプリケーションコードに AccessKey をハードコーディングすると、セキュリティリスクが生じ、認証情報のローテーションが困難になります。Key Management Service (KMS) のクラウドネイティブアクセスは、KMS Agent のサイドカーを Pod にインジェクトすることでこのリスクを排除します。これにより、アプリケーションは KMS で管理されている認証情報をローカル HTTP リクエストを通じて安全に取得できます。
仕組み
KMS のクラウドネイティブアクセス機能は、コンポーネントのインストールと設定のためのガイド付きワークフローを提供します。ACK クラスター内の Pod が HTTP リクエストを送信すると、Helm コンポーネント ack-kms-agent-webhook-injector を介して Pod に自動的にインジェクトされた KMS Agent がリクエストを受信し、OpenID Connect (OIDC) JWT または RAM ロールを使用して認証します。KMS が権限を検証した後、Agent を通じて認証情報を返します。Agent は認証情報をローカルにキャッシュして、リクエストの繰り返しを減らし、認証情報取得のレイテンシーを低減します。
前提条件
KMS インスタンスが作成され、認証情報がそのインスタンスで管理されていること。詳細については、「通常インスタンスの作成と管理」および「専用 KMS インスタンスの作成と管理」をご参照ください。
ACK クラスターが KMS インスタンスと同じリージョンに作成されていること。詳細については、「ACK マネージドクラスターの作成」および「ACK サーバーレスクラスターの作成」をご参照ください。
KMS Agent のインストール
クラスター作成時に有効化
ACK マネージドクラスターまたは ACK Edge クラスターを作成する際、[クラスター設定] ステップに進み、[詳細オプション (任意)] を展開し、[RRSA OIDC] の横にある [有効化] をクリックします。

既存のクラスターで有効化
-
ACK コンソールにログインします。左側のナビゲーションペインで、[クラスター] をクリックします。
-
クラスターの名前をクリックします。左側のナビゲーションペインで、[クラスター情報] をクリックします。
-
[基本情報] タブで、[セキュリティと監査] セクションまでスクロールし、[RRSA OIDC] の横にある [有効化] をクリックします。

-
[RRSA の有効化] ダイアログボックスで、[確認] をクリックします。クラスターのステータスが [更新中] から [実行中] に変わるまで待ちます。これで RRSA が有効になりました。
ステップ 1:名前空間とサービスアカウントの作成 (任意)
名前空間は、ACK クラスターを開発、テスト、本番などのさまざまな環境用に、論理的に分離された仮想空間に分割します。デフォルトでは、異なる名前空間のアプリケーションは互いのリソースにアクセスできません。ビジネスアプリケーション用の名前空間とサービスアカウントが既にある場合は、このステップをスキップしてください。
名前空間を作成します。
YAML ファイルを使用して名前空間を作成します。次の例では、
app1-namespace.yamlを使用して、app1-devという名前の名前空間を作成します。apiVersion: v1 kind: Namespace metadata: name: app1-dev次のコマンドを実行して、名前空間を作成します。
kubectl apply -f app1-namespace.yaml名前空間が作成されたことを確認します。出力に
app1-devが含まれていれば、名前空間は作成されています。kubectl get namespaces
サービスアカウントを作成します。
YAML ファイルを使用してサービスアカウントを作成します。次の例では、
app1-serviceaccount.yamlを使用して、前のステップで作成したapp1-dev名前空間にapp1-serviceという名前のサービスアカウントを作成します。apiVersion: v1 kind: ServiceAccount metadata: name: app1-service namespace: app1-dev次のコマンドを実行して、サービスアカウントを作成します。
kubectl apply -f app1-serviceaccount.yamlサービスアカウントが作成されたことを確認します。出力に
app1-serviceが含まれていれば、サービスアカウントは作成されています。kubectl get serviceaccount -n app1-dev
ステップ 2:権限の設定
KMS クラウドネイティブアクセスは、以下の 2 つの認証方式をサポートしています。
ほとんどのシナリオでは、設定がより簡単な OpenID Connect (OIDC) を推奨します。既存の RAM ロールポリシーを再利用する必要がある場合や、クロスアカウントアクセスが必要な場合は、RAM ロールを使用してください。
認証方式 | 特徴 |
OIDC (ACK) | ACK クラスターは、OpenID Connect (OIDC) 標準の JWT を使用して認証します。Agent はサービスアカウントトークンを自動的に取得し、Pod の ID を KMS に証明します。RAM ロールは不要で、設定が最も簡単です。 |
RAM ロール | RAM ロールの STS 一時認証情報を使用して KMS にアクセスします。この方法は、既存の RAM ロールの設定を再利用したいシナリオに適しています。 |
OIDC (ACK)
表示される設定パネルで、Authentication Method を [OIDC (ACK)] に設定します。
次のパラメーターを設定します。
パラメーター
説明
Namespace
Pod が属する名前空間の名前 (例:
app1-dev)。ServiceAccount
Pod が使用するサービスアカウント (例:
app1-service)。PodNamePrefix
Pod 名のプレフィックス。このパラメーターを設定すると、名前がプレフィックスに一致する Pod のみが検証を通過できます。このパラメーターを設定しない場合、名前空間とサービスアカウントのみが検証されます。
[スコープ]
KMS へのアクセス方法。有効な値:
Specified KMS Instance:インスタンスエンドポイントを使用して、特定の KMS インスタンス内のキーと認証情報にアクセスします。
[Shared KMS Gateway]:KMS サービスエンドポイントを使用して、認証情報にアクセスします。
[Application Access Point Name]
識別と管理のための、アプリケーションアクセスポイント (アクセス認証情報) のカスタム名。
[Policy Name]
RAM ポリシーのカスタム名。RAM コンソールで事前に作成することなく、このステップで直接ポリシーを作成します。
[RBAC の権限]
RBAC (ロールベースのアクセス制御) の権限レベル。アプリケーションの認証情報操作権限を決定します。
スコープとして [Specified KMS Instance] を選択した場合:
CryptoServiceKeyUser:KMS インスタンス内のキーを使用して認証情報を暗号化できます。
CryptoServiceSecretUser:KMS インスタンス内の認証情報を使用でき、インスタンスの認証情報 API をサポートします。
スコープとして Shared KMS Gateway を選択した場合:[SecretUser] のみがサポートされており、現在のアカウント配下のすべての認証情報を使用できます。
[アクセス可能のリソース]
アプリケーションがアクセスする必要のある認証情報とキー (認証情報の暗号化と復号化に使用) を選択します。
重要複数の認証情報を選択し、認証情報名の合計長が制限を超えると、"parameter invalid" エラーが返されます。この場合、ワイルドカードを使用して許可する認証情報を指定します (例:
secret/rds-ibm*)。これにより、rds-ibmプレフィックスを持つ認証情報へのアクセスが許可されます。[Description]
任意。アプリケーションアクセスポイントの詳細な説明。最大長:8,192 文字。
OK をクリックして次に進みます。
RAM ロール
ID プロバイダー情報を取得します。
対象クラスターの名前をクリックして、詳細ページに移動します。
基本情報 タブの セキュリティと監査 セクションで、RRSA (RAM Roles for Service Accounts) OIDC の横にある [Enabled] ラベルにポインターを合わせると、プロバイダーの URL と ARN 情報を表示できます。

RAM ロールを作成します。
信頼されたエンティティタイプとして IdP を選択し、[エディターに切り替え] をクリックします。
[ビジュアルエディター] セクションで、次の項目を設定します。
基本設定
パラメーター
説明
Effect
[Allow] を選択します。
Action
デフォルト値の
sts:AssumeRoleを維持します。Condition
キーに
oidc:sub、演算子にStringEquals、値にsystem:serviceaccount:<namespace>:<ServiceAccountName>を指定した条件を追加します。ここで、namespaceとServiceAccountNameは、ワークロードを実行している Pod の名前空間とサービスアカウントに対応します。プリンシパル設定:
[プリンシパル] として [ID プロバイダー] を選択し、その下にある [編集] をクリックします。
[ID プロバイダー] 設定ページで、次のパラメーターを設定し、OK をクリックします。
パラメーター
説明
IdP タイプ
[OIDC] を選択します。
ID プロバイダー
RRSA が有効になった後、ACK クラスターによって自動的に作成された ID プロバイダーを選択します:
ack-rrsa-<cluster_id>。
設定完了後、[OK] をクリックしてロール名 (例:
app1-rrsa) を設定し、確認 をクリックします。
ポリシーを作成し、RAM ロールにアタッチします。詳細については、「カスタムポリシーの作成」および「RAM ロールへのポリシーのアタッチ」をご参照ください。
ポリシーの作成 をクリックし、[スクリプトエディター] を選択して、次の例を使用してポリシーを設定します。
説明この例では、ポリシー名は
dev-role-for-rrsa-kms-policyで、タグsecret:app1を持つ認証情報へのアクセスのみを許可します。{ "Version": "1", "Statement": [ { "Effect": "Allow", "Action": [ "kms:Decrypt", "kms:GetSecretValue" ], "Resource": "*", "Condition": { "StringEqualsIgnoreCase": { "kms:tag/secret": [ "app1" ] } } } ] }ポリシー一覧に戻り、対象のポリシーを見つけ、[操作] 列の [ID にアタッチ] をクリックします。
[プリンシパル] セクションで、作成した RAM ロールを選択し、[確認] をクリックします。
ステップ 3:ack-kms-agent-webhook-injector のインストール
[Helm] ページで、デプロイ をクリックします。基本情報 セクションを設定し、次 をクリックします。
パラメーター
説明
[アプリケーション名]
デフォルトのアプリケーション名
ack-kms-agent-webhook-injectorを使用します。[名前空間]
デフォルトのチャート名前空間
kube-systemを使用します。ACK クラスターごとに 1 つの名前空間にインストールするため、複数回インストールする必要はありません。[発生元]
デフォルト:Marketplace。このパラメーターは変更できません。
チャート
ack-kms-agent-webhook-injectorを検索して選択します。確認ダイアログが表示されたら、情報を確認して 可 をクリックします。
パラメーター ページで、ステップ 2 で選択した認証方式に基づいてパラメーターを設定します。
OIDC (ACK):デフォルト設定を維持します。
RAM ロール:
agent.auth.roleArnを空のままにし、agent.auth.roleArnMappingを<Namespace>:<ServiceAccountName>:<RAM Role ARN>に設定します。次の例では、ステップ 2 で作成したデータを使用します。説明NamespaceとServiceAccountNameは、ワークロードを実行している Pod の名前空間とサービスアカウントに対応します。RAM Role ARNは RAM ロールの詳細ページで確認できます。agent: auth: roleArn: roleArnMapping: app1-dev:app1-service: acs:ram::190325303126****:role/app1-rrsa
設定完了後、OK をクリックします。アプリケーションの詳細ページにリダイレクトされます。
ステップ 4:Agent サイドカーのインジェクト
Pod アノテーションの追加:アノテーションキーを
kms-agent-webhook-injector/injectに、値をtrueに設定します。ワークロードが実行されている名前空間に切り替え、デプロイメントに Pod アノテーションを追加します。
重要RAM ロール認証方式の場合、デプロイメントの YAML 設定を変更し、
ServiceAccountNameパラメーターをワークロードを実行している Pod のサービスアカウント名 (例:app1-service) に設定します。OIDC (ACK) 認証方式の場合、変更は不要です。新しいデプロイメントの作成
[イメージによる作成]
デプロイメントリストの上にある イメージによる作成 をクリックし、パラメーターを設定します。
上級 を設定する際、Labels and Annotations セクションに移動し、Pod アノテーションを追加します:名前 列に
kms-agent-webhook-injector/injectを、値 列にtrueを入力します。作成する をクリックして完了します。
[YAML のリソースの作成]
デプロイメントリストの上にある YAML のリソースの作成 をクリックします。
YAML ファイルを編集し、
spec.template.metadata.annotationsの下にkms-agent-webhook-injector/inject: "true"を追加します (このセクションが存在しない場合は作成します)。作成する をクリックして完了します。
既存のデプロイメントの変更
対象のワークロードを見つけ、アクション > 詳細 をクリックします。
詳細ページで、右上隅の YAML の編集 をクリックします。
spec.template.metadata.annotationsの下にkms-agent-webhook-injector/inject: "true"を追加します (このセクションが存在しない場合は作成します)。更新 をクリックし、ワークロードの準備が完了するまで待ちます。
インジェクトの検証
ポッド タブで、イメージ 列を確認します。KMS Agent がサイドカーとして Pod にインジェクトされていることを確認できます。
説明Pod に KMS Agent が 2 回インジェクトされることがあります。これは、初期化に init コンテナが使用されるために発生します。init コンテナは初期化完了後に終了 (Terminated) し、アプリケーションに悪影響を与えたり、コンピューティングリソースを継続的に消費したりすることはありません。
アプリケーションの統合
デプロイメントに KMS Agent がインジェクトされると、アプリケーションコンテナは KMS Agent への HTTP リクエストを通じて KMS から認証情報を取得できます。コードに AccessKey を設定する必要はありません。次の例は、認証情報を取得する方法を示しています。<SecretId> を実際の認証情報名に置き換えてください。
KMS Agent は 127.0.0.1 でのみリッスンします。つまり、同じマシン上のアプリケーションまたはプロセスのみが通信できます。外部ネットワークデバイスは接続できません。アクセスアドレスは localhost または 127.0.0.1 のみをサポートし、アプリケーションのローカル IP はサポートしません。次の例では localhost を使用しています。
KMS Agent によるアクセス方法に加えて、KMS は SDK 経由のアクセスもサポートしています。具体的な操作については、「Secrets Manager クライアント」をご参照ください。
OIDC (ACK)
curl の使用
通常コマンド:
# ファイルからトークンを読み取り、AapArn を指定 curl -v -H "X-KMS-Token:$(</var/run/kmstoken/token)" -H "AapArn:<AapArn>" 'http://localhost:2025/secretsmanager/get?secretId=<SecretId>'$(<file)構文は bash や zsh などのシェルでのみサポートされています。Pod のベースイメージが Alpine (デフォルトシェルは BusyBox ash) や、この構文をサポートしない他のイメージを使用している場合は、代わりに次のコマンドを使用してください。# ファイルからトークンを読み取り、AapArn を指定 (Alpine/BusyBox 互換) curl -v -H "X-KMS-Token:$(cat /var/run/kmstoken/token)" -H "AapArn:<AapArn>" 'http://localhost:2025/secretsmanager/get?secretId=<SecretId>'
Go コードの例
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main() {
// versionStage または versionId を指定して、特定の認証情報バージョンを取得できます。
// 次の例では、versionId を使用して認証情報を取得します。
// url := fmt.Sprintf("http://localhost:2025/secretsmanager/get?secretId=%s&versionId=%s", "agent-test", "version-id")
aapArn := "acs:kms:cn-hangzhou:19*********224:applicationaccesspoint/****"
url := fmt.Sprintf("http://localhost:2025/secretsmanager/get?secretId=%s", "agent-test")
token, err := ioutil.ReadFile("/var/run/kmstoken/token")
if err != nil {
fmt.Printf("トークンファイルの読み取りエラー: %v\n", err)
}
req, err := http.NewRequest("GET", url, nil)
if err != nil {
fmt.Printf("リクエストの作成エラー: %v\n", err)
}
req.Header.Add("X-KMS-Token", string(token))
req.Header.Add("AapArn", aapArn)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Printf("リクエストの送信エラー: %v \n", err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Printf("ステータスコード %d - %s \n", resp.StatusCode, string(body))
}RAM ロール
curl の使用
通常コマンド:
# ファイルからトークンを読み取る curl -v -H "X-KMS-Token:$(</var/run/kmstoken/token)" 'http://localhost:2025/secretsmanager/get?secretId=<SecretId>' # またはトークンを直接書き込む curl -v -H "X-KMS-Token:<token>" 'http://localhost:2025/secretsmanager/get?secretId=<SecretId>'$(<file)構文は bash や zsh などのシェルでのみサポートされています。Pod のベースイメージが Alpine (デフォルトシェルは BusyBox ash) や、この構文をサポートしない他のイメージを使用している場合は、代わりに次のコマンドを使用してください。# ファイルからトークンを読み取る (Alpine/BusyBox 互換) curl -v -H "X-KMS-Token:$(cat /var/run/kmstoken/token)" 'http://localhost:2025/secretsmanager/get?secretId=<SecretId>'
Go コードの例
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main() {
// versionStage または versionId を指定して、特定の認証情報バージョンを取得できます。
// 次の例では、versionId を使用して認証情報を取得します。
// url := fmt.Sprintf("http://localhost:2025/secretsmanager/get?secretId=%s&versionId=%s", "agent-test", "version-id")
url := fmt.Sprintf("http://localhost:2025/secretsmanager/get?secretId=%s", "agent-test")
token, err := ioutil.ReadFile("/var/run/kmstoken/token")
if err != nil {
fmt.Printf("トークンファイルの読み取りエラー: %v\n", err)
}
req, err := http.NewRequest("GET", url, nil)
if err != nil {
fmt.Printf("リクエストの作成エラー: %v\n", err)
}
req.Header.Add("X-KMS-Token", string(token))
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Printf("リクエストの送信エラー: %v \n", err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Printf("ステータスコード %d - %s \n", resp.StatusCode, string(body))
}課金
KMS 側のコスト:
ACK 側のコスト:
ack-kms-agent-webhook-injector コンポーネントは無料です。インジェクトされたサイドカーと Webhook ワークロードが消費するコンピューティングリソースに追加コストがかかる場合があります。
ack-kms-agent-webhook-injector コンポーネントをインストールすると、Webhook サービスワークロードが生成され、コンピューティングリソースを消費するためコストが発生します。設定ファイルでこのワークロードの CPU とメモリ使用量を制限してください。
対象となるワークロードを作成または更新すると、ack-kms-agent-webhook-injector は KMS Agent をサイドカーとしてコンテナにインジェクトします。KMS Agent はコンピューティングリソースを消費するため、コストが発生します。
トラブルシューティング
KMS Agent のインストールまたは使用中に問題が発生した場合は、以下の一般的な問題を参照してトラブルシューティングを行ってください。
原因 | 解決策 |
Agent のインストール失敗 |
|
ネットワーク到達不能またはタイムアウト | ACK クラスターが KMS サービスに到達できることを確認します。VPC 経由で KMS にアクセスする場合、ACK クラスターが存在する VPC が KMS インスタンスとネットワーク接続されていることを確認します。 |
権限不足 | 次の設定を確認します。
|
Agent のインジェクト失敗 | ack-kms-agent-webhook-injector コンポーネントが正しくインストールされ、正常に実行されていることを確認します。Pod アノテーション |
RRSA が有効になっていない | OIDC (ACK) 認証方式は、RRSA (RAM Roles for Service Accounts) 機能に依存します。ACK コンソールで、クラスターの「セキュリティと監査」モジュールに移動して RRSA を有効にします。詳細な手順については、ステップ 2 の RAM ロールタブの ID プロバイダー設定をご参照ください。 |