配置 HAProxy (可选)¶
在 OpenStack-Ansible 部署的高可用架构中,当硬件负载均衡器不可用时,HAProxy 提供负载均衡服务和 SSL 终止。如果 haproxy_hosts 组中存在多个主机,则默认的 HAProxy 配置通过 keepalived 提供高可用负载均衡服务。
重要提示
请务必审查 HAProxy 暴露的服务,并将这些服务的访问权限仅限于受信任的用户和网络。有关更多详细信息,请参阅保护 OpenStack 服务网络访问部分。
注意
为了成功安装,您需要一个负载均衡器。您可能更倾向于使用硬件负载均衡器而不是 HAProxy。如果正在使用硬件负载均衡器,则在执行部署之前,请先实施服务的负载均衡配置。
要在 OpenStack-Ansible 环境中部署 HAProxy,请定义运行 HAProxy 的目标主机
haproxy_hosts: infra1: ip: 172.29.236.101 infra2: ip: 172.29.236.102 infra3: ip: 172.29.236.103
在 /etc/openstack_deploy/conf.d/haproxy.yml.example 中已提供示例配置文件。将其重命名为 haproxy.yml,并配置正确的 target hosts 以在 OpenStack-Ansible 部署中使用 HAProxy。
使 HAProxy 高可用¶
如果在清单中有多个主机,请通过安装 Keepalived 以高可用的方式部署 HAProxy。
要使 Keepalived 工作,请在 user_variables.yml 中至少编辑以下变量
haproxy_keepalived_external_vip_cidr: 192.168.0.4/25
haproxy_keepalived_internal_vip_cidr: 172.29.236.54/16
haproxy_keepalived_external_interface: br-flat
haproxy_keepalived_internal_interface: br-mgmt
haproxy_keepalived_internal_interface和haproxy_keepalived_external_interface表示部署节点上 keepalived 节点绑定内部和外部 vip 的接口。默认情况下,使用br-mgmt。在上述接口上,
haproxy_keepalived_internal_vip_cidr和haproxy_keepalived_external_vip_cidr分别表示内部和外部的 vip(带有它们的网络前缀长度)。设置其他变量以适应您的部署中的 Keepalived。有关更多说明,请参阅
user_variables.yml。
始终部署(或升级到)最新稳定版本的 Keepalived。编辑 /etc/openstack_deploy/user_variables.yml
keepalived_use_latest_stable: True
HAProxy 节点具有已应用的组变量,这些变量定义了 Keepalived 的配置。此配置存储在 group_vars/haproxy_all/keepalived.yml 中。它包含 Keepalived 角色(主节点和备份节点)所需的变量。
Keepalived 会 ping 一个公共 IP 地址和一个私有 IP 地址来检查其状态。默认地址是 193.0.14.129。要更改此默认值,请在 user_variables.yml 文件中设置 keepalived_external_ping_address 和 keepalived_internal_ping_address 变量。
注意
Keepalived 测试仅支持 IPv4 地址。
您可以通过以下任一方式使 Keepalived 适应您的环境:使用我们的覆盖机制(按主机使用用户空间的 host_vars,按组使用用户空间的``group_vars``,或全局使用用户空间的 user_variables.yml 文件)
如果您希望部署多个 HAProxy 主机而无需 Keepalived,并自行提供它们之间的故障转移机制,请编辑 /etc/openstack_deploy/user_variables.yml 以跳过 Keepalived 的部署。为此,请设置以下内容
haproxy_use_keepalived: False
配置 Keepalived ping 检查¶
OpenStack-Ansible 会使用一个检查脚本来配置 Keepalived,该脚本会 ping 一个外部资源,并使用此 ping 来确定节点是否已丢失网络连接。如果 ping 失败,Keepalived 将故障转移到另一台节点,HAProxy 将在那里处理请求。
目标地址、ping 次数和 ping 间隔可以通过 Ansible 变量在 /etc/openstack_deploy/user_variables.yml 中进行配置
keepalived_external_ping_address: # Public IP address to ping
keepalived_internal_ping_address: # Private IP address to ping
keepalived_ping_count: # ICMP packets to send (per interval)
keepalived_ping_interval: # How often ICMP packets are sent
默认情况下,OpenStack-Ansible 配置 Keepalived 来 ping 由 RIPE 运营的根 DNS 服务器之一。您可以将此 IP 地址更改为不同的外部地址或您内部网络上的另一个地址。
如果外部连接失败,内部服务仍然可以访问 HAProxy 实例非常重要。在 ping 某些外部主机失败且内部 ping 未分离的情况下,所有 Keepalived 实例都会进入故障状态,尽管内部连接仍然可用。内部和外部连接的独立 ping 检查确保当一个实例失败时,另一个 VIP 保持运行。
使用 SSL 证书保护 HAProxy 通信¶
OpenStack-Ansible 项目提供了使用自签名或用户提供的 SSL 证书来保护 HAProxy 通信的功能。默认情况下,HAProxy 使用自签名证书。但是,您可以使用以下 Ansible 变量提供自己的证书
haproxy_user_ssl_cert: # Path to certificate
haproxy_user_ssl_key: # Path to private key
haproxy_user_ssl_ca_cert: # Path to CA certificate
有关这些配置选项的更多信息,以及如何提供自己的证书和密钥与 HAProxy 一起使用,请参阅使用 SSL 证书保护服务。用户提供的证书应折叠并格式化为 64 个字符。HAProxy 将不接受单行证书,这将导致 SSL 验证失败。请在此处查看有关将证书转换为各种格式的信息。
使用 Let's Encrypt 的证书¶
如果您想使用 Let’s Encrypt <https://letsencrypt.openssl.ac.cn/>`_,您可以通过在 /etc/openstack_deploy/user_variables.yml 中提供以下配置来激活此功能。请注意,这需要 /etc/openstack_deploy/openstack_user_config.yml 中的 external_lb_vip_address 设置为外部 DNS 地址。
必须为 HAProxy 主机设置以下变量。
haproxy_ssl_letsencrypt_enable: True
haproxy_ssl_letsencrypt_email: example@example.com
haproxy_interval: 2000
以下变量是配置单个 HAProxy 以对同一主机上的服务(从 127.0.0.1:80 提供服务)进行 SSL 终止的示例。配置了一个额外的 HAProxy 后端,它将在证书续订时接收 acme-challenge 请求。
haproxy_service_configs:
# the external facing service which serves the apache test site, with a acl for LE requests
- haproxy_service_name: test
haproxy_redirect_http_port: 80 #redirect port 80 to port ssl
haproxy_redirect_scheme: "https if !{ ssl_fc } !{ path_beg /.well-known/acme-challenge/ }" #redirect all non-ssl traffic to ssl except acme-challenge
haproxy_port: 443
haproxy_frontend_acls: #use a frontend ACL specify the backend to use for acme-challenge
letsencrypt-acl:
rule: "path_beg /.well-known/acme-challenge/"
backend_name: letsencrypt
haproxy_ssl: True
haproxy_backend_nodes: #apache is running on locally on 127.0.0.1:80 serving a dummy site
- name: local-test-service
ip_addr: 127.0.0.1
haproxy_balance_type: http
haproxy_backend_port: 80
haproxy_backend_options:
- "httpchk HEAD /" # request to use for health check for the example service
# an internal only service for acme-challenge whose backend is certbot on the haproxy host
- haproxy_service_name: letsencrypt
haproxy_backend_nodes:
- name: localhost
ip_addr: {{ ansible_host }} #certbot binds to the internal IP
backend_rise: 1 #quick rise and fall time for multinode deployment to succeed
backend_fall: 2
haproxy_bind:
- 127.0.0.1 #bind to 127.0.0.1 as the local internal address will be used by certbot
haproxy_port: 8888 #certbot is configured with http-01-port to be 8888
haproxy_balance_type: http
通过将 Let’s Encrypt 服务的 haproxy_backend_nodes 设置为包含所有 HAProxy 内部地址,可以实现使用 certbot 初始化和续订证书的 HAProxy 配置。每个 HAProxy 实例将检查其自身节点以及其他节点上运行的 certbot,并将任何传入的 acme-challenge 请求定向到正在执行续订的 HAProxy 实例。
Let’s Encrypt 证书将覆盖的域通过 haproxy_ssl_letsencrypt_domains 变量定义,该变量可以设置为列表。默认情况下,证书仅为 external_lb_vip_address 颁发。
另一个重要方面是定义将使用已颁发证书的前端列表。默认情况下,它将仅用于类型为 external 的 VIP。您可以通过覆盖 haproxy_vip_binds 变量来控制和定义类型。
在 H/A 设置中,有必要通过 haproxy_ssl_letsencrypt_certbot_bind_address 变量配置 certbot 以绑定到 HAProxy 节点本地内部 IP 地址。
配置其他服务¶
可以通过在 /etc/openstack_deploy/user_variables.yml 中设置 haproxy_extra_services 来配置额外的 HAProxy 服务条目
有关服务字典语法的更多信息,请参考 playbooks/vars/configs/haproxy_config.yml
HTTP 服务示例可能如下所示
haproxy_extra_services:
- haproxy_service_name: extra-web-service
haproxy_backend_nodes: "{{ groups['service_group'] | default([]) }}"
haproxy_ssl: "{{ haproxy_ssl }}"
haproxy_port: 10000
haproxy_balance_type: http
# If backend connections should be secured with SSL (default False)
haproxy_backend_ssl: True
haproxy_backend_ca: /path/to/ca/cert.pem
# Or to use system CA for validation
# haproxy_backend_ca: True
# Or if certificate validation should be disabled
# haproxy_backend_ca: False
此外,您可以通过手动指定其主机名/IP 地址来指定未在 Ansible 清单中管理的 HAProxy 服务
haproxy_extra_services:
- haproxy_service_name: extra-non-inventory-service
haproxy_backend_nodes:
- name: nonInvHost01
ip_addr: 172.0.1.1
- name: nonInvHost02
ip_addr: 172.0.1.2
- name: nonInvHost03
ip_addr: 172.0.1.3
haproxy_ssl: "{{ haproxy_ssl }}"
haproxy_port: 10001
haproxy_balance_type: http
添加额外的全局 VIP 地址¶
在某些情况下,您可能需要向负载均衡器前端添加额外的内部 VIP 地址。您可以使用 HAProxy 角色通过在 extra_lb_vip_addresses 或 extra_lb_tls_vip_addresses 变量中设置它们来将额外的 VIP 添加到所有前端。
以下示例显示了在 user_variables.yml 文件中定义的额外 VIP 地址
extra_lb_vip_addresses:
- 10.0.0.10
- 192.168.0.10
以下示例显示了在 user_variables.yml 文件中定义的启用了 TLS 的额外 VIP 地址
extra_lb_tls_vip_addresses:
- 10.0.0.10
- 192.168.0.10
控制 HAProxy 前端绑定¶
HAProxy 前端可以绑定到特定的 IP(VIP)地址或以太网接口。控制此行为的变量是 haproxy_vip_binds。除非在服务级别定义了 haproxy_bind,否则它将用于该服务。在这种情况下,service.haproxy_bind 的优先级高于 haproxy_vip_binds。
haproxy_vip_binds 由角色根据其他“便利”变量生成,例如 haproxy_bind_external_lb_vip_address、haproxy_bind_external_lb_vip_interface、haproxy_bind_internal_lb_vip_address 和 haproxy_bind_internal_lb_vip_interface。
尽管如此,您仍然可以覆盖 haproxy_vip_binds 来精细控制 HAProxy 实例的绑定过程。
覆盖 HAProxy 绑定的地址¶
在某些情况下,您可能希望覆盖 HAProxy 绑定到 external_lb_vip_address 和 internal_lb_vip_address 中指定的地址的默认行为。例如,如果这些是主机名,而您希望 HAProxy 绑定到 IP 地址,同时为 TLS 证书和端点 URI 保留名称。
这可以在 user_variables.yml 文件中设置
haproxy_bind_external_lb_vip_address: 10.0.0.10
haproxy_bind_internal_lb_vip_address: 192.168.0.10
将 HAProxy 绑定到接口¶
在某些情况下,将 HAProxy 绑定到接口而不是特定 IP 地址可能更方便。例如,如果您决定使用 DNS RR 在 HAProxy 实例之间进行负载均衡,每个 HAProxy 都有自己的 VIP,这些 VIP 将故障转移到其他实例,那么这种方式非常有用。
可以通过在 user_variables.yml 文件中提供以下变量来设置绑定到接口
haproxy_bind_external_lb_vip_address: "*"
haproxy_bind_internal_lb_vip_address: "*"
haproxy_bind_external_lb_vip_interface: bond0
haproxy_bind_internal_lb_vip_interface: br-mgmt
向 HAProxy 前端添加访问控制列表¶
在 HAProxy 中添加 ACL 规则很容易。您只需定义 haproxy_acls 并在变量中添加规则
这是一个示例,展示了如何实现此目标
- haproxy_service_name: influxdb-relay
haproxy_acls:
write_queries:
rule: "path_sub -i write"
read_queries:
rule: "path_sub -i query"
backend_name: "influxdb"
这将向前端添加两条 acl 规则 path_sub -i write 和 path_sub -i query,并使用规则中指定的后端。如果没有指定后端,它将使用默认的 haproxy_service_name 后端。
如果前端服务通过 ACL 指向多个后端服务,并且后端服务不需要其自己的对应前端,则可以指定 haproxy_backend_only 选项
- haproxy_service_name: influxdb
haproxy_backend_only: true # Directed by the 'influxdb-relay' service above
haproxy_backend_nodes:
- name: influxdb-service
ip_addr: 10.100.10.10
为 HAProxy 添加 Prometheus 指标¶
自 HAProxy 2.0 起,可以公开 Prometheus 指标。https://www.haproxy.com/blog/haproxy-exposes-a-prometheus-metrics-endpoint 如果您需要为它创建一个前端,可以使用 haproxy_frontend_only 选项
- haproxy_service_name: prometheus-metrics
haproxy_port: 8404
haproxy_bind:
- '127.0.0.1'
haproxy_whitelist_networks: "{{ haproxy_whitelist_networks }}"
haproxy_frontend_only: True
haproxy_frontend_raw:
- 'http-request use-service prometheus-exporter if { path /metrics }'
haproxy_service_enabled: True
haproxy_balance_type: 'http'