Skip to content
Snippets Groups Projects
Commit 1ce52077 authored by Thomas Schneider's avatar Thomas Schneider
Browse files

Add etcd role

parent 823bd185
No related branches found
No related tags found
No related merge requests found
Pipeline #5518 passed
---
etcd_manage_certs: false
etcd_ssl: "{{ etcd_manage_certs }}"
# etcd_ca_private_key_file: {{ inventory_dir }}/etcd_ca_key.pem
# etcd_ca_private_key_passphrase: hunter2
# etcd_ca_certificate_file: {{ inventory_dir }}/etcd_ca_cert.pem
etcd_listen_peer_url: >-
http{{ 's' if etcd_ssl }}://{{
lookup('community.general.dig', ansible_fqdn) }}:2380
etcd_listen_peer_urls:
- "{{ etcd_listen_peer_url }}"
etcd_listen_client_url: >-
http{{ 's' if etcd_ssl }}://{{
lookup('community.general.dig', ansible_fqdn) }}:2379
etcd_listen_client_urls:
- "{{ etcd_listen_client_url }}"
etcd_initial_advertise_peer_urls: "{{ etcd_listen_peer_urls }}"
etcd_advertise_client_urls: "{{ etcd_listen_client_urls }}"
etcd_member_url_format: "http{{ 's' if etcd_ssl }}://%s:2380"
# Set etcd_members to override automatic construction based on
# `etcd_member_url_format` and `ansible_play_hosts`
# etcd_members:
# a: https://10.0.0.1:2380
# b: https://10.0.0.2:2380
# c: https://10.0.0.3:2380
# Set `etcd_initial_cluster_token` to override automatic generation based on
# hashing `etcd_members`.
# etcd_initial_cluster_token: etcd-cluster
# Arbitrary extra config variables
# etcd_extra:
# wal_dir: /srv/ssd/etcd-wal
---
- name: Restart etcd
ansible.builtin.systemd:
name: etcd.service
state: restarted
---
- name: Check and configure CA
run_once: true
delegate_to: localhost
block:
- name: Check that CA private key exists
ansible.builtin.assert:
that:
- etcd_ca_private_key_file is defined
- etcd_ca_private_key_passphrase
fail_msg: >-
Please ensure `etcd_ca_private_key_file` points to a suitable private
key for the CA and `etcd_ca_private_key_passphrase` contains its
passphrase.
quiet: true
- name: Check that CA private key is usable
community.crypto.openssl_privatekey_info:
path: "{{ etcd_ca_private_key_file }}"
passphrase: "{{ etcd_ca_private_key_passphrase }}"
register: ca_privkey_check
failed_when: ca_privkey_check.failed or not ca_privkey_check.can_parse_key
- name: Check if CA certificate exists
community.crypto.x509_certificate_info:
path: "{{ etcd_ca_certificate_file }}"
register: ca_cert_exists
ignore_errors: true
- name: Create CA
when: ca_cert_exists.failed or ca_cert_exists.expired
block:
- name: Create CA CSR temporary file
ansible.builtin.tempfile: {}
register: tempfile
- name: Create CA CSR
community.crypto.openssl_csr:
common_name: etcd CA
basic_constraints_critical: true
basic_constraints:
- "CA:TRUE"
create_subject_key_identifier: true
key_usage_critical: true
key_usage:
- Certificate Sign
- CRL Sign
name_constraints_critical: true
name_constraints_excluded: >-
{{ etcd_ca_name_constraints_excluded | default(omit) }}
name_constraints_permitted: >-
{{ etcd_ca_name_constraints_permitted | default(omit) }}
path: "{{ tempfile.path }}"
privatekey_path: "{{ etcd_ca_private_key_file }}"
privatekey_passphrase: "{{ etcd_ca_private_key_passphrase }}"
use_common_name_for_san: false
- name: Create CA certificate
community.crypto.x509_certificate:
csr_path: "{{ tempfile.path }}"
path: "{{ etcd_ca_certificate_file }}"
privatekey_path: "{{ etcd_ca_private_key_file }}"
privatekey_passphrase: "{{ etcd_ca_private_key_passphrase }}"
provider: selfsigned
always:
- name: Delete CSR
ansible.builtin.file:
path: "{{ tempfile.path }}"
state: absent
- name: Install CA certificate
ansible.builtin.copy:
src: "{{ etcd_ca_certificate_file }}"
dest: /var/lib/etcd/ca.pem
owner: root
group: root
mode: "0644"
- name: Create node certificate private key
community.crypto.openssl_privatekey:
path: /var/lib/etcd/node_priv.pem
owner: root
group: etcd
mode: "0640"
type: Ed25519
- name: Check if node certificate exists
community.crypto.x509_certificate_info:
path: /var/lib/etcd/node_cert.pem
register: node_cert_exists
ignore_errors: true
- name: Create node certificate
when: node_cert_exists.failed or node_cert_exists.expired
block:
- name: Create node CSR temporary file
ansible.builtin.tempfile: {}
register: tempfile
- name: Create node CSR
community.crypto.openssl_csr:
common_name: "{{ ansible_fqdn }}"
basic_constraints_critical: true
basic_constraints:
- "CA:FALSE"
create_subject_key_identifier: true
extended_key_usage:
- TLS Web Server Authentication
- TLS Web Client Authentication
key_usage_critical: true
key_usage:
- Digital Signature
- Key Encipherment
path: "{{ tempfile.path }}"
privatekey_path: /var/lib/etcd/node_priv.pem
subject_alt_name: >-
{{ (ansible_all_ipv4_addresses|map("regex_replace", "^", "IP:")|list)
+ (ansible_all_ipv6_addresses|map("regex_replace", "^", "IP:")|list)
+ ["DNS:%s" % ansible_fqdn, "DNS:%s" % ansible_hostname]
}}
return_content: true
register: node_csr
- name: Create temporary file for node certificate
ansible.builtin.tempfile:
suffix: "{{ inventory_hostname }}"
register: cert_tempfile
- name: Create node certificate
delegate_to: localhost
community.crypto.x509_certificate:
csr_content: "{{ node_csr.csr }}"
path: "{{ cert_tempfile.path }}"
provider: ownca
ownca_path: "{{ etcd_ca_certificate_file }}"
ownca_privatekey_path: "{{ etcd_ca_private_key_file }}"
ownca_privatekey_passphrase: "{{ etcd_ca_private_key_passphrase }}"
- name: Install certificate
ansible.builtin.copy:
src: "{{ cert_tempfile.path }}"
dest: /var/lib/etcd/node_cert.pem
owner: root
group: etcd
mode: "0640"
always:
- name: Delete temporary certificate file
ansible.builtin.file:
path: "{{ cert_tempfile.path }}"
state: absent
delegate_to: localhost
- name: Delete CSR
ansible.builtin.file:
path: "{{ tempfile.path }}"
state: absent
---
- name: Install etcd
ansible.builtin.apt:
name:
- etcd-client
- etcd-server
policy_rc_d: 101 # do not start service
- name: Setup certificates
ansible.builtin.include_tasks: certs.yml
when: etcd_manage_certs
- name: Set etcd cluster members and peer URLs fact
ansible.builtin.set_fact:
etcd_members: >-
{{ dict(ansible_play_hosts | zip(values_list)) }}
vars:
# Following ansible-lint would worsen readability, because it does not read
# the `>-` multiline string as such and complains about a space that is
# actually a newline.
# noqa: jinja[spacing]
values_list: >-
[{% for h in ansible_play_hosts -%}
"{{ etcd_member_url_format | format(h) }}"
{%- if not loop.last %},{% endif -%}
{%- endfor %}]
when: etcd_members is not defined
- name: Set etcd initial cluster token
ansible.builtin.set_fact:
etcd_initial_cluster_token: >-
{{ etcd_members | dictsort | to_json | hash("md5") }}
when: etcd_initial_cluster_token is not defined
- name: Configure etcd
ansible.builtin.template:
src: environment.j2
dest: /etc/default/etcd
owner: root
group: root
mode: "0640"
notify:
- Restart etcd
- name: Enable and start etcd
ansible.builtin.systemd:
name: etcd.service
enabled: true
state: started
ETCD_NAME="{{ inventory_hostname }}"
ETCD_LISTEN_PEER_URLS="{{ etcd_listen_peer_urls | join(',') }}"
ETCD_LISTEN_CLIENT_URLS="{{ etcd_listen_client_urls | join(',') }}"
ETCD_INITIAL_ADVERTISE_PEER_URLS="{{ etcd_initial_advertise_peer_urls|join(',') }}"
ETCD_INITIAL_CLUSTER="{% for k, v in etcd_members.items() -%}
{{ k }}={{ v }}
{%- if not loop.last %},{% endif -%}
{%- endfor %}"
{# Scaling not yet supported. #}
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="{{ etcd_initial_cluster_token }}"
ETCD_ADVERTISE_CLIENT_URLS="{{ etcd_advertise_client_urls | join(',') }}"
{% if etcd_ssl %}
ETCD_KEY_FILE="/var/lib/etcd/node_priv.pem"
ETCD_CERT_FILE="/var/lib/etcd/node_cert.pem"
ETCD_PEER_TRUSTED_CA_FILE="/var/lib/etcd/ca.pem"
ETCD_PEER_KEY_FILE="/var/lib/etcd/node_priv.pem"
ETCD_PEER_CERT_FILE="/var/lib/etcd/node_cert.pem"
ETCD_PEER_CLIENT_CERT_AUTH="true"
{% endif %}
{% for k, v in etcd_extra | default({}) | items %}
ETCD_{{ k | upper }}="{{ v }}"
{% endfor %}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment