Я уже описывал как можно развернуть небольшой локальный k8s кластер тут, а также как настроить ингресс здесь. В конце статьи мы смогли зайти через доменное имя нашего ингреса на kubernetes dashboard, но только с указанием номера порта (nodePort). Сегодня посмотрим как можно решить данное неудобство с помощью сервиса metallb.
Metallb — это решение, которое позволяет использовать тип LoadBalancer в bare-metal кластерах, то есть тех, которые развернуты не в облаке. У него много настроек и возможностей, но мы сегодня рассмотрим самую простую, это настройка layer 2 режима. В этом режиме metallb использует стандартные сетевые протоколы канального уровня, такие как ARP (Address Resolution Protocol) для IPv4 и NDP (Neighbor Discovery Protocol) для IPv6, чтобы объявить внешние IP-адреса служб. Это позволяет обеспечить доступность Kubernetes-служб типа LoadBalancer без необходимости настройки сложных сетевых протоколов или изменения конфигурации существующего сетевого оборудования.
Суть работы примерно следующая. Нужно настроить пул адресов, которые находятся в той же подсети, что и узлы k8s, у меня это моя домашняя сеть. Затем, когда мы создаем k8s service с типом LoadBalancer, metallb автоматически выделяет один из ip адресов из пула для этого сервиса.
Наша цель — использовать любые ингресс домены внутри куба без необходимости указания nodePort, следовательно настроив metallb, мы получим на service ingress-controller внешний адресс из пула, который доступен в домашней сети, без дополнительных настроек, затем пропишем wildcard DNS запись на тот адрес, который будет назначен сервису.
Установка metallb
Работаем согласно официальной документации. Я использую kube-proxy, поэтому для начала нужно проверить включен ли режим strictARP или нет у IPVS.
kubectl get configmap kube-proxy -n kube-system -o yaml | \
sed -e "s/strictARP: false/strictARP: true/" | \
kubectl diff -f - -n kube-system
Видим, что режим не включен. Я использую разные alias, так как у меня есть еще множество рабочих кластеров, поэтому на скрине k-local.
Включаем strictARP:
kubectl get configmap kube-proxy -n kube-system -o yaml | \
sed -e "s/strictARP: false/strictARP: true/" | \
kubectl apply -f - -n kube-system
Далее устанавливаем сам манифест metallb.
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.8/config/manifests/metallb-native.yaml
В документации также указано, как установить с помощью helm или kustomize. На мой взгляд это пока лишнее, так как для домашних тестов подобная вещь проходит по разряду «настроил и забыл».
Один из компонентов metallb — speaker это DaemonSet, который запускается на каждой ноде кластреа. Так как у меня есть кастомный taint на ingress ноду, я добавил в манифет speaker новую толерантность.
- key: ingress
operator: Equal
value: 'true'
effect: NoSchedule
Правки в service ingress-nginx-controller
Сервис (кубовый) для ingress у меня был развернут с типом nodePort. Удаляем старый сервис
kubectl delete svc ingress-nginx-controller -n ingress-nginx
И создаем такой же, но с типом LoadBalancer
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
spec:
type: LoadBalancer
ports:
- name: http
protocol: TCP
port: 80
targetPort: http
- name: https
protocol: TCP
port: 443
targetPort: https
selector:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/component: controller
Вначале сервис зависнет в состоянии «Pending». Это нормально, так как мы еще не настроили metallb.
Настройка metallb
Для настройки нам нужно применить два манифеста.
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: default
namespace: metallb-system
spec:
addresses:
- 192.168.10.101-192.168.10.110
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: default
namespace: metallb-system
Первый с Kind: IPAddressPool — это собственно пул ip адресов, которые metallb будет назначать сервисам с типом LoadBalancer. Это как раз адреса из домашней подсети. Я указал немного, так как вряд ли где-то еще кроме сервиса ингресс контроллера это понадобится.
Второй манифест это то, с чем должен быть ассоциирован пул адресов (первый манифест). В своей документации metallb пишет, что если в спецификации L2Advertisement не указывать конкретные имена пулов, то ассоциация будет идти со всеми существующими. У меня это всего один, поэтому данная конфигурация подходит. Если же нужно указать конкретную связку, то делается это так:
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: example
namespace: metallb-system
spec:
ipAddressPools:
- first-pool
Как видим ipAddressPools является массивом и может принимать множетсво имен пулов.
После применения манифестов, можно увидеть что сервис ингресс контроллера получил ip адрес.
В моем случае был назначен 192.168.10.101.
Настройка DNS
Осталось добавить wildcard запись на этот адрес. Я использую dnsmasq (о нем было в предыдущих статья по kubernetes).
В файле /etc/dnsmasq.conf необходимо добавить следующее:
address=/.dev.local/192.168.10.101
И выполнить перезагрузку демона dnsmasq
sudo systemctl restart dnsmasq
Пробуем открыть домен с дашбордом.