GKE Sandbox を使用すると、信頼できないコードや不明なコードを実行するコンテナから Google Kubernetes Engine(GKE)ノードのホストカーネルを保護できます。このドキュメントでは、セキュリティ スペシャリストが GKE Sandbox を有効にして、サンドボックスで Pod を実行し、分離を確認する方法について説明します。
GKE Sandbox に精通している必要があります。
使用可能なサンドボックス タイプ
GKE Sandbox は、次のサンドボックス タイプをサポートしています。各タイプは、特定のテクノロジーを使用してアプリケーション コードをホストカーネルから分離します。
gvisor: 権限昇格を必要としない Linux カーネル API のユーザー空間を再実装したものです。ユーザー空間カーネルは、ホストカーネルに代わってシステム コールの大部分をインターセプトして処理するため、ホストカーネルへの直接アクセスが制限されます。microvm: ネストされた仮想化を使用してホスト VM にネストされた軽量 VM。ノード上の各 Pod は、独自のゲストカーネルを持つ独自のネストされた VM で実行されます。コードは専用の VM で実行されるため、このサンドボックス タイプは gVisor サンドボックスよりも強力な分離を提供します。
各サンドボックス タイプの仕組みと、特定のタイプを使用するタイミングについては、GKE Sandbox についてをご覧ください。
制限事項
GKE Sandbox と特定のサンドボックス テクノロジーには、GPU と TPU のサポートや特定の Linux 機能と Kubernetes 機能のサポートなど、さまざまな制限があります。詳細については、制限事項をご覧ください。
始める前に
作業を始める前に、次のタスクが完了していることを確認してください。
- Google Kubernetes Engine API を有効にする。 Google Kubernetes Engine API を有効化
- このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化します。gcloud CLI をインストール済みの場合は、
gcloud components updateコマンドを実行して最新のバージョンを取得します。以前のバージョンの gcloud CLI では、このドキュメントのコマンドを実行できない場合があります。
- 自動作成ノードのサンドボックス タイプを選択するセクションの手順に沿って、既存の Autopilot クラスタまたは Standard クラスタを使用します。microVM サンドボックスを使用するには、ノードで GKE バージョン 1.37.0-gke.4713000 以降を実行する必要があります。
自動作成されたノードのサンドボックス タイプを選択する
ComputeClasses を Autopilot モードまたはノードプールの自動作成で使用すると、GKE が作成するノードで GKE Sandbox を有効にできます。Autopilot クラスタでは、gVisor がデフォルトでサポートされているため、ComputeClass からサンドボックス構成を省略できます。
自動作成されたノード用に GKE Sandbox を構成する手順は次のとおりです。
既存の Autopilot クラスタまたは Standard クラスタに接続します。
gcloud container clusters get-credentials CLUSTER_NAME \ --location=CONTROL_PLANE_LOCATION次のように置き換えます。
CLUSTER_NAME: クラスタの名前。CONTROL_PLANE_LOCATION: クラスタのコントロール プレーンのリージョンまたはゾーン。
必要なサンドボックス テクノロジーに応じて、次のいずれかの ComputeClass マニフェストを保存します。
gVisor:
apiVersion: cloud.google.com/v1 kind: ComputeClass metadata: name: sandbox-gvisor-class spec: priorities: - machineFamily: n4 - machineFamily: c4 nodePoolConfig: sandbox: type: gvisor nodePoolAutoCreation: enabled: true whenUnsatisfiable: DoNotScaleUpmicroVM:
apiVersion: cloud.google.com/v1 kind: ComputeClass metadata: name: sandbox-microvm-class spec: priorities: - machineFamily: n4 - machineFamily: c4 nodePoolConfig: sandbox: type: microvm priorityDefaults: enableNestedVirtualization: true nodePoolAutoCreation: enabled: true whenUnsatisfiable: DoNotScaleUpmicroVM サンドボックスの ComputeClass では、
enableNestedVirtualizationフィールドを使用してネストされた仮想化を有効にします。このフィールドは microVM サンドボックスで必須です。このフィールドを使用するには、クラスタでバージョン 1.37.0-gke.4713000 以降を実行する必要があります。
これらのマニフェストの例では、
nodePoolAutoCreationフィールドを使用してノードプールの自動作成を有効にしています。autopilotフィールドを使用して Autopilot モードで Pod を実行する ComputeClass でサンドボックス構成を指定することもできます。Autopilot クラスタを使用する場合、GKE はnodePoolAutoCreationフィールドとautopilotフィールドの両方を無視します。ComputeClass を作成します。
kubectl apply -f PATH_TO_COMPUTE_CLASS_MANIFESTPATH_TO_COMPUTE_CLASS_MANIFESTは、ComputeClass マニフェストのパスに置き換えます。
この ComputeClass を選択してサンドボックス環境をリクエストするには、Pod のサンドボックス環境をリクエストするをご覧ください。
ノードプールの作成時にサンドボックス タイプを選択する
Standard クラスタで新しいノードプールを作成するときに、GKE Sandbox を手動で有効にできます。GKE Sandbox を手動で有効にする場合は、次の制限が適用されます。
- Standard クラスタの作成時に GKE Sandbox を有効にするには、少なくとも 1 つの追加ノードプールを構成する必要があります。GKE では、GKE マネージド システム ワークロードを実行するために、GKE Sandbox を使用しないノードプールがクラスタに少なくとも 1 つ必要であるため、追加のノードプールが必要です。gcloud CLI を使用してクラスタを作成する場合は、クラスタを作成してから、GKE Sandbox を使用するノードプールを作成する必要があります。
- microVM サンドボックス タイプを選択するには、gcloud CLI または GKE API を使用する必要があります。Google Cloud コンソールでは、microVM サンドボックス タイプを選択できません。
gVisor サンドボックス タイプを有効にする
新しいノードプールを作成するときに gVisor サンドボックスを手動で有効にするには、次のいずれかのオプションを選択します。
コンソール
Google Cloud コンソールで [Kubernetes クラスタ] ページに移動します。
変更するクラスタの名前をクリックします。[クラスタの詳細] ページが開きます。
[ノード] タブをクリックします。
[ノードプール] セクションで、 [ユーザー管理のノードプールを追加] をクリックします。[ノードプールの追加] ページが開きます。
ナビゲーション メニューで [ノード] をクリックし、次の設定を構成します。
- [イメージの種類] プルダウン リストで、[containerd(cos_containerd)が含まれている Container-Optimized OS] を選択します。
- [マシンの構成] セクションで、ノードのマシンシリーズとマシンタイプを選択します。
- 省略可: サポートされている GPU タイプまたはサポートされている TPU タイプを選択します。
ナビゲーション メニューで [セキュリティ] をクリックします。[ノードのセキュリティ] ページが開きます。
[gVisor でサンドボックスを有効にする] チェックボックスをオンにします。
ノードプールを作成するには、[作成] をクリックします。
gcloud
サンドボックスに gVisor を使用するノードプールを作成するには、次のコマンドを実行します。
gcloud container node-pools create NODE_POOL_NAME \
--cluster=CLUSTER_NAME \
--location=CONTROL_PLANE_LOCATION \
--sandbox=type=gvisor
次のように置き換えます。
NODE_POOL_NAME: ノードプールの名前。CLUSTER_NAME: クラスタの名前。CONTROL_PLANE_LOCATION: クラスタのコントロール プレーンのリージョンまたはゾーン。
サポートされている GPU タイプまたはサポートされている TPU タイプを使用するノードプールを作成するときに、gVisor サンドボックスを有効にすることもできます。詳細については、次のドキュメントをご覧ください。
microVM サンドボックス タイプを有効にする
microVM サンドボックス タイプは、gcloud CLI または GKE API を使用してノードプールを作成するときに有効にできます。 Google Cloud コンソールでは、microVM サンドボックス タイプの有効化はサポートされていません。microVM サンドボックスを使用するノードプールを作成するには、次のコマンドを実行します。
gcloud container node-pools create NODE_POOL_NAME \
--cluster=CLUSTER_NAME \
--location=CONTROL_PLANE_LOCATION \
--sandbox=type=microvm \
--enable-nested-virtualization \
--machine-type=MACHINE_TYPE
次のように置き換えます。
NODE_POOL_NAME: ノードプールの名前。CLUSTER_NAME: クラスタの名前。CONTROL_PLANE_LOCATION: クラスタのコントロール プレーンのリージョンまたはゾーン。MACHINE_TYPE: ノードのマシンタイプ。この値は、ネストされた仮想化をサポートするマシンタイプにする必要があります。詳細については、マシンシリーズの比較表の「ネストされた仮想化」行をご覧ください。
モニタリングとロギングの有効化
サンドボックスからログと指標を収集して表示するには、クラスタで次のオブザーバビリティ サービスが有効になっていることを確認します。
これらのサービスは、新しいすべての GKE クラスタでデフォルトで有効になっています。
Pod のサンドボックス環境をリクエストする
サンドボックスで特定の Pod を実行するには、Pod 仕様で gvisor または microvm RuntimeClass を指定します。GKE は、指定されたサンドボックス タイプを使用するノードで Pod をスケジュールします。Pod 仕様でサンドボックス タイプを選択する手順は次のとおりです。
ComputeClass を使用して GKE Sandbox を有効にするか、手動で作成したノードプールを使用するかに応じて、次のいずれかの Deployment マニフェストの例を保存します。
ComputeClasses:
apiVersion: apps/v1 kind: Deployment metadata: name: sandbox-pod labels: environment: sandbox spec: replicas: 2 selector: matchLabels: environment: sandbox template: metadata: labels: environment: sandbox spec: nodeSelector: cloud.google.com/compute-class: COMPUTECLASS_NAME runtimeClassName: SANDBOX_TYPE containers: - name: nginx image: nginx次のように置き換えます。
COMPUTECLASS_NAME: 自動作成されたノードのサンドボックス タイプを選択するで説明されているように、作成した ComputeClass の名前。SANDBOX_TYPE: Pod に使用するサンドボックス タイプ。次の値を使用できます。gvisormicrovm
指定するサンドボックス タイプは、選択した ComputeClass で有効になっているサンドボックス タイプと一致する必要があります。
手動で作成したノードプール:
apiVersion: apps/v1 kind: Deployment metadata: name: httpd labels: app: httpd spec: replicas: 1 selector: matchLabels: app: httpd template: metadata: labels: app: httpd spec: runtimeClassName: SANDBOX_TYPE containers: - name: httpd image: httpdSANDBOX_TYPEは、サンドボックス タイプに置き換えます。次の値を使用できます。gvisormicrovm
指定するサンドボックス タイプは、クラスタ内の既存のノードプールのサンドボックス タイプと一致する必要があります。
Deployment を作成します。
kubectl apply -f PATH_TO_DEPLOYMENT_MANIFESTPATH_TO_DEPLOYMENT_MANIFESTは、Deployment マニフェストのパスに置き換えます。Pod が作成されたことを確認します。
kubectl get pods出力は次のようになります。
NAME READY STATUS RESTARTS AGE httpd-db5899bc9-dk7lk 1/1 Running 0 24s
runtimeClassName フィールドを使用して、サポートされている GPU タイプまたはサポートされている TPU タイプで Pod を実行するときに、サンドボックスをリクエストすることもできます。詳細については、次のドキュメントをご覧ください。
- GKE Standard に GPU ワークロードをデプロイする
- GKE Standard に TPU ワークロードをデプロイする
- Autopilot に GPU ワークロードをデプロイする
- Autopilot に TPU ワークロードをデプロイする
通常の Pod とサンドボックス Pod を実行する
このセクションの手順は、Standard モードのワークロードに適用されます。Autopilot モードでは、通常の Pod をサンドボックス Pod と並行して実行する必要はありません。これは、Autopilot 料金モデルによって、ノードでスケジュールされる Pod の数を手動で最適化する必要がないためです。
ノードプールで GKE Sandbox を有効にした後、Node Taints と許容値でサンドボックスを使用するのではなく、信頼できるアプリケーションをノードで実行できます。 これらの Pod は、「通常の Pod」といわれ、サンドボックスの Pod と区別されます。
通常のポッドは、サンドボックス化されたポッドと同様に、他のGoogle Cloud サービスやクラスタ メタデータにアクセスできません。この設定は、ノードの構成時に有効になります。通常の Pod またはサンドボックス化された Pod がGoogle Cloud サービスにアクセスする必要がある場合は、Workload Identity Federation for GKE を使用します。
GKE Sandbox は、サンドボックス化されたポッドを実行できるノードに次のラベルと taint を追加します。
sandbox.gke.io/runtime: SANDBOX_TYPEノードラベル。sandbox.gke.io/runtime=SANDBOX_TYPE:NoScheduleノード taint。一致する toleration を持つ Pod のみ、ノードにスケジュールできます。
RuntimeClass フィールドを使用してサンドボックスで Pod を実行すると、GKE は自動的にノード アフィニティと toleration を Pod に適用します。GKE Sandbox を使用するノードで通常の Pod を実行するには、次のセレクタを Pod 仕様に手動で適用する必要があります。
- 必要に応じて GKE Sandbox を使用するノードで Pod を実行できるようにするには、ノード taint の toleration のみを追加します。
- GKE Sandbox を使用するノードでのみ Pod を実行するには、ノードセレクタとノード taint の toleration を追加します。
次の手順では、GKE Sandbox を使用するノードで通常の Pod を実行する方法について説明します。
次の Deployment マニフェストを
httpd-regular.yamlとして保存します。apiVersion: apps/v1 kind: Deployment metadata: name: httpd-regular labels: app: httpd-regular spec: replicas: 1 selector: matchLabels: app: httpd-regular template: metadata: labels: app: httpd-regular spec: containers: - name: httpd-regular image: httpd affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: sandbox.gke.io/runtime operator: In values: - SANDBOX_TYPE tolerations: - effect: NoSchedule key: sandbox.gke.io/runtime operator: Equal value: SANDBOX_TYPESANDBOX_TYPEは、gvisorやmicrovmなどのサンドボックス タイプに置き換えます。Deployment を作成します。
kubectl apply -f httpd-regular.yamlPod のスケジュールを設定できない場合は、Pod のマニフェストでノード アフィニティと toleration が正しく設定されていることを確認します。
Pod がサンドボックスにないことを確認します。
kubectl get pods -o jsonpath=$'{range .items[*]}{.metadata.name}: {.spec.runtimeClassName}\n{end}'出力は次のようになります。
httpd-db5899bc9-dk7lk: SANDBOX_TYPE httpd-regular-5bf87996c6-cfmmd:httpd-regularPod には RuntimeClass 値がありません。これは、Pod がサンドボックスにないことを意味します。通常の Pod が GKE Sandbox を使用するノードで実行されていることを確認します。
kubectl get pod -o jsonpath=$'{range .items[*]}{.metadata.name}: {.spec.nodeName}\n{end}'出力は次のようになります。
httpd-db5899bc9-dk7lk: gke-cluster-2-pool-1-75c8fc63-h373 httpd-regular-5bf87996c6-cfmmd: gke-cluster-2-pool-1-75c8fc63-h373サンドボックス Pod と通常の Pod の両方が同じノードに存在します。これは、通常の Pod が GKE Sandbox を使用するノードで実行されていることを示しています。
サンドボックスの構成を確認する
以降のセクションでは、Pod がサンドボックスで実行されていることと、サンドボックス化された Pod がホスト カーネルから分離されていることを確認する方法について説明します。これらのセクションでは、Pod のサンドボックス環境をリクエストするで作成した Deployment の例を使用します。
Pod がサンドボックスで実行されていることを確認する
Pod がサンドボックスを使用しているかどうかを確認するには、Pod の RuntimeClass を取得します。この方法は、サンドボックス内のデータが表示されないため、Pod 内でコマンドを実行するよりも信頼性が高くなります。サンドボックス内から報告されたものは信頼できません。問題が存在していることや、悪意のある可能性があります。
実行中の各 Pod の RuntimeClass を取得します。
kubectl get pods -l=app=httpd -o jsonpath=$'{range .items[*]}{.metadata.name}: {.spec.runtimeClassName}\n{end}'出力は次のようになります。
httpd-db5899bc9-dk7lk: gvisor httpd-db5899bc9-ab3cd: gvisor出力に
gvisorまたはmicrovmが表示されている場合、Pod はサンドボックスで実行されています。
サンドボックス化された Pod がホストから分離されていることを確認する
サンドボックス化された Pod がホストノードから分離されているかどうかを確認するには、利用可能な仮想デバイスと、Pod がアクセスできるカーネルのバージョンを確認します。
gVisor サンドボックスと microVM サンドボックスの場合は、Pod がアクセスできるカーネルのバージョンがホストノードのカーネル バージョンと異なるかどうかを確認します。
Pod がアクセスできるカーネルのバージョンを取得します。
kubectl exec POD_NAME -- uname -rPOD_NAMEは、Pod の名前で置き換えます。出力は次のようになります。
4.19.0-gvisorホストノードのカーネルのバージョンを取得します。
kubectl get node NODE_NAME \ -o jsonpath='{.status.nodeInfo.kernelVersion}'NODE_NAMEは、Pod を実行するノードの名前に置き換えます。出力は次のようになります。
6.12.94+
Pod は gVisor のユーザー空間カーネルまたは microVM のゲスト カーネルのみを認識するため、ホストノードのカーネル バージョンは、サンドボックス化された Pod がアクセスできるカーネル バージョンとは異なります。
microVM サンドボックスの場合、Pod がアクセスできるデバイスが Cloud Hypervisor によって仮想化されているかどうかを確認することもできます。
kubectl exec POD_NAME -- cat /sys/class/dmi/id/product_name出力が
cloud-hypervisorの場合、Pod は microVM サンドボックスにあります。
GKE Sandbox を無効にする
GKE Autopilot クラスタまたは GKE Standard ノードプールでは GKE Sandbox を無効にできません。GKE Sandbox の使用を停止する場合は、ノードプールを削除します。