【问题标题】:How do GCP load balancers route traffic to GKE services?GCP 负载平衡器如何将流量路由到 GKE 服务?
【发布时间】:2019-01-07 05:40:38
【问题描述】:

我对 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:

卷曲负载均衡器 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 的任何提及。

【问题讨论】:

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


    【解决方案1】:

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

    网络负载平衡器将流量重定向到集群中的节点而不修改数据包 - 端口 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,并在那里重写。

    【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 谢谢! LoadBalancer 如何知道将流量发送到哪个节点端口?我在 LoadBalancer 配置中的任何地方都看不到它们
    • 每个 LoadBalancer 服务在底层也是一个 NodePort 服务 :)
    • 抱歉我的评论不清楚 - 我主要对 GCP 网络负载均衡器如何配置以访问服务感兴趣,因为它们似乎没有转发到 NodePort。经过进一步研究,我添加了一个我希望是准确的答案。
    猜你喜欢
    • 1970-01-01
    • 2021-01-27
    • 1970-01-01
    • 2020-04-11
    • 2020-06-09
    • 1970-01-01
    • 1970-01-01
    • 2021-12-03
    • 2019-11-14
    相关资源
    最近更新 更多