您可以停用控制平面虚拟机 (VM) 实例的外部 IP 地址,从而提高 Google Kubernetes Engine (GKE) 控制平面的安全性。本文档向安全工程师介绍了如何控制来自 Kubernetes API 服务器的出站流量,以及如何避免对准入 Webhook 造成潜在中断。
您应该已经熟悉以下内容:
限制级别
您可以在创建或更新集群时指定以下某个限制级别:
- **无流量 (
NONE)**:停用每个 控制平面虚拟机实例的外部 IP 地址,并将所有 API 服务器出站流量路由到 黑洞。 此限制级别具有以下影响:- GKE 会阻止从 API 服务器到 集群外部运行的准入 Webhook 服务器 的直接出站流量。任何使用网址或 IP 地址与 Webhook 服务器联系的准入 Webhook 都会受到影响。
- GKE 会阻止从 API 服务器 到外部服务(包括互联网和 Google Cloud 服务)的任何直接出站流量。用于 GKE 身份验证和系统组件(例如元数据服务器)的流量不受影响。
- 任何其他类型的出站流量(例如关键系统流量或来自节点的流量)都不会受到影响。
- GKE 使用 ValidatingAdmissionPolicy 拒绝创建或更新使用
clientConfig.url字段的 ValidatingWebhookConfigurations 或 MutatingWebhookConfigurations。
- 所有流量 (
VIA_CONTROL_PLANE) :保留每个控制平面实例的外部 IP 地址,并允许 API 服务器使用该 IP 地址进行出站流量。此选项是 GKE 中的默认选项。
限制
如果您通过将限制级别设置为 NONE 来停用出站流量,则集群无法使用以非公开方式使用的公共 IP (PUPI) 地址。
准备工作
在开始之前,请确保您已执行以下任务:
- 启用 Google Kubernetes Engine API。 启用 Google Kubernetes Engine API
- 如果您要使用 Google Cloud CLI 执行此任务,
安装并
初始化
gcloud CLI。如果您之前安装了 gcloud CLI,请通过运行
gcloud components update命令来获取最新 版本。较早版本的 gcloud CLI 可能不支持运行本文档中的命令。
- 确保您拥有运行 1.35.1-gke.1396000 版或更高版本的 GKE Autopilot 或 Standard 集群。 您还可以 创建 Autopilot 集群。
- 如果您有任何外部 Webhook 服务器,请验证您是否使用 服务引用 与这些服务器联系。当您停用来自 API 服务器的出站流量时,任何使用网址与 Webhook 服务器联系的 Webhook 都会失败。GKE 管理的 Webhook 不受影响。
自定义来自 API 服务器的出站流量
您可以在创建或更新集群时自定义来自 API 服务器的出站流量的限制级别。如需更新现有集群,请使用 --control-plane-egress 标志:
gcloud container clusters update CLUSTER_NAME \
--location=CONTROL_PLANE_LOCATION \
--control-plane-egress=CONTROL_PLANE_EGRESS_MODE
替换以下内容:
CLUSTER_NAME:您的集群的名称。CONTROL_PLANE_LOCATION:集群控制平面所在的区域或可用区,例如us-central1或us-central1-a。CONTROL_PLANE_EGRESS_MODE:来自 API 服务器的出站流量的限制级别。请使用以下某个值:NONE:停用控制平面虚拟机实例的外部 IP 地址,并阻止来自 API 服务器的所有非关键出站流量。 GKE 会阻止创建使用clientConfig.url字段的新 Webhook 配置。VIA_CONTROL_PLANE:保留控制平面虚拟机实例的外部 IP 地址,并允许来自 API 服务器的出站流量。 这是默认值。
验证出站流量限制
如需检查 GKE 是否阻止来自 API 服务器的出站流量,请使用以下任一方法:
检查集群配置:
gcloud container clusters describe CLUSTER_NAME \ --location=CONTROL_PLANE_LOCATION \ --format='value(controlPlaneEgress)'输出为以下其中一项:
NONE:出站流量受到限制。VIA_CONTROL_PLANE:出站流量不受限制。
如需验证更改对新 Webhook 的影响,请尝试创建使用
clientConfig.url字段的 Webhook 配置:cat <<EOF | kubectl apply -f - apiVersion: admissionregistration.k8s.io/v1 kind: MutatingWebhookConfiguration metadata: name: test-webhook-config webhooks: - name: my-webhook.example.com clientConfig: url: "https://my-webhook.example.com:9443/my-webhook-path"输出类似于以下内容:
ValidatingAdmissionPolicy 'gke-restrict-webhook-url' denied request: Egress traffic from the API server through the control plane is disabled. As a result, direct API server calls to external webhook servers are blocked. To connect to external webhooks, update any webhook configurations that use clientConfig.url to use clientConfig.service instead.此输出表明,GKE ValidatingAdmissionPolicy 会阻止您创建或更新包含
clientConfig.url字段的 Webhook 配置。如果您删除 ValidatingAdmissionPolicy,则可以创建或更新配置,但准入请求不会到达 Webhook 服务器。如需验证更改对集群中现有 Webhook 的影响,请尝试向集群外部的 IP 地址发送直接请求:
- 为集群启用
API_SERVER日志 。 删除
gke-restrict-webhook-urlValidatingAdmissionPolicy:kubectl delete validatingadmissionpolicy gke-restrict-webhook-url删除 ValidatingAdmissionPolicy 后,您可以创建或更新包含
clientConfig.url字段的 Webhook 配置。集群会自动重新创建 ValidatingAdmissionPolicy,因此这种绕过是暂时的。在 ValidatingWebhookConfiguration 或 MutatingWebhookConfiguration 的
clientConfig.url字段中,指定要向其发送请求的 IP 地址或网址。您可以使用示例值,例如http://example.com或203.0.113.100。检查 API 服务器日志中是否存在类似如下的错误消息:
Error from server (InternalError): error when creating "STDIN": Internal error occurred: failed calling webhook WEBHOOK_NAME": failed to call webhook: Post "WEBHOOK_URL": proxyconnect tcp: dial tcp: lookup master-internet-access-unavailable.localhost on 169.254.169.254:53: no such host此输出表明,即使删除了 ValidatingAdmissionPolicy,准入请求也无法使用服务器 IP 地址或网址到达 Webhook 服务器。
- 为集群启用
停用控制平面虚拟机实例的外部 IP 地址后,GKE 会阻止流向任何使用网址与外部 Webhook 服务器联系的 Webhook
的流量。您必须在 Webhook 配置中使用 clientConfig.service 字段,为 API 服务器设置备用路由。
如需了解详情,请参阅
外部 Webhook 配置。