在專屬節點集區中隔離工作負載

本頁面說明如何在 Google Distributed Cloud (GDC) 實體隔離方案中,將容器工作負載隔離在專屬節點集區,進一步控管 Pod。工作負載隔離可帶來以下優點:

  • 降低 Kubernetes 叢集發生權限提升攻擊的風險。
  • 進一步控管需要額外資源的 Pod。

在這些情況下,建議您隔離容器工作負載,以便進一步控管及最佳化。

為什麼要隔離工作負載?

您不一定要將工作負載隔離到專屬節點集區,但為了避免潛在問題,建議採取這項謹慎的行動。但請注意,管理專屬節點集區需要更多監督,而且通常是不必要的。

Kubernetes 叢集會使用 GDC 管理的具備特殊權限的工作負載,啟用特定叢集功能和特性,例如收集指標。這些工作負載會獲得特殊權限,可在叢集中正確執行。

部署至節點的工作負載可能會遭到惡意實體入侵。如果這些工作負載與具備權限的 GDC 管理工作負載一起執行,表示攻擊者只要從遭入侵的容器中脫逃,就能使用節點上具備權限的工作負載憑證,在叢集中提升權限。

當您要排程的 pod 比其他 pod 需要更多資源 (例如更多記憶體或更多本機磁碟空間) 時,專屬節點集區也十分實用。

您可以使用下列機制,在專屬節點集區中排定工作負載:

節點 taint 會通知 Kubernetes 叢集,避免在這些節點上排定沒有相應容許條件的工作負載,例如 GDC 管理的工作負載。自有工作負載的節點親和性會告知叢集,將 Pod 排程至專屬節點。

節點隔離的限制

  • 攻擊者仍可從遭入侵的節點發動阻斷服務 (DoS) 攻擊。

  • 遭入侵的節點仍可讀取許多資源,包括叢集中的所有 Pod 和命名空間。

  • 遭入侵的節點可以存取在該節點上執行的每個 Pod 所使用的密鑰和憑證。

  • 使用個別節點集區隔離工作負載可能會影響成本效益、自動調度資源和資源用量。

  • 遭入侵的節點仍可略過輸出網路政策。

  • 部分 GDC 管理的工作負載必須在叢集中的每個節點上執行,且設定為可容許所有汙點。

  • 如果您部署具有提升權限且可容忍任何汙染的 DaemonSet 資源,這些 Pod 可能會成為遭入侵節點的權限提升路徑。

節點隔離的運作方式

如要為工作負載實作節點隔離,請完成下列步驟:

  1. 為工作負載汙染節點集區並加上標籤。

  2. 使用對應的容許度和節點親和性規則更新工作負載。

本指南假設您從叢集中的一個節點集區開始。除了節點汙染之外,使用節點親和性並非必要,但我們建議您這麼做,因為這樣可以更有效控管排程。

事前準備

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

  • 為要用於專屬節點集區的節點汙點和節點標籤選擇特定名稱。例如 workloadType=untrusted

  • 如有需要,請要求機構 IAM 管理員授予您「使用者叢集開發人員」角色 (user-cluster-developer),這個角色不會繫結至命名空間。

汙染並標記新的節點集區

將汙點或標籤套用至新的節點集區時,所有節點 (包括稍後新增的節點) 都會自動取得指定的汙點和標籤。

如要為新的節點集區新增汙點和標籤,請完成下列步驟:

  1. 建立節點集區時,直接編輯自訂資源的 nodePools 區段:Cluster

    nodePools:
      ...
      - machineTypeName: n2-standard-2-gdc
        name: nodepool-1
        nodeCount: 3
        taints: TAINT_KEY=TAINT_VALUE:TAINT_EFFECT
        labels: LABEL_KEY=LABEL_VALUE
    

    更改下列內容:

    • TAINT_KEY=TAINT_VALUE:與排程 TAINT_EFFECT 相關聯的鍵/值組合。例如:workloadType=untrusted
    • TAINT_EFFECT:下列其中一個效果值:
      • NoSchedule:系統不會把無法容許此 taint 的 Pod 排程到節點上,也不會將現有的 Pod 自節點中移除。
      • PreferNoSchedule:Kubernetes 會避免將無法容忍此 taint 的 Pod 排程到節點上。
      • NoExecute:如果 Pod 已在節點上執行,系統會移除節點中的 Pod。如果尚未在節點上執行,也不會將 Pod 排程到節點上。
    • LABEL_KEY=LABEL_VALUE: 節點標籤的鍵/值組合,對應至您在工作負載資訊清單中指定的選取器。
  2. 套用 Cluster 資源,建立新的節點集區:

    kubectl apply -f cluster.yaml \
        --kubeconfig MANAGEMENT_API_SERVER
    

    MANAGEMENT_API_SERVER 替換為 Kubernetes 叢集所在區域 API 伺服器的 kubeconfig 路徑。如果您尚未在目標區域中為 API 伺服器產生 kubeconfig 檔案,請參閱「登入」一文瞭解詳情。

汙染及標記現有節點集區

如要將汙點或標籤套用至現有節點集區,您必須對每個現有節點套用變更。您無法動態更新節點集區設定。

如要在現有節點集區中新增汙點和標籤,請完成下列步驟:

  1. 列出專屬節點集區中的節點:

    kubectl get node --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG \
        -l baremetal.cluster.gke.io/node-pool=NODE_POOL_NAME
    

    請替換下列變數:

    • KUBERNETES_CLUSTER_KUBECONFIG:Kubernetes 叢集的 kubeconfig 路徑。
    • NODE_POOL_NAME:專屬節點集區的名稱。

    從輸出內容中記下節點集區中所有節點的節點 ID。

  2. 針對節點集區中的每個節點,套用以下 taint:

    kubectl taint nodes NODE_ID \
        TAINT_KEY=TAINT_VALUE:TAINT_EFFECT \
        --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
    

    請替換下列變數:

    • NODE_ID:專屬節點集區中的工作站節點 ID。
    • TAINT_KEY=TAINT_VALUE:與排程相關聯的鍵/值組合。TAINT_EFFECT例如:workloadType=untrusted
    • TAINT_EFFECT:下列其中一個效果值:
      • NoSchedule:系統不會把無法容許此 taint 的 Pod 排程到節點上,也不會將現有的 Pod 自節點中移除。
      • PreferNoSchedule:Kubernetes 會避免將無法容忍此 taint 的 Pod 排程到節點上。
      • NoExecute:如果 Pod 已在節點上執行,系統會移除節點中的 Pod。如果尚未在節點上執行,也不會將 Pod 排程到節點上。
    • KUBERNETES_CLUSTER_KUBECONFIG:Kubernetes 叢集的 kubeconfig 路徑。
  3. 針對節點集區中的每個節點,套用與您在容器工作負載中定義的選取器相應的標籤:

    kubectl label NODE_ID \
        LABEL_KEY:LABEL_VALUE \
        --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
    

    請替換下列變數:

    • NODE_ID:專屬節點集區中的工作站節點 ID。
    • LABEL_KEY:LABEL_VALUE:節點標籤的鍵/值組合,對應至您在工作負載資訊清單中指定的選取器。
    • KUBERNETES_CLUSTER_KUBECONFIG:Kubernetes 叢集的 kubeconfig 路徑。

新增容許度和節點親和性規則

為專屬節點集區設定污點後,除非工作負載具有與您新增污點相應的容許條件,否則無法排程至該節點集區。在工作負載的規格中新增容許條件,讓這些 Pod 在受汙染的節點集區中排程。

如果您已為專屬節點集區加上標籤,也可以新增節點親和性規則,告知 GDC 只在該節點集區中排定工作負載。

如要設定容器工作負載,使其在專屬節點集區中執行,請完成下列步驟:

  1. 在容器工作負載的 .spec.template.spec 區段中新增下列區段:

    kind: Deployment
    apiVersion: apps/v1
        ...
        spec:
        ...
          template:
            spec:
              tolerations:
              - key: TAINT_KEY
                operator: Equal
                value: TAINT_VALUE
                effect: TAINT_EFFECT
              affinity:
                nodeAffinity:
                  requiredDuringSchedulingIgnoredDuringExecution:
                    nodeSelectorTerms:
                    - matchExpressions:
                      - key: LABEL_KEY
                        operator: In
                        values:
                        - "LABEL_VALUE"
              ...
    

    更改下列內容:

    • TAINT_KEY:您套用至專屬節點集區的汙點鍵。
    • TAINT_VALUE:您套用至專屬節點集區的汙點值。
    • TAINT_EFFECT:下列其中一個效果值:
      • NoSchedule:系統不會把無法容許此 taint 的 Pod 排程到節點上,也不會將現有的 Pod 自節點中移除。
      • PreferNoSchedule:Kubernetes 會避免將無法容忍此 taint 的 Pod 排程到節點上。
      • NoExecute:如果 Pod 已在節點上執行,系統會移除節點中的 Pod。如果尚未在節點上執行,也不會將 Pod 排程到節點上。
    • LABEL_KEY:您套用至專屬節點集區的節點標籤鍵。
    • LABEL_VALUE:您套用至專屬節點集區的節點標籤值。

    舉例來說,下列 Deployment 資源會新增 workloadType=untrusted:NoExecute taint 的容許度,以及 workloadType=untrusted 節點標籤的節點親和性規則:

    kind: Deployment
    apiVersion: apps/v1
    metadata:
      name: my-app
      namespace: default
      labels:
        app: my-app
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: my-app
      template:
        metadata:
          labels:
            app: my-app
        spec:
          tolerations:
          - key: workloadType
            operator: Equal
            value: untrusted
            effect: NoExecute
          affinity:
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                - matchExpressions:
                  - key: workloadType
                    operator: In
                    values:
                    - "untrusted"
          containers:
          - name: my-app
            image: harbor-1.org-1.zone1.google.gdc.test/harborproject/my-app
            ports:
            - containerPort: 80
          imagePullSecrets:
          - name: SECRET
    
  2. 更新部署作業:

    kubectl apply -f deployment.yaml -n NAMESPACE \
        --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
    

    請替換下列變數:

    • NAMESPACE:容器工作負載的專案命名空間。
    • KUBERNETES_CLUSTER_KUBECONFIG:Kubernetes 叢集的 kubeconfig 路徑。

GDC 會重新建立受影響的 Pod。節點親和性規則會強制將 Pod 放到您建立的專屬節點集區。容許度只允許這些 Pod 放置在節點上。

確認分離功能是否正常運作

如要確認排程是否正常運作,請執行下列指令,並檢查工作負載是否位於專屬節點集區:

kubectl get pods -o=wide -n NAMESPACE \
    --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG

建議做法與最佳做法

設定節點隔離後,建議您採取下列做法:

  • 建立新節點集區時,請在這些節點集區中新增自己的汙染,防止大多數 GDC 管理的工作負載在這些節點上執行。
  • 每當您將新工作負載部署至叢集時 (例如安裝第三方工具),請稽核 Pod 要求的權限。盡可能避免將使用提升權限的工作負載部署至共用節點。