openstack-ansible-haproxy_s.../doc/source/configure-haproxy.rst
Danny Meloy 8120c9a3c5 Add haproxy_backend_only flag to service template
Addition of a `haproxy_backend_only` flag to the service template
for instances in which a frontend service uses ACLs to propgate
requests to multiple backend services, and not all backend services
require a corresponding frontend. This should prevent the
proliferation of spurious frontend services.

Change-Id: I8c419be82cffd289ffcc5086afac923d6eb1a78a
2020-09-01 11:14:55 +00:00

372 lines
14 KiB
ReStructuredText

==============================
Configuring HAProxy (optional)
==============================
HAProxy provides load balancing services and SSL termination when hardware
load balancers are not available for high availability architectures deployed
by OpenStack-Ansible. The default HAProxy configuration provides highly-
available load balancing services via keepalived if there is more than one
host in the ``haproxy_hosts`` group.
.. important::
Ensure you review the services exposed by HAProxy and limit access
to these services to trusted users and networks only. For more details,
refer to the :dev_docs:`Securing network access to OpenStack services <reference/architecture/security.html#securing-network-access-to-openstack-services>` section.
.. note::
For a successful installation, you require a load balancer. You may
prefer to make use of hardware load balancers instead of HAProxy. If hardware
load balancers are in use, then implement the load balancing configuration for
services prior to executing the deployment.
To deploy HAProxy within your OpenStack-Ansible environment, define target
hosts to run HAProxy:
.. code-block:: yaml
haproxy_hosts:
infra1:
ip: 172.29.236.101
infra2:
ip: 172.29.236.102
infra3:
ip: 172.29.236.103
There is an example configuration file already provided in
``/etc/openstack_deploy/conf.d/haproxy.yml.example``. Rename the file to
``haproxy.yml`` and configure it with the correct target hosts to use HAProxy
in an OpenStack-Ansible deployment.
Making HAProxy highly-available
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If multiple hosts are found in the inventory, deploy
HAProxy in a highly-available manner by installing keepalived.
To make keepalived work, edit at least the following variables
in ``user_variables.yml``:
.. code-block:: yaml
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`` and
``haproxy_keepalived_external_interface`` represent the interfaces on the
deployed node where the keepalived nodes bind the internal and external
vip. By default, use ``br-mgmt``.
- On the interface listed above, ``haproxy_keepalived_internal_vip_cidr`` and
``haproxy_keepalived_external_vip_cidr`` represent the internal and
external (respectively) vips (with their prefix length).
- Set additional variables to adapt keepalived in your deployment.
Refer to the ``user_variables.yml`` for more descriptions.
To always deploy (or upgrade to) the latest stable version of keepalived.
Edit the ``/etc/openstack_deploy/user_variables.yml``:
.. code-block:: yaml
keepalived_use_latest_stable: True
The HAProxy nodes have group vars applied that define the configuration
of keepalived. This configuration is stored in
``group_vars/haproxy_all/keepalived.yml``. It contains the variables
needed for the keepalived role (master and backup nodes).
Keepalived pings a public IP address to check its status. The default
address is ``193.0.14.129``. To change this default,
set the ``keepalived_ping_address`` variable in the
``user_variables.yml`` file.
.. note::
The keepalived test works with IPv4 addresses only.
You can adapt keepalived to your environment by either using our override
mechanisms (per host with userspace ``host_vars``, per group with
userspace``group_vars``, or globally using the userspace
``user_variables.yml`` file)
If you wish to deploy multiple haproxy hosts without keepalived and
provide your own means for failover between them, edit
``/etc/openstack_deploy/user_variables.yml`` to skip the deployment
of keepalived.
To do this, set the following:
.. code-block:: yaml
haproxy_use_keepalived: False
Configuring keepalived ping checks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
OpenStack-Ansible configures keepalived with a check script that pings an
external resource and uses that ping to determine if a node has lost network
connectivity. If the pings fail, keepalived fails over to another node and
HAProxy serves requests there.
The destination address, ping count and ping interval are configurable via
Ansible variables in ``/etc/openstack_deploy/user_variables.yml``:
.. code-block:: yaml
keepalived_ping_address: # IP address to ping
keepalived_ping_count: # ICMP packets to send (per interval)
keepalived_ping_interval: # How often ICMP packets are sent
By default, OpenStack-Ansible configures keepalived to ping one of the root
DNS servers operated by RIPE. You can change this IP address to a different
external address or another address on your internal network.
Securing HAProxy communication with SSL certificates
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The OpenStack-Ansible project provides the ability to secure HAProxy
communications with self-signed or user-provided SSL certificates. By default,
self-signed certificates are used with HAProxy. However, you can
provide your own certificates by using the following Ansible variables:
.. code-block:: yaml
haproxy_user_ssl_cert: # Path to certificate
haproxy_user_ssl_key: # Path to private key
haproxy_user_ssl_ca_cert: # Path to CA certificate
Refer to `Securing services with SSL certificates`_ for more information on
these configuration options and how you can provide your own
certificates and keys to use with HAProxy. User provided certificates should
be folded and formatted at 64 characters long. Single line certificates
will not be accepted by HAProxy and will result in SSL validation failures.
Please have a look here for information on `converting your certificate to
various formats <https://search.thawte.com/support/ssl-digital-certificates/index?page=content&actp=CROSSLINK&id=SO26449>`_.
Using Certificates from LetsEncrypt
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you want to use `LetsEncrypt SSL Service <https://letsencrypt.org/>`_
you can activate the feature by providing the following configuration in
``/etc/openstack_deploy/user_variables.yml``. Note that this requires
that ``external_lb_vip_address`` in
``/etc/openstack_deploy/openstack_user_config.yml`` is set to the
external DNS address.
The following variables must be set for the haproxy hosts.
.. code-block:: yaml
haproxy_ssl_letsencrypt_enable: True
haproxy_ssl_letsencrypt_install_method: "distro"
haproxy_ssl_letsencrypt_setup_extra_params: "--http-01-address {{ ansible_host }} --http-01-port 8888"
haproxy_ssl_letsencrypt_email: example@example.com
haproxy_interval: 2000
The following variables serve as an example for how to configure a
single HAProxy providing SSL termination for a service on the same
host, served from 127.0.0.1:80. An additional HAProxy backend is
configured which will receive the acme-challenge requests when
certificates are renewed.
.. code-block:: yaml
haproxy_service_configs:
# the external facing service which serves the apache test site, with a acl for LE requests
- service:
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
- service:
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
It is possible to use an HA configuration of HAProxy with certificates
initialised and renewed using certbot by setting haproxy_backend_nodes
for the LetsEncrypt service to include all HAProxy internal addresses.
Each HAProxy instance will be checking for certbot running on its own
node plus each of the others, and direct any incoming acme-challenge
requests to the HAProxy instance which is performing a renewal.
It is necessary to configure certbot to bind to the HAproxy node local
internal IP address via the --http-01-address parameter in a H/A setup
Using Certificates from LetsEncrypt (legacy method)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you want to use `LetsEncrypt SSL Service <https://letsencrypt.org/>`_
you can activate the feature by providing the following configuration in
``/etc/openstack_deploy/user_variables.yml``. Note that this requires
that ``external_lb_vip_address`` in
``/etc/openstack_deploy/openstack_user_config.yml`` is set to the
external DNS address.
.. code-block:: yaml
haproxy_ssl_letsencrypt_enable: true
haproxy_ssl_letsencrypt_email: example@example.com
.. warning::
There is no certificate distribution implementation at this time, so
this will only work for a single haproxy-server environment. The
renewal is automatically handled via CRON and currently will shut
down haproxy briefly during the certificate renewal. The
haproxy shutdown/restart will result in a brief service interruption.
.. _Securing services with SSL certificates: https://docs.openstack.org/project-deploy-guide/openstack-ansible/draft/app-advanced-config-sslcertificates.html
Configuring additional services
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Additional haproxy service entries can be configured by setting
``haproxy_extra_services`` in ``/etc/openstack_deploy/user_variables.yml``
For more information on the service dict syntax, please reference
``playbooks/vars/configs/haproxy_config.yml``
An example HTTP service could look like:
.. code-block:: yaml
haproxy_extra_services:
- service:
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 if certificate validation should be disabled
# haproxy_backend_ca: False
Additionally, you can specify haproxy services that are not managed
in the Ansible inventory by manually specifying their hostnames/IP Addresses:
.. code-block:: yaml
haproxy_extra_services:
- service:
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
Adding additional global VIP addresses
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In some cases, you might need to add additional internal VIP addresses
to the load balancer front end. You can use the HAProxy role to add
additional VIPs to all front ends by setting them in the
``extra_lb_vip_addresses`` or ``extra_lb_tls_vip_addresses`` variables.
The following example shows extra VIP addresses defined in the
``user_variables.yml`` file:
.. code-block:: yaml
extra_lb_vip_addresses:
- 10.0.0.10
- 192.168.0.10
The following example shows extra VIP addresses with TLS enabled
defined in the ``user_variables.yml`` file:
.. code-block:: yaml
extra_lb_tls_vip_addresses:
- 10.0.0.10
- 192.168.0.10
Overriding the address haproxy will bind to
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In some cases you may want to override the default of having haproxy
bind to the addresses specified in ``external_lb_vip_address`` and
``internal_lb_vip_address``. For example if those are hostnames and you
want haproxy to bind to IP addresses while preserving the names for TLS-
certificates and endpoint URIs.
This can be set in the ``user_variables.yml`` file:
.. code-block:: yaml
haproxy_bind_external_lb_vip_address: 10.0.0.10
haproxy_bind_internal_lb_vip_address: 192.168.0.10
Adding Access Control Lists to HAProxy front end
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Adding ACL rules in HAProxy is easy. You just need to define haproxy_acls and
add the rules in the variable
Here is an example that shows how to achieve the goal
.. code-block:: yaml
- service:
haproxy_service_name: influxdb-relay
haproxy_acls:
write_queries:
rule: "path_sub -i write"
read_queries:
rule: "path_sub -i query"
backend_name: "influxdb"
This will add two acl rules ``path_sub -i write`` and ``path_sub -i query`` to
the front end and use the backend specified in the rule. If no backend is specified
it will use a default ``haproxy_service_name`` backend.
If a frontend service directs to multiple backend services using ACLs, and a
backend service does not require its own corresponding front-end, the
`haproxy_backend_only` option can be specified:
.. code-block:: yaml
- service:
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