本页面介绍如何在 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
以获取最新版本。
在新的标准集群上启用 GKE Sandbox
默认节点池是在您创建新集群时创建的,如果它是集群中唯一的节点池,则不能使用 GKE Sandbox,因为 GKE 管理的系统工作负载必须与不受信任的沙盒工作负载分开运行。要在集群创建期间启用 GKE Sandbox,您必须向集群添加至少一个额外的节点池。
控制台
要查看集群,请访问 Google Cloud 控制台中的 Google Kubernetes Engine 菜单。
转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。
点击 add_box 创建。
可选但建议执行的操作:在导航菜单中的集群下,点击功能,然后选中以下复选框,以便系统记录 gVisor 消息:
- Cloud Logging
- Cloud Monitoring
- Managed Service for Prometheus
点击 add_box 添加节点池。
在导航菜单中的节点池下,展开新的节点池,然后点击节点。
为节点池配置以下设置:
- 在映像类型下拉列表中,选择包含 Containerd 的 Container-Optimized OS (cos_containerd)。 这是 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 消息。
然后使用 gcloud container node-pools create
命令,并将 --
sandbox
标志设置为 type=gvisor
。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 的 Container-Optimized OS (cos_containerd)。 这是 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 版或更高版本。
在沙盒中运行应用
如需让 Deployment 在启用了 GKE Sandbox 的节点上运行,请将其 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
Pod 已部署到启用了 GKE Sandbox 的节点。如需验证部署,请找到部署了 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,然后查找 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/compute-class: "Accelerator" cloud.google.com/gke-accelerator: nvidia-tesla-t4 - name: my-gpu-container image: nvidia/samples:vectoradd-cuda10.2 resources: limits: nvidia.com/gpu: 1
您可以通过将 runtimeClassName: gvisor
字段添加到清单中,在 GKE Sandbox 上运行满足版本和 GPU 类型要求的任何 Autopilot 或 Standard 模式 GPU Pod。如需了解如何在 GKE 中运行 GPU Pod,请参阅以下资源:
运行常规 Pod 和沙盒化的 Pod
本部分中的步骤适用于 Standard 模式工作负载。不需要在 Autopilot 模式下同时运行常规 Pod 和沙盒 Pod,因为 Autopilot 价格模式消除了手动优化节点上调度的 Pod 数量的需求。
在节点池上启用 GKE Sandbox 后,您无需使用沙盒,即可通过使用节点污点和容忍设置,在这些节点上运行受信任的应用。这些 Pod 称为“常规 Pod”,以将它们与沙盒化的 Pod 区分开来。
与沙盒化的 Pod 一样,常规 Pod 也无法访问其他 Google Cloud 服务或集群元数据。此防护措施是节点配置的一部分。如果您的常规 Pod 或沙盒化的 Pod 需要访问 Google Cloud 服务,请使用适用于 GKE 的工作负载身份联合。
GKE Sandbox 会向可运行沙盒化 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 并添加上述污点和容忍设置,在具有沙盒化 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 值,因此未在沙盒中运行。
接下来,通过运行以下命令,验证未沙盒化的 Deployment 正在具有 GKE Sandbox 的节点上运行:
kubectl get pod -o jsonpath=$'{range .items[*]}{.metadata.name}: {.spec.nodeName}\n{end}'
在值 nodeName
中嵌入节点池的名称。验证 Pod 是否在节点池中启用了 GKE Sandbox 的节点上运行。
验证元数据保护
如需验证元数据免受可运行沙盒化 Pod 的节点影响的断言,您可以运行以下测试:
使用
kubectl apply -f
从以下清单创建沙盒化 Deployment。它使用fedora
映像,其中包含curl
命令。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"]
使用
kubectl get pods
获取 Pod 的名称,然后使用kubectl exec
以交互方式连接到 Pod。kubectl exec -it POD_NAME /bin/sh
您在
/bin/sh
会话中连接到 Pod 中运行的容器。在交互式会话中,尝试访问返回集群元数据的网址:
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。在没有 GKE Sandbox 的节点上终止沙盒化的 Pod,然后重新创建它。获取新的 Pod 名称,使用
kubectl exec
连接到它,然后再次运行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 的连接。移除该 Deployment:
kubectl delete deployment fedora
停用 GKE Sandbox
无法在 GKE Autopilot 集群或 GKE Standard 节点池中停用 GKE Sandbox。如果要停止使用 GKE Sandbox,请删除节点池。