Для реализации ALB средствами NGINX Ingress controller используется модуль ingress-nginx.
Модуль ingress-nginx устанавливает NGINX Ingress controller и управляет им с помощью кастомных ресурсов.
Если узлов для размещения Ingress-контроллера больше одного, он устанавливается в отказоустойчивом режиме, с учётом особенностей инфраструктуры как облачных, так и bare-metal сред, а также различных типов Kubernetes-кластеров.
Поддерживается одновременный запуск нескольких экземпляров Ingress-контроллеров с независимой конфигурацией: одного основного и произвольного количества дополнительных. Это, например, позволяет разделять внешние и внутренние (intranet) Ingress-ресурсы приложений.
Варианты терминации трафика
Трафик к ingress-nginx может быть отправлен несколькими способами:
- напрямую, без использования внешнего балансировщика;
- через внешний LoadBalancer, в том числе поддерживаются:
- Qrator,
- Cloudflare,
- AWS LB,
- GCE LB,
- ACS LB,
- Yandex LB,
- OpenStack LB.
Терминация HTTPS
Для каждого экземпляра NGINX Ingress Controller можно настраивать политики безопасности HTTPS, включая:
- параметры HSTS;
- набор доступных версий SSL/TLS и протоколов шифрования.
Также модуль интегрирован с модулем cert-manager, при взаимодействии с которым возможны автоматический заказ SSL-сертификатов и их дальнейшее использование Ingress-контроллерами.
Мониторинг и статистика
В этой реализации ingress-nginx добавлена система сбора статистики в Prometheus с множеством метрик:
- по длительности времени всего ответа и апстрима отдельно;
- кодам ответа;
- количеству повторов запросов (retry);
- размерам запроса и ответа;
- методам запросов;
- типам
content-type; - географии распределения запросов и т. д.
Данные представлены в нескольких разрезах:
namespace;vhost;ingress-ресурсы;location(в nginx).
Все графики сгруппированы в дашборды Grafana. Реализована возможность drill-down: например, при просмотре статистики по namespace можно перейти по ссылке на соответствующий дашборд и получить детализированные данные по vhosts в этом namespace — и далее по иерархии.
Статистика
Основные принципы сбора статистики
- На стадии
log_by_lua_blockдля каждого запроса вызывается модуль, который рассчитывает необходимые данные и складывает их в буфер (у каждого NGINX worker свой буфер). - На стадии
init_by_lua_blockдля каждого NGINX worker запускается процесс, который раз в секунду асинхронно отправляет данные в форматеprotobufчерез TCP socket вprotobuf_exporter(разработка Deckhouse Kubernetes Platform). protobuf_exporterзапускается sidecar-контейнером в поде с ingress-controller, принимает сообщения в форматеprotobuf, разбирает, агрегирует их по установленным нами правилам и экспортирует в формате для Prometheus.- Prometheus каждые 30 секунд собирает метрики как в ingress-controller (там есть небольшое количество нужных метрик), так и
protobuf_exporter. На основе этих данных строится статистика.
Состав и представление метрик
У всех собираемых метрик есть служебные лейблы, идентифицирующие экземпляр контроллера: controller, app, instance и endpoint (они видны в /prometheus/targets).
- Все метрики (кроме geo), экспортируемые через
protobuf_exporter, представлены в трех уровнях детализации:ingress_nginx_overall_*— агрегированные метрики верхнего уровня (без детализации, у всех метрик есть лейблыnamespace,vhostиcontent_kind);ingress_nginx_detail_*— кроме лейблов уровня overall, добавляютсяingress,service,service_portиlocation;ingress_nginx_detail_backend_*— ограниченная часть данных, собирается в разрезе по бэкендам. У этих метрик, кроме лейблов уровня detail, добавляется лейблpod_ip.
- Для уровней overall и detail собираются следующие метрики:
*_requests_total— общее количества запросов (дополнительные лейблы —scheme,method);*_responses_total— количество ответов (дополнительный лейбл —status);*_request_seconds_{sum,count,bucket}— гистограмма времени ответа;*_bytes_received_{sum,count,bucket}— гистограмма размера запроса;*_bytes_sent_{sum,count,bucket}— гистограмма размера ответа;*_upstream_response_seconds_{sum,count,bucket}— гистограмма времени ответа upstream-сервиса (при нескольких upstream’ах — суммарное время);*_lowres_upstream_response_seconds_{sum,count,bucket}— упрощённая гистограмма (для визуализации; не подходит для расчета квантилей);*_upstream_retries_{count,sum}— количество и суммарное число повторных запросов (retry) к бэкенду.
- Для уровня overall собираются следующие метрики:
*_geohash_total— количество запросов по geohash (дополнительные лейблы —geohash,place).
- Для уровня detail_backend собираются следующие метрики:
*_lowres_upstream_response_seconds— упрощённая гистограмма времени ответа для overall и detail;*_responses_total— количество ответов (дополнительный лейбл —status_class, а не простоstatus);*_upstream_bytes_received_sum— суммарный объём данных, полученных от бэкендов.
Примеры настройки балансировки
Для настройки балансировки используйте кастомный ресурс IngressNginxController.
Пример для AWS (Network Load Balancer)
При создании балансировщика используются все доступные в кластере зоны.
В каждой зоне балансировщик получает собственный публичный IP. Если в зоне есть экземпляр с Ingress-контроллером, A-запись с IP-адресом балансировщика из этой зоны автоматически добавляется к доменному имени балансировщика.
Если в зоне не остается экземпляров с Ingress-контроллером, тогда IP автоматически убирается из DNS.
В том случае, если в зоне всего один экземпляр с Ingress-контроллером, при перезапуске пода IP-адрес балансировщика этой зоны временно исключается из DNS.
apiVersion: deckhouse.io/v1
kind: IngressNginxController
metadata:
name: main
spec:
ingressClass: nginx
inlet: LoadBalancer
loadBalancer:
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
Пример для GCP / Yandex Cloud / Azure
apiVersion: deckhouse.io/v1
kind: IngressNginxController
metadata:
name: main
spec:
ingressClass: nginx
inlet: LoadBalancer
В GCP на узлах необходимо указать аннотацию, которая разрешает принимать подключения на внешние адреса для сервисов с типом NodePort.
Пример для OpenStack
apiVersion: deckhouse.io/v1
kind: IngressNginxController
metadata:
name: main-lbwpp
spec:
inlet: LoadBalancerWithProxyProtocol
ingressClass: nginx
loadBalancerWithProxyProtocol:
annotations:
loadbalancer.openstack.org/proxy-protocol: "true"
loadbalancer.openstack.org/timeout-member-connect: "2000"
Пример для bare metal
apiVersion: deckhouse.io/v1
kind: IngressNginxController
metadata:
name: main
spec:
ingressClass: nginx
inlet: HostWithFailover
nodeSelector:
node-role.deckhouse.io/frontend: ""
tolerations:
- effect: NoExecute
key: dedicated.deckhouse.io
value: frontend
Пример для bare metal при использовании внешнего балансировщика
Пример подходит при использовании Cloudflare, Qrator, Nginx+, Citrix ADC, Kemp и других внешних балансировщиков.
apiVersion: deckhouse.io/v1
kind: IngressNginxController
metadata:
name: main
spec:
ingressClass: nginx
inlet: HostPort
hostPort:
httpPort: 80
httpsPort: 443
behindL7Proxy: true
Пример для bare metal (MetalLB в режиме BGP LoadBalancer)
Доступно только в DKP Enterprise Edition.
apiVersion: deckhouse.io/v1
kind: IngressNginxController
metadata:
name: main
spec:
ingressClass: nginx
inlet: LoadBalancer
nodeSelector:
node-role.deckhouse.io/frontend: ""
tolerations:
- effect: NoExecute
key: dedicated.deckhouse.io
value: frontend
В случае использования MetalLB его speaker-поды должны быть запущены на тех же узлах, что и поды Ingress–контроллера.
Чтобы Ingress-контроллер получал реальные IP-адреса клиентов, его сервис должен быть создан с параметром externalTrafficPolicy: Local, исключающим межузловой SNAT. Для соблюдения этого условия MetalLB speaker анонсирует этот Service только с тех узлов, где запущены целевые поды.
Таким образом, для данного примера конфигурация модуля metallb должна быть такой:
metallb:
speaker:
nodeSelector:
node-role.deckhouse.io/frontend: ""
tolerations:
- effect: NoExecute
key: dedicated.deckhouse.io
value: frontend
Пример для bare metal (балансировщик MetalLB в режиме L2 LoadBalancer)
Доступно только в Enterprise Edition.
-
Включите модуль
metallb:apiVersion: deckhouse.io/v1alpha1 kind: ModuleConfig metadata: name: metallb spec: enabled: true version: 2 -
Создайте ресурс MetalLoadBalancerClass:
apiVersion: network.deckhouse.io/v1alpha1 kind: MetalLoadBalancerClass metadata: name: ingress spec: addressPool: - 192.168.2.100-192.168.2.150 isDefault: false nodeSelector: node-role.kubernetes.io/loadbalancer: "" # Cелектор узлов-балансировщиков. type: L2 -
Создайте ресурс IngressNginxController:
apiVersion: deckhouse.io/v1 kind: IngressNginxController metadata: name: main spec: ingressClass: nginx inlet: LoadBalancer loadBalancer: loadBalancerClass: ingress annotations: # Количество адресов, которые будут выделены из пула, описанного в MetalLoadBalancerClass. network.deckhouse.io/l2-load-balancer-external-ips-count: "3"
Платформа создаст сервис с типом LoadBalancer, которому будет присвоено заданное количество адресов:
d8 k -n d8-ingress-nginx get svc
Пример вывода:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
main-load-balancer LoadBalancer 10.222.130.11 192.168.2.100,192.168.2.101,192.168.2.102 80:30689/TCP,443:30668/TCP 11s