uoi-io.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
目录中没有变量,所有变量可以通过 playbook 进行覆盖。
如果定义了值,空变量如 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 基本认证的统计
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 基本认证的统计
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"
依赖关系
无
示例 Playbook
以下示例展示了如何定义 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 使用示例
下面是如何在另一个 playbook 中使用该角色并在 Docker 中运行 HAProxy 的简短示例。
# 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 仓库,可以安装仓库文件。 下一个示例将为 CentOS 8 添加 HAProxy 2 的仓库
# 仓库
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。
你只需通过 pip
安装 molecule 并运行它。
当前的 molecule 配置基于 docker
驱动程序。
apt/yum install docker
systemctl start docker
pip install docker molecule molecule-plugins pytest-testinfra
molecule test
许可证
Apache
作者信息
该角色由 Gaëtan Trellu (goldyfruit) 于 2016 年创建。