Статья-инструкция по настройке MetalLB в связке с Ingress Nginx в кластере Kubernetes.
Зачем это нужно?
Классическое развертывание Ingress Nginx контроллера (далее Ingress) в Bare Metall инсталляции (на мой взгляд) выглядит так:
- Добавляем ноду с белым IP (или делаем DNAT на IP ноды) в кластер Kubernetes.
- Устанавливаем на эту ноду Ingress, указываем нужный IP как ExternalIP, ставим taint на запрет любых других подов.
- (Опционально) Добавляем cert manager.
Это делается легко, быстро и хорошо работает. До тех пор пока нода с Ingress не упадет по какой-либо причине (а такое бывает).
Если бы у нас было бы облако, мы бы автоматом при инсталляции Ingress (например, с помощью Helm chart) получили бы ExternalIP типа LoadBalancer и такой проблемы бы не было.
Здесь нам на помощью приходит MetalLB.
Установка и настройка MetalLB
Установка крайне проста, сделайте по гайду на официальной сайте.
https://metallb.universe.tf/installation
Я развернул MetalLB на 3-х нодах которые выполняют роль Ingress и только. Сейчас мне нечего балансировать на других узлах.
Теперь нужно создать пул адресов который будет предоставлять MetalLB. Во всех гайдах предлагают взять большую подсеть /24 под балансировку. В моём случае возьму всего 2 IP адреса, что бы потом сделать 2 DNAT на роутере и поднять две инсталляции Ingress. Эти адреса не должен быть на что-то назначены или быть в DHCP пуле. Просто берите адреса которые нигде не используются, ими будет управлять MetalLB.
Создам вот такой манифест metallb-pool.yaml (в любом текстовом редакторе)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
--- apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: default namespace: metallb-system spec: addresses: - 192.168.10.230-192.168.10.231 autoAssign: true --- apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: default namespace: metallb-system spec: ipAddressPools: - default |
Применю его с помощью kubectl
1 |
kubectl apply -f metallb-pool.yaml |
На этом настройка MetalLB закончена.
Установка и настройка Ingress Nginx
Установка Ingress Nginx (далее Ingress) тоже довольно проста.
Я разворачиваю с помощью Helm Chart, указывая правильные tollerations, affinity и настройки самого Ingress.
Сначала получаю все значения которые есть в Helm Chart.
1 |
helm show values ingress-nginx/ingress-nginx > values.yaml |
Очищаю всё лишнее и оставляю самый минимум.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
controller: name: controller ingressClassResource: name: nginx affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - ingress0 - ingress1 - ingress2 tolerations: - effect: NoSchedule key: node-role.kubernetes.io/ingress operator: Exists replicaCount: 3 service: externalTrafficPolicy: "Local" |
В моём случае важно указать tolerations и affinity, что бы поды поднимались на правильных узлах. Так же ставлю replicaCount в размере 3
Что обязательно надо сделать в любой инсталляции с MetalLB это выставить externalTrafficPolicy как Local.
С помощью ingressClassResource.name вы можете задать имя ingress class что бы дальше указывать его в объекте Ingress вашего http ресурса.
Теперь я могу поднять Ingress.
Сделаю первую инсталляцию.
1 2 |
helm upgrade ingress-nginx ingress-nginx/ingress-nginx -f values.yaml -n ingress-nginx --create-namespace\ --set controller.ingressClassResource.name="nginx-provider-1" |
Обратите внимание что я меняю ingress class name.
И вторую инсталляцию.
1 2 |
helm install ingress-nginx-second ingress-nginx/ingress-nginx -f values.yaml -n ingress-nginx \ --set controller.ingressClassResource.name="nginx-provider-2" |
В итогу инсталляция должна выглядеть следующим образом
Как видно, Service Ingress’а получил ExternalIP типа LoadBalancer. MetalLB работает.
Можно сделать curl по 192.168.19.230 и получить ответ от веб-сервера.
И даже если я погашу 2 ноды с ролью Ingress, веб-сервер все равно будет отвечать, что и требуется от балансировщика. Можно навешивать любые http приложения на веб-сервер.