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

时间:2019-01-07 05:40:39

标签: 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上拥有自己的公共IP,并且正在侦听端口80-443:

auto load balancer

对负载均衡器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
<

如果我进入GKE节点,则可以看到kube-proxy在服务nodePorts(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的任何内容。

2 个答案:

答案 0 :(得分:2)

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

网络负载平衡器将流量重定向到群集中的节点,而无需修改数据包-端口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无需分配NodePort即可使LoadBalancer正常工作

这也解释了为什么GKE创建一个自动防火墙规则,该规则允许从0.0.0.0/0到节点上端口80/443的流量。负载均衡器不会重写数据包,因此防火墙需要允许来自任何位置的流量到达节点上的iptables,然后将其重写。

答案 1 :(得分:1)

要了解LoadBalancer服务,您首先必须使用NodePort服务。这些工作的方式是在群集中的每个节点上都有一个代理(通常实际上已经针对perf在iptables或ipvs中实现,但是这是实现细节),并且在创建NodePort服务时,它会选择一个未使用的端口并设置每个这些代理之一可将数据包转发到您的Kubernetes Pod。 LoadBalancer服务建立在此之上,因此在GCP / GKE上,它会创建GCLB转发规则,将请求的端口映射到所有这些节点级代理的轮换。因此,GCLB监听端口80,该端口代理一个随机节点上的某个随机端口,该端口代理您的Pod上的内部端口。

该过程比该过程更具可定制性,但这是基本的默认设置。