У меня есть кластер Kubernetes с внешним балансировщиком нагрузки на собственном сервере под управлением NGINX. Я пытался активировать proxy_protocol
чтобы получить real_ip
клиентов, но журналы NGINX
2020/05/11 14:57:54 [error] 29614#29614: *1325 broken header: "▒▒▒▒▒▒▒Ωߑa"5▒li<c▒*▒ ▒▒▒s▒ ▒6▒▒▒▒▒X▒▒o▒▒▒E▒▒i▒{ ▒/▒0▒+▒,̨̩▒▒ ▒▒
▒▒/5▒" while reading PROXY protocol, client: 51.178.168.233, server: 0.0.0.0:443
Вот мой файл конфигурации NGINX:
worker_processes 4;
worker_rlimit_nofile 40000;
events {
worker_connections 8192;
}
stream {
upstream rancher_servers_http {
least_conn;
server <IP_NODE_1>:80 max_fails=3 fail_timeout=5s;
server <IP_NODE_2>:80 max_fails=3 fail_timeout=5s;
server <IP_NODE_3>:80 max_fails=3 fail_timeout=5s;
}
server {
listen 80;
proxy_protocol on;
proxy_pass rancher_servers_http;
}
upstream rancher_servers_https {
least_conn;
server <IP_NODE_1>:443 max_fails=3 fail_timeout=5s;
server <IP_NODE_2>:443 max_fails=3 fail_timeout=5s;
server <IP_NODE_3>:443 max_fails=3 fail_timeout=5s;
}
server {
listen 443 ssl proxy_protocol;
ssl_certificate /certs/fullchain.pem;
ssl_certificate_key /certs/privkey.pem;
proxy_pass rancher_servers_https;
proxy_protocol on;
}
}
Вот мой configmap
для ingress-контроллера:
apiVersion: v1
data:
compute-full-forwarded-for: "true"
proxy-body-size: 500M
proxy-protocol: "true"
use-forwarded-headers: "true"
kind: ConfigMap
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: '{"apiVersion":"v1","data":null,"kind":"ConfigMap","metadata":{"annotations":{},"labels":{"app":"ingress-nginx"},"name":"nginx-configuration","namespace":"ingress-nginx"}}'
creationTimestamp: "2019-12-09T13:26:59Z"
labels:
app: ingress-nginx
name: nginx-configuration
namespace: ingress-nginx
Все работало нормально, прежде чем я добавил proxy_protocol
директива, но теперь я получил все эти broken headers
ошибок, и я не могу получить доступ к службам за входящими данными, не получив connection reset
ошибка.
Что может быть не так с моей конфигурацией?
Должен ли я использовать обратный прокси-сервер http вместо обратного прокси-сервера tcp?
Спасибо.
редактировать:
Я также должен сказать, что у меня нет службы типа LoadBalancer
в моем кластере. Должен ли я иметь один? Я думаю о Metallb, но не уверен, что он добавит в мою конфигурацию, поскольку я уже балансирую нагрузку на узлы с помощью nginx.
Nginx позволяет указать, использовать ли proxy_protocol во входящих или исходящих запросах, и вы их запутаете.
Чтобы использовать proxy_protocol в входящий соединения, вы должны добавить proxy_protocol
к listen
строка вроде этой:
listen 443 ssl proxy_protocol;
Чтобы использовать proxy_protocol в исходящий подключений, вы должны использовать автономный proxy_protocol
директива, например:
proxy_protocol on;
Они есть не тот же самый. В балансировщике нагрузки входящий подключения происходят из браузеров, которые не поддерживают протокол прокси. Вам нужен протокол прокси только в исходящих запросах к nginx-ingress в вашем кластере kubernetes.
Поэтому удалите proxy_protocol
аргумент от listen
директива, и она должна работать.
Кроме того, вы хотите use-forwarded-headers: "false"
в вашей конфигурации nginx-ingress. Это контролирует, использовать ли X-Forwarded-For
& co. заголовки в входящий подключения (с точки зрения nginx-ingress, т.е. исходящий из вашего балансировщика нагрузки), и вы используете в них протокол прокси вместо заголовков. Если он включен, ваши пользователи могут иметь возможность подделывать IP-адреса, указав X-Forwarded-For, что может быть проблемой безопасности. (только если nginx-ingress отдает приоритет заголовкам над протоколом прокси, в чем я не уверен)
Замечу: сам nginx-ingress уже распределяет нагрузку между всеми модулями. В вашей архитектуре вы используете два «уровня» балансировщиков нагрузки, что, вероятно, не нужно. Если вы хотите упростить, принудительно запускайте nginx-ingress на одном узле (с nodeSelector
например) и просто отправьте весь свой трафик на этот узел. Если вы хотите сохранить балансировщик нагрузки на выделенной машине, вы можете присоединить 4-ю машину к кластеру и убедиться, что она просто запускает nginx-ingress (с ошибками и допусками).
Кроме того, убедитесь, что вы запускаете nginx-ingress с hostNetwork: true, иначе у вас может быть еще один уровень балансировки (kube-proxy, прокси-сервер kubernetes)