概要
IAM を使用して GKE クラスタへのアクセスを制御します。また、特権 Pod の作成を制限する Pod セキュリティ ポリシーを作成、テストし、IP アドレスと認証情報のローテーションを行います。
注: このラボでは、GKE Standard モードを使用します。このラボでは Pod セキュリティ ポリシーについて説明します。GKE Autopilot の組み込みのセキュリティ設定をオーバーライドするポリシーを作成することはできません。目標
このラボでは、次のタスクの実行方法について学びます。
- IAM を使用して GKE へのアクセスを制御する
- Pod セキュリティ ポリシーを作成して、Pod の作成を制御する
- IP アドレスと認証情報のローテーションを行う
注: Google Cloud Skills Boost の [接続の詳細] ダイアログで、このラボ用の 2 つのユーザー名が提供されています。 このラボでは、これらのアカウントを Username 1 と Username 2 とします。
タスク 1. IAM のロールを使用して、プロジェクト内のすべての GKE クラスタにアクセスできる管理者権限を付与する
1 人目のユーザーとして Google Cloud コンソールにログインする
- あらかじめ用意されている Username 1 を使用して、シークレット ウィンドウで通常どおりに Google Cloud コンソールにログインします。どちらのユーザー名でも同じパスワードを使用します。
- Google Cloud コンソールのタイトルバーで、Cloud Shell をアクティブにする(
)をクリックします。
- [続行] をクリックします。
プロビジョニングされると、Cloud Shell プロンプトが表示されます。
注: Username 1 アカウントからログアウトすると、Google Cloud Skills Boost によって Username 2 アカウントが削除される場合があります。そのため、このラボが終了するまで Username 1 でログインしたままにしてください。
2 人目のユーザーとして Google Cloud コンソールにログインして操作する
- シークレット ウィンドウで別のタブを開きます。
-
console.cloud.google.com にアクセスします。
- 画面右上にあるユーザー アイコンをクリックし、[アカウントを追加] をクリックします。
- 提供されている Username 2 を使用して Google Cloud コンソールにログインします。先ほど説明したように、Username 1 と同じパスワードを使用します。
注: Google Cloud コンソールの Username 2 のタブが開いていることを確認します。
-
Username 2 でログインした状態のまま、ナビゲーション メニュー(
)で [Kubernetes Engine] > [クラスタ] をクリックします。
-
ページの上部でラボのプロジェクト ID が選択されていることを確認します。
クラスタ作成のオプションが無効になっている点に注意してください。

注: この時点では、Username 2 はプロジェクトにアクセスできます。ただし、閲覧者ロールのみが付与されているため、プロジェクト内のリソースはすべて読み取り専用になります。
Username 2 に GKE 管理者の IAM ロールを付与する
これから、Username 2 が GKE クラスタを作成し、ワークロードをデプロイできるようにします。そのために、基本ロールを使用して、このプロジェクトのすべての GKE クラスタを管理し、それらのクラスタ内のリソースを管理するユーザー権限を付与します。Username 1 アカウントにはプロジェクト オーナーの権限があり、このアカウントを使用して Username 2 により多くの権限を付与します。
- Google Cloud コンソールの Username 1 のタブに戻ります。
注: Google Cloud コンソールの Username 1 のタブが開いていることを確認します。
-
ナビゲーション メニュー(
)で、[IAM と管理] > [IAM] をクリックします。
-
IAM コンソールで Username 2 に対応する行を見つけ、行の右端にある鉛筆アイコンをクリックして、このユーザーの権限を編集します。
-
現在、Username 2 には閲覧者のロールが付与されており、プロジェクト内のすべてのリソースに対する読み取り権限があります。
-
[別のロールを追加] をクリックします。ロールを選択するための別のプルダウンが表示されます。
-
[ロールを選択] プルダウン ボックスで、[Kubernetes Engine] > [Kubernetes Engine Cluster 管理者] を選択します。
-
[保存] をクリックします。
注: これにより、Username 2 は、プロジェクト内のすべての GKE クラスタを管理し、これらのクラスタ内のリソースを管理するアクセス権限を持つことになります。 組織においてこのレベルのアクセスが過剰である場合は、Kubernetes のロールベース アクセス制御を使用して、GKE クラスタ内でのユーザーの権限を制限できます。
[進行状況を確認] をクリックして、目標に沿って進んでいることを確認します。
Username 2 に GKE 管理者の IAM ロールを付与する
Username 2 のアクセスをテストする
Username 2 で GKE クラスタを作成して、結果を確認します。
- Google Cloud コンソールの Username 2 のタブに戻ります。
注: Google Cloud コンソールの Username 2 のタブが開いていることを確認します。
-
Username 2 でログインした状態のまま、ナビゲーション メニュー(
)で [Kubernetes Engine] > [クラスタ] をクリックします。
クラスタを作成するオプションが有効になっています。変更を反映するには、ウェブブラウザの Username 2 のタブを更新する必要がある場合があります。
-
[作成] をクリックして GKE クラスタの作成を開始します。
-
[Standard クラスタに切り替え] をクリックし、次のポップアップで切り替えを確定します。
注意: このラボでは、GKE Standard モードを使用する必要があります。
-
クラスタの名前を「standard-cluster-1」に設定します(デフォルトでこの名前に設定されていない場合)。
-
リージョン クラスタではなくゾーンクラスタが選択されていることを確認します。
-
クラスタのゾーンとして [] を選択します(デフォルトでこのゾーンが選択されていない場合)。
-
その他の値はすべてデフォルトのままにして、[作成] をクリックします。
クラスタのプロビジョニングが開始されますが、すぐに失敗します。
注: これは想定どおりの動作です。
- 画面上部のツールバーにある通知アイコンをクリックして、エラー メッセージを確認します。
Username 2 には、クラスタのデプロイに必要な権限の一部がまだありません。これは、GKE がノードとして Google Cloud Compute Engine インスタンスを利用しているためです。
GKE クラスタをデプロイするには、Compute Engine デフォルト サービス アカウントに対する iam.serviceAccountUser ロールもユーザーに割り当てられている必要があります。
Username 2 に ServiceAccountUser IAM ロールを付与する
IAM を使用して Username 2 に iam.serviceAccountUser ロールを付与し、Username 2 が GKE クラスタを正常にデプロイできるようにします。
- Google Cloud コンソールの Username 1 のタブに戻ります。
注: Google Cloud コンソールの Username 1 のタブが開いていることを確認します。
-
ナビゲーション メニュー(
)で、[IAM と管理] > [サービス アカウント] をクリックします。
-
IAM コンソールで、Compute Engine のデフォルトのサービス アカウントに対応する行をクリックして選択します。
-
[権限] をクリックして権限情報のパネルを開きます。
-
[権限] ページで [アクセス権を付与] をクリックします。
ウィンドウの右側に権限情報のパネルが開きます。
- [新しいプリンシパル] に Username 2 のユーザー名を入力します。この名前はラボの詳細ページからコピーできます。
- [ロールを選択] で、[サービス アカウント] > [サービス アカウント ユーザー] を選択してください。
- [保存] をクリックします。
[進行状況を確認] をクリックして、目標に沿って進んでいることを確認します。
Username 2 にサービス アカウント ユーザーの IAM ロールを付与する
Username 2 が GKE クラスタを作成できることを確認する
Username 2 で GKE クラスタを作成して、結果を確認します。
- Google Cloud コンソールの Username 2 のタブに戻ります。
注: Google Cloud コンソールの Username 2 のタブが開いていることを確認します。
-
Username 2 でログインした状態のまま、ナビゲーション メニュー(
)で [Kubernetes Engine] > [クラスタ] をクリックします。ウェブブラウザの更新が必要な場合もあります。
-
[作成] をクリックして GKE クラスタの作成を開始します。
-
[Standard クラスタに切り替え] をクリックし、次のポップアップで切り替えを確定します。
-
クラスタの名前を「standard-cluster-1」に設定します(デフォルトでこの名前に設定されていない場合)。
-
リージョン クラスタではなくゾーンクラスタが選択されていることを確認します。
-
クラスタのゾーンとして [] を選択します(デフォルトでこのゾーンが選択されていない場合)。
-
その他の値はすべてデフォルトのままにして、[作成] をクリックします。
注: クラスタのデプロイが完了するまで数分待つ必要があります。
今回はクラスタが正常にデプロイされます。
[進行状況を確認] をクリックして、目標に沿って進んでいることを確認します。
GKE クラスタを作成する
タスク 2. Pod セキュリティ アドミッションを定義して使用する
PodSecurityは Kubernetes アドミッション コントローラであり、これにより GKE クラスタで実行されている Pod に Pod セキュリティの標準を適用できます。Pod セキュリティの標準は事前定義されたセキュリティ ポリシーであり、Kubernetes における Pod セキュリティの高度なニーズに対応しています。これらのポリシーは、制約の緩やかなものから非常に厳格なものまで多岐にわたります。
このタスクでは、クラスタのデフォルト Namespace に非特権 Pod を作成することを許可する Pod セキュリティ ポリシーを作成します。非特権 Pod では、ユーザーは root としてコードを実行することは許可されず、ホスト上のデバイスへのアクセス権が制限されます。
そこで、非特権 Pod のデプロイを要求するアカウントとこのポリシーを結合する、ロール バインディングで使用できる ClusterRole を作成します。
特権 Pod をデプロイできることを必要とするユーザーには、Pod セキュリティ ポリシーが有効になった後に、管理者ユーザーが Pod をデプロイできるようにするためのビルトイン PSP へのアクセス権を付与することができます。
コンポーネントを構成したら、PodSecurityPolicy コントローラを有効にして、これらのポリシーを適用します。その後、権限が異なるユーザーにどのように影響するかをテストします。
GKE クラスタに接続する
- Google Cloud コンソールの Username 1 のタブに戻ります。
注: Google Cloud コンソールの Username 1 のタブが開いていることを確認します。
- Cloud Shell で次のコマンドを入力して、このラボ用のクラスタの作成に使用する Google Cloud ゾーンとクラスタ名を表す環境変数を作成します。
export my_zone={{{project_0.default_zone | ZONE }}}
export my_cluster=standard-cluster-1
- kubectl コマンドライン ツールのタブ補完を構成します。
source <(kubectl completion bash)
- kubectl がクラスタにアクセスできるよう構成します。
gcloud container clusters get-credentials $my_cluster --zone $my_zone
PodSecurity を使用して Pod セキュリティの標準を適用する
PodSecurity アドミッション コントローラを使用するには、特定の Pod セキュリティの標準を特定のモードで特定の Namespace に適用する必要があります。
新しい Namespace を作成する
クラスタで Namespace を作成します。
kubectl create ns baseline-ns
kubectl create ns restricted-ns
このコマンドを実行すると、次の Namespace が作成されます。
- baseline-ns: 制約のないワークロードの場合
- restricted-ns: ワークロードの制約が厳格な場合
ラベルを使用してセキュリティ ポリシーを適用する
次の Pod セキュリティの標準を適用します。
- Baseline: warn モードで baseline-ns に適用
- Restricted: enforce モードで restricted-ns に適用
kubectl label --overwrite ns baseline-ns pod-security.kubernetes.io/warn=baseline
kubectl label --overwrite ns restricted-ns pod-security.kubernetes.io/enforce=restricted
これらのコマンドで次のような結果が得られます。
- baseline-ns Namespace で Baseline ポリシーに違反するワークロードが許可され、クライアントに警告メッセージが表示されます。
- restricted-ns Namespace で Restricted ポリシーに違反するワークロードが拒否され、GKE によって監査ログにエントリが追加されます。
ラベルが追加されたことを確認します。
kubectl get ns --show-labels
出力は次のようになります。
baseline-ns Active 74s kubernetes.io/metadata.name=baseline-ns,pod-security.kubernetes.io/warn=baseline
restricted-ns Active 18s kubernetes.io/metadata.name=restricted-ns,pod-security.kubernetes.io/enforce=restricted
default Active 57m kubernetes.io/metadata.name=default
kube-public Active 57m kubernetes.io/metadata.name=kube-public
kube-system Active 57m kubernetes.io/metadata.name=kube-system
[進行状況を確認] をクリックして、目標に沿って進んでいることを確認します。
Namespace とラベルを作成する
構成されたポリシーをテストする
PodSecurity アドミッション コントローラが意図したとおりに動作することを確認するには、Baseline ポリシーと Restricted ポリシーに違反するワークロードを両方の Namespace にデプロイします。次のマニフェストの例では、権限昇格を許可する nginx コンテナをデプロイしています。
-
psa-workload.yaml
というファイルを作成し、次のコマンドを実行して nano で開きます。
nano psa-workload.yaml
- nano が開いたら、以下を
psa-workload.yaml
ファイルに貼り付けます。
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
securityContext:
privileged: true
-
Ctrl+O キーの次に Enter キーを押し、編集したファイルを保存します。
-
Ctrl+X キーを押して nano テキスト エディタを終了します。
-
マニフェストを baseline-ns Namespace に適用します。
kubectl apply -f psa-workload.yaml --namespace=baseline-ns
出力は次のようになります。
Warning: would violate PodSecurity "baseline:latest": privileged (container "nginx" must not set securityContext.privileged=true)
pod/nginx created
Baseline ポリシーは、Pod を Namespace にデプロイすることを許可します。
- Pod が正常にデプロイされたことを確認します。
kubectl get pods --namespace=baseline-ns -l=app=nginx
- マニフェストを restricted-ns Namespace に適用します。
kubectl apply -f psa-workload.yaml --namespace=restricted-ns
出力は次のようになります。
Error from server (Forbidden): error when creating "workload.yaml": pods "nginx"
is forbidden: violates PodSecurity "restricted:latest": allowPrivilegeEscalation
!= false (container "nginx" must set securityContext.allowPrivilegeEscalation=false),
unrestricted capabilities (container "nginx" must set securityContext.capabilities.drop=["ALL"]),
runAsNonRoot != true (pod or container "nginx" must set securityContext.runAsNonRoot=true),
seccompProfile (pod or container "nginx" must set securityContext.seccompProfile.type
to "RuntimeDefault" or "Localhost")
Pod は Namespace にはデプロイされません。ログに監査エントリが追加されます。
[進行状況を確認] をクリックして、目標に沿って進んでいることを確認します。
マニフェストを「restricted-ns」Namespace に適用する
監査ログでポリシー違反を確認する
監査モードと自動適用モードでのポリシー違反は、クラスタの監査ログに記録されます。これらのログは、Google Cloud コンソールのログ エクスプローラを使用して表示できます。
-
Google Cloud コンソールのタイトルバーにある [検索] フィールドに「ログ エクスプローラ」と入力し、検索結果から [ログ エクスプローラ] をクリックします。
-
クエリ フィールドに次のクエリを指定します。
resource.type="k8s_cluster"
protoPayload.response.reason="Forbidden"
protoPayload.resourceName="core/v1/namespaces/restricted-ns/pods/nginx"
-
[クエリを実行] をクリックします。
-
[クエリ結果] セクションで [Forbidden] ログエントリを展開します。詳細は次のようになります。
{
...
protoPayload: {
@type: "type.googleapis.com/google.cloud.audit.AuditLog"
authenticationInfo: {1}
authorizationInfo: [1]
methodName: "io.k8s.core.v1.pods.create"
request: {6}
requestMetadata: {2}
resourceName: "core/v1/namespaces/restricted-ns/pods/nginx"
response: {
@type: "core.k8s.io/v1.Status"
apiVersion: "v1"
code: 403
details: {2}
kind: "Status"
message: "pods "nginx" is forbidden: violates PodSecurity "restricted:latest": privileged
(container "nginx" must not set securityContext.privileged=true),
allowPrivilegeEscalation != false (container "nginx" must set
securityContext.allowPrivilegeEscalation=false), unrestricted capabilities
(container "nginx" must set securityContext.capabilities.drop=["ALL"]),
runAsNonRoot != true (pod or container "nginx" must set securityContext.runAsNonRoot=true),
seccompProfile (pod or container "nginx" must set securityContext.seccompProfile.type
to "RuntimeDefault" or "Localhost")"
metadata: {0}
reason: "Forbidden"
status: "Failure"
}
serviceName: "k8s.io"
status: {2}
}
receiveTimestamp: "2022-12-01T19:19:25.353235326Z"
resource: {2}
timestamp: "2022-12-01T19:19:21.469360Z"
}
(省略可)タスク 3. IP アドレスと認証情報のローテーションを行う
クラスタ上で IP アドレスと認証情報のローテーションを行います。認証情報の存続時間を短くしてセキュリティを強化するために、定期的にこの操作を行うことをおすすめします。対象の IP と認証情報のローテーションを行う別個のコマンドもありますが、認証情報をローテーションすると、追加で IP もローテーションされます。
- Cloud Shell で次のコマンドを実行します。
gcloud container clusters update $my_cluster --zone $my_zone --start-credential-rotation
- 「
Y
」と入力して続行します。
- 処理が完了するまで Cloud Shell を開いたままにします。
Cloud Shell でコマンドが完了したら、クラスタで各ノードを更新するプロセスが開始されます。このプロセスは、クラスタで最大 15 分
ほどかかる場合があります。また、このプロセスでは現在のユーザーの kubeconfig エントリも自動的に更新されます。
- これで、元の IP アドレスに加えて新しい IP アドレスにも一時的にクラスタ マスターが対応するようになりました。
注: アクセス権が失われるのを防ぐには、ローテーションのプロセスが完了する前に、kubectl または API を使用してマスターにアクセスするその他のシステムで kubeconfig ファイルを更新する必要があります。
- 次のコマンドを実行して、認証情報と IP アドレスのローテーションのタスクを完了します。
gcloud container clusters update $my_cluster --zone $my_zone --complete-credential-rotation
これにより、ローテーションのプロセスが終了し、元のクラスタの IP アドレスが削除されます。
注: 認証情報のローテーションが完了せず、エラー メッセージが返される場合は、次のコマンドを実行します。
gcloud container clusters upgrade $my_cluster --node-pool=default-pool --zone $my_zone
-
「Y
」と入力して続行します。
-
クラスタが正常にアップグレードされたら、次のコマンドを再実行します。
gcloud container clusters update $my_cluster --zone $my_zone --complete-credential-rotation
ラボを終了する
ラボが完了したら、[ラボを終了] をクリックします。ラボで使用したリソースが Google Cloud Skills Boost から削除され、アカウントの情報も消去されます。
ラボの評価を求めるダイアログが表示されたら、星の数を選択してコメントを入力し、[送信] をクリックします。
星の数は、それぞれ次の評価を表します。
- 星 1 つ = 非常に不満
- 星 2 つ = 不満
- 星 3 つ = どちらともいえない
- 星 4 つ = 満足
- 星 5 つ = 非常に満足
フィードバックを送信しない場合は、ダイアログ ボックスを閉じてください。
フィードバックやご提案の送信、修正が必要な箇所をご報告いただく際は、[サポート] タブをご利用ください。