使用外部代理连接到 Internet 时路由到 GKE 时出现问题

Problems routing to GKE when using an external proxy to the internet

当从相当普通的 GKE 安装中的 pod 请求时,我似乎遇到了进出公司出口代理之外的站点的路由问题。我已经在有和没有 istio 网格的 GKE 集群上尝试过这个。

这是我的观察。

从 GKE 实例所在的同一 GCP 子网上的虚拟机,我可以 运行 以下内容并获得预期的响应:

$ https_proxy=$PROXY_DNS:$PROXY_PORT curl https://en.wikipedia.org/wiki/Main_Page | grep -o "<title>.*</title>"
<title>Wikipedia, the free encyclopedia</title>

如果我 ssh 到 GKE 实例的一个节点,我可以 运行 相同的请求并获得预期的响应。

但是,如果我在 GKE 实例(在这种情况下使用 istio 网格)中的 pod 上获得 shell 并且 运行 以下 curl 具有详细输出,我见:

$ HTTPS_PROXY=$PROXY_DNS:$PROXY_PORT curl -v https://en.wikipedia.org/wiki/Main_Page | grep -o "<title>.*</title>"
* Uses proxy env variable HTTPS_PROXY == '<PROXY_DNS value>:<PROXY_PORT value>'
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0*   Trying <IP of PROXY_DNS>:<PROXY_PORT value>...
* Connected to <PROXY_DNS value> (<IP of PROXY_DNS>) port <PROXY_PORT value> (#0)
* allocate connect buffer!
* Establish HTTP proxy tunnel to en.wikipedia.org:443
> CONNECT en.wikipedia.org:443 HTTP/1.1
> Host: en.wikipedia.org:443
> User-Agent: curl/7.82.0-DEV
> Proxy-Connection: Keep-Alive
> 
  0     0    0     0    0     0      0      0 --:--:--  0:00:09 --:--:--     0* Recv failure: Connection reset by peer
* Received HTTP code 0 from proxy after CONNECT
* CONNECT phase completed!
* Closing connection 0
curl: (56) Recv failure: Connection reset by peer

在这种情况下,似乎通过代理成功连接到维基百科,但没有收到 return。

如果我在 GKE 实例中的 pod 上获得 shell(在这种情况下没有 istio 网格)和 运行 相同的 curl,我会看到以下内容:

# HTTPS_PROXY=$PROXY_DNS:$PROXY_PORT curl -v https://en.wikipedia.org/wiki/Main_Page | grep -o "<title>.*</title>"
* Uses proxy env variable HTTPS_PROXY == '<PROXY_DNS value>:<PROXY_PORT value>'
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0*   Trying <IP of PROXY_DNS>...
* TCP_NODELAY set
  0     0    0     0    0     0      0      0 --:--:--  0:02:10 --:--:--     0* connect to <IP of PROXY_DNS> port <PROXY_PORT value> failed: Connection timed out
* Failed to connect to <PROXY_DNS value> port <PROXY_PORT value>: Connection timed out
* Closing connection 0
curl: (7) Failed to connect to <PROXY_DNS value> port <PROXY_PORT value>: Connection timed out

在这种情况下,curl 似乎无法访问代理。

注意:没有代理环境变量设置的curl -v https://en.wikipedia.org/wiki/Main_Page | grep -o "<title>.*</title>"在两个GKE集群中从pods成功。

所以,对于带有 istio 网格的集群,我在来自代理的 return 路径上有一个路由问题。在没有 istio 网格的集群中,我什至无法路由到代理。由于我可以成功地使用来自任一集群上的节点的代理和该 GCP 子网上的普通 VM,我在集群和它们 运行 所在的节点之间的跃点上遇到了一些问题,但我不知所措至于哪里出了问题。

我正在寻找从 GKE 集群到代理的路由问题的解决方案,因为我怀疑这只是我集群设置中的一些问题。

tl;dr;

这是设置的详细信息。我已经建立了一个从 GCP 中的项目到 AWS 的 VPN,并通过结合这两个 posts:

在 AWS 中设置了一个 VPC 代理

从 GCP 子网上的 vanilla VM 成功使用代理以及从 GKE 实例的节点成功使用代理表明设置运行良好。我从这些结果中得知,从子网到 VPN 并通过(squid)代理的路由正在运行。

我首先设置了 vanilla GKE 实例并尝试了一些 posts 来让它工作,包括:

在对这些 post 进行了大量工作之后,我仍然从该集群中得到了上述结果。即无法访问代理。

然后我尝试设置另一个 GKE 集群并使用 istio 网格。我遵循了以下 post:

这个 post 演示了在不同命名空间但在同一个 Kubernetes(在我的例子中是 GKE)集群上使用 Squid 代理并路由到它 'externally'。我从这个开始,并且能够使用 default 命名空间中的 external 命名空间中的代理,如 post 中所述。在证明可以在 external 命名空间中使用代理后,我尝试在 VPN 的另一端使用在 AWS 中设置的代理。如上文所述,请求进一步增加,但似乎从节点到 pod 的 return 路径没有成功。

我们已经找到解决上述问题的方法。我们设置的 GKE 集群在 pod IP 地址离开节点进入更广泛的网络时,默认情况下不会进行 IP 伪装。可以在 GKE 中找到有关 IP 伪装代理的信息 here. The configuration of the agent is described here. (NOTE this is for regular clusters, auto pilot clusters have a specific configuration page,但我们没有关注这个,所以 YMMV。)

我们能够使用给定的 daemonset 示例而无需更改,并且在 configmap 中,我们将 nonMasqueradeCIDRs 设置为 pod 范围和集群子网范围的数组。

一旦我们应用了配置映射和守护程序集,pods 上的工作负载就可以使用代理设置并通过代理路由到目标站点并成功返回。此外,如果不使用代理设置,请求将路由出 GCP 互联网网关,在我们的案例中,该网关可从 GKE 集群所在的子网获得。