使用 GKE Sandbox 隔離工作負載

您可以使用 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 中省略 Sandbox 設定。

如要為自動建立的節點設定 GKE Sandbox,請按照下列步驟操作:

  1. 連線至現有的 Autopilot 或 Standard 叢集:

    gcloud container clusters get-credentials CLUSTER_NAME \
        --location=CONTROL_PLANE_LOCATION
    

    更改下列內容:

    • CLUSTER_NAME:叢集名稱。
    • CONTROL_PLANE_LOCATION:叢集控制層的區域或可用區。
  2. 請根據所需的沙箱技術,儲存下列其中一個 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: DoNotScaleUp
      
    • microVM:

      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: DoNotScaleUp
      

      microVM 沙箱的 ComputeClass 會使用 enableNestedVirtualization 欄位啟用巢狀虛擬化功能。這是 microVM 沙箱的必填欄位。如要使用這個欄位,叢集必須執行 1.37.0-gke.4713000 以上版本。

    這些範例資訊清單會使用 nodePoolAutoCreation 欄位啟用節點集區自動建立功能。您也可以在 ComputeClass 中指定沙箱設定,使用 autopilot 欄位在 Autopilot 模式下執行 Pod。如果您使用 Autopilot 叢集,GKE 會忽略 nodePoolAutoCreation 和 autopilot 欄位。

  3. 建立 ComputeClass:

    kubectl apply -f PATH_TO_COMPUTE_CLASS_MANIFEST
    

    將 PATH_TO_COMPUTE_CLASS_MANIFEST 替換為 ComputeClass 資訊清單的路徑。

如要選取這個 ComputeClass 並要求沙箱環境,請參閱「要求 Pod 的沙箱環境」。

建立節點集區時選擇沙箱類型

在 Standard 叢集中建立新節點集區時,您可以手動啟用 GKE Sandbox。手動啟用 GKE Sandbox 時,須注意下列限制:

  • 如要在建立 Standard 叢集時啟用 GKE Sandbox,您必須設定至少一個額外節點集區。由於 GKE 叢集必須至少有一個節點集區不使用 GKE Sandbox 執行 GKE 管理的系統工作負載,因此需要額外的節點集區。如果使用 gcloud CLI 建立叢集,則必須先建立叢集,再建立使用 GKE Sandbox 的節點集區。
  • 如要選取 microVM 沙箱類型,必須使用 gcloud CLI 或 GKE API。控制台 Google Cloud 不支援選取 microVM 沙箱類型。

啟用 gVisor 沙箱類型

如要在建立新節點集區時手動啟用 gVisor 沙箱,請選取下列任一選項:

控制台

  1. 前往 Google Cloud 控制台的「Kubernetes clusters」(Kubernetes 叢集) 頁面。

    前往 Kubernetes 叢集

  2. 點按要修改的叢集名稱。「叢集詳細資料」頁面隨即開啟。

  3. 按一下「Nodes」(節點) 分頁標籤。

  4. 在「節點集區」部分,按一下 「新增使用者管理的節點集區」。「Add a node pool」(新增節點集區) 頁面隨即開啟。

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

    1. 在「Image type」(映像檔類型) 下拉式選單中,選取「採用 Containerd 的 Container-Optimized OS (cos_containerd)」。
    2. 在「機器設定」部分,為節點選取機器系列和機型。
    3. 選用:選取支援的 GPU 類型或支援的 TPU 類型。
  6. 按一下導覽選單中的「Security」(安全性)。「Node security」(節點安全性) 頁面隨即開啟。

  7. 勾選「啟用 Sandbox with gVisor」核取方塊。

  8. 如要建立節點集區,請按一下「Create」(建立)。

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 沙箱類型

使用 gcloud CLI 或 GKE API 建立節點集區時,您可以啟用 microVM 沙箱類型。 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 規格中指定 gvisor 或 microvm RuntimeClass。GKE 會在採用指定沙箱類型的節點上排定 Pod。如要在 Pod 規格中選取沙箱類型,請按照下列步驟操作:

  1. 根據您是使用 ComputeClasses 啟用 GKE Sandbox,還是手動建立節點集區,儲存下列其中一個部署資訊清單範例:

    • 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 的沙箱類型。支援下列值:

        • gvisor
        • microvm

        您指定的沙箱類型必須與所選 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: httpd
      

      將 SANDBOX_TYPE 替換為沙箱類型。支援下列值:

      • gvisor
      • microvm

      您指定的沙箱類型必須與叢集中現有節點集區的沙箱類型相符。

  2. 建立 Deployment:

    kubectl apply -f PATH_TO_DEPLOYMENT_MANIFEST
    

    將 PATH_TO_DEPLOYMENT_MANIFEST 替換為 Deployment 資訊清單的路徑。

  3. 確認 Pod 已建立:

    kubectl get pods
    

    輸出結果會與下列內容相似:

    NAME                    READY   STATUS    RESTARTS   AGE
    httpd-db5899bc9-dk7lk   1/1     Running   0          24s
    

在支援的 GPU 類型或支援的 TPU 類型上執行 Pod 時,您也可以使用 runtimeClassName 欄位要求沙箱。詳情請參閱下列文件:

執行一般 Pod 和沙箱 Pod

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

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

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

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

  • sandbox.gke.io/runtime: SANDBOX_TYPE 節點標籤。
  • sandbox.gke.io/runtime=SANDBOX_TYPE:NoSchedule 節點 taint。只有具備相符容許條件的 Pod 才能排程到節點上。

如果您使用 RuntimeClass 欄位在沙箱中執行 Pod,GKE 會自動將節點親和性和容許條件套用至 Pod。如要在使用 GKE Sandbox 的節點上執行一般 Pod,您必須手動將下列選取器套用至 Pod 規格:

  • 如要讓 Pod 在必要時,於使用 GKE Sandbox 的節點上執行,請僅新增節點污點的容忍度。
  • 如要只在採用 GKE Sandbox 的節點上執行 Pod,請新增節點選取器和節點 taint 容許條件。

下列步驟說明如何在採用 GKE Sandbox 的節點上執行一般 Pod:

  1. 將下列部署資訊清單儲存為 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_TYPE
    

    將 SANDBOX_TYPE 替換為沙箱類型,例如 gvisor 或 microvm。

  2. 建立 Deployment:

    kubectl apply -f httpd-regular.yaml
    

    如果 Pod 無法排程,請確認 Pod 資訊清單中的節點親和性和容許條件設定正確。

  3. 確認 Pod 不在沙箱中:

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

    輸出結果會與下列內容相似:

    httpd-db5899bc9-dk7lk: SANDBOX_TYPE
    httpd-regular-5bf87996c6-cfmmd:
    

    httpd-regular Pod 沒有 RuntimeClass 值,表示 Pod 不在沙箱中。

  4. 確認一般 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 是否與主機節點隔離。

  1. 如果是 gVisor 和 microVM 沙箱,請檢查 Pod 可存取的核心版本是否與主機節點的核心版本不同:

    1. 取得 Pod 可存取的核心版本:

      kubectl exec POD_NAME -- uname -r
      

      將 POD_NAME 替換為 Pod 名稱。

      輸出結果會與下列內容相似:

      4.19.0-gvisor
      
    2. 取得主機節點的核心版本:

      kubectl get node NODE_NAME \
          -o jsonpath='{.status.nodeInfo.kernelVersion}'
      

      將 NODE_NAME 替換為執行 Pod 的節點名稱。

      輸出結果會與下列內容相似:

      6.12.94+
      

    主機節點的核心版本與沙箱 Pod 可存取的核心版本不同,因為 Pod 只會看到 gVisor 的使用者空間核心,或是微型 VM 的客體核心。

  2. 如果是 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,請刪除節點集區。

後續步驟