このページでは、Pod 内のコンテナが不明なコードや信頼できないコードを実行したとき、またはそのノードから特別に切り離す必要があるときに、GKE Sandbox を使用してノードのホストカーネルを保護する方法について説明します。
GKE Sandbox の可用性
GKE Sandbox は、GKE バージョン 1.27.4-gke.800 以降を実行する Autopilot クラスタで使用できます。サンドボックスで Autopilot ワークロードのデプロイを開始するには、GKE Sandbox を使用するに進みます。
新規または既存の GKE Standard クラスタで GKE Sandbox を使用するには、クラスタで GKE Sandbox を手動で有効にする必要があります。
GPU ワークロードは、バージョン 1.29.2-gke.11080000 以降の GKE Sandbox でプレビュー版として利用できます。
始める前に
作業を始める前に、次のことを確認してください。
- Google Kubernetes Engine API を有効にする。 Google Kubernetes Engine API の有効化
- このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化する。すでに gcloud CLI をインストールしている場合は、
gcloud components update
を実行して最新のバージョンを取得する。
新しい Standard クラスタで GKE Sandbox を有効にする
新しいクラスタの作成時に作成されるデフォルトのノードプールでは、それがクラスタ内の唯一のノードプールである場合、GKE Sandbox を使用できません。これは、GKE マネージド システムのワークロードは、信頼できないサンドボックス化されたワークロードとは別に実行する必要があるためです。クラスタの作成時に GKE Sandbox を有効にするには、クラスタに少なくとも 1 つのノードプールを追加する必要があります。
コンソール
クラスタを表示するには、Google Cloud コンソールで Google Kubernetes Engine のメニューに移動します。
Google Cloud コンソールで Google Kubernetes Engine のページに移動します。
[add_box 作成] をクリックします。
省略可能、ただし推奨: ナビゲーション メニューの [クラスタ] で [機能] をクリックし、次のチェックボックスをオンにします。これにより、gVisor がメッセージがロギングされます。
- Cloud Logging
- Cloud Monitoring
- Managed Service for Prometheus
[add_box ノードプールを追加] をクリックします。
ナビゲーション メニューの [ノードプール] で新しいノードプールを開き、[ノード] をクリックします。
ノードプールに次の設定を構成します。
- [イメージの種類] プルダウン リストから、[containerd(cos_containerd)が含まれている Container-Optimized OS] を選択します。 これは、GKE Sandbox でサポートされている唯一のイメージタイプです。
- [マシンの構成] で [シリーズ] と [マシンタイプ] を選択します。
サポートされている GKE バージョンを実行している場合は、必要に応じて GPU タイプを選択します。次のいずれかのタイプを指定する必要があります。
nvidia-tesla-t4
nvidia-tesla-a100
nvidia-a100-80gb
nvidia-l4
nvidia-h100-80gb
GKE Sandbox の GPU はプレビュー版として提供されています。
GKE Sandbox の GPU(プレビュー版)を使用する場合は、
latest
ドライバ バリアントを選択またはインストールします。
ナビゲーション メニューで、構成するノードプールの名前の下にある [セキュリティ] をクリックし、[gVisor でサンドボックスを有効にする] チェックボックスをオンにします。
クラスタとノードプールを必要に応じて構成します。
[作成] をクリックします。
gcloud
デフォルトのノードプールで GKE Sandbox を有効にすることはできません。また、新しいクラスタを作成するときに、gcloud
コマンドを実行します。代わりに、通常どおりにクラスタを作成します。必須ではありませんが、Logging と Monitoring を有効にして、gVisor メッセージをロギングすることをおすすめします。
次に、--
sandbox
フラグを type=gvisor
に設定して、gcloud container node-pools create
コマンドを実行します。GKE Sandbox では、ノードイメージ タイプを cos_containerd
にする必要があります。
gcloud container node-pools create NODE_POOL_NAME \
--cluster=CLUSTER_NAME \
--node-version=NODE_VERSION \
--machine-type=MACHINE_TYPE \
--image-type=cos_containerd \
--sandbox type=gvisor
次の変数を置き換えます。
NODE_POOL_NAME
: 新しいノードプールの名前。CLUSTER_NAME
: クラスタの名前。NODE_VERSION
: ノードプールに使用するバージョン。MACHINE_TYPE
: ノードに使用するマシンのタイプ。
GKE Sandbox で GPU ノードプールを作成するには、次のコマンドを実行します。
gcloud container node-pools create NODE_POOL_NAME \
--cluster=CLUSTER_NAME \
--node-version=NODE_VERSION \
--machine-type=MACHINE_TYPE \
--accelerator=type=GPU_TYPE,gpu-driver-version=latest \
--image-type=cos_containerd \
--sandbox type=gvisor
次のように置き換えます。
GPU_TYPE
: サポートされている GPU タイプ。詳細については、GKE Sandbox をご覧ください。MACHINE_TYPE
: リクエストされた GPU タイプに一致するマシン。詳細については、Google Kubernetes Engine の GPU 要件をご覧ください。
既存の Standard クラスタで GKE Sandbox を有効にする
既存の Standard クラスタで GKE Sandbox を有効にするには、新しいノードプールを追加し、そのノードプールのこの機能を有効にします。
コンソール
GKE Sandbox を有効にして新しいノードプールを作成するには:
Google Cloud コンソールで Google Kubernetes Engine のページに移動します。
変更するクラスタの名前をクリックします。
[add_box ノードプールを追加] をクリックします。
必要に応じて [ノードプールの詳細] ページを構成します。
ナビゲーション メニューで [ノード] をクリックし、次の設定を構成します。
- [イメージの種類] プルダウン リストから、[containerd(cos_containerd)が含まれている Container-Optimized OS] を選択します。これは、GKE Sandbox でサポートされている唯一のイメージタイプです。
- [マシンの構成] で [シリーズ] と [マシンタイプ] を選択します。
サポートされている GKE バージョンを実行している場合は、必要に応じて GPU タイプを選択します。次のいずれかのタイプを指定する必要があります。
nvidia-tesla-t4
nvidia-tesla-a100
nvidia-a100-80gb
nvidia-l4
nvidia-h100-80gb
GKE Sandbox の GPU はプレビュー版として提供されています。
GKE Sandbox の GPU(プレビュー版)を使用する場合は、
latest
ドライバ バリアントを選択またはインストールします。
ナビゲーション メニューで [セキュリティ] をクリックし、[gVisor でサンドボックスを有効にする] チェックボックスをオンにします。
[作成] をクリックします。
gcloud
GKE Sandbox を有効にする新しいノードプールを作成するには、次のようなコマンドを使用します。
gcloud container node-pools create NODE_POOL_NAME \
--cluster=CLUSTER_NAME \
--machine-type=MACHINE_TYPE \
--image-type=cos_containerd \
--sandbox type=gvisor
GKE Sandbox では、ノードイメージ タイプを cos_containerd
にする必要があります。
GKE Sandbox で GPU ノードプールを作成するには、次のコマンドを実行します。
gcloud container node-pools create NODE_POOL_NAME \
--cluster=CLUSTER_NAME \
--node-version=NODE_VERSION \
--machine-type=MACHINE_TYPE \
--accelerator=type=GPU_TYPE,gpu-driver-version=latest \
--image-type=cos_containerd \
--sandbox type=gvisor
次のように置き換えます。
GPU_TYPE
: サポートされている GPU タイプ。詳細については、GKE Sandbox をご覧ください。MACHINE_TYPE
: リクエストされた GPU タイプに一致するマシン。詳細については、Google Kubernetes Engine の GPU 要件をご覧ください。
省略可: モニタリングとロギングを有効にする
クラスタで Cloud Logging と Cloud Monitoring を有効にして、gVisor メッセージをログに記録します。この操作は省略可能ですが、行うことをおすすめします。これらのサービスは、新しいクラスタではデフォルトで有効になります。
Google Cloud コンソールを使用して、既存のクラスタでこれらの機能を有効にできます。
Google Cloud コンソールで Google Kubernetes Engine のページに移動します。
変更するクラスタの名前をクリックします。
[機能] の [Cloud Logging] フィールドで、[edit Cloud Logging の編集] をクリックします。
[Cloud Logging を有効にする] チェックボックスをオンにします。
[変更を保存] をクリックします。
[Cloud Monitoring] フィールドと [Managed Service for Prometheus] フィールドで同じ手順を繰り返し、これらの機能を有効にします。
Autopilot と Standard で GKE Sandbox を使用する
GKE Sandbox が有効になっている Autopilot クラスタと Standard クラスタでは、Pod 仕様で gvisor
RuntimeClass を指定して Pod のサンドボックス環境をリクエストします。
Autopilot クラスタでは、GKE バージョン 1.27.4-gke.800 以降を実行していることを確認します。
サンドボックスでのアプリケーションの実行
GKE Sandbox が有効になっているノードで Deployment を実行するには、次の例のように spec.template.spec.runtimeClassName
を gvisor
に設定します。
# httpd.yaml
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: gvisor
containers:
- name: httpd
image: httpd
Deployment を作成します。
kubectl apply -f httpd.yaml
GKE Sandbox が有効になっているノードに Pod がデプロイされます。デプロイを確認するには、Pod がデプロイされているノードを探します。
kubectl get pods
出力は次のようになります。
NAME READY STATUS RESTARTS AGE
httpd-db5899bc9-dk7lk 1/1 Running 0 24s
出力で Pod の名前を探してから、RuntimeClass の値を確認します。
kubectl get pods POD_NAME -o jsonpath='{.spec.runtimeClassName}'
出力は gvisor
です。
または、各 Pod の RuntimeClass を一覧表示して、gvisor
に設定されている Pod を探します。
kubectl get pods -o jsonpath=$'{range .items[*]}{.metadata.name}: {.spec.runtimeClassName}\n{end}'
次のような出力が表示されます。
POD_NAME: gvisor
Pod がサンドボックス内で実行されていることを確認する方法は、サンドボックス内のデータに依存しないため、信頼性が高い方法となります。サンドボックス内から報告されたものは信頼できません。問題が存在していることや、悪意のある可能性があります。
GKE Sandbox で GPU を使用して Pod を実行する
GKE Sandbox で GPU ワークロードを実行するには、次の例のように、runtimeClassName: gvisor
フィールドをマニフェストに追加します。
Standard モードの GPU Pod のマニフェストの例:
apiVersion: v1 kind: Pod metadata: name: my-gpu-pod spec: runtimeClassName: gvisor containers: - name: my-gpu-container image: nvidia/samples:vectoradd-cuda10.2 resources: limits: nvidia.com/gpu: 1
Autopilot モードの GPU Pod のマニフェストの例:
apiVersion: v1 kind: Pod metadata: name: my-gpu-pod spec: runtimeClassName: gvisor nodeSelector: cloud.google.com/gke-gpu-driver-version: "latest" cloud.google.com/gke-accelerator: nvidia-tesla-t4 containers: - name: my-gpu-container image: nvidia/samples:vectoradd-cuda10.2 resources: limits: nvidia.com/gpu: 1
マニフェストに runtimeClassName: gvisor
フィールドを追加すると、バージョンと GPU タイプの要件を満たす Autopilot モードまたは Standard モードの GPU Pod を GKE Sandbox で実行できます。GKE で GPU Pod を実行する手順については、次のリソースをご覧ください。
通常の Pod とサンドボックス Pod の実行
このセクションの手順は、Standard モードのワークロードに適用されます。Autopilot モードでは、通常の Pod をサンドボックス Pod と並行して実行する必要はありません。これは、Autopilot 料金モデルによって、ノードでスケジュールされる Pod の数を手動で最適化する必要がないためです。
ノードプールで GKE Sandbox を有効にした後、Node Taints と許容値でサンドボックスを使用するのではなく、信頼できるアプリケーションをノードで実行できます。 これらの Pod は、「通常の Pod」といわれ、サンドボックスの Pod と区別されます。
通常の Pod は、サンドボックス化された Pod と同様に、他の Google Cloud サービスやクラスタ メタデータにアクセスできません。この設定は、ノードの構成時に有効になります。通常の Pod またはサンドボックス化された Pod が Google Cloud サービスにアクセスする必要がある場合は、GKE 用 Workload Identity 連携を使用します。
GKE Sandbox は、サンドボックス化されたポッドを実行できるノードに次のラベルと taint を追加します。
labels:
sandbox.gke.io/runtime: gvisor
taints:
- effect: NoSchedule
key: sandbox.gke.io/runtime
value: gvisor
GKE Sandbox は、Pod マニフェストのノード アフィニティと toleration に加えて、次のノード アフィニティと許容値をすべての Pod に適用し、RuntimeClass
を gvisor
に設定します。
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: sandbox.gke.io/runtime
operator: In
values:
- gvisor
tolerations:
- effect: NoSchedule
key: sandbox.gke.io/runtime
operator: Equal
value: gvisor
GKE Sandbox が有効なノードで通常の Pod のスケジュールを設定するには、上記のノード アフィニティと toleration を Pod マニフェストに手動で適用します。
- GKE Sandbox が有効なノードで Pod が実行可能な場合は、toleration を追加します。
- GKE Sandbox が有効なノードで Pod を実行する必要がある場合は、上記のノード アフィニティと toleration の両方を追加します。
たとえば、次のマニフェストでは、サンドボックスでのアプリケーションの実行で使用したマニフェストを変更します。runtimeClass を削除して上記の taint と toleration の両方を追加し、サンドボックス化した Pod を含むノードで通常の Pod として実行します。
# httpd-no-sandbox.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpd-no-sandbox
labels:
app: httpd
spec:
replicas: 1
selector:
matchLabels:
app: httpd
template:
metadata:
labels:
app: httpd
spec:
containers:
- name: httpd
image: httpd
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: sandbox.gke.io/runtime
operator: In
values:
- gvisor
tolerations:
- effect: NoSchedule
key: sandbox.gke.io/runtime
operator: Equal
value: gvisor
まず、サンドボックスで Deployment が実行されていないことを確認します。
kubectl get pods -o jsonpath=$'{range .items[*]}{.metadata.name}: {.spec.runtimeClassName}\n{end}'
出力は次のようになります。
httpd-db5899bc9-dk7lk: gvisor
httpd-no-sandbox-5bf87996c6-cfmmd:
前に作成した httpd
Deployment はサンドボックス内で実行されます。これは、runtimeClass が gvisor
のためです。httpd-no-sandbox
Deployment の runtimeClass には値が設定されていないため、サンドボックスでは実行されません。
次に、GKE Sandbox を使用するノードで、サンドボックス化されていない Deployment が実行されていることを確認します。
kubectl get pod -o jsonpath=$'{range .items[*]}{.metadata.name}: {.spec.nodeName}\n{end}'
ノードプールの名前は、nodeName
の値に埋め込まれます。GKE Sandbox が有効なノードプール内のノードで、Pod が実行されていることを確認します。
メタデータの保護の確認
サンドボックス ポッドを実行できるノードからメタデータが保護されていることを確認するには、次のようにテストを行います。
kubectl apply -f
を使用して、次のマニフェストから、サンドボックス化された Deployment を作成します。curl
コマンドを含むfedora
イメージを使用します。ポッドは/bin/sleep
コマンドを実行して、Deployment が 10,000 秒間実行されるようにします。# sandbox-metadata-test.yaml apiVersion: apps/v1 kind: Deployment metadata: name: fedora labels: app: fedora spec: replicas: 1 selector: matchLabels: app: fedora template: metadata: labels: app: fedora spec: runtimeClassName: gvisor containers: - name: fedora image: fedora command: ["/bin/sleep","10000"]
kubectl get pods
を使用して Pod の名前を取得し、kubectl exec
を使用して、Pod にインタラクティブに接続します。kubectl exec -it POD_NAME /bin/sh
/bin/sh
セッションで、ポッド内のコンテナに接続されます。インタラクティブ セッションで、クラスタ メタデータを返す URL にアクセスします。
curl -s "http://169.254.169.254/computeMetadata/v1/instance/attributes/kube-env" -H "Metadata-Flavor: Google"
パケットがサイレントで破棄されるため、コマンドが停止し、最終的にタイムアウトになります。
Ctrl + C を押して
curl
コマンドを終了し、exit
を入力して Pod から切断します。YAML マニフェストから
RuntimeClass
を削除し、kubectl apply -f FILENAME
を使用して Pod を再デプロイします。サンドボックス化された Pod が終了し、GKE Sandbox のないノードで再作成されます。新しい Pod 名を取得し、
kubectl exec
を使用して Pod に接続します。curl
コマンドを再度実行します。今回は、結果が返されます。この出力例は省略されています。ALLOCATE_NODE_CIDRS: "true" API_SERVER_TEST_LOG_LEVEL: --v=3 AUTOSCALER_ENV_VARS: kube_reserved=cpu=60m,memory=960Mi,ephemeral-storage=41Gi;... ...
exit
と入力して、Pod から切断します。デプロイを削除します。
kubectl delete deployment fedora
GKE Sandbox を無効にする
GKE Autopilot クラスタまたは GKE Standard ノードプールでは GKE Sandbox を無効にできません。GKE Sandbox の使用を停止する場合は、ノードプールを削除します。