114 lines
4.8 KiB
Markdown
114 lines
4.8 KiB
Markdown
Role Name
|
|
=========
|
|
|
|
A role that configures a docker swarm cluster, adding Portainer CE and HAPROXY
|
|
|
|
Role Variables
|
|
--------------
|
|
|
|
The most important variables are listed below:
|
|
|
|
``` yaml
|
|
docker_swarm_cluster_haproxy_install: true
|
|
# mesh, keepalive, global
|
|
docker_swarm_haproxy_installation_type: 'keepalive'
|
|
docker_swarm_haproxy_networks:
|
|
- '{{ docker_swarm_portainer_network }}'
|
|
#
|
|
docker_swarm_expose_api_via_haproxy: false
|
|
docker_swarm_expose_api_hostname: 'swarm.example.com'
|
|
# Portainer
|
|
docker_swarm_cluster_portainer_install: true
|
|
docker_swarm_portainer_hostname: 'portainer-swarm.example.com'
|
|
docker_swarm_portainer_additional_constraints: []
|
|
# - 'node.hostname != docker01'
|
|
docker_swarm_portainer_nfs_volume: false
|
|
docker_swarm_portainer_nfs_type: 'nfs4'
|
|
docker_swarm_portainer_nfs_o: 'nfsvers=4,addr=127.0.0.1,rw,nolock,soft'
|
|
docker_swarm_portainer_nfs_device: ':/tmp'
|
|
|
|
docker_swarm_portainer_network: 'agent_network'
|
|
docker_swarm_portainer_http_port: '9000'
|
|
docker_swarm_portainer_service_port: '8000'
|
|
|
|
docker_swarm_haproxy_additional_services: []
|
|
# - { acl_name: 'service', acl_rule: 'hdr_dom(host) -i service.example.com', service_name: 'service-', service_replica_num: '1', service_port: '9999', service_overlay_network: 'service-network', http_redirect_to_https: True }
|
|
```
|
|
|
|
HAPROXY configuration
|
|
------------
|
|
|
|
`docker_swarm_haproxy_plain_http_global_acl_rules` allows the definition of arbitrary acl with the corresponding http-request rules, for the *plain http* listener
|
|
`docker_swarm_haproxy_global_acl_rules` allows the definition of arbitrary acl with the corresponding http-request rules, for the *https* listener
|
|
|
|
`haproxy_docker_swarm_additional_services` is the dictionary that contains the backends definitions and their acls
|
|
|
|
A plain http listener can be defined, using the following variables. The syntax of `haproxy_docker_swarm_plain_http_services` is identical to the `haproxy_docker_swarm_additional_services` one.
|
|
|
|
```yaml
|
|
haproxy_docker_swarm_plain_http_listener: true
|
|
haproxy_docker_swarm_plain_http_port: 8080
|
|
haproxy_docker_swarm_plain_http_services: []
|
|
```
|
|
|
|
Optional HAProxy features
|
|
-------------------------
|
|
|
|
The generated `haproxy.cfg` can serve `robots.txt`, deny blacklisted user agents,
|
|
apply a per-source flood control with a browser-validation challenge, handle CORS
|
|
and enforce OIDC/JWT authentication. Everything is off by default; see
|
|
`defaults/main.yml` for the variables and the per-service opt-in fields.
|
|
|
|
**These features need files, and on Swarm HAProxy runs in a container.** The role
|
|
only writes the configuration: getting the files in place is a deployment
|
|
decision, and there are three ways to do it.
|
|
|
|
1. **Through the directory that is already mounted.** With
|
|
`haproxy_docker_mount_conf_file: true` the `haproxy` role bind-mounts
|
|
`/etc/haproxy` on the manager node to `/usr/local/etc/haproxy` inside the
|
|
container. Anything rendered under `/etc/haproxy/static/` and
|
|
`/etc/haproxy/lua/` is therefore visible to HAProxy with no additional volume,
|
|
and an in-place reload picks it up without recreating the service. The path
|
|
defaults in this role assume exactly this layout. It covers `robots.txt`, the
|
|
user-agent blacklists and `cors.lua`.
|
|
|
|
2. **Docker configs / secrets.** Cleaner distribution (the manager pushes them,
|
|
nothing to manage per node) but config objects are immutable: changing one
|
|
means creating a new object and updating the service, i.e. a rolling restart
|
|
instead of a reload. Reasonable for files that never change, awkward for
|
|
blacklists. Use a secret for the stats password if the config file is moved to
|
|
a config object, since config objects are not secret; HAProxy expands
|
|
`${VARIABLE}` from its environment, so a small entrypoint wrapper that exports
|
|
the secret file's content is enough.
|
|
|
|
3. **A custom image.** Required — not merely convenient — for the OIDC scripts:
|
|
they `require` cjson, socket, ssl and ltn12, and the stock
|
|
`haproxytech/haproxy-debian` image ships HAProxy built with Lua support but not
|
|
a single Lua module, which cannot be installed at run time. The build itself is
|
|
trivial, since that image is Debian based and the Debian/Ubuntu module packages
|
|
(`lua-cjson`, `lua-socket`, `lua-sec`) install for every Lua ABI from 5.1 to
|
|
5.4, so they cover whatever the image links. What it costs is owning an image
|
|
build and publish pipeline tied to HAProxy version bumps. `cors.lua` needs no
|
|
modules and works in the stock image.
|
|
|
|
Recommended split: option 1 for the static files and CORS, and either a custom
|
|
image or a separate `oauth2-proxy` service for OIDC. `oauth2-proxy` avoids the
|
|
image pipeline altogether and does not depend on the Lua code path, which has
|
|
never run in production.
|
|
|
|
Dependencies
|
|
------------
|
|
|
|
* docker
|
|
* keepalived, when haproxy is installed in HA host mode
|
|
|
|
License
|
|
-------
|
|
|
|
EUPL-1.2
|
|
|
|
Author Information
|
|
------------------
|
|
|
|
Andrea Dell'Amico, <andrea.dellamico@isti.cnr.it>
|