使用 GKE Sandbox 強化工作負載隔離


本頁面說明當 Pod 中的容器要執行未知或不受信任的程式碼,或需要與節點額外隔離時,如何使用 GKE Sandbox 保護節點上的主機核心。本頁說明如何啟用 GKE Sandbox,以及在 GKE Sandbox 執行時監控叢集。

本頁內容適用於需要隔離工作負載的安全性專家,以防範未知或不受信任的程式碼。如要進一步瞭解 Google Cloud 內容中提及的常見角色和範例工作,請參閱常見的 GKE Enterprise 使用者角色和工作

閱讀本頁面之前,請先熟悉 GKE Sandbox 一般總覽

啟用 GKE Sandbox

執行 GKE 1.27.4-gke.800 以上版本的 Autopilot 叢集,即可使用 GKE Sandbox。如要開始在沙箱中部署 Autopilot 工作負載,請跳至「使用 GKE Sandbox」。

如要在新的或現有的 GKE Standard 叢集中使用 GKE Sandbox,您必須手動在叢集上啟用 GKE Sandbox。

GKE Sandbox 中的硬體加速工作負載現已正式發布,適用於下列版本:

  • 1.29.15-gke.1134000
  • 1.30.11-gke.1093000
  • 1.31.7-gke.1149000
  • 1.32.2-gke.1182003 以上版本

事前準備

開始之前,請確認你已完成下列工作:

  • 啟用 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,請務必在叢集中新增至少一個節點集區。

控制台

如要查看叢集,請前往Google Cloud console 的「Google Kubernetes Engine」選單。

  1. 在 Google Cloud 控制台中,前往「建立 Kubernetes 叢集」頁面。

    前往「建立 Kubernetes 叢集」

  2. 選用 (建議使用):在導覽選單中,按一下「Cluster」(叢集) 下方的「Features」(功能),然後選取下列核取方塊,以記錄 gVisor 訊息:

    • Cloud Logging
    • Cloud Monitoring
    • Managed Service for Prometheus
  3. 按一下 「Add Node Pool」(新增節點集區)

  4. 在導覽選單的「Node Pools」(節點集區) 下方,展開新的節點集區,然後按一下「Nodes」(節點)

  5. 為節點集區設定下列項目:

    1. 在「映像檔類型」下拉式清單中,選取「含有 Containerd (cos_containerd) 的 Container-Optimized OS」。這是 GKE 沙箱唯一支援的映像檔類型。
    2. 在「機器設定」下方,選取「系列」和「機器類型」
    3. 如果您執行的是支援的 GKE 版本,也可以選取 GPU 或 TPU 類型。必須是下列其中一種 GPU 類型:

      • nvidia-tesla-t4
      • nvidia-tesla-a100
      • nvidia-a100-80gb
      • nvidia-l4
      • nvidia-h100-80gb

      或下列 TPU 類型:

      • v4
      • v5e
      • v5p
      • v6e
  6. 在導覽選單中,點選要設定的節點集區名稱下方的「安全性」,然後勾選「啟用 gVisor 沙箱」核取方塊。

  7. 視需要繼續設定叢集和節點集區。

  8. 點選「建立」

gcloud

GKE Sandbox 無法在預設節點集區上啟用,也無法在使用 gcloud 指令建立新叢集時建立其他節點。請改為按照平常方式建立叢集。建議您啟用記錄與監控功能,以記錄 gVisor 訊息 (此為選用功能)。

接下來使用 gcloud container node-pools create 指令,將 -- sandbox 旗標設為 type=gvisor。節點映像檔類型必須是 cos_containerd,才能使用 GKE Sandbox。

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=DRIVER_VERSION \
  --image-type=cos_containerd \
  --sandbox type=gvisor

更改下列內容:

  • GPU_TYPE:支援的 GPU 類型。詳情請參閱「GKE Sandbox」。

  • MACHINE_TYPE:符合所要求 GPU 類型的機器。詳情請參閱 Google Kubernetes Engine GPU 需求

  • DRIVER_VERSION:要安裝的 NVIDIA 驅動程式版本。可以是下列任一值:

    • default:安裝 GKE 版本的預設驅動程式版本。
    • latest:為 GKE 版本安裝最新可用驅動程式版本。僅適用於使用 Container-Optimized OS 的節點。

如要建立啟用 GKE Sandbox 的 TPU 節點集區,請執行下列指令:

gcloud container node-pools create NODE_POOL_NAME \
  --cluster=CLUSTER_NAME \
  --node-version=NODE_VERSION \
  --num-nodes=NUM_NODES \
  --tpu-topology=TPU_TOPOLOGY \
  --machine-type=MACHINE_TYPE \
  --image-type=cos_containerd \
  --sandbox type=gvisor
  • MACHINE_TYPE:支援的 TPU 類型。詳情請參閱「GKE Sandbox」。

在現有的 Standard 叢集上啟用 GKE Sandbox

您可以在現有 Standard 叢集上啟用 GKE Sandbox,方法是新增節點集區並啟用該節點集區的功能。

控制台

如要建立啟用 GKE Sandbox 的新節點集區,請按照下列步驟操作:

  1. 前往 Google Cloud 控制台的「Google Kubernetes Engine」頁面。

    前往「Google Kubernetes Engine」

  2. 按一下您要修改的叢集名稱。

  3. 按一下 「Add Node Pool」(新增節點集區)

  4. 視需要設定「節點集區詳細資料」頁面。

  5. 在導覽選單中,按一下「節點」,然後設定下列項目:

    1. 在「映像檔類型」下拉式清單中,選取「含有 Containerd (cos_containerd) 的 Container-Optimized OS」。這是 GKE 沙箱唯一支援的映像檔類型。
    2. 在「機器設定」下方,選取「系列」和「機器類型」
    3. 如果您執行的是支援的 GKE 版本,也可以選取 GPU 或 TPU 類型。必須是下列其中一種 GPU 類型:

      • nvidia-tesla-t4
      • nvidia-tesla-a100
      • nvidia-a100-80gb
      • nvidia-l4
      • nvidia-h100-80gb

      或下列 TPU 類型:

      • v4
      • v5e
      • v5p
      • v6e
  6. 在導覽選單中按一下「安全性」,然後選取「啟用 gVisor 沙箱」核取方塊。

  7. 點選「建立」

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=DRIVER_VERSION \
  --image-type=cos_containerd \
  --sandbox type=gvisor

更改下列內容:

  • GPU_TYPE:支援的 GPU 類型。詳情請參閱「GKE Sandbox」。

  • MACHINE_TYPE:符合所要求 GPU 類型的機器。詳情請參閱 Google Kubernetes Engine GPU 需求

  • DRIVER_VERSION:要安裝的 NVIDIA 驅動程式版本。可以是下列任一值:

    • default:安裝 GKE 版本的預設驅動程式版本。
    • latest:為 GKE 版本安裝最新可用驅動程式版本。僅適用於使用 Container-Optimized OS 的節點。

如要建立啟用 GKE Sandbox 的 TPU 節點集區,請執行下列指令:

gcloud container node-pools create NODE_POOL_NAME \
  --cluster=CLUSTER_NAME \
  --node-version=NODE_VERSION \
  --num-nodes=NUM_NODES \
  --tpu-topology=TPU_TOPOLOGY \
  --machine-type=MACHINE_TYPE \
  --image-type=cos_containerd \
  --sandbox type=gvisor
  • MACHINE_TYPE:支援的 TPU 類型。詳情請參閱「GKE Sandbox」。

選用:啟用監控和記錄功能

請在叢集上啟用 Cloud Logging 和 Cloud Monitoring 以記錄 gVisor 訊息,此為選擇性,但建議採用。新叢集預設會啟用這些服務。

您可以使用 Google Cloud 控制台,在現有叢集上啟用這些功能。

  1. 前往 Google Cloud 控制台的「Google Kubernetes Engine」頁面。

    前往「Google Kubernetes Engine」

  2. 按一下您要修改的叢集名稱。

  3. 在「功能」下方的「Cloud Logging」欄位中,依序點選 「編輯 Cloud Logging」

  4. 勾選「啟用 Cloud Logging」核取方塊。

  5. 按一下 [儲存變更]。

  6. 針對「Cloud Monitoring」和「Managed Service for Prometheus」欄位重複相同步驟,啟用這些功能。

在 Autopilot 和 Standard 中使用 GKE Sandbox

在 Autopilot 叢集和啟用 GKE Sandbox 的 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 上執行搭載加速器的 Pod

如要在 GKE Sandbox 上執行 GPU 或 TPU 工作負載,請在資訊清單中加入 runtimeClassName: gvisor 欄位,如下列範例所示:

  • 標準模式 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
    
  • Standard 或 Autopilot 模式 TPU Pod 的資訊清單範例:

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-tpu-pod
    spec:
      runtimeClassName: gvisor
      nodeSelector:
        cloud.google.com/gke-tpu-accelerator: tpu-v5-lite-podslice
        cloud.google.com/gke-tpu-topology: 1x1
      containers:
      - name: my-tpu-container
        image: python:3.10
        command:
          - bash
          - -c
          - |
            pip install 'jax[tpu]' -f https://storage.googleapis.com/jax-releases/libtpu_releases.html
            python -c 'import jax; print("TPU cores:", jax.device_count())'
        resources:
          limits:
            google.com/tpu: 1
          requests:
            google.com/tpu: 1
    

如要在 GKE Sandbox 上執行符合版本和加速器類型需求的 Autopilot 或 Standard 模式加速器 Pod,請在資訊清單中新增 runtimeClassName: gvisor 欄位。如要在 GKE 中執行 GPU Pod,請參閱下列內容:

如要在 GKE 中執行 TPU Pod,請參閱下列內容:

執行一般 Pod 以及採用沙箱機制的 Pod

本節中的步驟適用於標準模式工作負載。在 Autopilot 模式下,您不需要在沙箱 Pod 旁執行一般 Pod,因為 Autopilot 定價模式可免除手動調整節點上排程 Pod 數量的需求。

在節點集區上啟用 GKE Sandbox 後,可以使用節點 taint 和容許條件,以此方式在不使用沙箱的情況下,在這類節點上執行可信任的應用程式。這些 Pod 稱為「一般 Pod」,以便和採用沙箱機制沙箱的 Pod 做出區別。

一般 Pod 與採用沙箱機制的 Pod 相同,無法存取其他Google Cloud 服務或叢集中繼資料。這項防護措施是節點設定的一部分。如果一般 Pod 或採用沙箱機制的 Pod 需要存取Google Cloud 服務,請使用 Workload Identity Federation for GKE

GKE Sandbox 會將以下標籤和 taint 新增至可執行沙箱 Pod 的節點:

labels:
  sandbox.gke.io/runtime: gvisor
taints:
- effect: NoSchedule
  key: sandbox.gke.io/runtime
  value: gvisor

除了 Pod 資訊清單中的任何節點的相依性和容許條件設定之外,GKE Sandbox 也會將下列節點相依性和容許條件套用至所有將 RuntimeClass 設為gvisor 的 Pod:

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,請在 Pod 資訊清單中,手動套用先前所述的節點相依性和容許條件。

  • 如果您的 pod 可以在啟用 GKE Sandbox 的節點上執行,請加入容許條件。
  • 如果您的 pod 必須在啟用 GKE Sandbox 的節點上執行,請同時新增節點相依性和容許條件。

舉例來說,下列資訊清單會修改在沙箱中執行應用程式一節中使用的資訊清單,移除 runtimeClass 並加入先前說明的 taint 和容許條件,以此方式在具有沙箱 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:

由於 runtimeClass 為 gvisor,沙箱中正在執行之前建立的 httpd Deployment。httpd-no-sandbox Deployment 沒有 runtimeClass 的值,因此不會在沙箱中執行。

接下來,請執行以下指令,確認非採用沙箱機制的 Deployment 是否正在使用 GKE Sandbox 的節點上執行:

kubectl get pod -o jsonpath=$'{range .items[*]}{.metadata.name}: {.spec.nodeName}\n{end}'

節點集區的名稱會嵌入 nodeName 值中。確認在節點上執行的 Pod 是否在已啟用 GKE Sandbox 的節點集區內。

驗證中繼資料保護措施

如要驗證中繼資料是否確定受到保護,不會受到可執行沙箱 Pod 的節點的影響,可執行以下測試:

  1. 使用 kubectl apply -f,從下列資訊清單建立使用沙箱機制的 Deployment。其會使用包含 curl 指令的 fedora 映像檔。Pod 會執行 /bin/sleep 指令,以確保 Deployment 執行 10000 秒。

    # 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"]
    
  2. 使用 kubectl get pods 取得 Pod 名稱,然後使用 kubectl exec 以互動方式連線至 Pod。

    kubectl exec -it POD_NAME /bin/sh
    

    系統會在 /bin/sh 工作階段將您連線到在 Pod 中執行的容器。

  3. 請在互動式工作階段中,嘗試存取會傳回叢集中繼資料的網址:

    curl -s "http://169.254.169.254/computeMetadata/v1/instance/attributes/kube-env" -H "Metadata-Flavor: Google"
    

    由於系統會以無訊息的方式捨棄封包,使得指令停滯,最後逾時。

  4. 按下 Ctrl + C 鍵可終止 curl指令,再輸入 exit 即可中斷 Pod 的連線。

  5. 從 YAML 資訊清單中刪除 RuntimeClass 列,並使用 kubectl apply -f FILENAME 重新部署 Pod。使用沙箱機制的 Pod 會終止,並在沒有 GKE Sandbox 的節點上重新建立。

  6. 取得新的 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 中斷連線。

  7. 移除部署:

    kubectl delete deployment fedora
    

停用 GKE Sandbox

您無法在 GKE Autopilot 叢集或 GKE Standard 節點集區中停用 GKE Sandbox。如要停止使用 GKE Sandbox,請刪除節點集區

後續步驟