在专用节点池中隔离工作负载

本页面介绍如何通过将 GKE on AWS 配置为在远离特权代管式工作负载的单独专用节点池上调度工作负载,来降低集群中的提权攻击风险。

概览

GKE on AWS 集群使用我们管理的特权工作负载来启用特定集群功能和特性,例如指标收集。这些工作负载有一些特殊权限,以便它们在集群中正确运行。

部署到节点的工作负载可能会被恶意实体破解。将这些工作负载与特权系统工作负载一起运行意味着攻破遭破解容器的攻击者可以使用节点上的特权工作负载的凭据来提升集群中的权限。

防止容器故障

您的主要防御措施应该是您的应用。GKE on AWS 提供了多个功能来强化集群和 Pod 的安全性。在大多数情况下,我们强烈建议使用 Policy Controller 和内核安全功能来强化工作负载的安全性。如需了解更多安全建议,请参阅安全概览

避免提升权限攻击

除了其他安全强化措施之外,如果您还需要额外的隔离层,可以使用节点污点节点亲和性在专用节点池上调度您的工作负载。

节点污点会告知 GKE on AWS 避免在这些节点上调度没有相应容忍设置的工作负载(例如,GKE on AWS 管理的工作负载)。您自己的工作负载上的节点亲和性会告知 GKE on AWS 在专用节点上调度您的 Pod。

节点隔离的限制

  • 攻击者仍然可以从遭破解的节点发起拒绝服务 (DoS) 攻击。
  • 遭破解的节点仍然可以读取许多资源,包括集群中的所有 Pod 和命名空间。
  • 遭破解的节点可以访问在该节点上运行的每个 Pod 使用的 Secret 和凭据。
  • 使用单独的节点池隔离工作负载可能会影响费用效率、自动扩缩和资源利用率。
  • 遭破解的节点仍然可以绕过出站网络政策。
  • 某些由 GKE on AWS 管理的工作负载必须在集群的每个节点上运行,并配置为容忍所有污点。
  • 如果您部署的 DaemonSet 具有提升的权限并且可以容忍任何污点,这些 Pod 可能会成为从遭破解节点提权的一个途径。

节点隔离的工作原理

如需为工作负载实现节点隔离,您必须执行以下操作:

  1. 为工作负载添加节点池污点和标签。
  2. 使用相应的容忍和节点亲和性规则更新工作负载。

本指南假设您从集群中的一个节点池开始。使用节点亲和性以及节点污点并非强制性要求,但我们建议您使用,因为您可以更好地控制调度。

准备工作

如需执行本页面中的步骤,请先完成以下步骤:

为工作负载添加节点池污点和标签

为您的工作负载创建新的节点池,并应用节点污点和节点标签。在节点池级层应用污点或标签时,所有新节点(例如由自动扩缩功能创建的节点)都将自动获取指定的污点和标签。

您还可以向现有节点池添加节点污点和节点标签。如果使用 NoExecute 效果,GKE on AWS 会逐出在这些节点上运行且不容忍新污点的任何 Pod。

如需向新节点池添加污点和标签,请运行以下命令:

gcloud container aws node-pools create POOL_NAME \
    --cluster CLUSTER_NAME \
    --node-taints TAINT_KEY=TAINT_VALUE:TAINT_EFFECT \
    --node-labels LABEL_KEY=LABEL_VALUE

替换以下内容:

  • POOL_NAME:工作负载的新节点池的名称。
  • CLUSTER_NAME:GKE on AWS 集群的名称。
  • TAINT_KEY=TAINT_VALUE:与调度 TAINT_EFFECT 关联的键值对。例如 workloadType=untrusted
  • TAINT_EFFECT:以下效果值之一:NoSchedulePreferNoScheduleNoExecuteNoExecute 提供比 NoSchedule 更好的逐出保证。
  • LABEL_KEY=LABEL_VALUE:节点标签的键值对,与您在工作负载清单中指定的选择器对应。

为您的工作负载添加容忍和节点亲和性规则

污染专用节点池后,任何工作负载都无法在其上调度,除非它们具有与您添加的污染相对应的容忍度。将容忍度添加到您的工作负载规范中,让这些 Pod 在您的受污染节点池上调度。

如果您已为专用节点池添加标签,则还可以添加节点亲和性规则,以指示 GKE on AWS 仅在该节点池上调度工作负载。

以下示例为 workloadType=untrusted:NoExecute 污点添加容忍设置,并为 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: TAINT_KEY
        operator: Equal
        value: TAINT_VALUE
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: LABEL_KEY
                operator: In
                values:
                - "LABEL_VALUE"
      containers:
      - name: sleep
        image: ubuntu
        command: ["/bin/sleep", "inf"]

替换以下内容:

  • TAINT_KEY:您应用于专用节点池的污点键。
  • TAINT_VALUE:您应用于专用节点池的污点值。
  • LABEL_KEY:您应用于专用节点池的节点标签键。
  • LABEL_VALUE:您应用于专用节点池的节点标签值。

使用 kubectl apply 更新 Deployment 时,GKE on AWS 会重新创建受影响的 Pod。节点亲和性规则强制 Pod 推送到您创建的专用节点池。容忍设置仅允许将这些 Pod 放置在节点上。

验证分离是否有效

要验证调度是否正常运行,请运行以下命令并检查您的工作负载是否在专用节点池上:

kubectl get pods -o=wide

建议和最佳实践

设置节点隔离后,我们建议您执行以下操作:

  • 通过添加 components.gke.io/gke-managed-components 污点,将特定节点池限制为仅由 GKE on AWS 管理的工作负载。添加此污点可防止您自己的 Pod 在这些节点上调度,从而改善隔离。
  • 创建新的节点池时,您可以通过向这些节点池添加自己的污点,阻止大多数由 GKE on AWS 管理的工作负载在这些节点上运行。
  • 每当您将新工作负载部署到集群时(例如安装第三方工具时),请审核 Pod 所需的权限。如果可能,请避免将使用提升权限的工作负载部署到共享节点。

后续步骤