Вопрос или проблема
Я настроил окружение K3S Kubernetes в своей частной домашней лаборатории на Raspberry PIs для того, чтобы научиться использовать Kubernetes (новичок), применяя NGINX в качестве контроллера входящего трафика, и я как-то застрял на этапе передачи реального IP запросов в целевые поды, в моем случае — экземпляр Nextcloud. Версия K3S — v1.22.5+k3s1
.
K3S был настроен с использованием Docker в качестве среды выполнения контейнеров и с опцией --no-deploy traefik
.
После этого я развернул контроллер входящего трафика NGINX, используя
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.0/deploy/static/provider/baremetal/deploy.yaml
Затем, после развертывания подов Nextcloud, я развернул входящий трафик:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
annotations:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
tls:
- hosts:
- my.own-dns.org
secretName: very-secret-ssl-secret
ingressClassName: nginx
rules:
- host: my.own-dns.org
http:
paths:
- path: /somepath
pathType: Prefix
backend:
service:
name: someservice-service
port:
number: 8081
- path: /
pathType: Prefix
backend:
service:
name: nextcloud-service
port:
number: 80
В развертывании IngressController я добавил следующие записи в ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
labels:
helm.sh/chart: ingress-nginx-4.0.10
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 1.1.0
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: controller
name: ingress-nginx-controller
namespace: ingress-nginx
data:
allow-snippet-annotations: 'true'
compute-full-forwarded-for: 'true'
use-forwarded-headers: 'true'
enable-real-ip: 'true'
proxy-add-original-uri-header: 'true'
forwarded-for-header: 'X-Forwarded-For'
и изменил ServiceType сервиса http на LoadBalancer
, поэтому мой сервис IngressController выглядит так:
apiVersion: v1
kind: Service
metadata:
annotations:
labels:
helm.sh/chart: ingress-nginx-4.0.10
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 1.1.0
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: controller
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
type: LoadBalancer
ipFamilyPolicy: SingleStack
ipFamilies:
- IPv4
ports:
- name: http
port: 80
protocol: TCP
targetPort: http
appProtocol: http
- name: https
port: 443
protocol: TCP
targetPort: https
appProtocol: https
selector:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/component: controller
Пока все хорошо, доступ к экземпляру Nextcloud из интернета работает отлично, включая перенаправление на https и т.д. Но в журнале аудита Nextcloud регистрируется только внутренний IP-кластер в качестве IP-источника (удивительно, но это не IP какого-либо сервиса, который я запускаю внутри кластера), а не реальный из внешнего мира.
Что я упускаю? Я пытался установить use-proxy-protocol
в true, но это приводит к ERR_CONNECTION_RESET
.
Вы пробовали установить spec.externalTrafficPolicy в local? Посмотрите документацию Kubernetes о последствиях.
Ответ или решение
Введение
Ваша задача — настроить корректную передачу реального IP-адреса пользователя через NGINX в Kubernetes-кластере K3S, развернутом в домашней лаборатории на Raspberry Pi. На данный момент ваше приложение Nextcloud получает внутренние кластерационные IP-адреса вместо реального IP-адреса клиента, и вы хотите исправить это. Давайте разберемся, как это сделать.
Теория
Для начала стоит обсудить, почему в вашей конфигурации IP-адреса клиента подменяются на внутренние кластерационные. Это поведение связано с уровнем абстракции и маршрутизации в Kubernetes. Пакеты, поступающие извне, проходят через несколько сетевых слоев, и на их пути становятся NAT’ированными для работы с внутренними резолверами или службами.
Одним из решений этой проблемы является обеспечение правильной работы capture-заголовков, таких как X-Forwarded-For
, которые стандартно используются для передачи реальных IP-адресов клиента через прокси. Не менее важным аспектом является настройка параметров, таких как externalTrafficPolicy
, который может значительно повлиять на фиксирование реальных пользовательских IP.
Пример
Рассмотрим ваш текущий YAML манифест для NGINX Controller и варианты внесения изменений:
-
externalTrafficPolicy: Local
Измените параметр
spec.externalTrafficPolicy
для вашего Ingress Service наLocal
. Это установка позволит службам сохранять исходный IP-адрес, поскольку трафик больше не будет проходить через внутренний узел API, который меняет IP на внутренний.apiVersion: v1 kind: Service metadata: name: ingress-nginx-controller namespace: ingress-nginx spec: type: LoadBalancer externalTrafficPolicy: Local ports: - name: http port: 80 protocol: TCP targetPort: http appProtocol: http - name: https port: 443 protocol: TCP targetPort: https appProtocol: https selector: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/component: controller
-
Проверка заголовков X-Forwarded-For
Убедитесь, что конфигурация включена для использования правильных заголовков. Ваша конфигурация для
use-forwarded-headers
иenable-real-ip
— это правильный шаг, но также важно, чтобы вы настраивали правильное поведение для Forwarded заголовков.Убедитесь, что ваш бэкенд-приложение (Nextcloud) также настроено для чтения и обработки информации
X-Forwarded-For
. -
Прокси-протокол
Вы упомянули о попытках применения
use-proxy-protocol
, которые закончились неудачей. Данная функция требует дополнительных настроек и поддержки как со стороны бэкенда, так и со стороны прокси-конфигураций. Если эта функция вам необходима, убедитесь, что вы изменили конфигурацию внешнего балансира нагрузки, чтобы он правильно использовал прокси-протокол.
Применение
-
Обновите YAML файл вашего сервисного ресурса, используя
externalTrafficPolicy: Local
, чтобы NGINX начал использовать реальный IP клиента. -
Перезапустите или примените обновления к существующему контроллеру Ingress.
-
Проверьте логи вашего приложения Nextcloud, чтобы убедиться, что они теперь получают реальный IP-адрес клиента.
-
Если обнаружите, что ваши изменения не приводят к желаемым результатам, рассмотрите возможность использования инструментов сетевой диагностики, таких как
kubectl logs
,tcpdump
для проверки сетевого трафика и заголовков на разных этапах маршрутизации.
Заключение
Правильная настройка заголовков и политика трафика — это важные элементы для корректной работы реального IP-адреса клиента в кластере Kubernetes. Вышеперечисленные рекомендации помогут вам добиться желаемой конфигурации, где приложение Lexcloud сможет правильно идентифицировать IP-адреса. Убедитесь в совместимости всех конфигураций как на уровне инграції, так и на уровне общения между прокси и конечными сервисами.