Google 容器引擎 Kubernetes 服务 LoadBalancer 是否正在向无响应的主机发送流量?

Is the Google Container Engine Kubernetes Service LoadBalancer sending traffic to unresponsive hosts?

问题:由 Kubernetes(通过 Google 容器引擎)创建的 Google 云网络 LoadBalancer 是否向未监听的主机发送流量? "This target pool has no health check, so traffic will be sent to all instances regardless of their status."

我有一个针对特定 pods 并使 TCP: 80, 443 可用的服务(NGINX 反向代理)。在我的示例中,实例池中只有 1 个 NGINX pod 运行。服务类型是 "LoadBalancer"。使用 Google Container Engine 这会创建一个新的 LoadBalancer (LB),它指定目标池、特定的 VM 实例。然后创建 LB 的临时外部 IP 地址和允许传入流量的关联防火墙规则。

我的问题是Kubernetes自动生成的防火墙规则描述是"KubernetesAutoGenerated_OnlyAllowTrafficForDestinationIP_1.1.1.1"(IP是LB外网IP)。在测试中,我注意到即使每个 VM 实例都有一个外部 IP 地址,我也无法在任一实例 IP 地址的端口 80 或 443 上联系它,只能联系 LB IP。这对外部用户流量来说并不坏,但是当我尝试为我的 LB 创建健康检查时,我发现它在单独检查每个 VM 实例时总是将服务视为不可用。

我有适当的防火墙规则,因此任何 IP 地址都可以在我的池中的任何实例上联系 TCP 443、80,所以这不是问题。

谁能给我解释一下,因为这让我觉得 LB 正在将 HTTP 请求传递给两个实例,尽管其中只有一个实例上有 NGINX pod 运行。

Is the Google Cloud network LoadBalancer that's created by Kubernetes (via Google Container Engine) sending traffic to hosts that aren't listening?

所有主机(当前是 运行 功能 kube-proxy 进程)都能够接收和处理外部化服务的传入请求。请求将落在集群中的任意节点 VM 上,匹配 iptables 规则并转发(通过 kube-proxy 进程)到具有与服务匹配的标签选择器的 pod。

因此,如果您的节点 VM 运行 处于损坏状态,那么健康检查器会阻止请求被丢弃的情况。 VM 仍具有与转发规则匹配的目标标记,但无法处理传入的数据包。

In testing I've noticed that even though each VM Instance has a external IP address I cannot contact it on port 80 or 443 on either of the instance IP addresses, only the LB IP.

这是按预期工作的。每个服务都可以使用任何需要的端口,这意味着多个服务可以使用端口 80 和 443。如果数据包到达主机 IP 的端口 80,主机无法知道哪个(可能很多)服务使用端口80 数据包应该被转发到。服务的 iptables 规则处理发往虚拟内部集群服务 IP 和外部服务 IP 而不是主机 IP 的数据包。

This isn't bad for external user traffic but when I tried to create a Health Check for my LB I found that it always saw the services as unavailable when it checked each VM Instance individually.

如果您想设置健康检查来验证节点是否正常工作,您可以通过安装防火墙规则对端口 运行 上的 运行 kubelet 进程进行健康检查:

$ gcloud compute firewall-rules create kubelet-healthchecks \
  --source-ranges 130.211.0.0/22 \
  --target-tags $TAG \
  --allow tcp:10250

(查看 Container Engine HTTP Load Balancer 文档以帮助找到您应该为 $TAG 使用的内容)。

直接对 kube-proxy 进程进行健康检查会更好,但它只能 binds to localhost, whereas the kubelet process binds to all interfaces 因此健康检查器可以访问它,它应该作为节点健康的良好指标足以满足对您的服务的请求。