Как читать IP-адреса клиентов из HTTP-запросов за услугами Kubernetes?
мое веб-приложение работает как модуль Kubernetes за обратным прокси-сервером nginx для SSL. Как прокси, так и мое приложение используют службы Kubernetes для балансировки нагрузки (как описано здесь).
Проблема в том, что во всех моих журналах HTTP-запросов отображаются только IP-адреса внутреннего кластера вместо адресов фактических HTTP-клиентов. Есть ли способ заставить службы Kubernetes передавать эту информацию на мои серверы приложений?
Ответы
Ответ 1
Вы можете получить kube-proxy из цикла полностью двумя способами:
Ответ 2
Начиная с версии 1.5, если вы работаете в GCE (с расширением GKE) или AWS, вам просто нужно добавить аннотацию к вашей службе, чтобы обеспечить сохранение источника HTTP.
...
kind: Service
metadata:
annotations:
service.beta.kubernetes.io/external-traffic: OnlyLocal
...
В основном он предоставляет сервис напрямую через порты узлов, а не предоставляет прокси-сервер - выставляя проверку работоспособности на каждом узле, балансировщик нагрузки может определить, на какие узлы направлять трафик.
В версии 1.7 эта конфигурация стала GA, поэтому вы можете установить "externalTrafficPolicy": "Local"
в своей спецификации сервиса.
Нажмите сюда, чтобы узнать больше
Ответ 3
Прямо сейчас, нет.
Службы используют kube_proxy для распространения трафика на свои серверы. Kube-proxy использует iptables для маршрутизации IP-адреса службы в локальный порт, где он прослушивает, а затем открывает новое соединение с одним из серверов. Внутренний IP-адрес, который вы видите, это IP-порт kube-proxy, работающий на одном из ваших узлов.
Только kipt-прокси iptables в работе. Это сохранит исходный IP-адрес источника.
Ответ 4
Как и в случае с Kubernetes 1.1, существует kube-прокси, основанный на iptables, который исправляет эту проблему в некоторых случаях. Он отключен по умолчанию; см. этот пост для получения инструкций по его включению. В заключение сделаем:
for node in $(kubectl get nodes -o name); do kubectl annotate $node net.beta.kubernetes.io/proxy-mode=iptables; done
В случае трафика Pod-to-Pod с помощью kube-proxy iptables вы теперь увидите истинный источник-IP в целевом контейнере.
Однако, если ваша Служба перенаправляет трафик извне кластера (например, NodePort, Служба LoadBalancer), нам все равно придется заменить (SNAT) исходный IP. Это связано с тем, что мы делаем DNAT на входящем трафике, чтобы перенаправить его в сервис Pod (возможно, на другой Node), поэтому DNATing Node необходимо вставить в обратный путь, чтобы иметь возможность un-DNAT ответ.
Ответ 5
Для запросов, отличных от HTTP (HTTPS, gRPC и т.д.), это планируется в Kubernetes 1.4. См.: https://github.com/kubernetes/features/issues/27
Ответ 6
externalTrafficPolicy: Local
Это параметр, который можно указать в списке служб Kubernetes типа балансировки нагрузки или типа NodePort. (Входные контроллеры обычно включают yaml для предоставления LB-сервисов.)
externalTrafficPolicy: Local
Делает 3 вещи:
1. Отключает SNAT, чтобы вместо модуля входного контроллера, рассматривая IP-адрес источника в качестве IP-адреса узла Kubernetes, предполагал, что IP-адрес реального источника.
2. Избавляется от дополнительного сетевого перехода, добавляя 2 правила:
-if трафик попадает в порт узла без входных модулей, которые он отбрасывает.
-if трафик попадает в порт узла узла, а входящие модули отправляют его в модуль на том же узле.
3. Обновляет Cloud Load Balancers HealthCheck с конечной точкой /healthz, которая должна была сделать это так, чтобы LB не перенаправлял к узлам, если бы он был отброшен, и только к узлам с входными модулями.
(Перефразируя для пояснения: по умолчанию, иначе "externalTrafficPolicy: Cluster", трафик распределяется по нагрузке между узлами NodePorts каждого рабочего узла. "externalTrafficPolicy: Local" позволяет отправлять трафик только подмножеству узлов, имеющих блоки Ingress Controller). поэтому если у вас есть кластер из 100 узлов, а не балансировщик нагрузки облака, отправляющий трафик на 97 узлов, он будет отправлять его только на ~ 3-5 узлов, на которых выполняются модули Ingress Controller)
Важное примечание !:
"externalTrafficPolicy: Local" не поддерживается в AWS.
(Предположительно, он отлично работает на GCP и Azure, и, как говорится, я также вспоминаю, что читал, что в минорной версии Kubernetes 1.14 + была регрессия, которая нарушала некоторые версии Cilium CNI, где он также ломался, так что имейте в виду, что по умолчанию externalTrafficPolicy: Cluster стабильно стабильный и, как правило, предпочтительнее, если вам не нужны функциональные возможности. Также имейте в виду, что если у вас есть WAF в качестве службы в любом случае, то вы можете использовать это, чтобы увидеть откуда приходит клиентский трафик.)
(Это вызывает проблемы с копами и EKS, другие дистрибутивы, работающие на AWS, могут быть фактически не затронуты, подробнее об этом ниже.)
"externalTrafficPolicy: Local", не поддерживаемый в AWS, является проблемой, известной сопровождающим Kubernetes, но недостаточно документированной. Кроме того, раздражает то, что если вы попробуете это, вам повезет с этим/это будет работать, и это заставит достаточно людей думать, что это работает.
externalTrafficPolicy: локальный сбой в AWS выполняется двумя способами, и для обоих разрывов есть обходные пути, заставляющие его работать:
1-й перерыв + обходной путь: начальное создание/healthz конечной точки является ошибочным + логика цикла согласования нарушена.
При первоначальном применении он будет работать для некоторых узлов, а не для других, и никогда не будет обновляться.
https://github.com/kubernetes/kubernetes/issues/80579
^ описывает проблему более подробно.
https://github.com/kubernetes/kubernetes/issues/61486
^ описывает обходной путь, чтобы заставить его работать, используя крючок Kops
(Когда вы решаете логику цикла согласования конечной точки /healthz, вы разблокируете преимущества № 2 и № 3, меньше переходов + LB, только отправляя трафик на подмножество рабочих узлов. Но исходный IP-адрес преимущества № 1 по-прежнему не будет правильным.)
2-й перерыв + 2 варианта обхода:
Желаемый конечный результат - входной модуль, который видит истинный IP-адрес клиента.
Но на самом деле произошло то, что входной модуль сместился с просмотра исходного IP-адреса узла k8s на просмотр исходного IP-адреса Классического ELB.
Обходной вариант 1.)
Переключитесь на сетевой LB (L4 LB), который больше работает как Azure LB. Это связано с тем, что вы не можете использовать ACM (Менеджер сертификатов AWS) для прекращения использования TLS при подготовке и ротации сертификатов TLS AWS LB/handle.
вариант 2).
Продолжайте использовать классический ELB AWS (и вы продолжите использовать ACM), вам просто нужно добавить конфигурацию к обоим классическим ELB (в форме аннотации службы LB) + добавить конфигурацию для входного контроллера. Так что оба используют прокси-протокол или x forward заголовки, я вспоминаю еще один пост Qaru, посвященный этому, поэтому я не буду повторять его здесь.
Ответ 7
Для kubernetes 1. 7+ установите service.spec.externalTrafficPolicy
в Local
, чтобы разрешить его.
Более подробная информация здесь: Документы Kubernetes