:satellite: Ansible role for Hashicorp Consul clusters
This Ansible role installs Consul, including establishing a filesystem structure and server or client agent configuration with support for some common operational features.
It can also bootstrap a development or evaluation cluster of 3 server agents running in a Vagrant and VirtualBox based environment. See README_VAGRANT.md and the associated Vagrantfile for more details.
“Another flaw in the human character is that everybody wants to build and nobody wants to do maintenance.”
― Kurt Vonnegut, Hocus Pocus
Please note that the original design goal of this role was more concerned with the initial installation and bootstrapping of a Consul server cluster environment and so it does not currently concern itself (all that much) with performing ongoing maintenance of a cluster.
Many users have expressed that the Vagrant based environment makes getting a working local Consul server cluster environment up and running an easy process — so this role will target that experience as a primary motivator for existing.
If you get some mileage from it in other ways, then all the better!
This role was originally developed by Brian Shumate and was known on Ansible Galaxy as brianshumate.consul. Brian asked the community to be relieved of the maintenance burden, and therefore Bas Meijer transferred the role to ansible-collections so that a team of volunteers can maintain it. To install this role into your project you should create a file requirements.yml
in the subdirectory roles/
of your project with this content:
---
- src: https://github.com/ansible-collections/ansible-consul.git
name: ansible-consul
scm: git
version: master
This repo has tagged releases that you can use to pin the version.
Tower will install the role automatically, if you use the CLI to control ansible, then install it like:
ansible-galaxy install -p roles -r roles/requirements.yml
This role requires a FreeBSD, Debian, or Red Hat Enterprise Linux distribution or Windows Server 2012 R2.
The role might work with other OS distributions and versions, but is known to function well with the following software versions:
Note that for the "local" installation mode (the default), this role will locally download only one instance of the Consul archive, unzip it and install the resulting binary on all desired Consul hosts.
To do so requires that unzip
is available on the Ansible control host and the role will fail if it doesn't detect unzip
in the PATH.
Collection requirements for this role are listed in the requirements.yml
file. It is your responsibility to make sure that you install these collections to ensure that the role runs properly. Usually, this can be done with:
ansible-galaxy collection install -r requirements.yml
This role does not fully support the limit option (ansible -l
) to limit the hosts, as this will break populating required host variables. If you do use the limit option with this role, you can encounter template errors like:
Undefined is not JSON serializable.
The role uses variables defined in these 3 places:
examples/vagrant_hosts
for an example)vars/*.yml
(primarily OS/distributions specific variables)defaults/main.yml
(everything else):warning: NOTE: The role relies on the inventory host group for the consul servers to be defined as the variable
consul_group_name
and it will not function properly otherwise. Alternatively the consul servers can be placed in the default host group[consul_instances]
in the inventory as shown in the examples below.
Many role variables can also take their values from environment variables as well; those are noted in the description where appropriate.
consul_version
latest
for the latest available version of consulconsul_architecture_map
consul_architecture
{{ consul_architecture_map[ansible_architecture] }}
consul_os
{{ ansible_os_family | lower }}
consul_install_dependencies
consul_zip_url
https://releases.hashicorp.com/consul/{{ consul_version }}/consul_{{ consul_version }}_{{ consul_os }}_{{ consul_architecture }}.zip
consul_checksum_file_url
https://releases.hashicorp.com/consul/{{ consul_version }}/{{ consul_version }}_SHA256SUMS
consul_bin_path
/usr/local/bin
C:\ProgramData\consul\bin
consul_config_path
/etc/consul
C:\ProgramData\consul\config
consul_configd_path
{{ consul_config_path }}/consul.d
C:\ProgramData\consul\config.d
consul_data_path
/opt/consul
C:\ProgramData\consul\data
consul_configure_syslogd
consul_syslog_enable
is true, but the syslog daemon won't be configured to write Consul logs to their own logfile.
CONSUL_CONFIGURE_SYSLOGD
environment variableconsul_log_path
consul_syslog_enable
is false
consul_syslog_enable
is true
consul_configure_syslogd
is false./var/log/consul
CONSUL_LOG_PATH
environment variableC:\ProgramData\consul\log
consul_log_file
consul_syslog_enable
is false
consul_syslog_enable
is true
consul_configure_syslogd
is false.CONSUL_LOG_FILE
environment variableconsul.log
consul_log_rotate_bytes
CONSUL_LOG_ROTATE_BYTES
environment variableconsul_syslog_enable
is trueconsul_log_rotate_duration
CONSUL_LOG_ROTATE_DURATION
environment variableconsul_syslog_enable
is trueconsul_log_rotate_max_files
CONSUL_LOG_ROTATE_MAX_FILES
environment variableconsul_syslog_enable
is trueconsul_syslog_facility
CONSUL_SYSLOG_FACILITY
environment variablesyslog_user
rsyslogd
process on Linux. consul_log_path
's ownership is set to this user on Linux. Ignored if consul_configure_syslogd
is false.
SYSLOG_USER
environment variablesyslog_group
rsyslogd
process on Linux. consul_log_path
's group ownership is set to this group on Linux. Ignored if consul_configure_syslogd
is false.
SYSLOG_GROUP
environment variableconsul_run_path
/run/consul
C:\ProgramData\consul
consul_user
consul_manage_user
consul_user
or notconsul_group
consul_manage_group
consul_group
or notconsul_group_name
CONSUL_GROUP_NAME
environment variableconsul_retry_interval
consul_retry_interval_wan
consul_retry_join_skip_hosts
consul_retry_max
consul_retry_max_wan
consul_join
consul_join_wan
consul_servers
It's typically not necessary to manually alter this list.
consul_group_name
with
consul_node_role
set to server or bootstrapconsul_bootstrap_expect
consul_bootstrap_expect_value
consul_gather_server_facts
This feature makes it possible to gather the consul_advertise_address(_wan)
from servers that are currently not targeted by the playbook.
To make this possible the delegate_facts
option is used; note that his option has been problematic.
consul_datacenter
CONSUL_DATACENTER
environment variable- Default value: dc1
consul_domain
CONSUL_DOMAIN
environment variableconsul_alt_domain
CONSUL_ALT_DOMAIN
environment variableconsul_node_meta
consul_node_meta:
node_type: "my-custom-type"
node_meta1: "metadata1"
node_meta2: "metadata2"
consul_log_level
CONSUL_LOG_LEVEL
environment variableconsul_syslog_enable
CONSUL_SYSLOG_ENABLE
environment variableconsul_iface
CONSUL_IFACE
environment variable{{ ansible_default_ipv4.interface }}
consul_bind_address
CONSUL_BIND_ADDRESS
environment variableconsul_iface
consul_advertise_address
consul_bind_address
consul_advertise_address_wan
consul_bind_address
consul_translate_wan_address
consul_advertise_addresses
consul_advertise_addresses_*
variablesconsul_advertise_addresses:
serf_lan: "{{ consul_advertise_addresses_serf_lan | default(consul_advertise_address+':'+consul_ports.serf_lan) }}"
serf_wan: "{{ consul_advertise_addresses_serf_wan | default(consul_advertise_address_wan+':'+consul_ports.serf_wan) }}"
rpc: "{{ consul_advertise_addresses_rpc | default(consul_bind_address+':'+consul_ports.server) }}"
consul_client_address
consul_addresses
consul_addresses_*
variablesconsul_addresses:
dns: "{{ consul_addresses_dns | default(consul_client_address, true) }}"
http: "{{ consul_addresses_http | default(consul_client_address, true) }}"
https: "{{ consul_addresses_https | default(consul_client_address, true) }}"
rpc: "{{ consul_addresses_rpc | default(consul_client_address, true) }}"
grpc: "{{ consul_addresses_grpc | default(consul_client_address, true) }}"
grpc_tls: "{{ consul_addresses_grpc_tls | default(consul_client_address, true) }}"
consul_ports
For example, to enable the consul HTTPS API it is possible to set the variable as follows:
consul_ports:
dns: "{{ consul_ports_dns | default('8600', true) }}"
http: "{{ consul_ports_http | default('8500', true) }}"
https: "{{ consul_ports_https | default('-1', true) }}"
rpc: "{{ consul_ports_rpc | default('8400', true) }}"
serf_lan: "{{ consul_ports_serf_lan | default('8301', true) }}"
serf_wan: "{{ consul_ports_serf_wan | default('8302', true) }}"
server: "{{ consul_ports_server | default('8300', true) }}"
grpc: "{{ consul_ports_grpc | default('-1', true) }}"
grpc_tls: "{{ consul_ports_grpc_tls | default('-1', true) }}"
Notice that the dict object has to use precisely the names stated in the documentation! And all ports must be specified. Overwriting one or multiple ports can be done using the consul_ports_*
variables.
consul_node_name
consul_recursors
CONSUL_RECURSORS
environment variableconsul_iptables_enable
CONSUL_IPTABLES_ENABLE
environment variableconsul_acl_policy
CONSUL_ACL_POLICY
environment variableconsul_acl_enable
CONSUL_ACL_ENABLE
environment variableconsul_acl_ttl
CONSUL_ACL_TTL
environment variableconsul_acl_token_persistence
CONSUL_ACL_TOKEN_PERSISTENCE
environment variableconsul_acl_datacenter
CONSUL_ACL_DATACENTER
environment variable{{ consul_datacenter }}
(dc1
)consul_acl_down_policy
CONSUL_ACL_DOWN_POLICY
environment variableconsul_acl_token
CONSUL_ACL_TOKEN
environment variableconsul_acl_agent_token
CONSUL_ACL_AGENT_TOKEN
environment variableconsul_acl_agent_master_token
CONSUL_ACL_AGENT_MASTER_TOKEN
environment variableconsul_acl_default_policy
CONSUL_ACL_DEFAULT_POLICY
environment variableconsul_acl_master_token
CONSUL_ACL_MASTER_TOKEN
environment variableconsul_acl_master_token_display
CONSUL_ACL_MASTER_TOKEN_DISPLAY
environment variableconsul_acl_replication_enable
CONSUL_ACL_REPLICATION_TOKEN_ENABLE
environment variableconsul_acl_replication_token
CONSUL_ACL_REPLICATION_TOKEN_DISPLAY
environment variableconsul_tls_enable
CONSUL_ACL_TLS_ENABLE
environment variableconsul_tls_copy_keys
consul_tls_enable
) but want to manage the
TLS files on your ownconsul_tls_dir
CONSUL_TLS_DIR
environment variable/etc/consul/ssl
consul_tls_ca_crt
CONSUL_TLS_CA_CRT
environment variableca.crt
consul_tls_server_crt
CONSUL_TLS_SERVER_CRT
environment variableserver.crt
consul_tls_server_key
CONSUL_TLS_SERVER_KEY
environment variableserver.key
consul_tls_files_remote_src
consul_encrypt_enable
consul_encrypt_verify_incoming
consul_encrypt_verify_outgoing
consul_disable_keyring_file
consul_raw_key
consul_tls_verify_incoming
CONSUL_TLS_VERIFY_INCOMING
environment variableconsul_tls_verify_outgoing
CONSUL_TLS_VERIFY_OUTGOING
environment variableconsul_tls_verify_incoming_rpc
CONSUL_TLS_VERIFY_INCOMING_RPC
environment variableconsul_tls_verify_incoming_https
CONSUL_TLS_VERIFY_INCOMING_HTTPS
environment variableconsul_tls_verify_server_hostname
CONSUL_TLS_VERIFY_SERVER_HOSTNAME
environment variableconsul_tls_min_version
CONSUL_TLS_MIN_VERSION
environment variableconsul_tls_cipher_suites
consul_tls_prefer_server_cipher_suites
CONSUL_TLS_PREFER_SERVER_CIPHER_SUITES
environment variableauto_encrypt
auto_encrypt:
enabled: false
auto_encrypt:
enabled: true
dns_san: ["consul.com"]
ip_san: ["127.0.0.1"]
consul_force_install
consul_version
.consul_install_remotely
consul_install_from_repo
consul_ui
consul_ui_legacy
consul_disable_update_check
consul_enable_script_checks
consul_enable_local_script_checks
.consul_enable_local_script_checks
consul_raft_protocol
consul_node_role
One server should be designated as the bootstrap server, and the other servers will connect to this server. You can also specify client as the role, and Consul will be configured as a client agent instead of a server.
There are two methods to setup a cluster, the first one is to explicitly choose the bootstrap server, the other one is to let the servers elect a leader among themselves.
Here is an example of how the hosts inventory could be defined for a simple cluster of 3 servers, the first one being the designated bootstrap / leader:
[consul_instances]
consul1.consul consul_node_role=bootstrap
consul2.consul consul_node_role=server
consul3.consul consul_node_role=server
consul4.local consul_node_role=client
Or you can use the simpler method of letting them do their election process:
[consul_instances]
consul1.consul consul_node_role=server consul_bootstrap_expect=true
consul2.consul consul_node_role=server consul_bootstrap_expect=true
consul3.consul consul_node_role=server consul_bootstrap_expect=true
consul4.local consul_node_role=client
Note that this second form is the preferred one, because it is simpler.
consul_autopilot_enable
Autopilot is a set of new features added in Consul 0.8 to allow for automatic operator-friendly management of Consul servers. It includes cleanup of dead servers, monitoring the state of the Raft cluster, and stable server introduction.
https://www.consul.io/docs/guides/autopilot.html
CONSUL_AUTOPILOT_ENABLE
environment variableconsul_autopilot_cleanup_dead_Servers
Dead servers will periodically be cleaned up and removed from the Raft peer set, to prevent them from interfering with the quorum size and leader elections. This cleanup will also happen whenever a new server is successfully added to the cluster.
CONSUL_AUTOPILOT_CLEANUP_DEAD_SERVERS
environment variableconsul_autopilot_last_contact_threshold
Used in the serf health check to determine node health.
CONSUL_AUTOPILOT_LAST_CONTACT_THRESHOLD
environment variableconsul_autopilot_max_trailing_logs
CONSUL_AUTOPILOT_MAX_TRAILING_LOGS
environment variableconsul_autopilot_server_stabilization_time
CONSUL_AUTOPILOT_SERVER_STABILIZATION_TIME
environment variableconsul_autopilot_redundancy_zone_tag
Consul Enterprise Only (requires that CONSUL_ENTERPRISE is set to true)
CONSUL_AUTOPILOT_REDUNDANCY_ZONE_TAG
environment variableconsul_autopilot_disable_upgrade_migration
Consul Enterprise Only (requires that CONSUL_ENTERPRISE is set to true)
CONSUL_AUTOPILOT_DISABLE_UPGRADE_MIGRATION
environment variableconsul_autopilot_upgrade_version_tag
Consul Enterprise Only (requires that CONSUL_ENTERPRISE is set to true)
CONSUL_AUTOPILOT_UPGRADE_VERSION_TAG
environment variableconsul_debug
consul_config_template_path
templates/config.json.j2
.consul_rolling_restart
consul_rolling_restart_delay_sec
As Consul loads the configuration from files and directories in lexical order, typically merging on top of previously parsed configuration files, you may set custom configurations via consul_config_custom
, which will be expanded into a file named config_z_custom.json
within your consul_config_path
which will be loaded after all other configuration by default.
An example usage for enabling telemetry
:
vars:
consul_config_custom:
telemetry:
dogstatsd_addr: "localhost:8125"
dogstatsd_tags:
- "security"
- "compliance"
disable_hostname: true
Consul snapshot agent takes backup snaps on a set interval and stores them. Must have enterprise
consul_snapshot
consul_snapshot_storage
{{ consul_config_path }}/snaps
consul_snapshot_interval
consul_snapshot_retain
The consul
binary works on most Linux platforms and is not distribution
specific. However, some distributions require installation of specific OS
packages with different package names.
consul_centos_pkg
{{ consul_version }}_linux_amd64.zip
consul_centos_url
{{ consul_zip_url }}
consul_centos_sha256
consul_centos_os_packages
consul_debian_pkg
{{ consul_version }}_linux_amd64.zip
consul_debian_url
{{ consul_zip_url }}
consul_debian_sha256
consul_debian_os_packages
consul_redhat_pkg
{{ consul_version }}_linux_amd64.zip
consul_redhat_url
{{ consul_zip_url }}
consul_redhat_sha256
consul_redhat_os_packages
RestartSec
optionLimitNOFILE
optionRestart
optionon-failure
consul_ubuntu_pkg
{{ consul_version }}_linux_amd64.zip
consul_ubuntu_url
{{ consul_zip_url }}
consul_ubuntu_sha256
consul_ubuntu_os_packages
consul_windows_pkg
{{ consul_version }}_windows_amd64.zip
consul_windows_url
{{ consul_zip_url }}
consul_windows_sha256
consul_windows_os_packages
consul_performance
raft_multiplier
leave_drain_time
Node leave drain time is the dwell time for a server to honor requests while gracefully leaving
Default value: 5s
rpc_hold_timeout
leave_on_terminate
consul_limit
consul_limits:
http_max_conns_per_client: 250
rpc_max_conns_per_client: 150
Ansible requires GNU tar and this role performs some local use of the unarchive module for efficiency, so ensure that your system has gtar
and unzip
installed and in the PATH. If you don't this role will install unzip
on the remote machines to unarchive the ZIP files.
If you're on system with a different (i.e. BSD) tar
, like macOS and you see odd errors during unarchive tasks, you could be missing gtar
.
Installing Ansible on Windows requires the PowerShell Community Extensions. These already installed on Windows Server 2012 R2 and onward. If you're attempting this role on Windows Server 2008 or earlier, you'll want to install the extensions here.
Basic installation is possible using the included site.yml
playbook:
ansible-playbook -i hosts site.yml
You can also pass variables in using the --extra-vars
option to the
ansible-playbook
command:
ansible-playbook -i hosts site.yml --extra-vars "consul_datacenter=maui"
Be aware that for clustering, the included site.yml
does the following:
Basic support for ACLs is included in the role. You can set the environment variables CONSUL_ACL_ENABLE
to true, and also set the CONSUL_ACL_DATACENTER
environment variable to its correct value for your environment prior to executing your playbook; for example:
CONSUL_ACL_ENABLE=true CONSUL_ACL_DATACENTER=maui \
CONSUL_ACL_MASTER_TOKEN_DISPLAY=true ansible-playbook -i uat_hosts aloha.yml
If you want the automatically generated ACL Master Token value emitted to standard out during the play, set the environment variable CONSUL_ACL_MASTER_TOKEN_DISPLAY
to true as in the above example.
If you want to use existing tokens, set the environment variables CONSUL_ACL_MASTER_TOKEN
and CONSUL_ACL_REPLICATION_TOKEN
as well, for example:
CONSUL_ACL_ENABLE=true CONSUL_ACL_DATACENTER=stjohn \
CONSUL_ACL_MASTER_TOKEN=0815C55B-3AD2-4C1B-BE9B-715CAAE3A4B2 \
CONSUL_ACL_REPLICATION_TOKEN=C609E56E-DD0B-4B99-A0AD-B079252354A0 \
CONSUL_ACL_MASTER_TOKEN_DISPLAY=true ansible-playbook -i uat_hosts sail.yml
There are a number of Ansible ACL variables you can override to further refine your initial ACL setup. They are not all currently picked up from environment variables, but do have some sensible defaults.
Check defaults/main.yml
to see how some of he defaults (i.e. tokens) are automatically generated.
The role now includes support for DNS forwarding with Dnsmasq.
Enable like this:
ansible-playbook -i hosts site.yml --extra-vars "consul_dnsmasq_enable=true"
Then, you can query any of the agents via DNS directly via port 53, for example:
dig @consul1.consul consul3.node.consul
; <<>> DiG 9.8.3-P1 <<>> @consul1.consul consul3.node.consul
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 29196
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;consul3.node.consul. IN A
;; ANSWER SECTION:
consul3.node.consul. 0 IN A 10.1.42.230
;; Query time: 42 msec
;; SERVER: 10.1.42.210#53(10.1.42.210)
;; WHEN: Sun Aug 7 18:06:32 2016
;;
consul_delegate_datacenter_dns
consul_dnsmasq_enable
CONSUL_DNSMASQ_ENABLE
environment variableconsul_dnsmasq_bind_interfaces
consul_dnsmasq_listen_addresses
optionconsul_dnsmasq_consul_address
consul_address.dns
0.0.0.0
)consul_dnsmasq_cache
consul_dnsmasq_servers
consul_dnsmasq_revservers
consul_dnsmasq_no_poll
consul_dnsmasq_no_resolv
consul_dnsmasq_local_service
consul_dnsmasq_listen_addresses
consul_connect_enabled
consul_cleanup_ignore_files
This role can also use iptables instead of Dnsmasq for forwarding DNS queries to Consul. You can enable it like this:
ansible-playbook -i hosts site.yml --extra-vars "consul_iptables_enable=true"
Note that iptables forwarding and DNSmasq forwarding cannot be used simultaneously and the execution of the role will stop with error if such a configuration is specified.
You can enable TLS encryption by dropping a CA certificate, server certificate, and server key into the role's files
directory.
By default these are named:
ca.crt
(can be overridden by {{ consul_tls_ca_crt }})server.crt
(can be overridden by {{ consul_tls_server_crt }})server.key
(can be overridden by {{ consul_tls_server_key }})Then either set the environment variable CONSUL_TLS_ENABLE=true
or use the Ansible variable consul_tls_enable=true
at role runtime.
You can create a configuration file for consul services.
Add a list of service in the consul_services
.
name | Required | Type | Default | Comment |
---|---|---|---|---|
consul_services | False | List | [] |
List of service object (see below) |
Services object:
name | Required | Type | Default | Comment |
---|---|---|---|---|
name | True | string | Name of the service | |
id | False | string | Id of the service | |
tags | False | list | List of string tags | |
address | False | string | service-specific IP address | |
meta | False | dict | Dict of 64 key/values with string semantics | |
port | False | int | Port of the service | |
enable_tag_override | False | bool | enable/disable the anti-entropy feature for the service | |
kind | False | string | identify the service as a Connect proxy instance | |
proxy | False | dict | proxy configuration | |
checks | False | list | List of checks configuration | |
connect | False | dict | Connect object configuration | |
weights | False | dict | Weight of a service in DNS SRV responses | |
token | False | string | ACL token to use to register this service |
Configuration example:
consul_services:
- name: "openshift"
tags: ['production']
- name: "redis"
id: "redis"
tags: ['primary']
address: ""
meta:
meta: "for my service"
proxy:
destination_service_name: "redis"
destination_service_id: "redis1"
local_service_address: "127.0.0.1"
local_service_port: 9090
config: {}
upstreams: []
checks:
- args: ["/home/consul/check.sh"]
interval: "10s"
Then you can check that the service is well added to the catalog
> consul catalog services
consul
openshift
redis
Note: to delete a service that has been added from this role, remove it from the
consul_services
list and apply the role again.
See examples/README_VAGRANT.md for details on quick Vagrant deployments under VirtualBox for development, evaluation, testing, etc.
BSD
Special thanks to the folks listed in CONTRIBUTORS.md for their contributions to this project.
Contributions are welcome, provided that you can agree to the terms outlined in CONTRIBUTING.md.