Как балансировщики нагрузки GCP направляют трафик на сервисы GKE? - PullRequest
0 голосов
/ 07 января 2019

Я относительно новичок (<1 года) в GCP, и я все еще в процессе сопоставления различных сервисов с моей существующей сетевой ментальной моделью. </p>

Однажды пробел в знаниях, который я пытаюсь заполнить, заключается в том, как HTTP-запросы сбалансированы по нагрузке для служб, работающих в наших кластерах GKE.

В тестовом кластере я создал службу перед модулями, которые обслуживают HTTP:

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. Он имеет собственный публичный IP-адрес 35.x.y.z и прослушивает порты 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
<

Если я 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.

Ответы [ 2 ]

0 голосов
/ 07 января 2019

Я думаю, что нашел ответ на свой вопрос - кто-нибудь может подтвердить, что я на правильном пути?

Балансировщик сетевой нагрузки перенаправляет трафик на узел в кластере без изменения пакета - пакеты для порта 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 на узле, и он переписывается там.

0 голосов
/ 07 января 2019

Чтобы понять сервисы LoadBalancer, вы должны сначала воспользоваться сервисами NodePort. То, как они работают, заключается в том, что на каждом узле в вашем кластере есть прокси-сервер (обычно фактически реализованный в iptables или ipvs, но это детали реализации), и при создании службы NodePort он выбирает неиспользуемый порт и устанавливает каждый один из этих прокси для пересылки пакетов в ваш модуль Kubernetes. Сервис LoadBalancer построен поверх этого, поэтому в GCP / GKE он создает правило пересылки GCLB, отображающее запрашиваемый порт на ротацию всех прокси уровня узла. Таким образом, GCLB прослушивает порт 80, который проксирует некоторый случайный порт на случайном узле, который проксирует внутренний порт вашего модуля.

Процесс немного более настраиваемый, но это основные настройки по умолчанию.

...