Container Service for Kubernetes (ACK) 上でコンテナ化されたワークロードを実行する際、アプリケーションコード内に AccessKey をハードコードするとセキュリティリスクが生じ、認証情報のローテーションも困難になります。KMS クラウドネイティブアクセス機能は、Pod に KMS エージェントサイドカーを注入することでこのリスクを解消し、アプリケーションがローカル HTTP リクエストを通じて KMS で管理されている認証情報を安全に取得できるようにします。
仕組み
Key Management Service (KMS) のクラウドネイティブアクセス機能は、コンポーネントのインストールおよび構成をガイド付きワークフローで提供します。ご利用の Container Service for Kubernetes (ACK) クラスター内の Pod が HTTP リクエストを送信すると、Helm コンポーネント ack-kms-agent-webhook-injector によって自動的に Pod に注入された KMS エージェントがそのリクエストを受信し、OpenID Connect (OIDC) JWT または Resource Access Management (RAM) ロールを使用して認証を行います。KMS が権限を検証した後、認証情報をエージェント経由で返却します。エージェントは認証情報をローカルにキャッシュすることで、繰り返しのリクエストを削減し、認証情報取得のレイテンシを低減します。
範囲
-
ACK クラスタータイプの制限:ACK マネージドクラスターおよび専用クラスター、ACK Serverless クラスター、およびACS クラスターの作成がサポートされています。
説明ACK 専用クラスターおよび ACK 登録済みクラスターについては、「ACK に KMS エージェントをデプロイしてシークレットを取得する」をご参照ください。
-
リージョンの制限:ACK クラスターと KMS インスタンスは同一リージョン内に配置する必要があります。
-
パフォーマンスの制限:各 Pod は独立して KMS エージェントサイドカーコンテナを実行します。ビジネスで多数の Pod をデプロイしており、認証時に STS トークンリクエストが 1 分あたり 500 回を超える場合、レート制限がトリガーされ、KMS エージェントの正常な動作に影響を及ぼす可能性があります。
KMS エージェントのインストール
クラスター作成時の有効化
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-dev名前空間内にapp1-serviceという名前のサービスアカウントをapp1-serviceaccount.yamlを使用して作成します。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 を使用して認証します。エージェントは自動的にサービスアカウントトークンを取得し、Pod の ID を KMS に証明します。RAM ロールは不要で、構成が最もシンプルです。 |
|
RAM ロール |
RAM ロールの STS 一時認証情報を使用して KMS にアクセスします。この方式は、既存の RAM ロール設定を再利用したいシナリオに適しています。 |
OIDC (ACK)
-
表示される構成パネルで、Authentication MethodをOIDC (ACK)に設定します。
-
以下のパラメーターを構成します。
パラメーター
説明
名前空間
Pod が存在する名前空間の名前(例:
app1-dev)。ServiceAccount
Pod が使用するサービスアカウント(例:
app1-service)。PodNamePrefix
Pod 名のプレフィックス。このパラメーターを構成すると、プレフィックスに一致する名前の Pod のみが検証を通過できます。このパラメーターを構成しない場合、名前空間とサービスアカウントのみが検証されます。
スコープ
KMS へのアクセス方法。有効な値:
-
指定された KMS インスタンス:インスタンスエンドポイントを使用して特定の KMS インスタンス内のキーおよび認証情報にアクセスします。
-
Shared KMS Gateway:KMS サービスエンドポイントを使用して認証情報にアクセスします。
Application Access Point Name
識別および管理用のアプリケーションアクセスポイント(アクセス認証情報)のカスタム名。
Policy Name
RAM ポリシーのカスタム名。このステップで直接ポリシーを作成でき、RAM コンソールで事前に作成する必要はありません。
RBAC の権限
RBAC(ロールベースアクセス制御)の権限レベル。アプリケーションの認証情報操作権限を決定します。
-
指定された KMS インスタンスが範囲に選択されている場合:
-
CryptoServiceKeyUser:KMS インスタンス内のキーを使用して認証情報を暗号化できます。
-
CryptoServiceSecretUser:KMS インスタンス内の認証情報の使用を許可し、インスタンス向けの認証情報 API をサポートします。
-
-
Shared KMS Gatewayが範囲に選択されている場合:SecretUser のみがサポートされ、現在のアカウント配下のすべての認証情報の使用が許可されます。
アクセス可能のリソース
アプリケーションがアクセスする必要のある認証情報およびキー(認証情報の暗号化・復号に使用)を選択します。
重要複数の認証情報を選択し、認証情報名の合計文字数が制限を超える場合、「パラメーターが無効です」というエラーが返されます。その場合はワイルドカードを使用して許可する認証情報を指定してください(例:
secret/rds-ibm*)。これにより、rds-ibmで始まる認証情報へのアクセスが許可されます。Description
任意。アプリケーションアクセスポイントの詳細な説明。最大長:8,192 文字。
-
-
OK をクリックして次に進みます。
RAM ロール
-
ID プロバイダー情報を取得します。
-
対象クラスターの名前をクリックして詳細ページに移動します。
-
基本情報タブで、セキュリティと監査セクション内の RRSA (RAM Roles for Service Accounts) OIDC の横にある「有効」ラベルにポインターを合わせると、プロバイダー URL および ARN 情報が表示されます。プロバイダー URL は
https://oidc-ack-<region>.oss-<region>.aliyuncs.com/<cluster_id>形式、プロバイダー ARN はacs:ram::<account_id>:oidc-provider/ack-rrsa-<cluster_id>形式です。
-
-
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で、タグenv: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。このパラメーターは変更できません。
Chart
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:エージェントサイドカーの注入
-
Pod アノテーションの追加:アノテーションキーを
kms-agent-webhook-injector/inject、値をtrueに設定します。-
ワークロードが実行されている名前空間に切り替え、Deployment に Pod アノテーションを追加します。
重要RAM ロール認証方式の場合、Deployment YAML 構成を変更し、
ServiceAccountNameパラメーターをワークロードを実行している Pod のサービスアカウント名(例:app1-service)に設定します。OIDC (ACK) 認証方式の場合は、変更は不要です。-
新しい Deployment の作成
イメージによる作成
-
Deployment リストの上部でイメージによる作成をクリックし、パラメーターを構成します。
-
[上級] を構成する場合は、[Labels and Annotations] セクションに移動し、Pod アノテーションを追加します。名前 列に
kms-agent-webhook-injector/injectを、値 列にtrueを入力します。 -
作成するをクリックして完了します。
YAML のリソースの作成
-
Deployment リストの上部でYAML のリソースの作成をクリックします。
-
YAML ファイルを編集し、
spec.template.metadata.annotations配下にkms-agent-webhook-injector/inject: "true"を追加します(該当セクションが存在しない場合は新たに作成します)。 -
作成するをクリックして完了します。
-
-
既存の Deployment の変更
-
対象ワークロードを見つけ、アクション > 詳細をクリックします。
-
詳細ページの右上隅でYAML の編集をクリックします。
-
spec.template.metadata.annotations配下にkms-agent-webhook-injector/inject: "true"を追加します(該当セクションが存在しない場合は新たに作成します)。 -
更新をクリックし、ワークロードが準備完了になるまで待ちます。
-
-
-
-
注入の確認
-
ポッドタブで、イメージ列を確認します。KMS エージェントがサイドカーとして Pod に注入されていることが確認できます。
説明Pod に KMS エージェントが 2 回注入されているように見える場合があります。これは初期化用の init コンテナが使用されているためです。init コンテナは初期化完了後に終了(Terminated)し、アプリケーションに悪影響を及ぼしたり、計算リソースを継続的に消費したりすることはありません。
-
アプリケーション統合
Deployment に KMS エージェントが注入された後、アプリケーションコンテナは KMS エージェントへの HTTP リクエストを通じて KMS から認証情報を取得できます。コード内に AccessKey を構成する必要はありません。以下の例は認証情報の取得方法を示しています。<SecretId> は実際の認証情報名に置き換えてください。
-
KMS エージェントは 127.0.0.1 のみでリッスンしており、同じマシン上のアプリケーションまたはプロセスのみが通信できます。外部ネットワークデバイスからの接続はできません。アクセスアドレスは localhost または 127.0.0.1 のみをサポートし、アプリケーションのローカル IP はサポートしません。以下の例では localhost を使用しています。
-
KMS エージェントアクセス方式に加え、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>'
wget を使用
-
次のコマンドを実行して認証情報を取得します。
# トークンをファイルから読み取り、AapArn を指定 wget -q -O - --header "X-KMS-Token:$(</var/run/kmstoken/token)" --header "AapArn:<AapArn>" 'http://localhost:2025/secretsmanager/get?secretId=<SecretId>' -
$(<file)構文は bash や zsh などのシェルでのみサポートされます。Pod ベースイメージが Alpine(デフォルトシェルは ash)またはこの構文をサポートしない他のシェルを使用している場合は、代わりに以下のコマンドを使用してください。# トークンをファイルから読み取り、AapArn を指定(Alpine 互換) wget -q -O - --header "X-KMS-Token:$(cat /var/run/kmstoken/token)" --header "AapArn:<AapArn>" 'http://localhost:2025/secretsmanager/get?secretId=<SecretId>'
Go コード例
以下の例は 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>'
wget を使用
-
次のコマンドを実行して認証情報を取得します。
# トークンをファイルから読み取り wget -q -O - --header "X-KMS-Token:$(</var/run/kmstoken/token)" 'http://localhost:2025/secretsmanager/get?secretId=<SecretId>' # またはトークンを直接記述 wget -q -O - --header "X-KMS-Token:<token>" 'http://localhost:2025/secretsmanager/get?secretId=<SecretId>' -
$(<file)構文は bash や zsh などのシェルでのみサポートされます。Pod ベースイメージが Alpine(デフォルトシェルは ash)またはこの構文をサポートしない他のシェルを使用している場合は、代わりに以下のコマンドを使用してください。# トークンをファイルから読み取り(Alpine 互換) wget -q -O - --header "X-KMS-Token:$(cat /var/run/kmstoken/token)" 'http://localhost:2025/secretsmanager/get?secretId=<SecretId>'
Go コード例
以下の例は 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 エージェントをサイドカーとしてコンテナに注入します。KMS エージェントは計算リソースを消費してコストが発生します。
-
トラブルシューティング
KMS エージェントのインストールまたは使用中に問題が発生した場合は、以下の一般的な問題を参考にトラブルシューティングを行ってください。
|
原因 |
解決策 |
|
エージェントのインストールに失敗 |
|
|
ネットワークが到達不能またはタイムアウト |
ACK クラスターが KMS サービスに到達可能であることを確認します。VPC 経由で KMS にアクセスする場合、ACK クラスターが配置されている VPC が KMS インスタンスとネットワーク接続されていることを確認してください。 |
|
権限が不十分 |
以下の構成を確認してください。
|
|
エージェントの注入に失敗 |
ack-kms-agent-webhook-injector コンポーネントが正しくインストールされ、正常に実行されていることを確認します。Pod アノテーション |
|
RRSA が有効化されていない |
OIDC (ACK) 認証方式は RRSA (RAM Roles for Service Accounts) 機能に依存しています。ACK コンソールでクラスターのセキュリティおよび監査モジュールに移動し、RRSA を有効化してください。詳細な手順については、手順 2 の RAM ロールタブの ID プロバイダー設定をご参照ください。 |