Как настроить 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
Другие вопросы по тегам