プロキシレス gRPC を使用してサービス セキュリティを設定する
このガイドでは、プロキシレス gRPC サービス メッシュ用にセキュリティ サービスを構成する方法について説明します。
要件
gRPC プロキシレス サービス メッシュのサービス セキュリティを構成する前に、次の要件を満たしていることを確認してください。
- デプロイメントが、Envoy とプロキシレス ワークロードを使用したサービス ルーティング API の設定の準備要件を満たしている。
- xDS v3 を使用している。
- 次のいずれかの言語で、必要な xDS バージョンと証明書プロバイダの機能にアクセスできる。
- gRPC Java
- gRPC C++
- gRPC Python
- gRPC Go 必要な言語バージョンは、github で確認できます。
- ブートストラップ ジェネレータ、バージョン 0.16.0 にアクセスできる。ブートストラップ ジェネレータ イメージが Google Cloud コンテナ リポジトリに存在する。
- gRPC プロキシレス サービス メッシュ ロード バランシングのすべての前提条件を満たしている。
- PSM セキュリティを使用するための Cloud Service Mesh と Google Cloud のサービス メッシュ リソースを作成または更新するための十分な権限がある。必要な権限の詳細については、プロキシレス gRPC サービスを使用した Cloud Service Mesh の設定の準備をご覧ください。
- Certificate Authority Service を使用するために必要な権限がある(証明書を発行する認証局の作成をご覧ください)
Identity and Access Management を構成する
Google Kubernetes Engine を使用するための権限が必要です。その場合、少なくとも次のロールが必要になります。
roles/container.clusterAdmin
GKE ロールroles/compute.instanceAdmin
Compute Engine ロールroles/iam.serviceAccountUser
ロール
設定に必要なリソースを作成するには、compute.NetworkAdmin
ロールが必要です。このロールには、必要なリソースの作成、更新、削除、一覧表示、使用(他のリソースでの参照)に必要なすべての権限が含まれています。プロジェクトのオーナー編集者には、このロールが自動的に付与されます。
バックエンド サービスのリソースでこれらのリソースを参照する場合、networksecurity.googleapis.com.clientTlsPolicies.use
と networksecurity.googleapis.com.serverTlsPolicies.use
は適用されません。
今後これが適用され、compute.NetworkAdmin
ロールを使用している場合、このチェックの適用時に問題は検出されません。
カスタムロールを使用していて、今後このチェックが適用される場合は、各 .use
権限を含める必要があります。そうしないと、今後、バックエンド サービスから clientTlsPolicy
または serverTlsPolicy
を参照するために必要な権限がカスタムロールに含まれなくなる場合があります。
設定を準備する
プロキシレス サービス メッシュ(PSM)セキュリティは、プロキシレス gRPC サービスのドキュメントに従って、ロード バランシング用に設定されたサービス メッシュにセキュリティを追加します。プロキシレス サービス メッシュでは、gRPC クライアントが URI のスキーム xds:
を使用してサービスにアクセスし、PSM ロード バランシングとエンドポイント検出機能を有効にします。
gRPC クライアントとサーバーを正しいバージョンに更新する
ご使用の言語でサポートされている gRPC の最小バージョンを使用して、アプリケーションを構築または再構築します。
ブートストラップ ファイルを更新する
gRPC アプリケーションは単一のブートストラップ ファイルを使用します。このファイルには、gRPC のクライアント側コードとサーバー側コードに必要なすべてのフィールドが含まれている必要があります。ブートストラップ ジェネレータは、PSM セキュリティで必要とされるフラグと値を含むブートストラップ ファイルを自動的に生成します。詳細については、ブートストラップ ファイル セクションをご覧ください。ここでは、サンプル ブートストラップ ファイルを使用しています。
設定の概要
この設定プロセスは、GKE とプロキシレス gRPC サービスを使用した Cloud Service Mesh の設定の拡張機能です。この設定手順の既存の変更されていないステップは、適用するすべての場所で参照されます。
GKE での Cloud Service Mesh の設定の主な機能強化は次のとおりです。
- CA Service の設定。プライベート CA プールと必要な認証局を作成します。
- Workload Identity Federation for GKE とメッシュ証明書の機能、CA Service の統合による GKE クラスタの作成。
- クラスタでのメッシュ証明書の発行の構成。
- クライアントとサーバー サービス アカウントの作成。
- xDS API と xDS サーバー認証情報を使用して Cloud Service Mesh からセキュリティ構成を取得するサーバーの例。
- xDS 認証情報を使用するサンプル クライアントの設定。
- セキュリティ構成を含める Cloud Service Mesh 構成の更新。
xDS 認証情報を使用するコード例は、次の場所で確認できます。
Google Cloud CLI を更新する
Google Cloud CLI を更新するには、次のコマンドを実行します。
gcloud components update
環境変数を設定する
このガイドでは Cloud Shell コマンドを使用します。コマンド内の繰り返し情報は、さまざまな環境変数で表されます。コマンドを実行する前に、シェル環境で特定の値を次の環境変数に設定します。各コメント行は、関連する環境変数の意味を示しています。
# Your project ID PROJECT_ID=PROJECT_ID # GKE cluster name and zone for this example. CLUSTER_NAME=CLUSTER_NAME ZONE=ZONE gcloud config set compute/zone $ZONE # GKE cluster URL derived from the above GKE_CLUSTER_URL="https://container.googleapis.com/v1/projects/${PROJECT_ID}/locations/${ZONE}/clusters/${CLUSTER_NAME}" # Workload pool to be used with the GKE cluster WORKLOAD_POOL="${PROJECT_ID}.svc.id.goog" # Kubernetes namespace to run client and server demo. K8S_NAMESPACE='default' DEMO_BACKEND_SERVICE_NAME='grpc-gke-helloworld-service' # Compute other values # Project number for your project PROJNUM=$(gcloud projects describe ${PROJECT_ID} --format="value(projectNumber)") # VERSION is the GKE cluster version. Install and use the most recent version # from the rapid release channel and substitute its version for # CLUSTER_VERSION, for example: # VERSION=latest available version # Note that the minimum required cluster version is 1.21.4-gke.1801. VERSION="CLUSTER_VERSION" SA_GKE=service-${PROJNUM}@container-engine-robot.iam.gserviceaccount.com
必要な API へのアクセスを有効にする
このセクションでは、必要な API へのアクセスを有効にする方法を説明します。
次のコマンドを実行して、Cloud Service Mesh と、プロキシレス gRPC サービス メッシュ セキュリティに必要なその他の API を有効にします。
gcloud services enable \ container.googleapis.com \ cloudresourcemanager.googleapis.com \ compute.googleapis.com \ trafficdirector.googleapis.com \ networkservices.googleapis.com \ networksecurity.googleapis.com \ privateca.googleapis.com \ gkehub.googleapis.com
次のコマンドを実行して、デフォルトのサービス アカウントで Cloud Service Mesh セキュリティ API にアクセスできるようにします。
GSA_EMAIL=$(gcloud iam service-accounts list --format='value(email)' \ --filter='displayName:Compute Engine default service account') gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member serviceAccount:${GSA_EMAIL} \ --role roles/trafficdirector.client
GKE クラスタを作成または更新する
Cloud Service Mesh サービスのセキュリティは、GKE と CA Service のインテグレーションに依存します。GKE クラスタは、設定要件に加えて、次の要件を満たしている必要があります。
- 1.21.4-gke.1801 の最小クラスタ バージョンを使用します。新しいバージョンの機能が必要な場合は、Rapid リリース チャンネルからそのバージョンを取得できます。
- 証明書を発行する認証局の作成で説明されているように、GKE クラスタを有効にして、メッシュ証明書で構成する必要があります。
Workload Identity Federation for GKE 連携を使用する新しいクラスタを作成します。既存のクラスタを更新する場合は、次のステップに進みます。
--tags
に指定する値は、Cloud Load Balancing コンポーネントを使用した Cloud Service Mesh の構成セクションで説明しているfirewall-rules create
コマンドの--target-tags
フラグに渡される名前と一致している必要があります。# Create a GKE cluster with GKE managed mesh certificates. gcloud container clusters create CLUSTER_NAME \ --release-channel=rapid \ --scopes=cloud-platform \ --image-type=cos_containerd \ --machine-type=e2-standard-2 \ --zone=ZONE \ --workload-pool=PROJECT_ID.svc.id.goog \ --enable-mesh-certificates \ --cluster-version=CLUSTER_VERSION \ --enable-ip-alias \ --tags=allow-health-checks \ --workload-metadata=GKE_METADATA
クラスタの作成が完了するまでに数分かかることがあります。
既存のクラスタを使用している場合は、Workload Identity Federation for GKE と GKE メッシュ証明書を有効にします。クラスタが
--enable-ip-alias
フラグで作成されていることを確認してください。このフラグは、update
コマンドでは使用できません。gcloud container clusters update CLUSTER_NAME \ --enable-mesh-certificates
次のコマンドを実行して、
kubectl
コマンドのデフォルト クラスタとして新しいクラスタに切り替えます。gcloud container clusters get-credentials CLUSTER_NAME \ --zone ZONE
フリートにクラスタを登録する
GKE クラスタの作成で作成または更新したクラスタをフリートに登録します。クラスタを登録すると、複数のプロジェクトにまたがるクラスタを簡単に構成できるようになります。
各ステップが完了するまでに最大で 10 分かかることがあります。
クラスタをフリートに登録します。
gcloud container fleet memberships register CLUSTER_NAME \ --gke-cluster=ZONE/CLUSTER_NAME \ --enable-workload-identity --install-connect-agent \ --manifest-output-file=MANIFEST-FILE_NAME
変数を、次のように置き換えます。
- CLUSTER_NAME: クラスタの名前。
- ZONE: クラスタのゾーン。
- MANIFEST-FILE_NAME: これらのコマンドが登録用のマニフェストを生成するファイルパス。
登録プロセスが成功すると、次のようなメッセージが表示されます。
Finished registering the cluster CLUSTER_NAME with the fleet.
生成されたマニフェスト ファイルをクラスタに適用します。
kubectl apply -f MANIFEST-FILE_NAME
適用プロセスが成功すると、次のようなメッセージが表示されます。
namespace/gke-connect created serviceaccount/connect-agent-sa created podsecuritypolicy.policy/gkeconnect-psp created role.rbac.authorization.k8s.io/gkeconnect-psp:role created rolebinding.rbac.authorization.k8s.io/gkeconnect-psp:rolebinding created role.rbac.authorization.k8s.io/agent-updater created rolebinding.rbac.authorization.k8s.io/agent-updater created role.rbac.authorization.k8s.io/gke-connect-agent-20210416-01-00 created clusterrole.rbac.authorization.k8s.io/gke-connect-impersonation-20210416-01-00 created clusterrolebinding.rbac.authorization.k8s.io/gke-connect-impersonation-20210416-01-00 created clusterrolebinding.rbac.authorization.k8s.io/gke-connect-feature-authorizer-20210416-01-00 created rolebinding.rbac.authorization.k8s.io/gke-connect-agent-20210416-01-00 created role.rbac.authorization.k8s.io/gke-connect-namespace-getter created rolebinding.rbac.authorization.k8s.io/gke-connect-namespace-getter created secret/http-proxy created deployment.apps/gke-connect-agent-20210416-01-00 created service/gke-connect-monitoring created secret/creds-gcp create
クラスタからメンバー リソースを取得します。
kubectl get memberships membership -o yaml
出力には、フリートによって割り当てられた Workoad Identity プールが含まれています。ここで、PROJECT_ID はプロジェクト ID です。
workload_identity_pool: PROJECT_ID.svc.id.goog
これは、クラスタが正常に登録されたことを意味します。
証明書を発行する認証局を作成する
Pod に対して証明書を発行するには、CA Service プールと次の認証局(CA)を作成します。
- ルート CA。これは、発行されるすべてのメッシュ証明書のルート オブ トラストです。既存のルート CA が存在する場合はそれを使用できます。ルート CA を
enterprise
階層に作成します。ルート CA は有効期間が長く、少量の証明書の発行に適しています。 - 下位 CA。この CA はワークロード用の証明書を発行します。クラスタがデプロイされるリージョンで下位 CA を作成します。下位 CA を
devops
階層に作成します。下位 CA は有効期間が短く、大量の証明書の発行に適しています。
下位 CA の作成は任意ですが、GKE メッシュの証明書を発行するためにルート CA を使用するよりも、下位 CA を作成することを強くおすすめします。ルート CA を使用してメッシュ証明書を発行する場合は、デフォルトの構成ベースの発行モードが引き続き許可されることを確認してください。
下位 CA はクラスタと異なるリージョンに設定できますが、パフォーマンスを最適化するために、クラスタと同じリージョンに作成することをおすすめします。ただし、ルート CA または下位 CA は別々のリージョンに作成でき、それによるパフォーマンスや可用性への影響はありません。
CA Service では、以下のリージョンがサポートされます。
リージョン名 | リージョンの説明 |
---|---|
asia-east1 |
台湾 |
asia-east2 |
香港 |
asia-northeast1 |
東京 |
asia-northeast2 |
大阪 |
asia-northeast3 |
ソウル |
asia-south1 |
ムンバイ |
asia-south2 |
デリー |
asia-southeast1 |
シンガポール |
asia-southeast2 |
ジャカルタ |
australia-southeast1 |
シドニー |
australia-southeast2 |
メルボルン |
europe-central2 |
ワルシャワ |
europe-north1 |
フィンランド |
europe-southwest1 |
マドリッド |
europe-west1 |
ベルギー |
europe-west2 |
ロンドン |
europe-west3 |
フランクフルト |
europe-west4 |
オランダ |
europe-west6 |
チューリッヒ |
europe-west8 |
ミラノ |
europe-west9 |
パリ |
europe-west10 |
ベルリン |
europe-west12 |
トリノ |
me-central1 |
ドーハ |
me-central2 |
Dammam |
me-west1 |
テルアビブ |
northamerica-northeast1 |
モントリオール |
northamerica-northeast2 |
トロント |
southamerica-east1 |
サンパウロ |
southamerica-west1 |
サンチアゴ |
us-central1 |
アイオワ |
us-east1 |
サウスカロライナ |
us-east4 |
北バージニア |
us-east5 |
コロンバス |
us-south1 |
ダラス |
us-west1 |
オレゴン |
us-west2 |
ロサンゼルス |
us-west3 |
ソルトレイクシティ |
us-west4 |
ラスベガス |
サポートされているロケーションのリストを確認するには、次のコマンドを実行します。
gcloud privateca locations list
CA プールと CA を作成する個人に IAM
roles/privateca.caManager
を付与します。MEMBER の正しい形式はuser:userid@example.com
です。その個人が現在のユーザーであれば、シェルコマンド$(gcloud auth list --filter=status:ACTIVE --format="value(account)")
を使用してユーザー ID を取得できます。gcloud projects add-iam-policy-binding PROJECT_ID \ --member=MEMBER \ --role=roles/privateca.caManager
IAM ポリシーを変更する必要があるユーザーに CA Service のロール
role/privateca.admin
を付与します。ここで、MEMBER
はこのアクセスを必要とするユーザー(特に、privateca.auditor
ロールとprivateca.certificateManager
ロールを付与する次の手順を行うユーザー)です。gcloud projects add-iam-policy-binding PROJECT_ID \ --member=MEMBER \ --role=roles/privateca.admin
ルート CA Service プールを作成します。
gcloud privateca pools create ROOT_CA_POOL_NAME \ --location ROOT_CA_POOL_LOCATION \ --tier enterprise
ルート CA を作成します。
gcloud privateca roots create ROOT_CA_NAME --pool ROOT_CA_POOL_NAME \ --subject "CN=ROOT_CA_NAME, O=ROOT_CA_ORGANIZATION" \ --key-algorithm="ec-p256-sha256" \ --max-chain-length=1 \ --location ROOT_CA_POOL_LOCATION
このデモ設定では、変数に次の値を使用します。
- ROOT_CA_POOL_NAME=td_sec_pool
- ROOT_CA_NAME=pkcs2-ca
- ROOT_CA_POOL_LOCATION=us-east1
- ROOT_CA_ORGANIZATION="TestCorpLLC"
下位プールと下位 CA を作成します。デフォルトの構成ベースの発行モードが許可されることを確認します。
gcloud privateca pools create SUBORDINATE_CA_POOL_NAME \ --location SUBORDINATE_CA_POOL_LOCATION \ --tier devops
gcloud privateca subordinates create SUBORDINATE_CA_NAME \ --pool SUBORDINATE_CA_POOL_NAME \ --location SUBORDINATE_CA_POOL_LOCATION \ --issuer-pool ROOT_CA_POOL_NAME \ --issuer-location ROOT_CA_POOL_LOCATION \ --subject "CN=SUBORDINATE_CA_NAME, O=SUBORDINATE_CA_ORGANIZATION" \ --key-algorithm "ec-p256-sha256" \ --use-preset-profile subordinate_mtls_pathlen_0
このデモ設定では、変数に次の値を使用します。
- SUBORDINATE_CA_POOL_NAME="td-ca-pool"
- SUBORDINATE_CA_POOL_LOCATION=us-east1
- SUBORDINATE_CA_NAME="td-ca"
- SUBORDINATE_CA_ORGANIZATION="TestCorpLLC"
- ROOT_CA_POOL_NAME=td_sec_pool
- ROOT_CA_POOL_LOCATION=us-east1
GKE サービス アカウントからのアクセスを許可するために、ルート CA プールの IAM
privateca.auditor
ロールを付与します。gcloud privateca pools add-iam-policy-binding ROOT_CA_POOL_NAME \ --location ROOT_CA_POOL_LOCATION \ --role roles/privateca.auditor \ --member="serviceAccount:service-PROJNUM@container-engine-robot.iam.gserviceaccount.com"
GKE サービス アカウントからのアクセスを許可するために、下位 CA プールの IAM
privateca.certificateManager
ロールを付与します。gcloud privateca pools add-iam-policy-binding SUBORDINATE_CA_POOL_NAME \ --location SUBORDINATE_CA_POOL_LOCATION \ --role roles/privateca.certificateManager \ --member="serviceAccount:service-PROJNUM@container-engine-robot.iam.gserviceaccount.com"
次の
WorkloadCertificateConfig
YAML 構成を保存して、メッシュ証明書を発行する方法をクラスタに指示します。apiVersion: security.cloud.google.com/v1 kind: WorkloadCertificateConfig metadata: name: default spec: # Required. The CA service that issues your certificates. certificateAuthorityConfig: certificateAuthorityServiceConfig: endpointURI: ISSUING_CA_POOL_URI # Required. The key algorithm to use. Choice of RSA or ECDSA. # # To maximize compatibility with various TLS stacks, your workloads # should use keys of the same family as your root and subordinate CAs. # # To use RSA, specify configuration such as: # keyAlgorithm: # rsa: # modulusSize: 4096 # # Currently, the only supported ECDSA curves are "P256" and "P384", and the only # supported RSA modulus sizes are 2048, 3072 and 4096. keyAlgorithm: rsa: modulusSize: 4096 # Optional. Validity duration of issued certificates, in seconds. # # Defaults to 86400 (1 day) if not specified. validityDurationSeconds: 86400 # Optional. Try to start rotating the certificate once this # percentage of validityDurationSeconds is remaining. # # Defaults to 50 if not specified. rotationWindowPercentage: 50
以下を置き換えます。
- クラスタが実行されるプロジェクトのプロジェクト ID:
PROJECT_ID
- メッシュ証明書を発行する CA の完全修飾 URI(ISSUING_CA_POOL_URI)。下位 CA(推奨)またはルート CA のいずれかを指定できます。形式は次のとおりです。
//privateca.googleapis.com/projects/PROJECT_ID/locations/SUBORDINATE_CA_POOL_LOCATION/caPools/SUBORDINATE_CA_POOL_NAME
- クラスタが実行されるプロジェクトのプロジェクト ID:
次の
TrustConfig
YAML 構成を保存して、発行済み証明書を信頼する方法をクラスタに指示します。apiVersion: security.cloud.google.com/v1 kind: TrustConfig metadata: name: default spec: # You must include a trustStores entry for the trust domain that # your cluster is enrolled in. trustStores: - trustDomain: PROJECT_ID.svc.id.goog # Trust identities in this trustDomain if they appear in a certificate # that chains up to this root CA. trustAnchors: - certificateAuthorityServiceURI: ROOT_CA_POOL_URI
以下を置き換えます。
- クラスタが実行されるプロジェクトのプロジェクト ID:
PROJECT_ID
- ルート CA プールの完全修飾 URI(ROOT_CA_POOL_URI)。形式は次のとおりです。
//privateca.googleapis.com/projects/PROJECT_ID/locations/ROOT_CA_POOL_LOCATION/caPools/ROOT_CA_POOL_NAME
- クラスタが実行されるプロジェクトのプロジェクト ID:
この構成をクラスタに適用します。
kubectl apply -f WorkloadCertificateConfig.yaml kubectl apply -f TrustConfig.yaml
NEG を使用してプロキシレス gRPC サービスを作成する
PSM セキュリティには、Cloud Service Mesh からセキュリティ構成を取得するための xDS を使用できるプロキシレス gRPC サーバーが必要です。この手順は、PSM ロード バランシング設定ガイドの NEG を使用して GKE サービスを構成すると似ていますが、java-example-hostname
イメージではなく grpc-java
リポジトリ内の xDS サンプルで xDS 対応の helloworld
サーバーを使用します。
このサーバーは、openjdk:8-jdk
イメージから構築されたコンテナで構築して実行します。また、名前付きの NEG 機能を使用して、NEG の名前を指定できます。これにより、デプロイでは検索しなくても NEG の名前が把握されているため、後の手順が簡略化されます。
gRPC サーバーの Kubernetes 仕様の完全な例を次に示します。次の点に注意してください。
- この仕様では、gRPC サーバー Pod で使用される Kubernetes サービス アカウント
example-grpc-server
を作成します。 - この仕様では、サービスの
cloud.google.com/neg
アノテーションでname
フィールドを使用して NEG 名example-grpc-server
を指定します。 - 変数
${PROJNUM}
は、プロジェクトのプロジェクト番号を表します。 - この仕様では、
initContainers
セクションを使用してブートストラップ ジェネレータを実行し、プロキシレス gRPC ライブラリが必要とするブートストラップ ファイルに入力します。このブートストラップ ファイルは、example-grpc-server
という gRPC サーバー コンテナの/tmp/grpc-xds/td-grpc-bootstrap.json
にあります。
次のアノテーションを Pod の仕様に追加します。
annotations: security.cloud.google.com/use-workload-certificates: ""
従う完全な仕様で正しい配置を核にできます。
作成時には、各 Pod が /var/run/secrets/workload-spiffe-credentials
で Volume を取得します。この Volume には次のものが含まれます。
private_key.pem
は、自動生成された秘密鍵です。certificates.pem
は、クライアント証明書チェーンとしての別の Pod への提示や、サーバー証明書チェーンとしての使用ができる、PEM 形式の証明書のバンドルです。ca_certificates.pem
は、別の Pod によって提示されたクライアント証明書チェーン、または別の Pod に接続したときに受信したサーバー証明書チェーンを検証するときに信頼アンカーとして使用する、PEM 形式の証明書のバンドルです。
ca_certificates.pem
には、ワークロードのローカルの信頼ドメインの証明書が含まれていることに注意してください。これはクラスタのワークロード プールです。
certificates.pem
のリーフ証明書には、次の書式なしテキストの SPIFFE ID アサーションが含まれています。
spiffe://WORKLOAD_POOL/ns/NAMESPACE/sa/KUBERNETES_SERVICE_ACCOUNT
このアサーションでは次のようになります。
- WORKLOAD_POOL は、クラスタ ワークロード プールの名前です。
- NAMESPACE は、Kubernetes サービス アカウントの Namespace です。
- KUBERNETES_SERVICE_ACCOUNT は、Kubernetes サービス アカウントの名前です。
ご使用の言語の手順に沿って、この例で使用する仕様を作成します。
Java
次のコマンドを実行して、プロジェクト番号が正しく設定されていることを確認します。
if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
仕様を作成します。
cat << EOF > example-grpc-server.yaml apiVersion: v1 kind: ServiceAccount metadata: name: example-grpc-server namespace: default annotations: iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com --- apiVersion: v1 kind: Service metadata: name: example-grpc-server namespace: default labels: k8s-app: example-grpc-server annotations: cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}' spec: ports: - name: helloworld port: 8080 protocol: TCP targetPort: 50051 selector: k8s-app: example-grpc-server type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: name: example-grpc-server namespace: default labels: k8s-app: example-grpc-server spec: replicas: 1 selector: matchLabels: k8s-app: example-grpc-server strategy: {} template: metadata: annotations: security.cloud.google.com/use-workload-certificates: "" labels: k8s-app: example-grpc-server spec: containers: - image: openjdk:8-jdk imagePullPolicy: IfNotPresent name: example-grpc-server command: - /bin/sleep - inf env: - name: GRPC_XDS_BOOTSTRAP value: "/tmp/grpc-xds/td-grpc-bootstrap.json" ports: - protocol: TCP containerPort: 50051 resources: limits: cpu: 800m memory: 512Mi requests: cpu: 100m memory: 512Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/grpc-xds/ initContainers: - name: grpc-td-init image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0 imagePullPolicy: Always args: - --config-mesh-experimental - "grpc-mesh" - --output - "/tmp/bootstrap/td-grpc-bootstrap.json" - --node-metadata=app=helloworld resources: limits: cpu: 100m memory: 100Mi requests: cpu: 10m memory: 100Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/bootstrap/ serviceAccountName: example-grpc-server volumes: - name: grpc-td-conf emptyDir: medium: Memory EOF
C++
次のコマンドを実行して、プロジェクト番号が正しく設定されていることを確認します。
if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
仕様を作成します。
cat << EOF > example-grpc-server.yaml apiVersion: v1 kind: ServiceAccount metadata: name: example-grpc-server namespace: default annotations: iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com --- apiVersion: v1 kind: Service metadata: name: example-grpc-server namespace: default labels: k8s-app: example-grpc-server annotations: cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}' spec: ports: - name: helloworld port: 8080 protocol: TCP targetPort: 50051 selector: k8s-app: example-grpc-server type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: name: example-grpc-server namespace: default labels: k8s-app: example-grpc-server spec: replicas: 1 selector: matchLabels: k8s-app: example-grpc-server strategy: {} template: metadata: annotations: security.cloud.google.com/use-workload-certificates: "" labels: k8s-app: example-grpc-server spec: containers: - image: phusion/baseimage:18.04-1.0.0 imagePullPolicy: IfNotPresent name: example-grpc-server command: - /bin/sleep - inf env: - name: GRPC_XDS_BOOTSTRAP value: "/tmp/grpc-xds/td-grpc-bootstrap.json" ports: - protocol: TCP containerPort: 50051 resources: limits: cpu: 8 memory: 8Gi requests: cpu: 300m memory: 512Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/grpc-xds/ initContainers: - name: grpc-td-init image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0 imagePullPolicy: Always args: - --config-mesh-experimental - "grpc-mesh" - --output - "/tmp/bootstrap/td-grpc-bootstrap.json" - --node-metadata=app=helloworld resources: limits: cpu: 100m memory: 100Mi requests: cpu: 10m memory: 100Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/bootstrap/ serviceAccountName: example-grpc-server volumes: - name: grpc-td-conf emptyDir: medium: Memory EOF
Python
次のコマンドを実行して、プロジェクト番号が正しく設定されていることを確認します。
if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
仕様を作成します。
cat << EOF > example-grpc-server.yaml apiVersion: v1 kind: ServiceAccount metadata: name: example-grpc-server namespace: default annotations: iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com --- apiVersion: v1 kind: Service metadata: name: example-grpc-server namespace: default labels: k8s-app: example-grpc-server annotations: cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}' spec: ports: - name: helloworld port: 8080 protocol: TCP targetPort: 50051 selector: k8s-app: example-grpc-server type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: name: example-grpc-server namespace: default labels: k8s-app: example-grpc-server spec: replicas: 1 selector: matchLabels: k8s-app: example-grpc-server strategy: {} template: metadata: annotations: security.cloud.google.com/use-workload-certificates: "" labels: k8s-app: example-grpc-server spec: containers: - image: phusion/baseimage:18.04-1.0.0 imagePullPolicy: IfNotPresent name: example-grpc-server command: - /bin/sleep - inf env: - name: GRPC_XDS_BOOTSTRAP value: "/tmp/grpc-xds/td-grpc-bootstrap.json" ports: - protocol: TCP containerPort: 50051 resources: limits: cpu: 8 memory: 8Gi requests: cpu: 300m memory: 512Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/grpc-xds/ initContainers: - name: grpc-td-init image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0 imagePullPolicy: Always args: - --config-mesh-experimental - "grpc-mesh" - --output - "/tmp/bootstrap/td-grpc-bootstrap.json" - --node-metadata=app=helloworld resources: limits: cpu: 100m memory: 100Mi requests: cpu: 10m memory: 100Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/bootstrap/ serviceAccountName: example-grpc-server volumes: - name: grpc-td-conf emptyDir: medium: Memory EOF
Go
次のコマンドを実行して、プロジェクト番号が正しく設定されていることを確認します。
if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
仕様を作成します。
cat << EOF > example-grpc-server.yaml apiVersion: v1 kind: ServiceAccount metadata: name: example-grpc-server namespace: default annotations: iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com --- apiVersion: v1 kind: Service metadata: name: example-grpc-server namespace: default labels: k8s-app: example-grpc-server annotations: cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}' spec: ports: - name: helloworld port: 8080 protocol: TCP targetPort: 50051 selector: k8s-app: example-grpc-server type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: name: example-grpc-server namespace: default labels: k8s-app: example-grpc-server spec: replicas: 1 selector: matchLabels: k8s-app: example-grpc-server strategy: {} template: metadata: annotations: security.cloud.google.com/use-workload-certificates: "" labels: k8s-app: example-grpc-server spec: containers: - image: golang:1.16-alpine imagePullPolicy: IfNotPresent name: example-grpc-server command: - /bin/sleep - inf env: - name: GRPC_XDS_BOOTSTRAP value: "/tmp/grpc-xds/td-grpc-bootstrap.json" ports: - protocol: TCP containerPort: 50051 resources: limits: cpu: 8 memory: 8Gi requests: cpu: 300m memory: 512Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/grpc-xds/ initContainers: - name: grpc-td-init image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0 imagePullPolicy: Always args: - --config-mesh-experimental - "grpc-mesh" - --output - "/tmp/bootstrap/td-grpc-bootstrap.json" - --node-metadata=app=helloworld resources: limits: cpu: 100m memory: 100Mi requests: cpu: 10m memory: 100Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/bootstrap/ serviceAccountName: example-grpc-server volumes: - name: grpc-td-conf emptyDir: medium: Memory EOF
次のようにプロセスを完了します。
仕様を適用します。
kubectl apply -f example-grpc-server.yaml
サービス アカウントに必要なロールを付与します。
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:${PROJECT_ID}.svc.id.goog[default/example-grpc-server]" \ ${PROJNUM}-compute@developer.gserviceaccount.com gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member "serviceAccount:${PROJECT_ID}.svc.id.goog[default/example-grpc-server]" \ --role roles/trafficdirector.client
次のコマンドを実行して、Service と Pod が正しく作成されたことを確認します。
kubectl get deploy/example-grpc-server kubectl get svc/example-grpc-server
NEG 名が正しいことを確認します。
gcloud compute network-endpoint-groups list \ --filter "name=example-grpc-server" --format "value(name)"
コマンドから NEG 名
example-grpc-server
が返されます。
Google Cloud ロード バランシング コンポーネントを使用して Cloud Service Mesh を構成する
このセクションの手順は、ロード バランシング コンポーネントによる Cloud Service Mesh の構成と似ていますが、次のセクションで説明するように、いくつかの変更点があります。
ヘルスチェック、ファイアウォール ルール、バックエンド サービスを作成する
gRPC サーバーが mTLS を使用するように構成されている場合、ヘルスチェック クライアントはサーバーに有効なクライアント証明書を提示できないため、gRPC ヘルスチェックは機能しません。これには、次のいずれかの方法で対処できます。
最初の方法では、サーバーによってヘルスチェック ポートとして指定された提供ポートが追加で作成されます。これは、そのポートへの書式なしテキストまたは TLS として、特別なヘルスチェック サービスに関連付けられます。
xDS の helloworld
サンプル サーバーでは、平文のヘルスチェック ポートとして PORT_NUMBER
+ 1 を使用します。この例では、50051 が gRPC アプリケーション サーバーポートであるため、ヘルスチェック ポートとして 50052 を使用します。
2 つ目の方法では、ヘルスチェックを構成して、アプリケーション処理ポートへの TCP 接続だけを確認します。これにより、接続のみがチェックされ、TLS handshake の失敗が発生した場合は、サーバーへの不要なトラフィックが生成されます。このため、最初の方法を使用することをおすすめします。
ヘルスチェックを作成します。ヘルスチェックは、サーバーを作成して起動するまで開始されません。
ヘルスチェックに使用する専用のサービスポートを作成する場合は、次のコマンドを使用します(これが推奨の方法です)。
gcloud compute health-checks create grpc grpc-gke-helloworld-hc \ --enable-logging --port 50052
TCP ヘルスチェックを作成する場合は、次のコマンドを使用します(この方法は推奨されません)。
gcloud compute health-checks create tcp grpc-gke-helloworld-hc \ --use-serving-port
ファイアウォールを作成します。
--target-tags
の値が GKE クラスタを作成または更新するセクションで--tags
に指定した値と一致することを確認します。gcloud compute firewall-rules create grpc-gke-allow-health-checks \ --network default --action allow --direction INGRESS \ --source-ranges 35.191.0.0/16,130.211.0.0/22 \ --target-tags allow-health-checks \ --rules tcp:50051-50052
バックエンド サービスを作成します。
gcloud compute backend-services create grpc-gke-helloworld-service \ --global \ --load-balancing-scheme=INTERNAL_SELF_MANAGED \ --protocol=GRPC \ --health-checks grpc-gke-helloworld-hc
NEG をバックエンド サービスに接続します。
gcloud compute backend-services add-backend grpc-gke-helloworld-service \ --global \ --network-endpoint-group example-grpc-server \ --network-endpoint-group-zone ${ZONE} \ --balancing-mode RATE \ --max-rate-per-endpoint 5
Mesh
リソースと GRPCRoute
リソースを作成する
これは、プロキシレス gRPC サービスの設定で Mesh
リソースと GRPCRoute
リソースを設定する方法に似ています。
Mesh
仕様を作成し、mesh.yaml
というファイルに保存します。name: grpc-mesh
仕様から
Mesh
リソースをインポートします。gcloud network-services meshes import grpc-mesh \ --source=mesh.yaml \ --location=global
GRPCRoute
仕様を作成し、grpc_route.yaml
というファイルに保存します。name: helloworld-grpc-route hostnames: - helloworld-gke:8000 meshes: - projects/PROJECT_NUMBER/locations/global/meshes/grpc-mesh rules: - action: destinations: - serviceName: projects/PROJECT_NUMBER/locations/global/backendServices/grpc-gke-helloworld-service
grpc_route.yaml
仕様からGRPCRoute
リソースをインポートします。gcloud network-services grpc-routes import helloworld-grpc-route \ --source=grpc_route.yaml \ --location=global
プロキシレス gRPC セキュリティで Cloud Service Mesh を構成する
この例では、クライアント側とサーバー側に mTLS を構成する方法を示しています。
ポリシー参照の形式
サーバー TLS ポリシーとクライアント TLS ポリシーを参照する場合は、次の形式にする必要があります。
projects/PROJECT_ID/locations/global/[serverTlsPolicies|clientTlsPolicies]/[server-tls-policy|client-mtls-policy]
次に例を示します。
projects/PROJECT_ID/locations/global/serverTlsPolicies/server-tls-policy
projects/PROJECT_ID/locations/global/clientTlsPolicies/client-mtls-policy
サーバー側で mTLS を構成する
まず、サーバー TLS ポリシーを作成します。このポリシーにより、gRPC サーバー側で、serverCertificate
の一部である ID 証明書用の google_cloud_private_spiffe
という名前で識別される certificateProvicerInstance
プラグイン構成を使用することが求められます。mtlsPolicy
セクションは mTLS セキュリティを示し、clientValidationCa
のプラグイン構成と同じ google_cloud_private_spiffe
を使用します。これはルート(検証)証明書の仕様です。
次に、エンドポイント ポリシーを作成します。このポリシーでは、バックエンド(メタデータ ラベルの有無にかかわらずポート 50051
を使用する gRPC サーバーなど)が、server-mtls-policy
という名前の接続されたサーバー TLS ポリシーを受信することが指定されます。メタデータ ラベルは、MATCH_ALL
またはサポートされている値を使用して指定します。サポートされているメタデータ ラベルは、NetworkServicesEndpointPolicy ドキュメントの endpointMatcher.metadataLabelMatcher.metadataLabelMatchCriteria
フィールドにあります。エンドポイント ポリシー リソースの値を含む一時ファイル ep-mtls-psms.yaml
で、定義済みのポリシーを使用してエンドポイント ポリシーを作成します。
サーバー TLS ポリシー リソースの値を使用して、現在のディレクトリに一時ファイル
server-mtls-policy.yaml
を作成します。name: "projects/PROJECT_ID/locations/global/serverTlsPolicies/server-mtls-policy" serverCertificate: certificateProviderInstance: pluginInstance: google_cloud_private_spiffe mtlsPolicy: clientValidationCa: - certificateProviderInstance: pluginInstance: google_cloud_private_spiffe
一時ファイル
server-mtls-policy.yaml
をインポートして、server-mtls-policy
という名前のサーバー TLS ポリシー リソースを作成します。gcloud network-security server-tls-policies import server-mtls-policy \ --source=server-mtls-policy.yaml --location=global
一時ファイル
ep-mtls-psms.yaml
を作成して、エンドポイント ポリシーを作成します。name: "ep-mtls-psms" type: "GRPC_SERVER" serverTlsPolicy: "projects/PROJECT_ID/locations/global/serverTlsPolicies/server-mtls-policy" trafficPortSelector: ports: - "50051" endpointMatcher: metadataLabelMatcher: metadataLabelMatchCriteria: "MATCH_ALL" metadataLabels: - labelName: app labelValue: helloworld
ep-mtls-psms.yaml
ファイルをインポートして、エンドポイント ポリシー リソースを作成します。gcloud beta network-services endpoint-policies import ep-mtls-psms \ --source=ep-mtls-psms.yaml --location=global
クライアント側で mTLS を構成する
クライアント側のセキュリティ ポリシーがバックエンド サービスに接続されます。クライアントがバックエンド サービスを介してバックエンド(gRPC サーバー)にアクセスすると、接続されたクライアント側のセキュリティ ポリシーがクライアントに送信されます。
現在のディレクトリにある
client-mtls-policy.yaml
という一時ファイルにクライアント TLS ポリシー リソースを作成します。name: "client-mtls-policy" clientCertificate: certificateProviderInstance: pluginInstance: google_cloud_private_spiffe serverValidationCa: - certificateProviderInstance: pluginInstance: google_cloud_private_spiffe
一時ファイル
client-mtls-policy.yaml
をインポートして、client-mtls-policy
という名前のクライアント TLS ポリシー リソースを作成します。gcloud network-security client-tls-policies import client-mtls-policy \ --source=client-mtls-policy.yaml --location=global
次の例に示すように、一時ファイル内にスニペットを作成してこのポリシーを参照し、
SecuritySettings
メッセージにsubjectAltNames
の詳細を追加します。${PROJECT_ID}
は、プロジェクト ID の値に置き換えます。これは、前述の${PROJECT_ID}
環境変数の値です。subjectAltNames
のexample-grpc-server
は、デプロイ仕様の gRPC サーバー Pod で使用される Kubernetes サービス アカウント名です。if [ -z "$PROJECT_ID" ] ; then echo Please make sure PROJECT_ID is set. ; fi cat << EOF > client-security-settings.yaml securitySettings: clientTlsPolicy: projects/${PROJECT_ID}/locations/global/clientTlsPolicies/client-mtls-policy subjectAltNames: - "spiffe://${PROJECT_ID}.svc.id.goog/ns/default/sa/example-grpc-server" EOF
作成済みのバックエンド サービスに
securitySettings
メッセージを追加します。現在のバックエンド サービス コンテンツをエクスポートし、クライアントsecuritySetting
メッセージを追加します。新しいコンテンツを再度インポートし、バックエンド サービスを更新します。gcloud compute backend-services export grpc-gke-helloworld-service --global \ --destination=/tmp/grpc-gke-helloworld-service.yaml cat /tmp/grpc-gke-helloworld-service.yaml client-security-settings.yaml \ >/tmp/grpc-gke-helloworld-service1.yaml gcloud compute backend-services import grpc-gke-helloworld-service --global \ --source=/tmp/grpc-gke-helloworld-service1.yaml -q
構成を確認する
これで、サーバーサイドとクライアントサイドのセキュリティを含む Cloud Service Mesh の構成が完了しました。次に、サーバーとクライアントのワークロードを準備し、実行します。これでサンプルが完成します。
プロキシレス gRPC クライアントを作成する
この手順は、前の手順のプロキシレス gRPC サービスの作成と似ています。grpc-java
リポジトリの xDS サンプル ディレクトリにある xDS 対応の helloworld
クライアントを使用します。このクライアントは、openjdk:8-jdk
イメージから構築されたコンテナ内で構築して実行します。gRPC クライアントの Kubernetes 仕様は以下のように機能します。
- gRPC クライアント Pod で使用される Kubernetes サービス アカウント
example-grpc-client
を作成します。 ${PROJNUM}
はプロジェクトのプロジェクト番号を表し、実際の番号に置き換える必要があります。
次のアノテーションを Pod の仕様に追加します。
annotations: security.cloud.google.com/use-workload-certificates: ""
作成時には、各 Pod が /var/run/secrets/workload-spiffe-credentials
で Volume を取得します。この Volume には次のものが含まれます。
private_key.pem
は、自動生成された秘密鍵です。certificates.pem
は、クライアント証明書チェーンとしての別の Pod への提示や、サーバー証明書チェーンとしての使用ができる、PEM 形式の証明書のバンドルです。ca_certificates.pem
は、別の Pod によって提示されたクライアント証明書チェーン、または別の Pod に接続したときに受信したサーバー証明書チェーンを検証するときに信頼アンカーとして使用する、PEM 形式の証明書のバンドルです。
ca_certificates.pem
には、ワークロードのローカル トラスト ドメイン(クラスタのワークロード プール)のルート証明書が含まれています。
certificates.pem
のリーフ証明書には、次の書式なしテキストの SPIFFE ID アサーションが含まれています。
spiffe://WORKLOAD_POOL/ns/NAMESPACE/sa/KUBERNETES_SERVICE_ACCOUNT
このアサーションでは次のようになります。
- WORKLOAD_POOL は、クラスタ ワークロード プールの名前です。
- NAMESPACE は、Kubernetes サービス アカウントの名前です。
- KUBERNETES_SERVICE_ACCOUNT は、Kubernetes サービス アカウントの Namespace です。
ご使用の言語の手順に沿って、この例で使用する仕様を作成します。
Java
次のコマンドを実行して、プロジェクト番号が正しく設定されていることを確認します。
if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
次の仕様を作成します。
cat << EOF > example-grpc-client.yaml apiVersion: v1 kind: ServiceAccount metadata: name: example-grpc-client namespace: default annotations: iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com --- apiVersion: apps/v1 kind: Deployment metadata: name: example-grpc-client namespace: default labels: k8s-app: example-grpc-client spec: replicas: 1 selector: matchLabels: k8s-app: example-grpc-client strategy: {} template: metadata: annotations: security.cloud.google.com/use-workload-certificates: "" labels: k8s-app: example-grpc-client spec: containers: - image: openjdk:8-jdk imagePullPolicy: IfNotPresent name: example-grpc-client command: - /bin/sleep - inf env: - name: GRPC_XDS_BOOTSTRAP value: "/tmp/grpc-xds/td-grpc-bootstrap.json" resources: limits: cpu: 800m memory: 512Mi requests: cpu: 100m memory: 512Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/grpc-xds/ initContainers: - name: grpc-td-init image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0 imagePullPolicy: Always args: - --config-mesh-experimental - "grpc-mesh" - --output - --config-mesh-experimental - "grpc-mesh" - "/tmp/bootstrap/td-grpc-bootstrap.json" resources: limits: cpu: 100m memory: 100Mi requests: cpu: 10m memory: 100Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/bootstrap/ serviceAccountName: example-grpc-client volumes: - name: grpc-td-conf emptyDir: medium: Memory EOF
C++
次のコマンドを実行して、プロジェクト番号が正しく設定されていることを確認します。
if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
次の仕様を作成します。
cat << EOF > example-grpc-client.yaml apiVersion: v1 kind: ServiceAccount metadata: name: example-grpc-client namespace: default annotations: iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com --- apiVersion: apps/v1 kind: Deployment metadata: name: example-grpc-client namespace: default labels: k8s-app: example-grpc-client spec: replicas: 1 selector: matchLabels: k8s-app: example-grpc-client strategy: {} template: metadata: annotations: security.cloud.google.com/use-workload-certificates: "" labels: k8s-app: example-grpc-client spec: containers: - image: phusion/baseimage:18.04-1.0.0 imagePullPolicy: IfNotPresent name: example-grpc-client command: - /bin/sleep - inf env: - name: GRPC_XDS_BOOTSTRAP value: "/tmp/grpc-xds/td-grpc-bootstrap.json" resources: limits: cpu: 8 memory: 8Gi requests: cpu: 300m memory: 512Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/grpc-xds/ initContainers: - name: grpc-td-init image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0 imagePullPolicy: Always args: - --config-mesh-experimental - "grpc-mesh" - --output - "/tmp/bootstrap/td-grpc-bootstrap.json" resources: limits: cpu: 100m memory: 100Mi requests: cpu: 10m memory: 100Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/bootstrap/ serviceAccountName: example-grpc-client volumes: - name: grpc-td-conf emptyDir: medium: Memory EOF
Python
次のコマンドを実行して、プロジェクト番号が正しく設定されていることを確認します。
if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
次の仕様を作成します。
cat << EOF > example-grpc-client.yaml apiVersion: v1 kind: ServiceAccount metadata: name: example-grpc-client namespace: default annotations: iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com --- apiVersion: apps/v1 kind: Deployment metadata: name: example-grpc-client namespace: default labels: k8s-app: example-grpc-client spec: replicas: 1 selector: matchLabels: k8s-app: example-grpc-client strategy: {} template: metadata: annotations: security.cloud.google.com/use-workload-certificates: "" labels: k8s-app: example-grpc-client spec: containers: - image: phusion/baseimage:18.04-1.0.0 imagePullPolicy: IfNotPresent name: example-grpc-client command: - /bin/sleep - inf env: - name: GRPC_XDS_BOOTSTRAP value: "/tmp/grpc-xds/td-grpc-bootstrap.json" resources: limits: cpu: 8 memory: 8Gi requests: cpu: 300m memory: 512Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/grpc-xds/ initContainers: - name: grpc-td-init image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0 imagePullPolicy: Always args: - --config-mesh-experimental - "grpc-mesh" - --output - "/tmp/bootstrap/td-grpc-bootstrap.json" resources: limits: cpu: 100m memory: 100Mi requests: cpu: 10m memory: 100Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/bootstrap/ serviceAccountName: example-grpc-client volumes: - name: grpc-td-conf emptyDir: medium: Memory EOF
Go
次のコマンドを実行して、プロジェクト番号が正しく設定されていることを確認します。
if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
次の仕様を作成します。
cat << EOF > example-grpc-client.yaml apiVersion: v1 kind: ServiceAccount metadata: name: example-grpc-client namespace: default annotations: iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com --- apiVersion: apps/v1 kind: Deployment metadata: name: example-grpc-client namespace: default labels: k8s-app: example-grpc-client spec: replicas: 1 selector: matchLabels: k8s-app: example-grpc-client strategy: {} template: metadata: annotations: security.cloud.google.com/use-workload-certificates: "" labels: k8s-app: example-grpc-client spec: containers: - image: golang:1.16-alpine imagePullPolicy: IfNotPresent name: example-grpc-client command: - /bin/sleep - inf env: - name: GRPC_XDS_BOOTSTRAP value: "/tmp/grpc-xds/td-grpc-bootstrap.json" resources: limits: cpu: 8 memory: 8Gi requests: cpu: 300m memory: 512Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/grpc-xds/ initContainers: - name: grpc-td-init image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0 imagePullPolicy: Always args: - --config-mesh-experimental - "grpc-mesh" - --output - "/tmp/bootstrap/td-grpc-bootstrap.json" resources: limits: cpu: 100m memory: 100Mi requests: cpu: 10m memory: 100Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/bootstrap/ serviceAccountName: example-grpc-client volumes: - name: grpc-td-conf emptyDir: medium: Memory EOF
次のようにプロセスを完了します。
仕様を適用します。
kubectl apply -f example-grpc-client.yaml
サービス アカウントに必要なロールを付与します。
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:${PROJECT_ID}.svc.id.goog[default/example-grpc-client]" \ ${PROJNUM}-compute@developer.gserviceaccount.com gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member "serviceAccount:${PROJECT_ID}.svc.id.goog[default/example-grpc-client]" \ --role roles/trafficdirector.client
クライアント Pod が動作していることを確認します。
kubectl get pods
このコマンドでは、次のようなテキストが返されます。
NAMESPACE NAME READY STATUS RESTARTS AGE default example-grpc-client-7c969bb997-9fzjv 1/1 Running 0 104s [..skip..]
サーバーを実行する
前の手順で作成したサーバー Pod で、xDS 対応の helloworld
サーバーを構築して実行します。
Java
example-grpc-server
サービス用に作成された Pod の名前を取得します。kubectl get pods | grep example-grpc-server
次のようなフィードバックが表示されます。
default example-grpc-server-77548868d-l9hmf 1/1 Running 0 105s
サーバー Pod へのシェルを開きます。
kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/bash
シェルで、
/tmp/grpc-xds/td-grpc-bootstrap.json
のブートストラップ ファイルがブートストラップ ファイルセクションで説明されているスキーマと一致していることを確認します。gRPC Java バージョン 1.42.1 をダウンロードして、
xds-hello-world
サーバー アプリケーションを構築します。curl -L https://github.com/grpc/grpc-java/archive/v1.42.1.tar.gz | tar -xz cd grpc-java-1.42.1/examples/example-xds ../gradlew --no-daemon installDist
--xds-creds
フラグを指定してサーバーを実行し、50051
をリスニング ポート、xds-server
をサーバー ID 名として使用して、xDS 対応のセキュリティを指定します。./build/install/example-xds/bin/xds-hello-world-server --xds-creds 50051 xds-server
サーバーが Cloud Service Mesh から必要な構成を取得すると、次の出力が表示されます。
Listening on port 50051 plain text health service listening on port 50052
C++
example-grpc-server
サービス用に作成された Pod の名前を取得します。kubectl get pods | grep example-grpc-server
次のようなフィードバックが表示されます。
default example-grpc-server-77548868d-l9hmf 1/1 Running 0 105s
サーバー Pod へのシェルを開きます。
kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/bash
シェルで、
/tmp/grpc-xds/td-grpc-bootstrap.json
のブートストラップ ファイルがブートストラップ ファイルセクションで説明されているスキーマと一致していることを確認します。gRPC C++ をダウンロードして
xds-hello-world
サーバー アプリケーションを構築します。apt-get update -y && \ apt-get install -y \ build-essential \ clang \ python3 \ python3-dev curl -L https://github.com/grpc/grpc/archive/master.tar.gz | tar -xz cd grpc-master tools/bazel build examples/cpp/helloworld:xds_greeter_server
50051
をリッスンポートとして、xds_greeter_server
をサーバー ID 名として使用して、サーバーを実行します。bazel-bin/examples/cpp/helloworld/xds_greeter_server --port=50051 --maintenance_port=50052 --secure
認証情報なしでサーバーを実行するには、次のように指定します。
bazel-bin/examples/cpp/helloworld/xds_greeter_server --nosecure
サーバーが Cloud Service Mesh から必要な構成を取得すると、次の出力が表示されます。
Listening on port 50051 plain text health service listening on port 50052
Python
example-grpc-server
サービス用に作成された Pod の名前を取得します。kubectl get pods | grep example-grpc-server
次のようなフィードバックが表示されます。
default example-grpc-server-77548868d-l9hmf 1/1 Running 0 105s
サーバー Pod へのシェルを開きます。
kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/bash
シェルで、
/tmp/grpc-xds/td-grpc-bootstrap.json
のブートストラップ ファイルがブートストラップ ファイルセクションで説明されているスキーマと一致していることを確認します。gRPC Python バージョン 1.41.0 をダウンロードして、サンプル アプリケーションを構築します。
apt-get update -y
apt-get install -y python3 python3-pip
curl -L https://github.com/grpc/grpc/archive/v1.41.x.tar.gz | tar -xz
cd grpc-1.41.x/examples/python/xds/
python3 -m virtualenv venv
source venv/bin/activate
python3 -m pip install -r requirements.txt
--xds-creds
フラグを指定してサーバーを実行し、50051
をリスニング ポートとして使用して、xDS 対応のセキュリティを指定します。python3 server.py 50051 --xds-creds
サーバーが Cloud Service Mesh から必要な構成を取得すると、次の出力が表示されます。
2021-05-06 16:10:34,042: INFO Running with xDS Server credentials 2021-05-06 16:10:34,043: INFO Greeter server listening on port 50051 2021-05-06 16:10:34,046: INFO Maintenance server listening on port 50052
Go
example-grpc-server
サービス用に作成された Pod の名前を取得します。kubectl get pods | grep example-grpc-server
次のようなフィードバックが表示されます。
default example-grpc-server-77548868d-l9hmf 1/1 Running 0 105s
サーバー Pod へのシェルを開きます。
kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/sh
シェルで、
/tmp/grpc-xds/td-grpc-bootstrap.json
のブートストラップ ファイルがブートストラップ ファイルセクションで説明されているスキーマと一致していることを確認します。gRPC Go バージョン 1.41.0 をダウンロードし、
xds-hello-world
サーバー アプリケーションがあるディレクトリに移動します。apk add curl curl -L https://github.com/grpc/grpc-go/archive/v1.42.0.tar.gz | tar -xz cd grpc-go-1.42.0/examples/features/xds/server
リスニング ポートとして
50051
を使用します。--xds_creds
フラグを指定してサーバーを構築して実行し、xDS 対応のセキュリティを指定します。GRPC_GO_LOG_VERBOSITY_LEVEL=2 GRPC_GO_LOG_SEVERITY_LEVEL="info" \ go run main.go \ -xds_creds \ -port 50051
サーバーが Cloud Service Mesh から必要な構成を取得すると、次の出力が表示されます。
Using xDS credentials... Serving GreeterService on 0.0.0.0:50051 and HealthService on 0.0.0.0:50052
サーバーの起動後に、サービスが正常な状態であることを示すために 3~5 分かかります。
クライアントを実行して構成を確認する
前の手順で作成したクライアント Pod で、xDS 対応の helloworld
クライアントを構築して実行します。
Java
クライアント Pod の名前を取得します。
kubectl get pods | grep example-grpc-client
次のようなフィードバックが表示されます。
default example-grpc-client-7c969bb997-9fzjv 1/1 Running 0 105s
クライアント Pod へのシェルを開きます。
kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
コマンドシェルで gRPC Java バージョン 1.42.1 をダウンロードして、
xds-hello-world
クライアント アプリケーションを構築します。curl -L https://github.com/grpc/grpc-java/archive/v1.42.1.tar.gz | tar -xz cd grpc-java-1.42.1/examples/example-xds ../gradlew --no-daemon installDist
--xds-creds
フラグを指定してクライアントを実行し、xDS 対応のセキュリティ、クライアント名、ターゲット接続文字列を指定します。./build/install/example-xds/bin/xds-hello-world-client --xds-creds xds-client \ xds:///helloworld-gke:8000
次のような出力が表示されます。
Greeting: Hello xds-client, from xds-server
C++
クライアント Pod の名前を取得します。
kubectl get pods | grep example-grpc-client
次のようなフィードバックが表示されます。
default example-grpc-client-7c969bb997-9fzjv 1/1 Running 0 105s
クライアント Pod へのシェルを開きます。
kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
シェルを開いたら、gRPC C++ をダウンロードして
xds-hello-world
クライアント アプリケーションを構築します。apt-get update -y && \ apt-get install -y \ build-essential \ clang \ python3 \ python3-dev
curl -L https://github.com/grpc/grpc/archive/master.tar.gz | tar -xz
cd grpc-master
tools/bazel build examples/cpp/helloworld:xds_greeter_client
--xds-creds
フラグを指定してクライアントを実行し、xDS 対応のセキュリティ、クライアント名、ターゲット接続文字列を指定します。bazel-bin/examples/cpp/helloworld/xds_greeter_client --target=xds:///helloworld-gke:8000
認証情報を使用せずにクライアントを実行するには、次のように記述します。
bazel-bin/examples/cpp/helloworld/xds_greeter_client --target=xds:///helloworld-gke:8000 --nosecure
次のような出力が表示されます。
Greeter received: Hello world
Python
クライアント Pod の名前を取得します。
kubectl get pods | grep example-grpc-client
次のようなフィードバックが表示されます。
default example-grpc-client-7c969bb997-9fzjv 1/1 Running 0 105s
クライアント Pod へのシェルを開きます。
kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
シェルで、gRPC Python バージョン 1.41.0 をダウンロードして、サンプル クライアント アプリケーションを構築します。
apt-get update -y apt-get install -y python3 python3-pip python3 -m pip install virtualenv curl -L https://github.com/grpc/grpc/archive/v1.41.x.tar.gz | tar -xz cd grpc-1.41.x/examples/python/xds/ python3 -m virtualenv venv source venv/bin/activate python3 -m pip install -r requirements.txt
--xds-creds
フラグを指定してクライアントを実行し、xDS 対応のセキュリティ、クライアント名、ターゲット接続文字列を指定します。python3 client.py xds:///helloworld-gke:8000 --xds-creds
次のような出力が表示されます。
Greeter client received: Hello you from example-host!
Go
クライアント Pod の名前を取得します。
kubectl get pods | grep example-grpc-client
次のようなフィードバックが表示されます。
default example-grpc-client-7c969bb997-9fzjv 1/1 Running 0 105s
クライアント Pod へのシェルを開きます。
kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/sh
シェルを開いたら、gRPC Go バージョン 1.42.0 をダウンロードし、
xds-hello-world
クライアント アプリケーションがあるディレクトリに移動します。apk add curl curl -L https://github.com/grpc/grpc-go/archive/v1.42.0.tar.gz | tar -xz cd grpc-go-1.42.0/examples/features/xds/client
--xds_creds
フラグを指定してクライアントを構築して実行し、xDS 対応のセキュリティ、クライアント名、ターゲット接続文字列を指定します。GRPC_GO_LOG_VERBOSITY_LEVEL=2 GRPC_GO_LOG_SEVERITY_LEVEL="info" \ go run main.go \ -xds_creds \ -name xds-client \ -target xds:///helloworld-gke:8000
次のような出力が表示されます。
Greeting: Hello xds-client, from example-grpc-server-77548868d-l9hmf
認可ポリシーでサービスレベルのアクセスを構成する
認可ポリシーをサポートするには、gRFC A41 をサポートする必要があります。必要な言語バージョンは、github で確認できます。
次の手順を使用して、認可ポリシーでサービスレベルのアクセスを構成します。認可ポリシーを作成する前に、認可を使用してアクセスを制限するの注意事項を確認してください。
構成を簡単に検証できるように、クライアントで helloworld-gke
サービスを参照するために使用できる追加のホスト名を作成します。
以前に
grpc_route.yaml
に保存されていたGRPCRoute
仕様を更新します。name: helloworld-grpc-route hostnames: - helloworld-gke:8000 - helloworld-gke-noaccess:8000 meshes: - projects/PROJECT_NUMBER/locations/global/meshes/grpc-mesh rules: - action: destinations: - serviceName: projects/PROJECT_NUMBER/locations/global/backendServices/grpc-gke-helloworld-service
grpc_route.yaml
仕様からGRPCRoute
リソースを再度インポートします。gcloud network-services grpc-routes import helloworld-grpc-route \ --source=grpc_route.yaml \ --location=global
次の手順では、ホスト名が helloworld-gke:8000
でポートが 50051
の example-grpc-client
アカウントによるリクエストの送信を許可する認可ポリシーを作成します。
gcloud
認可ポリシーは、
helloworld-gke-authz-policy.yaml
という名前のファイルを作成することによって作成します。action: ALLOW name: helloworld-gke-authz-policy rules: - sources: - principals: - spiffe://PROJECT_ID.svc.id.goog/ns/default/sa/example-grpc-client destinations: - hosts: - helloworld-gke:8000 ports: - 50051
ポリシーをインポートします。
gcloud network-security authorization-policies import \ helloworld-gke-authz-policy \ --source=helloworld-gke-authz-policy.yaml \ --location=global
ep-mtls-psms.yaml
ファイルに次の行を追加して、新しい認可ポリシーを参照するようにエンドポイント ポリシーを更新します。authorizationPolicy: projects/${PROJECT_ID}/locations/global/authorizationPolicies/helloworld-gke-authz-policy
これにより、エンドポイント ポリシーに、
app:helloworld
というラベルを含む gRPC ブートストラップ ファイルを持つ Pod への受信リクエストに対して、mTLS と認可ポリシーの両方を適用する必要があることが定められました。ポリシーをインポートします。
gcloud network-services endpoint-policies import ep-mtls-psms \ --source=ep-mtls-psms.yaml --location=global
認可ポリシーを検証する
以下の手順を使用して、認可ポリシーが正しく機能することを確認します。
Java
前に使用したクライアント Pod でシェルを開きます。
kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
コマンドシェルで、次のコマンドを実行して設定を検証します。
cd grpc-java-1.42.1/examples/example-xds ./build/install/example-xds/bin/xds-hello-world-client --xds-creds xds-client \ xds:///helloworld-gke:8000
次のような出力が表示されます。
Greeting: Hello xds-client, from xds-server
別のサーバー名でクライアントを再度実行します。なお、これは失敗するケースです。認可ポリシーでは
helloworld-gke:8000
ホスト名へのアクセスのみが許可されるため、このリクエストは無効です。./build/install/example-xds/bin/xds-hello-world-client --xds-creds xds-client \ xds:///helloworld-gke-noaccess:8000
次のような出力が表示されます。
WARNING: RPC failed: Status{code=PERMISSION_DENIED}
この出力が表示されない場合は、認可ポリシーがまだ使用されていない可能性があります。数分待ってから、確認プロセス全体をもう一度試しくてださい。
Go
前に使用したクライアント Pod でシェルを開きます。
kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
コマンドシェルで、次のコマンドを実行して設定を検証します。
cd grpc-go-1.42.0/examples/features/xds/client GRPC_GO_LOG_VERBOSITY_LEVEL=2 GRPC_GO_LOG_SEVERITY_LEVEL="info" \ go run main.go \ -xds_creds \ -name xds-client \ -target xds:///helloworld-gke:8000
次のような出力が表示されます。
Greeting: Hello xds-client, from example-grpc-server-77548868d-l9hmf
別のサーバー名でクライアントを再度実行します。なお、これは失敗するケースです。認可ポリシーでは
helloworld-gke:8000
ホスト名へのアクセスのみが許可されるため、このリクエストは無効です。GRPC_GO_LOG_VERBOSITY_LEVEL=2 GRPC_GO_LOG_SEVERITY_LEVEL="info" \ go run main.go \ -xds_creds \ -name xds-client \ -target xds:///helloworld-gke-noaccess:8000
次のような出力が表示されます。
could not greet: rpc error: code = PermissionDenied desc = Incoming RPC is not allowed: rpc error: code = PermissionDenied desc = incoming RPC did not match an allow policy exit status 1
この出力が表示されない場合は、認可ポリシーがまだ使用されていない可能性があります。数分待ってから、確認プロセス全体をもう一度試しくてださい。
mTLS の代わりに TLS を使用する
この例の TLS を少し変更するだけで使用できます。
ServerTlsPolicy
でmtlsPolicy
を削除します。cat << EOF > server-tls-policy.yaml name: "server-tls-policy" serverCertificate: certificateProviderInstance: pluginInstance: google_cloud_private_spiffe EOF
代わりに
EndpointPolicy
でこのポリシーを使用します。cat << EOF > ep-tls-psms.yaml name: "ep-mtls-psms" type: "GRPC_SERVER" serverTlsPolicy: "projects/${PROJECT_ID}/locations/global/serverTlsPolicies/server-tls-policy" trafficPortSelector: ports: - "50051" endpointMatcher: metadataLabelMatcher: metadataLabelMatchCriteria: "MATCH_ALL" metadataLabels: [] EOF
TLS の場合、mTLS の
ClientTlsPolicy
も動作しますが、ポリシーのclientCertificate
セクションは TLS では不要なため、削除できます。cat << EOF > client-tls-policy.yaml name: "client-tls-policy" serverValidationCa: - certificateProviderInstance: pluginInstance: google_cloud_private_spiffe EOF
Wallet のサンプルでサービスのセキュリティを使用する
このセクションでは、Java、C++、Go 向けにサービス セキュリティを利用して Wallet のサンプルを有効にする方法の概要を説明します。
Java
Java のソースコードの例は github にあります。このコードでは、プロキシレス セキュリティの構成時に XdsChannel
と XdsServer
の認証情報を使用しています。
以下の手順では、Go を使用して Wallet を構成する例について説明します。このプロセスは Java の場合も同様です。この手順では、Google Cloud コンテナ リポジトリから取得した既存の Docker イメージを使用します。
サンプルを作成する手順は次のとおりです。
- リポジトリのクローンを作成し、gRPC サンプルのディレクトリにあるファイルを取得します。
00-common-env.sh
ファイルを編集します。WALLET_DOCKER_IMAGE
の値を Go Docker イメージに設定する行をコメントアウトし、WALLET_DOCKER_IMAGE
の値を Java Docker イメージに設定する行のコメント化を解除します。- Cloud Router インスタンスの作成と構成の手順を行うか、スクリプト
10.apis.sh
で関数create_cloud_router_instances
を使用して、Cloud Router インスタンスの作成と構成を行います。 hello world
の例の手順を行うか、スクリプト20-cluster.sh
で関数create_cluster
を使用してクラスタを作成します。- CA Service の手順またはスクリプト
30-private-ca-setup.sh
を使用して、プライベート認証局を作成します。 - スクリプト
40-k8s-resources.sh
を使用して、すべてのサービスのサービス アカウント、Namespace、Kubernetes Service、NEG、サーバー側の Deployment(account
、stats
、stats_premium
、wallet_v1
、wallet_v2
)を含む Kubernetes リソースを作成します。 - 作成したサービスごとに、スクリプト
50-td-components.sh
でcreate_health_check
とcreate_backend_service
を使用してヘルスチェックとバックエンド サービスを作成します。 - スクリプト
60-routing-components.sh
でcreate_routing_components
を使用して、Cloud Service Mesh ルーティング コンポーネントを作成します。 - スクリプト
70-security-components.sh
でcreate_security_components
を使用して、各バックエンド サービスの Cloud Service Mesh セキュリティ コンポーネントを作成します。 - スクリプト
75-client-deployment.sh
でcreate_client_deployment
を使用して、Wallet クライアントの Deployment を作成します。 - grpc-wallet クライアントで確認するの説明に沿ってクライアントを起動し、構成を確認します。
C++
C++ のソースコードの例は github にあります。このコードでは、プロキシレス セキュリティの構成時に XdsChannel
と XdsServer
の認証情報を使用しています。
以下の手順では、Go を使用して Wallet を構成する例について説明します。このプロセスは C++ の場合も同様です。この手順では、Google Cloud コンテナ リポジトリから取得した既存の Docker イメージを使用します。
サンプルを作成する手順は次のとおりです。
- リポジトリのクローンを作成し、gRPC サンプルのディレクトリにあるファイルを取得します。
00-common-env.sh
ファイルを編集します。WALLET_DOCKER_IMAGE
の値を Go Docker イメージに設定する行をコメントアウトし、WALLET_DOCKER_IMAGE
の値を C++ Docker イメージに設定する行のコメント化を解除します。- Cloud Router インスタンスの作成と構成の手順を行うか、スクリプト
10.apis.sh
で関数create_cloud_router_instances
を使用して、Cloud Router インスタンスの作成と構成を行います。 hello world
の例の手順を行うか、スクリプト20-cluster.sh
で関数create_cluster
を使用してクラスタを作成します。- CA Service の手順またはスクリプト
30-private-ca-setup.sh
を使用して、プライベート認証局を作成します。 - スクリプト
40-k8s-resources.sh
を使用して、すべてのサービスのサービス アカウント、Namespace、Kubernetes Service、NEG、サーバー側の Deployment(account
、stats
、stats_premium
、wallet_v1
、wallet_v2
)を含む Kubernetes リソースを作成します。 - 作成したサービスごとに、スクリプト
50-td-components.sh
でcreate_health_check
とcreate_backend_service
を使用してヘルスチェックとバックエンド サービスを作成します。 - スクリプト
60-routing-components.sh
でcreate_routing_components
を使用して、Cloud Service Mesh ルーティング コンポーネントを作成します。 - スクリプト
70-security-components.sh
でcreate_security_components
を使用して、各バックエンド サービスの Cloud Service Mesh セキュリティ コンポーネントを作成します。 - スクリプト
75-client-deployment.sh
でcreate_client_deployment
を使用して、Wallet クライアントの Deployment を作成します。 - grpc-wallet クライアントで確認するの説明に沿ってクライアントを起動し、構成を確認します。
Go
Go のソースコードの例は github にあります。このコードでは、プロキシレス セキュリティの構成時に XdsChannel
と XdsServer
の認証情報を使用しています。
この手順では、Google Cloud コンテナ リポジトリから取得した既存の Docker イメージを使用します。
サンプルを作成する手順は次のとおりです。
- リポジトリのクローンを作成し、gRPC サンプルのディレクトリにあるファイルを取得します。
00-common-env.sh
ファイルを編集して、環境変数に正しい値を設定します。- Cloud Router インスタンスの作成と構成の手順を行うか、スクリプト
10.apis.sh
で関数create_cloud_router_instances
を使用して、Cloud Router インスタンスの作成と構成を行います。 hello world
の例の手順を行うか、スクリプト20-cluster.sh
で関数create_cluster
を使用してクラスタを作成します。- CA Service の手順またはスクリプト
30-private-ca-setup.sh
を使用して、プライベート認証局を作成します。 - スクリプト
40-k8s-resources.sh
を使用して、すべてのサービスのサービス アカウント、Namespace、Kubernetes Service、NEG、サーバー側の Deployment(account
、stats
、stats_premium
、wallet_v1
、wallet_v2
)を含む Kubernetes リソースを作成します。 - 作成したサービスごとに、スクリプト
50-td-components.sh
でcreate_health_check
とcreate_backend_service
を使用してヘルスチェックとバックエンド サービスを作成します。 - スクリプト
60-routing-components.sh
でcreate_routing_components
を使用して、Cloud Service Mesh ルーティング コンポーネントを作成します。 - スクリプト
70-security-components.sh
でcreate_security_components
を使用して、各バックエンド サービスの Cloud Service Mesh セキュリティ コンポーネントを作成します。 - スクリプト
75-client-deployment.sh
でcreate_client_deployment
を使用して、Wallet クライアントの Deployment を作成します。 - grpc-wallet クライアントで確認するの説明に沿ってクライアントを起動し、構成を確認します。
ブートストラップ ファイル
このガイドの設定プロセスでは、ブートストラップ ジェネレータを使用して必要なブートストラップ ファイルを作成します。このセクションでは、ブートストラップ ファイル自体に関するリファレンス情報を提供します。
ブートストラップ ファイルには、プロキシレス gRPC コードに必要な構成情報(xDS サーバーの接続情報など)が含まれています。ブートストラップ ファイルには、プロキシレス gRPC のセキュリティ機能に必要なセキュリティ構成が含まれています。gRPC サーバーには、追加フィールドが 1 つ必要になります。ブートストラップ ファイルのサンプルは、次のようになります。
{ "xds_servers": [ { "server_uri": "trafficdirector.googleapis.com:443", "channel_creds": [ { "type": "google_default" } ], "server_features": [ "xds_v3" ] } ], "authorities": { "traffic-director-c2p.xds.googleapis.com": { "xds_servers": [ { "server_uri": "dns:///directpath-pa.googleapis.com", "channel_creds": [ { "type": "google_default" } ], "server_features": [ "xds_v3", "ignore_resource_deletion" ] } ], "client_listener_resource_name_template": "xdstp://traffic-director-c2p.xds.googleapis.com/envoy.config.listener.v3.Listener/%s" } }, "node": { "id": "projects/9876012345/networks/mesh:grpc-mesh/nodes/b59f49cc-d95a-4462-9126-112f794d5dd3", "cluster": "cluster", "metadata": { "INSTANCE_IP": "10.28.2.8", "TRAFFICDIRECTOR_DIRECTPATH_C2P_IPV6_CAPABLE": true, "TRAFFICDIRECTOR_GCP_PROJECT_NUMBER": "223606568246", "TRAFFICDIRECTOR_NETWORK_NAME": "default", "app": "helloworld" }, "locality": { "zone": "us-central1-c" } }, "certificate_providers": { "google_cloud_private_spiffe": { "plugin_name": "file_watcher", "config": { "certificate_file": "/var/run/secrets/workload-spiffe-credentials/certificates.pem", "private_key_file": "/var/run/secrets/workload-spiffe-credentials/private_key.pem", "ca_certificate_file": "/var/run/secrets/workload-spiffe-credentials/ca_certificates.pem", "refresh_interval": "600s" } } }, "server_listener_resource_name_template": "grpc/server?xds.resource.listening_address=%s" }
セキュリティ サービス用のブートストラップ ファイルを更新する
次のフィールドには、セキュリティと xDS v3 の使用に関連する変更が反映されています。
node
内の id
フィールドでは、gRPC クライアントの一意の ID を Cloud Service Mesh に提供します。次の形式のノード ID を使用して、Google Cloud プロジェクト番号とネットワーク名を指定する必要があります。
projects/{project number}/networks/{network name}/nodes/[UNIQUE_ID]
プロジェクト番号 1234 とデフォルトのネットワークの例は次のとおりです。
projects/1234/networks/default/nodes/client1
INSTANCE_IP
フィールドは、Pod の IP アドレス、または INADDR_ANY
を示す 0.0.0.0
です。このフィールドは、gRPC サーバーが Cloud Service Mesh から Listener リソースを取得するために使用され、サーバー側のセキュリティを確保します。
ブートストラップ ファイルのセキュリティ構成フィールド
JSON キー | タイプ | 値 | メモ |
---|---|---|---|
server_listener_resource_name_template |
文字列 | grpc/server?xds.resource.listening_address=%s |
gRPC サーバーには必須です。gRPC はこの値を使用して、Cloud Service Mesh から Listener リソースを取得してリソース名を作成し、サーバー側のセキュリティやその他の構成に使用します。gRPC はこの情報を使用してリソース名の文字列を作成します。 |
certificate_providers |
JSON 構造体 | google_cloud_private_spiffe |
必須。値は、証明書プロバイダ インスタンスに対する名前のマッピングを表す JSON 構造体です。証明書プロバイダ インスタンスは、ID とルート証明書を取得するために使用されます。サンプルのブートストラップ ファイルには、1 つの名前 google_cloud_private_spiffe が含まれ、証明書プロバイダ インスタンスの JSON 構造体が値として含まれています。各証明書プロバイダ インスタンスの JSON 構造体には、次の 2 つのフィールドがあります。
|
file_watcher
プラグインの config
JSON 構造の内容を以下に示します。
certificate_file
: 必須の文字列です。この値は ID 証明書のロケーションです。private_key_file
: 必須の文字列です。値は秘密鍵ファイルのロケーションで、ID 証明書と一致している必要があります。ca_certificate_file
: 必須の文字列です。値はルート証明書のロケーションで、信頼バンドルとも呼ばれます。refresh_interval
: オプションの文字列です。この値は、期間の JSON マッピングの文字列表現を使用して指定された更新間隔を示します。デフォルト値は「600s」で、10 分の期間です。
ブートストラップ ジェネレータ
ブートストラップ ジェネレータのコンテナ イメージは gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
で入手できます。ソースコードは https://github.com/GoogleCloudPlatform/traffic-director-grpc-bootstrap
で入手できます。よく使用されるコマンドライン オプションは次のとおりです。
--output
: このオプションを使用して、出力ブートストラップ ファイルが書き込まれる場所を指定します。たとえば、コマンド--output /tmp/bootstrap/td-grpc-bootstrap.json
を実行すると、Pod のファイル システム内の/tmp/bootstrap/td-grpc-bootstrap.json
にブートストラップ ファイルが生成されます。--config-mesh-experimental
: このオプションを使用して、Mesh
リソースに対応するメッシュ名を指定します。--node-metadata
: ブートストラップ ファイルでノード メタデータを入力するには、このフラグを使用します。これは、EndpointPolicy
でメタデータ ラベル マッチャーを使用する場合に必要となります。Cloud Service Mesh は、ブートストラップ ファイルのノード メタデータ セクションで指定されたラベルデータを使用します。引数は、key=value の形式で指定されます。例:--node-metadata version=prod --node-metadata type=grpc
上記の情報により、ブートストラップ ファイルのノード メタデータ セクションに次の内容が追加されます。
{ "node": { ... "metadata": { "version": "prod", "type": "grpc", ... }, ... }, ... }
デプロイを削除する
必要に応じて、これらのコマンドを実行して、このガイドに従って作成したデプロイを削除できます。
クラスタを削除するには、次のコマンドを実行します。
gcloud container clusters delete CLUSTER_NAME --zone ZONE --quiet
作成したリソースを削除するには、次のコマンドを実行します。
gcloud compute backend-services delete grpc-gke-helloworld-service --global --quiet gcloud compute network-endpoint-groups delete example-grpc-server --zone ZONE --quiet gcloud compute firewall-rules delete grpc-gke-allow-health-checks --quiet gcloud compute health-checks delete grpc-gke-helloworld-hc --quiet gcloud network-services endpoint-policies delete ep-mtls-psms \ --location=global --quiet gcloud network-security authorization-policies delete helloworld-gke-authz-policy \ --location=global --quiet gcloud network-security client-tls-policies delete client-mtls-policy \ --location=global --quiet gcloud network-security server-tls-policies delete server-tls-policy \ --location=global --quiet gcloud network-security server-tls-policies delete server-mtls-policy \ --location=global --quiet
トラブルシューティング
以降の手順を使用して、セキュリティのデプロイにおける問題を解決します。
ワークロードで Cloud Service Mesh から構成を取得できない
次のようなエラーが表示された場合:
PERMISSION_DENIED: Request had insufficient authentication scopes.
以下のことを確認してください。
--scopes=cloud-platform
引数を使用して GKE クラスタを作成した。- Kuberneters サービス アカウントに
roles/trafficdirector.client
を割り当てた。 roles/trafficdirector.client
をデフォルトの Google Cloud サービス アカウント(前述の ${GSA_EMAIL})に割り当てた。trafficdirector.googleapis.com
サービス(API)を有効にした。
Cloud Service Mesh 構成が正しい場合でも、gRPC サーバーで TLS/mTLS を使用しない
エンドポイント ポリシーの構成で GRPC_SERVER
を指定していることを確認してください。SIDECAR_PROXY
を指定した場合、gRPC では構成は無視されます。
リクエストされたクラスタ バージョンでは GKE クラスタを作成できない
GKE クラスタの作成コマンドが、次のようなエラーで失敗することがあります。
Node version "1.20.5-gke.2000" is unsupported.
クラスタ作成コマンドに引数 --release-channel rapid
を使用していることを確認します。このリリースの正しいバージョンを取得するには、Rapid リリース チャンネルを使用する必要があります。
No usable endpoint
エラーが表示される
No usable endpoint
エラーによりクライアントがサーバーと通信できない場合、ヘルス チェッカーがサーバーのバックエンドを異常としてマークしていた可能性があります。バックエンドの健全性を確認するには、次の gcloud
コマンドを実行します。
gcloud compute backend-services get-health grpc-gke-helloworld-service --global
コマンドからバックエンド ステータスが異常であると返された場合は、次のいずれかの原因が考えられます。
- ファイアウォールが作成されていないか、正しいソース IP 範囲を含まれていない。
- ファイアウォールのターゲットタグが、作成したクラスタのタグと一致していない。
ワークロードがセキュリティ設定で通信できない
プロキシレス サービス メッシュのセキュリティを設定してもワークロードが通信できない場合は、次の手順に沿って原因を特定してください。
- プロキシレス セキュリティを無効にして、プロキシレス サービス メッシュの負荷分散のユースケースにおける問題を解消します。メッシュ内のセキュリティを無効にするには、次のいずれかの対応をします。
- クライアント側とサーバー側で平文の認証情報を使用する。
- Cloud Service Mesh の構成でバックエンド サービスとエンドポイント ポリシーに対してセキュリティを構成しない。
デプロイにセキュリティが設定されていないため、プロキシレスの Cloud Service Mesh のデプロイに関するトラブルシューティングの手順を行います。
フォールバック認証情報としての平文の認証情報または安全でない認証情報とともに xDS 認証情報を使用するようにワークロードを変更します。前述のように、セキュリティを無効にして Cloud Service Mesh の構成を維持します。この場合、gRPC は Cloud Service Mesh でセキュリティの構成を許可していますが、Cloud Service Mesh はセキュリティ情報を送信しません。この場合、gRPC は前述の最初のケースのように機能する書式なしテキストの(または安全でない)認証情報にフォールバックします。このケースが機能しない場合は、次の操作を行います。
- gRPC と Cloud Service Mesh の間で交換された xDS メッセージを確認できるように、クライアントサイドとサーバーサイドの両方でロギングレベルを上げます。
- Cloud Service Mesh で、ワークロードに送信される CDS レスポンスと LDS レスポンスでセキュリティが有効になっていないことを確認します。
- ワークロードがチャネルで TLS モードまたは mTLS モードを使用していないことを確認します。TLS handshake に関連するログメッセージが表示された場合は、アプリケーションのソースコードを確認し、安全でない認証情報または平文の認証情報をフォールバック認証情報として使用していることを確認してください。アプリケーションのソースコードが正しい場合は、gRPC ライブラリのバグである可能性があります。
ユーザーガイドのトラブルシューティング手順に沿って、GKE クラスタに対して CA Service と GKE の統合が正しく機能していることを確認します。その機能で提供される証明書と鍵が、指定されたディレクトリ
/var/run/secrets/workload-spiffe-credentials/
で使用可能であることを確認してください。前述のように、メッシュ内で(mTLS ではなく)TLS を有効にして、クライアントとサーバーのワークロードを再起動します。
- gRPC と Cloud Service Mesh の間で交換された xDS メッセージを表示できるように、クライアントサイドとサーバーサイドの両方でロギングレベルを上げます。
- Cloud Service Mesh で、ワークロードに送信される CDS レスポンスと LDS レスポンスでセキュリティが有効になっていることを確認します。
クライアントが CertificateException
およびメッセージ Peer certificate SAN check failed
で失敗する
これは、SecuritySettings
メッセージの subjectAltNames
値に問題があることを示しています。なお、これらの値は、バックエンド サービス用に作成した Kubernetes Service に基づきます。作成した Kubernetes Service ごとに、次の形式の SPIFFE ID が関連付けられます。
spiffe://${WORKLOAD_POOL}/ns/${K8S_NAMESPACE}/sa/${SERVICE_ACCOUNT}
該当の値は次のとおりです。
WORKLOAD_POOL
: クラスタのワークロード プール(${PROJECT_ID}.svc.id.goog
)K8S_NAMESPACE
: サービスのデプロイに使用した Kubernetes NamespaceSERVICE_ACCOUNT
: サービスのデプロイに使用した Kubernetes サービス アカウント
ネットワーク エンドポイント グループとしてバックエンド サービスに接続したすべての Kubernetes Service について、SPIFFE ID が正しく計算され、その SPIFFE ID が SecuritySettings
メッセージの subjectAltNames
フィールドに追加されていることを確認してください。
アプリケーションが gRPC ライブラリで mTLS 証明書を使用できない
アプリケーションが gRPC ライブラリで mTLS 証明書を使用できない場合は、次の手順を行います。
Pod 仕様に、NEG を使用したプロキシレス gRPC サービスの作成で説明されている
security.cloud.google.com/use-workload-certificates
アノテーションが含まれていることを確認します。証明書チェーン、リーフ証明書、秘密鍵、信頼できる CA 証明書が含まれるファイルが、Pod 内から次のパスでアクセス可能であることを確認します。
- 証明書チェーンとリーフ証明書: "/var/run/secrets/workload-spiffe-credentials/certificates.pem"
- 秘密鍵: "/var/run/secrets/workload-spiffe-credentials/private_key.pem"
- CA バンドル: "/var/run/secrets/workload-spiffe-credentials/ca_certificates.pem"
前の手順で指定した証明書を使用できない場合は、次の手順を行います。
gcloud privateca subordinates describe SUBORDINATE_CA_POOL_NAME
--location=LOCATIONGKE のコントロール プレーンに正しい IAM ロールバインディングが付与されていることを確認し、CA Service へのアクセスを許可します。
# Get the IAM policy for the CA gcloud privateca roots get-iam-policy ROOT_CA_POOL_NAME # Verify that there is an IAM binding granting access in the following format - members: - serviceAccount:service-projnumber@container-engine-robot.iam.gserviceaccount.com role: roles/privateca.certificateManager # Where projnumber is the project number (e.g. 2915810291) for the GKE cluster.
証明書の有効期限が切れていないことを確認します。これは、
/var/run/secrets/workload-spiffe-credentials/certificates.pem
の証明書チェーンとリーフ証明書です。確認するには、次のコマンドを実行します。cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"
次のコマンドを実行して、アプリケーションでサポートされている鍵タイプを確認します。
cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Public Key Algorithm" -A 3
gRPC Java アプリケーションの
WorkloadCertificateConfig
YAML ファイルに、次のkeyAlgorithm
が含まれていることを確認します。
keyAlgorithm: rsa: modulusSize: 4096
CA が証明書鍵と同じ鍵ファミリーを使用していることを確認します。
アプリケーションの証明書がクライアント、サーバー、またはピアによって拒否される
- ピア アプリケーションが同じ信頼バンドルを使用して証明書を検証することを確認します。
- 使用中の証明書の有効期限が切れていないことを確認します(証明書チェーンとリーフ証明書: "/var/run/secrets/workload-spiffe-credentials/certificates.pem")。
Pod が保留状態のままになる
設定プロセス中に Pod が保留状態のままである場合は、デプロイ仕様の Pod の CPU とメモリリソースを増やします。
--enable-mesh-certificates
フラグを指定してクラスタを作成できない
gcloud CLI の最新バージョンを実行していることを確認します。
gcloud components update
--enable-mesh-certificates
フラグは gcloud beta
でのみ機能します。
Pod が起動しない
証明書のプロビジョニングが失敗した場合、GKE メッシュ証明書を使用する Pod が起動しない可能性があります。これは、次のような状況で発生します。
WorkloadCertificateConfig
またはTrustConfig
が正しく構成されていないか、存在しない。- CSR が承認されていない。
証明書のプロビジョニングが失敗するかどうかを確認するには、Pod イベントを確認します。
Pod のステータスを確認します。
kubectl get pod -n POD_NAMESPACE POD_NAME
以下を置き換えます。
POD_NAMESPACE
: Pod の名前空間。POD_NAME
: Pod の名前。
Pod の最近のイベントを確認します。
kubectl describe pod -n POD_NAMESPACE POD_NAME
証明書のプロビジョニングに失敗した場合、
Type=Warning
、Reason=FailedMount
、From=kubelet
が含まれるイベントと、先頭がMountVolume.SetUp failed for volume "gke-workload-certificates"
のMessage
フィールドが表示されます。Message
フィールドにはトラブルシューティング情報が含まれています。Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedMount 13s (x7 over 46s) kubelet MountVolume.SetUp failed for volume "gke-workload-certificates" : rpc error: code = Internal desc = unable to mount volume: store.CreateVolume, err: unable to create volume "csi-4d540ed59ef937fbb41a9bf5380a5a534edb3eedf037fe64be36bab0abf45c9c": caPEM is nil (check active WorkloadCertificateConfig)
Pod が起動しない原因がオブジェクトの構成が適切でないか、CSR が拒否されたことである場合は、以下のトラブルシューティングの手順をご覧ください。
WorkloadCertificateConfig
または TrustConfig
の構成に誤りがある
WorkloadCertificateConfig
オブジェクトと TrustConfig
オブジェクトが正しく作成されていることを確認してください。kubectl
を使用して、これらのオブジェクトの構成ミスを診断できます。
現在のステータスを取得します。
WorkloadCertificateConfig
:kubectl get WorkloadCertificateConfig default -o yaml
TrustConfig
:kubectl get TrustConfig default -o yaml
ステータスの出力を検査します。有効なオブジェクトには、
type: Ready
とstatus: "True"
の条件が設定されます。status: conditions: - lastTransitionTime: "2021-03-04T22:24:11Z" message: WorkloadCertificateConfig is ready observedGeneration: 1 reason: ConfigReady status: "True" type: Ready
無効なオブジェクトの場合は、
status: "False"
が代わりに表示されます。reason
フィールドとmessage
フィールドには、追加のトラブルシューティングの詳細が含まれます。
CSR が承認されていない
CSR 承認プロセス中に問題が発生した場合は、CSR の type: Approved
条件と type: Issued
条件でエラーの詳細を確認できます。
kubectl
を使用して、関連する CSR を一覧表示します。kubectl get csr \ --field-selector='spec.signerName=spiffe.gke.io/spiffe-leaf-signer'
Approved
でIssued
ではない CSR、またはApproved
でない CSR を選択します。kubectl を使用して、選択した CSR の詳細を取得します。
kubectl get csr CSR_NAME -o yaml
CSR_NAME
を、選択した CSR の名前に置き換えます。
有効な CSR には、type: Approved
と status: "True"
の条件と、status.certificate
フィールドに有効な証明書があります。
status:
certificate: <base64-encoded data>
conditions:
- lastTransitionTime: "2021-03-04T21:58:46Z"
lastUpdateTime: "2021-03-04T21:58:46Z"
message: Approved CSR because it is a valid SPIFFE SVID for the correct identity.
reason: AutoApproved
status: "True"
type: Approved
無効な CSR のトラブルシューティング情報が message
フィールドと reason
フィールドに表示されます。
Pod に証明書がない
Pod の Pod 仕様を取得します。
kubectl get pod -n POD_NAMESPACE POD_NAME -o yaml
以下を置き換えます。
POD_NAMESPACE
: Pod の名前空間。POD_NAME
: Pod の名前。
Pod 仕様に、mTLS 認証を受け取るように Pod を構成するで説明されている
security.cloud.google.com/use-workload-certificates
アノテーションが含まれていることを確認します。GKE メッシュ証明書のアドミッション コントローラが
workloadcertificates.security.cloud.google.com
タイプの CSI ドライバ ボリュームを Pod 仕様に正常に挿入したことを確認します。volumes: ... -csi: driver: workloadcertificates.security.cloud.google.com name: gke-workload-certificates ...
各コンテナにボリューム マウントが存在することを確認します。
containers: - name: ... ... volumeMounts: - mountPath: /var/run/secrets/workload-spiffe-credentials name: gke-workload-certificates readOnly: true ...
次の証明書バンドルと秘密鍵が Pod 内の次の場所にあることを確認します。
- 証明書チェーン バンドル:
/var/run/secrets/workload-spiffe-credentials/certificates.pem
- 秘密鍵:
/var/run/secrets/workload-spiffe-credentials/private_key.pem
- CA トラスト アンカー バンドル:
/var/run/secrets/workload-spiffe-credentials/ca_certificates.pem
- 証明書チェーン バンドル:
ファイルを利用できない場合は、次の手順を実行します。
クラスタの CA Service(プレビュー)インスタンスを取得します。
kubectl get workloadcertificateconfigs default -o jsonpath '{.spec.certificateAuthorityConfig.certificateAuthorityServiceConfig.endpointURI}'
CA Service(プレビュー)インスタンスのステータスを取得します。
gcloud privateca ISSUING_CA_TYPE describe ISSUING_CA_NAME \ --location ISSUING_CA_LOCATION
以下を置き換えます。
ISSUING_CA_TYPE
: 発行 CA のタイプ(subordinates
またはroots
のいずれか)。ISSUING_CA_NAME
: 発行 CA の名前。ISSUING_CA_LOCATION
: 発行 CA のリージョン。
ルート CA の IAM ポリシーを取得します。
gcloud privateca roots get-iam-policy ROOT_CA_NAME
ROOT_CA_NAME
は、ルート CA の名前に置き換えます。IAM ポリシーで、
privateca.auditor
ポリシー バインディングが存在することを確認します。... - members: - serviceAccount:service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com role: roles/privateca.auditor ...
この例では、
PROJECT_NUMBER
はクラスタのプロジェクト番号です。下位 CA の IAM ポリシーを取得します。
gcloud privateca subordinates get-iam-policy SUBORDINATE_CA_NAME
SUBORDINATE_CA_NAME
は、下位 CA 名に置き換えます。IAM ポリシーで、
privateca.certificateManager
ポリシー バインディングが存在することを確認します。... - members: - serviceAccount: service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com role: roles/privateca.certificateManager ...
この例では、
PROJECT_NUMBER
はクラスタのプロジェクト番号です。
アプリケーションで発行済みの mTLS 認証情報を使用できない
証明書の有効期限が切れていないことを確認します。
cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"
使用しているキータイプがアプリケーションでサポートされていることを確認します。
cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Public Key Algorithm" -A 3
発行 CA が証明書鍵と同じ鍵ファミリーを使用していることを確認します。
CA Service(プレビュー)インスタンスのステータスを取得します。
gcloud privateca ISSUING_CA_TYPE describe ISSUING_CA_NAME \ --location ISSUING_CA_LOCATION
以下を置き換えます。
ISSUING_CA_TYPE
: 発行 CA のタイプ(subordinates
またはroots
のいずれか)。ISSUING_CA_NAME
: 発行 CA の名前。ISSUING_CA_LOCATION
: 発行 CA のリージョン。
出力の
keySpec.algorithm
がWorkloadCertificateConfig
YAML マニフェストで定義したのと同じ鍵アルゴリズムであることを確認します。出力は次のようになります。config: ... subjectConfig: commonName: td-sub-ca subject: organization: TestOrgLLC subjectAltName: {} createTime: '2021-05-04T05:37:58.329293525Z' issuingOptions: includeCaCertUrl: true keySpec: algorithm: RSA_PKCS1_2048_SHA256 ...
証明書が拒否される
- ピア アプリケーションが同じ信頼バンドルを使用して証明書を検証することを確認します。
証明書の有効期限が切れていないことを確認します。
cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"
gRPC Go Credentials Reloading API を使用していない場合、クライアント コードがファイル システムから認証情報を定期的に更新することを確認します。
ワークロードが CA と同じ信頼ドメインに存在することを確認します。GKE メッシュ証明書は、単一の信頼ドメインにあるワークロード間の通信をサポートします。
制限事項
Cloud Service Mesh サービスのセキュリティは GKE でのみサポートされています。Compute Engine ではサービスのセキュリティをデプロイできません。
Cloud Service Mesh は、1 つのエンドポイントに同等に一致する 2 つ以上のエンドポイント ポリシー リソースがあるシナリオをサポートしていません。たとえば、同じラベルとポート向けの 2 つのポリシーや、1 つのエンドポイントのラベルに同等に一致する異なるラベル向けの 2 つ以上のポリシーです。エンドポイント ポリシーを 1 つのエンドポイントのラベルと一致させる方法については、EndpointPolicy.EndpointMatcher.MetadataLabelMatcher の API をご覧ください。このような状況では、Cloud Service Mesh はいかなる競合するポリシーからもセキュリティ構成を生成しません。