kubernetes - GCP 负载均衡器如何将流量路由到 GKE 服务?

标签 kubernetes google-cloud-platform google-kubernetes-engine

我是 GCP 的新手(< 1 年),我仍在将各种服务映射到我现有的网络心智模型上。

我努力填补的知识空白是如何将 HTTP 请求负载均衡到我们的 GKE 集群中运行的服务。

在测试集群上,我在服务于 HTTP 的 pod 前面创建了一个服务:

apiVersion: v1
kind: Service
metadata:
  name: contour
spec:
 ports:
 - port: 80
   name: http
   protocol: TCP
   targetPort: 8080
 - port: 443
   name: https
   protocol: TCP
   targetPort: 8443
 selector:
   app: contour
 type: LoadBalancer

该服务正在监听节点端口 30472 和 30816。:

$ kubectl get svc contour
NAME      TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
contour   LoadBalancer   10.63.241.69   35.x.y.z   80:30472/TCP,443:30816/TCP   41m

系统会自动为我创建一个 GCP 网络负载平衡器。它在 35.x.y.z 有自己的公共(public) IP,并且正在监听端口 80-443:

auto load balancer

Curling 负载均衡器 IP 有效:

$ curl -q -v 35.x.y.z
* TCP_NODELAY set
* Connected to 35.x.y.z (35.x.y.z) port 80 (#0)
> GET / HTTP/1.1
> Host: 35.x.y.z
> User-Agent: curl/7.62.0
> Accept: */*
> 
< HTTP/1.1 404 Not Found
< date: Mon, 07 Jan 2019 05:33:44 GMT
< server: envoy
< content-length: 0
<

如果我通过 ssh 进入 GKE 节点,我可以看到 kube-proxy 正在监听服务节点端口(30472 和 30816),并且没有套接字监听端口 80 或 443:

# netstat -lntp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 127.0.0.1:20256         0.0.0.0:*               LISTEN      1022/node-problem-d 
tcp        0      0 127.0.0.1:10248         0.0.0.0:*               LISTEN      1221/kubelet        
tcp        0      0 127.0.0.1:10249         0.0.0.0:*               LISTEN      1369/kube-proxy     
tcp        0      0 0.0.0.0:5355            0.0.0.0:*               LISTEN      297/systemd-resolve 
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      330/sshd            
tcp6       0      0 :::30816                :::*                    LISTEN      1369/kube-proxy     
tcp6       0      0 :::4194                 :::*                    LISTEN      1221/kubelet        
tcp6       0      0 :::30472                :::*                    LISTEN      1369/kube-proxy     
tcp6       0      0 :::10250                :::*                    LISTEN      1221/kubelet        
tcp6       0      0 :::5355                 :::*                    LISTEN      297/systemd-resolve 
tcp6       0      0 :::10255                :::*                    LISTEN      1221/kubelet        
tcp6       0      0 :::10256                :::*                    LISTEN      1369/kube-proxy

两个问题:

  1. 假设节点上没有任何内容正在监听端口 80 或 443,负载均衡器是否将流量定向到端口 30472 和 30816?
  2. 如果负载均衡器接受 80/443 上的流量并转发到 30472/30816,我在哪里可以看到该配置?在负载均衡器屏幕上四处点击,我看不到端口 30472 和 30816 的任何提及。

最佳答案

我想我找到了自己问题的答案 - 任何人都可以确认我在正确的轨道上吗?

网络负载均衡器将流量重定向到集群中的节点而不修改数据包 - 端口 80/443 的数据包在到达节点时仍然具有端口 80/443。

节点上的端口 80/443 上没有任何监听。然而,kube-proxy 编写了 iptables 规则,将数据包匹配到 负载均衡器 IP,并使用适当的 ClusterIP 和端口重写它们:

可以看到节点上的iptables配置:

$ iptables-save | grep KUBE-SERVICES | grep loadbalancer                                                                                                            
-A KUBE-SERVICES -d 35.x.y.z/32 -p tcp -m comment --comment "default/contour:http loadbalancer IP" -m tcp --dport 80 -j KUBE-FW-D53V3CDHSZT2BLQV                                                                 
-A KUBE-SERVICES -d 35.x.y.z/32 -p tcp -m comment --comment "default/contour:https loadbalancer IP" -m tcp --dport 443 -j KUBE-FW-J3VGAQUVMYYL5VK6  

$ iptables-save | grep KUBE-SEP-ZAA234GWNBHH7FD4
:KUBE-SEP-ZAA234GWNBHH7FD4 - [0:0]
-A KUBE-SEP-ZAA234GWNBHH7FD4 -s 10.60.0.30/32 -m comment --comment "default/contour:http" -j KUBE-MARK-MASQ
-A KUBE-SEP-ZAA234GWNBHH7FD4 -p tcp -m comment --comment "default/contour:http" -m tcp -j DNAT --to-destination 10.60.0.30:8080

$ iptables-save | grep KUBE-SEP-CXQOVJCC5AE7U6UC
:KUBE-SEP-CXQOVJCC5AE7U6UC - [0:0]
-A KUBE-SEP-CXQOVJCC5AE7U6UC -s 10.60.0.30/32 -m comment --comment "default/contour:https" -j KUBE-MARK-MASQ
-A KUBE-SEP-CXQOVJCC5AE7U6UC -p tcp -m comment --comment "default/contour:https" -m tcp -j DNAT --to-destination 10.60.0.30:8443

一个有趣的暗示是 nodePort 已创建但似乎未被使用。这与 kube docs 中的这条评论相匹配:

Google Compute Engine does not need to allocate a NodePort to make LoadBalancer work

它还解释了为什么 GKE 创建一个自动防火墙规则,允许从 0.0.0.0/0 到节点上的端口 80/443 的流量。负载均衡器不会重写数据包,因此防火墙需要允许来自任何地方的流量到达节点上的 iptables,并在那里重写。

关于kubernetes - GCP 负载均衡器如何将流量路由到 GKE 服务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54069030/

相关文章:

Kubernetes pod 未启动

Kubernetes 1.13,CoreDNS - 集群 curl 服务?

kubernetes:来自服务器的错误(禁止):即使在授予权限后,用户 "system:anonymous"也无法列出集群范围内的节点

kubernetes - "Limits"在 Kubernetes 集群中部署容器时忽略属性

google-cloud-platform - gcloud auth 登录抛出错误 : gcloud crashed (ConnectionError): HTTPSConnectionPool(host ='oauth2.googleapis.com' , 端口 = 443):超过最大重试次数

docker - k8s中如何等待其他容器完成执行?

kubernetes - 如何将启用 SSL 的 Cassandra 集群配置为 cassandra-reaper 的后端存储?

google-cloud-platform - Pub/Sub 出现超过截止日期错误

docker - 在 kubernetes (GKE) 上手动删除未使用的图像

kubernetes - 如何删除 Kubeflow 集群?