ansible-collections / ansible-consul

:satellite: Ansible role for Hashicorp Consul clusters
https://galaxy.ansible.com/ansible-community/consul/
BSD 2-Clause "Simplified" License
450 stars 313 forks source link
ansible ansible-role consul hacktoberfest hashicorp service-discovery

Consul

Molecule Average time to resolve an issue Percentage of issues still open

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.

Role Philosophy

“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!

Role migration and installation

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

Requirements

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

Caveats

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.

Role Variables

The role uses variables defined in these 3 places:

: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

consul_architecture_map

consul_architecture

consul_os

consul_install_dependencies

consul_zip_url

consul_checksum_file_url

consul_bin_path

consul_config_path

consul_configd_path

consul_data_path

consul_configure_syslogd

consul_log_path

consul_log_file

consul_log_rotate_bytes

consul_log_rotate_duration

consul_log_rotate_max_files

consul_syslog_facility

syslog_user

syslog_group

consul_run_path

consul_user

consul_manage_user

consul_group

consul_manage_group

consul_group_name

consul_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_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_domain

consul_alt_domain

consul_node_meta

consul_log_level

consul_syslog_enable

consul_iface

consul_bind_address

consul_advertise_address

consul_advertise_address_wan

consul_translate_wan_address

consul_advertise_addresses

consul_client_address

consul_addresses

consul_ports

For example, to enable the consul HTTPS API it is possible to set the variable as follows:

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_iptables_enable

consul_acl_policy

consul_acl_enable

consul_acl_ttl

consul_acl_token_persistence

consul_acl_datacenter

consul_acl_down_policy

consul_acl_token

consul_acl_agent_token

consul_acl_agent_master_token

consul_acl_default_policy

consul_acl_master_token

consul_acl_master_token_display

consul_acl_replication_enable

consul_acl_replication_token

consul_tls_enable

consul_tls_copy_keys

consul_tls_dir

consul_tls_ca_crt

consul_tls_server_crt

consul_tls_server_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_outgoing

consul_tls_verify_incoming_rpc

consul_tls_verify_incoming_https

consul_tls_verify_server_hostname

consul_tls_min_version

consul_tls_cipher_suites

consul_tls_prefer_server_cipher_suites

auto_encrypt

auto_encrypt:
  enabled: true
  dns_san: ["consul.com"]
  ip_san: ["127.0.0.1"]

consul_force_install

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_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_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_last_contact_threshold

Used in the serf health check to determine node health.

consul_autopilot_max_trailing_logs

consul_autopilot_server_stabilization_time

consul_autopilot_redundancy_zone_tag

_Consul Enterprise Only (requires that CONSULENTERPRISE is set to true)

consul_autopilot_disable_upgrade_migration

_Consul Enterprise Only (requires that CONSULENTERPRISE is set to true)

consul_autopilot_upgrade_version_tag

_Consul Enterprise Only (requires that CONSULENTERPRISE is set to true)

consul_debug

consul_config_template_path

consul_rolling_restart

Custom Configuration Section

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

Consul snapshot agent takes backup snaps on a set interval and stores them. Must have enterprise

consul_snapshot

consul_snapshot_storage

consul_snapshot_interval

consul_snapshot_retain

OS and Distribution Variables

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_centos_url

consul_centos_sha256

consul_centos_os_packages

consul_debian_pkg

consul_debian_url

consul_debian_sha256

consul_debian_os_packages

consul_redhat_pkg

consul_redhat_url

consul_redhat_sha256

consul_redhat_os_packages

consul_systemd_restart_sec

consul_systemd_limit_nofile

consul_systemd_restart

consul_ubuntu_pkg

consul_ubuntu_url

consul_ubuntu_sha256

consul_ubuntu_os_packages

consul_windows_pkg

consul_windows_url

consul_windows_sha256

consul_windows_os_packages

consul_performance

raft_multiplier

leave_drain_time

rpc_hold_timeout

leave_on_terminate

consul_limit

Dependencies

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.

Example Playbook

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:

  1. Executes consul role (installs Consul and bootstraps cluster)
  2. Reconfigures bootstrap node to run without bootstrap-expect setting
  3. Restarts bootstrap node

ACL Support

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.

Dnsmasq DNS Forwarding Support

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_bind_interfaces

consul_dnsmasq_consul_address

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

iptables DNS Forwarding Support

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.

TLS Support

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:

Then either set the environment variable CONSUL_TLS_ENABLE=true or use the Ansible variable consul_tls_enable=true at role runtime.

Service management Support

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.

Vagrant and VirtualBox

See examples/README_VAGRANT.md for details on quick Vagrant deployments under VirtualBox for development, evaluation, testing, etc.

License

BSD

Author Information

Brian Shumate

Contributors

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.