Ingress-controller в Kubernetes — что это и как его настроить

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

Готово, объект создан.