Как настроить kube-proxy для обслуживания только с локального узла
Мне нужно настроить kube-proxy на сервер из модулей, запущенных только на текущем узле, и избегать смещения соединений между различными узлами.
2 ответа
Нашел решение в документах:
Начиная с версии Kubernetes 1.5, пакеты, отправляемые в Сервисы с Type=NodePort, по умолчанию являются исходными. Вы можете проверить это, создав службу NodePort:
$ kubectl expose deployment source-ip-app --name=nodeport --port=80 --target-port=8080 --type=NodePort
service/nodeport exposed
$ NODEPORT=$(kubectl get -o jsonpath="{.spec.ports[0].nodePort}" services nodeport)
$ NODES=$(kubectl get nodes -o jsonpath='{ $.items[*].status.addresses[?(@.type=="ExternalIP")].address }')
Если вы работаете на облачном провайдере, вам может потребоваться открыть правило брандмауэра для узлов: portport, описанный выше. Теперь вы можете попытаться связаться с Сервисом из-за пределов кластера через выделенный выше порт узла.
$ for node in $NODES; do curl -s $node:$NODEPORT | grep -i client_address; done
client_address=10.180.1.1
client_address=10.240.0.5
client_address=10.240.0.3
Обратите внимание, что это не правильные клиентские IP-адреса, это кластерные внутренние IP-адреса. Вот что происходит: клиент отправляет пакет на узел 2: узел узла 2 заменяет IP-адрес источника (SNAT) в пакете своим собственным IP-адресом. Узел 2 заменяет IP-адрес назначения на пакете, а пакет IP-пакетов направляется на узел 1, а затем в конечную точку ответ модуля направляется обратно на узел 2 ответ модуля отправляется обратно клиенту
Визуально:
client
\ ^
\ \
v \
node 1 <--- node 2
| ^ SNAT
| | --->
v |
endpoint
Чтобы избежать этого, у Kubernetes есть функция для сохранения IP-адреса источника клиента (проверьте наличие этой возможности здесь). Установка для service.spec.externalTrafficPolicy значения Local будет выполнять только прокси-запросы к локальным конечным точкам, никогда не перенаправляя трафик на другие узлы и тем самым сохраняя исходный IP-адрес источника. Если локальных конечных точек нет, пакеты, отправленные на узел, отбрасываются, поэтому вы можете полагаться на правильный исходный IP-адрес в любых правилах обработки пакетов, которые вы можете применить для передачи пакета к конечной точке. Установите поле service.spec.externalTrafficPolicy следующим образом:
$ kubectl patch svc nodeport -p '{"spec":{"externalTrafficPolicy":"Local"}}'
service/nodeport patched
Теперь повторите тест:
$ for node in $NODES; do curl --connect-timeout 1 -s $node:$NODEPORT | grep -i client_address; done
client_address=104.132.1.79
Обратите внимание, что вы получили только один ответ с правильным IP-адресом клиента от одного узла, на котором работает модуль конечной точки. Вот что происходит: клиент отправляет пакет на узел2: узел-порт, у которого нет конечных точек, пакет отбрасывается, клиент отправляет пакет на узел1: узел-порт, который имеет конечные точки, узел1 направляет пакет в конечную точку с правильным исходным IP-адресом
Визуально:
client
^ / \
/ / \
/ v X
node 1 node 2
^ |
| |
| v
endpoint
Ссылаясь на документацию, используйте флаг:
--bind-address 127.0.0.1
Для этого флага вам нужно добавить скрипт запуска kube-proxy. Для systemd он хранится здесь:
/etc/systemd/system/kube-proxy.service
чем перезапустить сервис kube-proxy:
systemctl restart kube-proxy