Ingress-контроллер: что это и как выбрать
Kubernetes — достаточно сложная для понимания вещь, даже сами авторы это признают. В этой статье мы попытаемся простым языком объяснить, что такое Ingress-контроллер и для чего он нужен.
Принцип работы Ingress-контроллера
Чтобы не запутаться в терминологии, нужно разграничить два определения.
- Ingress — сущность кластера Kubernetes, где создается описание конфигурации самого Ingress Сontroller.
- Ingress Controller — обрабатывает трафик. Его конфигурация формируется из всех Ingress внутри одного кластера.
Вместе Ingress и Ingress-контроллер создают единую точку входа для трафика и выполняют одновременно роль прокси и балансировщика нагрузки.
На ум приходит аналогия с автомобилем. Ingress — автомобиль со снятым двигателем, а Ingress-контроллер — тот самый двигатель. Если вы создадите Ingress без установленного контроллера, то ничего работать не будет.
Основная задача выбора Ingress-контроллера в том, какое именно приложение будет разруливать весь трафик. В идеале различные типы Ingress-контроллеров должны работать одинаково по спецификации, но на практике все же есть различия. Также важно понимать, что Ingress-контроллер не отменяет необходимость во внешнем балансировщике нагрузки. Он лишь добавляет дополнительный уровень маршрутизации и большую гибкость в распределении трафика.
Ingress-контроллер можно реализовать на разных платформах. Из самых популярных — Nginx и haproxy. Размещение Ingress Controller’ов может варьироваться, но обычно они используются как точки подключения к сервисам, поэтому размещаются на отдельных узлах с внешними IP-адресами.
Ingress работает на седьмом, прикладном, уровне сетевой модели OSI. Если необходимо занять третий уровень — сетевой, используйте другие способы публикации приложений из списка:
- ClusterIP,
- LoadBalancer,
- NodePort.
Внутри Ingress Controller обычный Nginx, поэтому вы можете настроить распределение запросов по доменам или location. Посмотреть все настройки можно в документации на странице Nginx Configuration.
Ingress-контроллер не отменяет необходимости во внешнем балансировщике нагрузки, он лишь добавляет дополнительный уровень маршрутизации и большую гибкость в распределении трафика.
Сервисы для трафика на Ingress-контроллер
Reverse proxy в Ingress Controller слушает порты с HTTP/HTTPS-соединениями. Трафик может попадать на порты тремя способами:
- NodePort — на случайных портах в диапазоне 30000-32767;
- HostPort — можно повесить на порты 80 или 443;
- Host Network — Pod повесит свои порты на публичном сетевом интерфейсе, в этом случае откроются все порты контейнера, что не всегда безопасно.
NodePort
Ставить Ingress Controller на NodePort без LoadBalancer — плохая практика, поскольку URL будет включать только порт, который указан в NodePort .
Для таких сценариев лучше использовать Deployments. Это позволит проще скейлить количество подов, ответственных за входящий трафик, прописывать им nodeAffinity и запускать сразу группу контроллеров.
HostPort
При использовании HostPort порт пробрасывается с хоста, где запущен под, в этот самый Pod. LoadBalancer на входе не пригодится, но для работы сайта в DNS придется указать, что адрес домена есть на всех узлах.
Пример конфигурации DNS для трех воркеров:
ingress.example.org A 10.0.0.1
ingress.example.org A 10.0.0.2
ingress.example.org A 10.0.0.3
www.example.org CNAME ingress.example.org
Для этой установки лучше использовать DaemonSet, поскольку он позволяет запустить не более одного Pod на хосте. Deployment возможен, но со своими особенностями: надо прописать affinity, чтобы не назначить пару подов на один хост. Это поможет избежать конфликта портов.
Host Network
При запуске Ingress Controller в общей сети с хостом пробрасывать порт не нужно. Но в этом случае все порты, которые открыты в Pod, будут доступны из сети. Для запуска стоит применить DaemonSet. Аналогично с HostPort, чтобы избежать конфликта портов.
Что выбрать
Если LoadBalancer есть на входе, выбирайте NodePort, если нет — HostPort и DNS Round Robin. В тестовой песочнице можно попробовать Host Network, но на боевых проектах лучше так не экспериментировать.
Популярные контроллеры
Ingress от Nginx Inc
Это стабильное решение с обратной совместимостью, высокой скоростью и без Lua-плагинов или других модулей. Бесплатная версия имеет ограниченную функциональность, а в полной реализованы realtime-метрики, JWT-валидация, health check и другие инструменты. Есть поддержка TCP/UDP-трафика.
Kong Ingress
Kong Inc предлагает две версии продукта: для личного пользования и корпоративный. Контроллер все также опирается на Nginx в связке с целым рядом Lua-плагинов.
Решение создавалось для обработки и маршрутизации API-запросов, но постепенно развилось из API Gateway до полноценного Ingress-контроллера. Гибкий подход к модульной реализации позволяет конфигурировать решение с разными возможностями. Встроенная функциональность также хорошо развита.
Kong Ingress работает в рамках одного контура. Для другого контура нужен ещё один контроллер.
Traefik Kubernetes Ingress
Решение создавалось для маршрутизации запросов микросервисов и их динамической среды. Благодаря этому Traefik получил поддержку разных методов балансировки, обновление конфигураций без перезагрузки, поддержку различных протоколов, REST API, web-интерфейс и много других полезных фич.
Traefik из коробки поддерживает сертификаты Let’s Encrypt, но для организации высокой доступности нуждается в создании собственного KV-хранилища.
HAProxy
Один из самых популярных инструментов, применяется не только как балансировщик, но и в качестве proxy. Решение позволяет обновлять конфигурацию без потери трафика, service discovery на основе DNS, поддерживает динамическое конфигурирование через API. Шаблоны конфига полностью можно полностью отредактировать через смену CM, что достаточно удобно.
Voyager
Ingress-контроллер создан на базе предыдущего (HAproxy) и предлагает множество вариантов настроек и управления трафиком. В основном используется для балансировки в сетях L7 и L4.
Contour
Проект позволяет разделять управление ресурсами Ingress через специальный инструмент IngressRoute. Его удобно использовать, когда распределенные команды разработки используют один кластер. Это помогает защитить трафик и снижает риск появления ошибок при использовании ресурсов Ingress.
Из приятных возможностей балансировки — зеркалирование запросов, автоповторы и rate-ограничения. Есть опции мониторинга инцидентов.
Istio Ingress
Решение из разряда full service mesh, которое полностью управляет трафиком в кластере. Проект разработан на базе Envoy и пропагандирует максимальную управляемость, масштабируемость и безопасность. Решение позволяет контролировать маршрутизацию, мониторинг, авторизацию доступов и балансировку нагрузки.
Ambassador
Решение с Envoy под капотом. Полностью совместимо с K8s, предполагает тесную интеграцию с методами и сущностями кластеров и ряд других преимуществ.
Как работать с Ingress
Разберем настройку SSL/TLS-сертификатов, настройку LoadBalancer, логи и конфигурацию Ingress-контроллера.
SSL/TLS сертификаты в Ingress
SSL/TLS-сертификаты для Ingress хранятся в секретах Kubernetes. Его можно создать с помощью команды:
kubectl create secret tls my-tls --key my-tls.key --cert my-tls.cert
Полученный секрет используйте в конфигурации Ingress:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-my-tls
annotations:
ingress.kubernetes.io/ssl-redirect: "true"
spec:
tls:
- hosts:
- ingress.example.com
secretName: my-tls
rules:
- host: ingress.example.com
http:
paths:
- path: /
backend:
serviceName: nginx
servicePort: 80
Cert-manager
Cert-manager позволяет автоматически получать и продлевать сертификаты от Let’s Encrypt , HashiCorp Vault, Venafi и других центров. Давайте посмотрим, как с ним работать.
Далее мы будем использовать менеджер пакетов Helm, но вы можете воспользоваться и другими способами установки. Мы также будем работать с Ingress-контроллером с помощью Nginx.
Сначала добавляем репозиторий Helm и обновляем кеш локального репозитория:
helm repo add jetstack https://charts.jetstack.io
helm repo update
Устанавливаем CRD — Custom Resource Definitions:
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.3/cert-manager.crds.yaml
Устанавливаем Cert-manager:
И проверяем установку — пробуем выдать сертификат:
$ cat <<EOF > test-resources.yaml
apiVersion: v1
kind: Namespace
metadata:
name: cert-manager-test
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: test-selfsigned
namespace: cert-manager-test
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: selfsigned-cert
namespace: cert-manager-test
spec:
dnsNames:
- example.com
secretName: selfsigned-cert-tls
issuerRef:
name: test-selfsigned
EOF
Как установить Ingress-контроллер
По умолчанию Ingress-контроллер требует установленных в кластере CRD. Они появятся при установке чарта.
Нам понадобится чарт (Chart) — это основная сущность Helm, коллекция связанных манифестов Kubernetes. Получаем ресурсы с помощью команды:
helm install my-release oci://ghcr.io/nginxinc/charts/nginx-ingress --version 1.1.2
Меняем рабочую директорию на nginx-ingress:
cd nginx-ingress
И вводим команду, которая развенет Ingress-контроллер в вашем кластере Kubernetes с конфигурацией по умолчанию.
helm install your-first-release .
Вместо your-first-release укажите ваше название.
Как настроить LoadBalancer для Ingress-контроллера
Создайте файл с именем nginx-ingress.yaml:
vi nginx-ingress.yaml
Вставьте в этот файл следующую конфигурацию:
kind: Service
apiVersion: v1
metadata:
name: ingress-nginx
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
spec:
externalTrafficPolicy: Сluster
type: LoadBalancer
selector:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
ports:
- name: http
port: 80
targetPort: http
- name: https
port: 443
targetPort: https
Создайте службу Ingress:
kubectl apply -f nginx-ingress.yaml
Проверьте, подключен ли сервис к внешнему балансировщику нагрузки:
kubectl get svc -n ingress-nginx
Как сопоставить доменное имя с IP-адресом балансировщика нагрузки
Сопоставить доменное имя с IP-адресом можно двумя способами: через сингл или подстановочное DNS-сопоставление.
Сингл DNS-сопоставление — когда вы сопоставляете домен напрямую как A запись с IP-адресом LoadBalancer. Здесь можно указать для Ingress-контроллера лишь один домен и маршрутизировать трафик по нескольким путям.
www.selectel-example.ru —> Loadbalancer IP
При подстановочном сопоставлении DNS с Loadbalancer у вас могут быть динамические конечные точки DNS через Ingress. Можно подключить несколько поддоменов через один Ingress-контроллер, и каждый DNS может иметь собственную маршрутизацию.
*.apps.example.com
Вы можете бесплатно размещать домены и ресурсные записи на DNS-серверах Selectel.
Логи и конфиги Ingress-контроллера
При работе с Ingress-контроллером бывает полезно смотреть логи и менять конфигурацию.
Посмотреть логи можно с помощью команды:
kubectl logs ingress-nginx-controller-twwpb -n ingress-nginx
Конфигурацию Nginx внутри Ingress-контроллера можно посмотреть так:
kubectl exec -it ingress-nginx-controller-twwpb -n ingress-nginx cat /etc/nginx/nginx.conf > ~/ingress-nginx.conf
Вы также можете зайти в сам контейнер с Ingress-контроллером:
kubectl exec -it ingress-nginx-controller-twwpb -n ingress-nginx cat /etc/ingress-controller/ssl/default-fake-certificate.pem > ~/default-fake-certificate.pem
Полную инструкцию с конфигурацией для Ingress-контроллера вы найдете в документации Nginx.
Как создать объект в Ingress Kubernetes
Создайте файл с именем ingress.yaml. Добавьте в него следующую конфигурацию:
kind: Ingress
metadata:
name: test-ingress
namespace: dev
spec:
rules:
- host: selectel-test.info
http:
paths:
- backend:
serviceName: hi-selectel
servicePort: 80
И затем опишите объект для проверки конфигурации:
kubectl describe ingress -n dev
Готово, объект создан.