К Load Balancers в системах оркестрации (Kubernetes, Nomad и других) предъявляется больше требований, чем просто балансировка загрузки. Во-первых, Load Balancer должен уметь читать каталог, со списком сервисов, на которые необходимо перенаправлять трафик (или, как вариант, давать возможность сервисам регистрироваться на включение их в трафик). Во-вторых, делать это динамически, т.к. системы оркестрации в любой момент могут увеличить или уменьшить количество реплик сервисов, или переместить их на другие адреса в сети. И, в-третьих, делать это без остановки трафика.
В сегодняшнем сообщении я опишу работу с двумя Load Balancers — Traefik и HAProxy. Эти Load Balancers имеют возможность работать с внушительным списком средств оркестрации. В примерах будет описана работа с системой оркестрации Nomad.
В прошлом сообщении я уже приводил пример Load Balancers — Fabio. Его ограничения: работает только с http/https протоколами, и работает только с системой оркестрации Nomad. В отличие от Fabio, Load Balancers Troefik работает с впечатляющим количеством различных систем. Вот их неполный список, взятый с сайта разработчика: Docker, Swarm mode, Kubernetes, Marathon, Consul, Etcd, Rancher, Amazon ECS,…
Я продолжу пример из предыдущего сообщения, в котором создавалось несколько реплик сервиса django.
Traefik можно загрузить с сайта разработчика в виде исполняемого файла для наиболее распространенных операционных систем. Для интеграции с Nomad (собственно с Consul) необходимо создать файл конфигурации:
[entryPoints]
[entryPoints.http]
address = ":5001"
[web]
address = ":8080"
[consulCatalog]
endpoint = "127.0.0.1:8500"
domain = "consul.localhost"
exposedByDefault = false
prefix = "traefik"
И далее запустить на выполнение команду с приведенным файлом конфигурации:
traefik -c nomad/traefik.toml
После этого на порте 8080 будет доступен UI Traefik, в котором пока не опубликован ни один сервис. Для публикации сервисов существует несколько способов, которые в конечно счете делают одно и тоже — загружают в систему Traefik данные типа ключ/значение. Мы воспользуемся возможностью задавать пары ключ/значение через tags сервисов. Дополним конфигурационный файл сервиса django параметром tags:
job "django-job" {
datacenters = ["dc1"]
type = "service"
group "django-group" {
count = 3
restart {
attempts = 2
interval = "30m"
delay = "15s"
mode = "fail"
}
ephemeral_disk {
size = 300
}
task "django-job" {
driver = "docker"
config {
image = "apapacy/tut-django:1.0.1"
port_map {
lb = 8000
}
}
resources {
network {
mbits = 10
port "lb" {}
}
}
service {
name = "django"
tags = [
"traefik.enable=true",
"traefik.frontend.entryPoints=http",
"traefik.frontend.rule=Host:localhost;PathStrip:/test",
"traefik.tags=exposed"
]
port = "lb"
check {
name = "alive"
type = "http"
path = "/"
interval = "10s"
timeout = "2s"
}
}
}
}
}
В данном примере сервис будет опубликован на хосте localhost и примонтирован к роуту /test. В Troefik разработана гибкая и полная система правил для конфигурирования роутов, включая работу с регулярными выражениями. Перечень параметров для правил в документации разработчика.
После выполнения команды nomad job run nomad/django.conf
правила применятся, и на сервис будет направлен трафик с Load Balancer. Соответственно, можно менять эти параметры, деплоить новый вариант сервиса командой nomad job run nomad/django.conf
, и все изменения применятся без досадной остановки трафика.
Недостатком Troefik является то что он работает с протоколами семейства http/https (на всякий случай замечу что это семейство включает и веб-сокеты). Но все же есть такая вероятность, что возникнет необходимость работать и с другими протоколами. Поэтому перейдем к следующему более широкому решению на основе HAProxy. Какое-то время назад у HAProxy были проблемы с «мягкой» перегрузкой, что делало его использование с системами оркестрации сложным (на время рестарта приходилось на сетевом уровне приостанавливать движение пакетов). Сейчас это уже не проблема.
Для начала необходимо установить haproxy на компьютер. Здесь не подойдет вариант с установкой внутри контейнера. В haproxy только недавно появилась возможность рестартовать процесс в «мягком» режиме, но при этом все равно контейнер докер останавливается, так как фактически запускается второй процесс с haproxy, просто их смена проходит в режиме ожидания — что не работает с докером и его принципом «один-контейнер-один процесс».
Для работы haproxy необходимо иметь файл конфигурации, в котором прописаны необходимые правила. В Nomad (собственно в Consul) применяется система шаблонов, которая может генерировать конфигурации:
global
debug
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
frontend http_front
bind *:5001
stats uri /haproxy?stats
default_backend http_back
backend http_back
balance roundrobin{{range service "django"}}
server {{.Node}} {{.Address}}:{{.Port}} check{{end}}
Ключевое слово range
в данном случае выполняет роль итератора. Для трех сервисов «django» будет сформирован такой файл конфигурации:
global
debug
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
frontend http_front
bind *:5001
stats uri /haproxy?stats
default_backend http_back
backend http_back
balance roundrobin
server 228.195.86.224 127.0.0.1:21469 check
server 228.195.86.224 127.0.0.1:25872 check
server 228.195.86.224 127.0.0.1:25865 check
Для запуска процесса генерации по шаблону «на лету» применяется библиотека https://github.com/hashicorp/consul-template. С ресурса разработчика можно загрузить исполняемый файл для всех распространенных операционных систем, и запускать процесс от имени не привилегированного пользователя командой:
consul-template -template="haproxy/haproxy.cfg.tmpl:haproxy/haproxy.cfg:./haproxy/haproxy.reload.sh"
Параметр -template
содержит разделенные двоеточием параметры 1) имя шаблона, 2) имя получаемого файла конфигурации 3) команда, которая выполняется после генерации файла. Файл будет автоматически генерироваться если будут изменены переменные входящие в шаблон (например изменено количество реплик сервиса django).
После запуска шаблонизатора, который сгенерирует первую конфигурацию можно запускать haproxy:
haproxy -D -f haproxy/haproxy.cfg -p `pwd`/haproxy.pid
Мы явно указываем pid-файл, для того чтобы иметь возможность отправить сигнал на «мягкую» перегрузку haproxy:
haproxy -D -f ./haproxy/haproxy.cfg -p `pwd`/haproxy.pid -sf $(cat `pwd`/haproxy.pid)
В данном примере сервис опубликован на порту 5001. На этом же порту можно просмотреть статистику самого haproxy по адресу /haproxy?stats
.
Код примеров доступен в репозитарии
Полезные ссылки:
1. www.haproxy.com/blog/haproxy-and-consul-with-dns-for-service-discovery
2. m.mattmclaugh.com/traefik-and-consul-catalog-example-2c33fc1480c0
apapacy@gmail.com
24 февраля 2019 года
Автор: apapacy