为公共 GKE 集群设置 Cloud NAT

Posted

技术标签:

【中文标题】为公共 GKE 集群设置 Cloud NAT【英文标题】:Setup Cloud NAT for public GKE clusters 【发布时间】:2019-03-31 05:52:58 【问题描述】:

我想设置一个 NAT 网关,使用 Cloud NAT,以便公共 GKE 集群中的 VM/Pod 使用静态 IP 地址。

我面临的问题是 NAT 网关似乎只在虚拟机没有其他选项时才使用,即:

GCP 仅在流量没有其他匹配的路由或路径时才使用 Cloud NAT 转发流量。

但在公共 GKE 集群的情况下,虚拟机具有临时的外部 IP,因此它们不使用网关。

根据文档:

如果您在虚拟机的接口上配置外部 IP [...] NAT 将不会对此类数据包执行。但是,分配给接口的别名 IP 范围仍然可以使用 NAT,因为它们无法使用外部 IP 访问 Internet。

使用此配置,您可以通过 SSH 直接连接到 GKE 虚拟机,但让 GKE pod/容器使用 Cloud NAT 访问互联网。

这就是我想要的,但我看不出这里要设置什么。

alias IP ranges assigned to the interface can still use NAT 暗示了什么以及如何设置?

【问题讨论】:

【参考方案1】:

“很遗憾,目前情况并非如此。虽然 Cloud NAT 仍处于测试阶段,但某些设置尚未完全到位,因此即使使用 IP 别名,Pod 仍在使用 SNAT。由于 SNAT 到节点的 IP, pod 不会使用 Cloud NAT。”

确实,正如 Patrick W 上面所说,它目前没有按照记录的那样工作。我也尝试过,并在 Kubernetes Engine 频道中与 GCP Slack 小组的人们交谈。他们还在测试中确认它仅适用于 GKE 私有集群。我们还没有开始使用私有集群。我找不到关于这个简单问题的可靠文档:如果我创建了一个私有集群,我仍然可以在该集群中拥有公共 K8S 服务(又名负载均衡器)吗?所有关于私有 GKE 集群的文档都表明您不希望任何外部流量进入,但我们正在 GKE 集群上运行面向 Internet 的生产服务。

我向 GCP 支持提交了一份关于 Cloud NAT 问题的请求,他们是这样说的:

“我一直在检查您的配置,Cloud NAT 无法正常工作的原因是您的集群不是私有的。 要将 Cloud NAT 与 GKE 结合使用,您必须创建一个私有集群。在非私有集群中,集群的公共 IP 地址用于主节点和节点之间的通信。这就是 GKE 没有考虑您拥有的 Cloud NAT 配置的原因。 通过创建私有集群,您可以将 Cloud NAT 和 GKE 结合起来。

我知道这在我们的文档中不是很清楚,我已报告这需要澄清并准确解释它应该如何工作。”

我回应要求他们按照文档说明进行操作,而不是更改他们的文档。我正在等待他们的更新...

【讨论】:

在这里回答我自己的答案的内部问题供其他人查找:GCP Slack Kubernetes 频道回答/确认了我的问题:“是的。我们的私有集群中有面向互联网的服务类型 LB。在这种情况下,我将尽快将我们所有的 GKE 集群迁移为私有集群。我建议你也这样做,Sylvain。 确认,我刚刚在我们的一个开发环境中以“私有集群”模式重建了 GKE 集群(我们使用 Terraform 完成所有这些),并且确实:节点没有更多的公共 IP,我能够将他们以前使用的静态公共 IP 映射到我们的 Cloud NAT 配置文件,现在它们上的节点和 POD 都在出站时被 NAT 到 Cloud NAT IP 池!酷! 你们知道2019年有什么变化吗? :)【参考方案2】:

这里的想法是,如果您对集群使用原生 VPC(IP 别名),your pods will not use SNAT when routing out of the cluster。如果没有 SNAT,pod 将不会使用节点的外部 IP,因此应该使用 Cloud NAT。

很遗憾,目前情况并非如此。虽然 Cloud NAT 仍处于 Beta 阶段,但某些设置尚未完全到位,因此即使使用 IP 别名,Pod 仍在使用 SNAT。由于节点 IP 的 SNAT,Pod 不会使用 Cloud NAT。

话虽如此,为什么不使用私有集群呢?它更安全,可以与 Cloud NAT 一起使用。您不能直接通过 SSH 连接到节点,但是 A) 您可以在项目中创建一个堡垒 VM 实例,该实例可以SSH using the internal IP flag 和 B) 在大多数情况下您通常不需要通过 SSH 连接到节点。

【讨论】:

谢谢,我确实想知道为什么即使启用了 IP 别名也不使用 Cloud NAT。看起来我们唯一的选择是切换到私有集群或自己部署一个 nat 网关。 自从私有集群进入 Beta 版以来,我只使用过它们,而且非常棒,尤其是 Cloud NAT 的易用性 @PatrickW 你如何使用私有集群处理kubectl 主端点仍然可以公开公开,即使使用私有集群也是如此。如果您知道您只会在同一个 VPC 中管理集群,请继续删除外部终端节点。否则,请保留外部端点并使用主授权网络来保护它【参考方案3】:

将 google 的 Cloud NAT 与公共 GKE 集群一起使用!

首先需要使用保留的外部 IP 设置云 NAT 网关和路由器。

完成后,需要将 ip-masq-agent 配置更改为为集群内部请求目标的外部 IP 伪装 pod IP。在 ip-masq-agent 的 ConfigMap 中的 nonMasqueradeCidrs 列表中更改配置。

其工作方式是,对于每个对nonMasqueradeCidrs 列表中 IP 的传出请求,都不会进行 IP 伪装。所以请求似乎不是来自节点 IP,而是来自 pod IP。然后,此内部 IP 将由 Cloud NAT 网关/路由器自动进行 NAT。结果是请求似乎来自云 NAT 路由器的(稳定)IP。

来源:

https://rajathithanrajasekar.medium.com/google-cloud-public-gke-clusters-egress-traffic-via-cloud-nat-for-ip-whitelisting-7fdc5656284a https://cloud.google.com/kubernetes-engine/docs/how-to/ip-masquerade-agent

【讨论】:

【参考方案4】:

这可能对某人有帮助:

您可以简单地使用版本 TF 11 运行这个 terraform 脚本。它将创建 VM 并将其用作 NAT 网关并通过它路由所有公共 VM 流量。

https://github.com/GoogleCloudPlatform/terraform-google-nat-gateway/tree/master/examples/gke-nat-gateway

对于生产用例,还有 HA 设置:

https://github.com/GoogleCloudPlatform/terraform-google-nat-gateway/tree/master/examples/ha-nat-gateway

【讨论】:

以上是关于为公共 GKE 集群设置 Cloud NAT的主要内容,如果未能解决你的问题,请参考以下文章

使用私有 IP 从不同 VPC 网络中的 GKE 集群连接到 Cloud SQL

使用 terraform 将公共 GKE 更改为私有 GKE 集群

如何建立从GAE(具有公共访问权限)到私有GKE集群的安全连接。

Terraformed 私有 GKE 集群自动化访问

使用 GCP Cloud *** 在站点到站点 *** 用例中将 GKE 集群 pod IP 地址隐藏在单个 IP 地址后面

在创建 GKE 集群时启用自动扩缩