haproxy
Ansible HAproxy (готовый для OpenStack)
Эта роль поддерживает установку HAproxy на современных дистрибутивах:
- Rocky Linux 8 / 9
- Fedora 37 / 38 / 39
- Debian 10 / 11 / 12
- Ubuntu 18.04 / 20.04 / 22.04
Роль позволяет настраивать несколько секций HAproxy:
- Глобальная секция
- Секция по умолчанию
- Секция прослушивания
- Секция фронтенда
- Секция бэкенда
- Секция пира
- Секция статистики
Требования
Эта роль требует как минимум HAproxy 1.5 (поддержка SSL) и Ansible 2.8.
Переменные роли
В директории vars
нет переменных, все переменные могут быть переопределены через плейбук.
Пустая переменная, такая как haproxy_global_uid
, появится в /etc/haproxy/haproxy.cfg
, только если будет определено значение.
Переменные, такие как haproxy_global_stats: []
, являются массивами, в этом примере массив пустой. Эту переменную можно объявить двумя способами:
haproxy_global_stats:
- show-legends
- show-node
- refresh 20s
# файл: roles/haproxy/defaults/main.yml
# Sysctl
haproxy_bind_nonlocal_ip: true
haproxy_ip_forward: true
# Общие настройки
haproxy_mode: system # или docker
haproxy_firewalld: true
haproxy_selinux: true
haproxy_apt_backports: false
# значение по умолчанию для macOS и Docker; переопределяется в `vars/{{ ansible_os_family }}.yml`
haproxy_errors_directory: /usr/local/etc/haproxy/errors
# Настройки пакета
haproxy_package: haproxy
haproxy_selinux_packages:
- python3-libselinux
- python3-policycoreutils
haproxy_service: haproxy
haproxy_bin: haproxy
haproxy_config: /etc/haproxy/haproxy.cfg
# Брандмауэр
haproxy_fw_ports:
- "{{ haproxy_stats_port }}/tcp"
# Глобальные настройки
haproxy_global_maxconn: 4000
haproxy_global_chroot: /var/lib/haproxy
haproxy_global_group: haproxy
haproxy_global_user: haproxy
haproxy_global_uid:
haproxy_global_gid:
haproxy_global_pidfile: /var/run/haproxy.pid
haproxy_global_ca_base:
haproxy_global_crt_base:
haproxy_global_ssl_bind_options:
haproxy_global_ssl_bind_ciphers:
haproxy_global_ssl_bind_ciphersuites:
haproxy_global_ssl_server_options:
haproxy_global_ssl_server_ciphers:
haproxy_global_ssl_server_ciphersuites:
haproxy_global_ssl_server_verify:
haproxy_global_stats: []
haproxy_global_description:
haproxy_global_ulimit_n:
haproxy_global_logs:
- 127.0.0.1 local0 debug
haproxy_global_daemon: true
# nbproc устарел. Будет удален в версии 2.5
# haproxy_global_nbproc: 8
# haproxy_global_cpu_maps: [ 1 0, 2 1, 3 2, 4 3, 5 4, 6 5, 7 6, 8 7 ]
haproxy_global_tunes:
- tune.ssl.default-dh-param: 2048
# Секция по умолчанию
haproxy_default_logs:
- global
haproxy_default_log_format:
haproxy_default_mode:
haproxy_default_maxconn: 4000
haproxy_default_options:
- dontlognull
- forwardfor
- http-server-close
haproxy_default_retries: 3
haproxy_default_timeouts:
- http-request 10s
- queue 1m
- connect 10s
- client 1m
- server 1m
- http-keep-alive 10s
- check 10s
haproxy_default_balance:
haproxy_default_errorfiles:
- "400 {{ haproxy_errors_directory }}/400.http"
- "403 {{ haproxy_errors_directory }}/403.http"
haproxy_default_http_check:
haproxy_default_monitor_uri:
haproxy_default_unique_id_format:
# Список пользователей
haproxy_userlist:
- stats-auth:
groups:
- "admin users admin"
- "readonly users user"
users:
- "admin insecure-password opqrstuvw"
- "user insecure-password abcdefghi"
# Статистика с HTTP Basic Auth и одним пользователем
haproxy_stats: true
haproxy_stats_address: '*'
haproxy_stats_port: 9001
haproxy_stats_ssl: false
haproxy_stats_user: haproxy-stats
haproxy_stats_password: B1Gp4sSw0rD!!
haproxy_stats_uri: /
haproxy_stats_options:
- refresh 20s
- show-legends
- show-node
- hide-version
haproxy_stats_http_requests:
- use-service prometheus-exporter if { path /metrics }
haproxy_stats_listener_options:
- dontlog-normal
haproxy_stats_timeouts:
- client 100s
- server 100s
- connect 100s
- queue 100s
# Статистика с HTTP Basic Auth с использованием списка пользователей
haproxy_stats: true
haproxy_stats_address: "::"
haproxy_stats_port: 8081
haproxy_stats_ssl: false
haproxy_stats_uri: /stats
haproxy_stats_auth:
haproxy_stats_acls:
- "AUTH http_auth(stats-auth)"
- "AUTH_ADMIN http_auth_group(stats-auth) admin"
haproxy_stats_options:
- refresh 5s
- show-legends
- show-node
- http-request auth unless AUTH
- admin if AUTH_ADMIN
# SSL
haproxy_ssl_certificate: /etc/ssl/uoi.io/uoi.io.pem
haproxy_ssl_options: no-sslv3 no-tls-tickets force-tlsv12
haproxy_ssl_ciphers: AES128+EECDH:AES128+EDH
haproxy_ssl: 'ssl crt {{ haproxy_ssl_certificate }} ciphers {{ haproxy_ssl_ciphers }} {{ haproxy_ssl_options }}'
# Docker
# смотрите больше деталей в `tasks/docker.yml` и https://docs.ansible.com/ansible/latest/collections/community/general/docker_container_module.html
haproxy_docker_name: "haproxy"
haproxy_docker_image: "haproxy:alpine"
haproxy_docker_network_mode: default
haproxy_docker_network_name: "haproxy"
haproxy_docker_pull: true
haproxy_docker_recreate: false
haproxy_docker_ports:
- "8443:8443"
- "{{ haproxy_stats_port }}:{{ haproxy_stats_port }}"
haproxy_docker_sysctls:
net.ipv4.ip_nonlocal_bind: "{{ 1 if haproxy_bind_nonlocal_ip|bool else 0 }}"
net.ipv4.ip_forward: "{{ 1 if haproxy_ip_forward|bool else 0 }}"
net.core.somaxconn: 4096
net.ipv4.tcp_syncookies: 1
haproxy_docker_ulimits:
- "nofile:262144:262144"
haproxy_docker_volumes:
- {{ haproxy_config }}+":/usr/local/etc/haproxy/haproxy.cfg:ro"
Зависимости
Нет
Пример плейбука
Приведенные ниже примеры показывают, как определить frontend
, backend
, listen
, peer
.
# Фронтенд
haproxy_frontend:
- dashboard_cluster:
binds_ssl:
- :443 ssl crt /etc/ssl/uoi.io/uoi.io.pem no-sslv3
reqadds:
- X-Forwarded-Proto:\ https
default_backend: dashboard_backend
logs:
- 127.0.0.1 local0 debug
acls:
- url_static path_beg -i /static /images /javascript /stylesheets
- url_static path_end -i .jpg .gif .png .css .js
bind_process:
- 1
log_formats:
- "%ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r"
use_backends:
- static if url_static
capture:
- request header Host len 64
- request header X-Forwarded-For len 64
# Бэкенд
haproxy_backend:
- dashboard_backend:
balance: source
default_server: "inter 2s downinter 5s rise 3 fall 2 slowstart 30s maxconn 30 maxqueue 64 weight 100"
http_checks:
- 'send meth GET uri /check-haproxy.php hdr Host haproxy.check-vhost.de'
- 'expect string "All services running fine"'
bind_process:
- 1
server_templates:
- srv 3 service.local:80 check resolvers mydns init-addr none
servers:
- ctrl01 10.0.0.67:80 check inter 2000 rise 2 fall 5
- ctrl02 10.0.0.68:80 check inter 2000 rise 2 fall 5
- ctrl03 10.0.0.69:80 check inter 2000 rise 2 fall 5
- static:
balance: roundrobin
compression:
- algo gzip deflate
- type text/css text/html application/javascript
bind_process:
- 1
servers:
- cnd01 10.0.0.70:8080 check
- cnd02 10.0.0.71:8080 check
- cnd03 10.0.0.71:8080 check
# Прослушивание
haproxy_listen:
- dashboard_cluster:
mode: http
description: Horizon Dashboard
balance: roundrobin
default_server: "inter 2s downinter 5s rise 3 fall 2 slowstart 30s maxconn 30 maxqueue 64 weight 100"
binds:
- 10.0.0.100:80
binds_ssl:
- :443 ssl crt /etc/ssl/uoi.io/uoi.io.pem no-sslv3
options: [ tcpka, httpchk, tcplog ]
http-check: GET /auth/login
cookie: SERVERID insert indirect nocache
capture:
- cookie SERVERID len 32
timeouts:
- client 90m
- server 90m
bind_process:
- 1
http_requests:
- set-header X-Haproxy-Current-Date %T
servers:
- ctrl01 10.0.0.67:80 check cookie ctrl01inter 2000 rise 2 fall 5
- ctrl02 10.0.0.68:80 check cookie ctrl02 inter 2000 rise 2 fall 5
- ctrl03 10.0.0.69:80 check cookie ctrl03 inter 2000 rise 2 fall 5
- neutron_api_cluster:
binds_ssl:
- 10.0.0.100:9696 {{ haproxy_ssl }}
options: [ tcpka, httpchk, tcplog ]
bind_process: [ 2, 3, 4, 5, 6, 7 ]
balance: source
servers:
- ctrl01 10.0.0.62:9696 check inter 2000 rise 2 fall 5
- ctrl02 10.0.0.63:9696 check inter 2000 rise 2 fall 5
- ctrl03 10.0.0.64:9696 check inter 2000 rise 2 fall 5
# Пир
haproxy_peer:
- remote_peers:
peers:
- lb223 10.0.0.223:1024
- lb224 10.0.0.224:1024
- lb225 10.0.0.225:1024
# Резолверы
haproxy_resolvers:
- mydns:
nameservers:
- 'dns1 10.0.0.1:53'
- 'dns3 [email protected]:53'
parse_resolv_conf: true
resolve_retries: 5
timeouts:
- 'resolve 1s'
- 'retry 1s'
holds:
- 'other 30s'
- 'refused 30s'
- 'nx 30s'
- 'valid 30s'
Пример использования Docker
Вот короткий пример того, как использовать роль в другом плейбуке и запустить HAProxy в Docker.
# site.yml
- hosts: haproxy
name: HAProxy балансировщик нагрузки
tags:
- all
- haproxy
# может быть включен как через `role`, так и через `include_role`
# roles:
# - uoi-io.haproxy
tasks:
- include_role:
name: uoi-io.haproxy
# (group_vars|environments/<my env>/group_vars/haproxy.yml)
haproxy_mode: docker
haproxy_config: "{{ docker_persistent_path }}/haproxy/haproxy.cfg"
haproxy_firewalld: false
haproxy_selinux: false
# Глобальные настройки
haproxy_global_chroot: ""
# SSL
haproxy_ssl_certificate: /usr/local/etc/haproxy/ssl/haproxy.crt
# Фронтенд
haproxy_frontend:
# ... определение фронтенда
# Бэкенд
haproxy_backend_checks: "check inter 2000 rise 2 fall 5"
haproxy_backend:
- my_backend:
# ... определение бэкенда
# пример, что хосты могут быть динамически связаны на основе другой группы
servers: |-
{%- set _list = [] %}
{%- for _host in groups['MY_BACKEND_GROUP'] %}
{%- set _list = _list.append(_host.split('.')[0] ~ ' ' ~ _host ~ ':' ~ MY_SERVICE_PORT ~ ' ' ~ haproxy_backend_checks) %}
{%- endfor %}
{{- _list }}
# Docker
haproxy_docker_ports:
- "6443:6443"
- "{{ haproxy_stats_port }}:{{ haproxy_stats_port }}"
# haproxy_docker_volumes: []
haproxy_docker_volumes:
- "{{ haproxy_config }}:/usr/local/etc/haproxy/haproxy.cfg:ro"
- "{{ docker_persistent_path }}/haproxy/haproxy.key:/usr/local/etc/haproxy/ssl/haproxy.crt.key:ro"
- "{{ docker_persistent_path }}/haproxy/haproxy.crt:/usr/local/etc/haproxy/ssl/haproxy.crt:ro"
Репозиторий для RedHat
Если у вас есть собственный репозиторий с HAProxy, вы можете установить файл репозитория. Следующий пример добавит репозиторий с HAProxy 2 для CentOS 8
# Репозиторий
haproxy_repo_yum:
- name: haproxy
description: HAProxy 2 репозиторий - $basearch
baseurl: https://download.copr.fedorainfracloud.org/results/pzinchuk/haproxy/epel-8-$basearch/
priority: 1
gpgcheck: true
file: haproxy
repo_gpgcheck: false
skip_if_unavailable: true
gpgkey: https://download.copr.fedorainfracloud.org/results/pzinchuk/haproxy/pubkey.gpg
enabled: true
state: present
Тестирование
Эта роль использует ansible molecule.
Вам просто нужно установить molecule через pip
и запустить его.
В настоящее время конфигурация molecule основана на драйвере docker
.
apt/yum install docker
systemctl start docker
pip install docker molecule molecule-plugins pytest-testinfra
molecule test
Лицензия
Apache
Информация об авторе
Эта роль была создана в 2016 году Гаэтаном Треллю (goldyfruit).
Install and configure HAproxy
ansible-galaxy install uoi-io/ansible-haproxy