kubespray 2.24 추가

This commit is contained in:
변정훈
2024-02-16 17:08:09 +09:00
parent 1fa9b0df4b
commit f69d904725
1423 changed files with 89069 additions and 2 deletions

View File

@@ -0,0 +1,134 @@
---
- name: "Check_certs | Register certs that have already been generated on first etcd node"
find:
paths: "{{ etcd_cert_dir }}"
patterns: "ca.pem,node*.pem,member*.pem,admin*.pem"
get_checksum: true
delegate_to: "{{ groups['etcd'][0] }}"
register: etcdcert_master
run_once: true
- name: "Check_certs | Set default value for 'sync_certs', 'gen_certs' and 'etcd_secret_changed' to false"
set_fact:
sync_certs: false
gen_certs: false
etcd_secret_changed: false
- name: "Check certs | Register ca and etcd admin/member certs on etcd hosts"
stat:
path: "{{ etcd_cert_dir }}/{{ item }}"
get_attributes: no
get_checksum: yes
get_mime: no
register: etcd_member_certs
when: inventory_hostname in groups['etcd']
with_items:
- ca.pem
- member-{{ inventory_hostname }}.pem
- member-{{ inventory_hostname }}-key.pem
- admin-{{ inventory_hostname }}.pem
- admin-{{ inventory_hostname }}-key.pem
- name: "Check certs | Register ca and etcd node certs on kubernetes hosts"
stat:
path: "{{ etcd_cert_dir }}/{{ item }}"
register: etcd_node_certs
when: inventory_hostname in groups['k8s_cluster']
with_items:
- ca.pem
- node-{{ inventory_hostname }}.pem
- node-{{ inventory_hostname }}-key.pem
- name: "Check_certs | Set 'gen_certs' to true if expected certificates are not on the first etcd node(1/2)"
set_fact:
gen_certs: true
when: force_etcd_cert_refresh or not item in etcdcert_master.files | map(attribute='path') | list
run_once: true
with_items: "{{ expected_files }}"
vars:
expected_files: >-
['{{ etcd_cert_dir }}/ca.pem',
{% set etcd_members = groups['etcd'] %}
{% for host in etcd_members %}
'{{ etcd_cert_dir }}/admin-{{ host }}.pem',
'{{ etcd_cert_dir }}/admin-{{ host }}-key.pem',
'{{ etcd_cert_dir }}/member-{{ host }}.pem',
'{{ etcd_cert_dir }}/member-{{ host }}-key.pem',
{% endfor %}
{% set k8s_nodes = groups['kube_control_plane'] %}
{% for host in k8s_nodes %}
'{{ etcd_cert_dir }}/node-{{ host }}.pem',
'{{ etcd_cert_dir }}/node-{{ host }}-key.pem'
{% if not loop.last %}{{ ',' }}{% endif %}
{% endfor %}]
- name: "Check_certs | Set 'gen_certs' to true if expected certificates are not on the first etcd node(2/2)"
set_fact:
gen_certs: true
run_once: true
with_items: "{{ expected_files }}"
vars:
expected_files: >-
['{{ etcd_cert_dir }}/ca.pem',
{% set etcd_members = groups['etcd'] %}
{% for host in etcd_members %}
'{{ etcd_cert_dir }}/admin-{{ host }}.pem',
'{{ etcd_cert_dir }}/admin-{{ host }}-key.pem',
'{{ etcd_cert_dir }}/member-{{ host }}.pem',
'{{ etcd_cert_dir }}/member-{{ host }}-key.pem',
{% endfor %}
{% set k8s_nodes = groups['k8s_cluster'] | unique | sort %}
{% for host in k8s_nodes %}
'{{ etcd_cert_dir }}/node-{{ host }}.pem',
'{{ etcd_cert_dir }}/node-{{ host }}-key.pem'
{% if not loop.last %}{{ ',' }}{% endif %}
{% endfor %}]
when:
- kube_network_plugin in ["calico", "flannel", "cilium"] or cilium_deploy_additionally | default(false) | bool
- kube_network_plugin != "calico" or calico_datastore == "etcd"
- force_etcd_cert_refresh or not item in etcdcert_master.files | map(attribute='path') | list
- name: "Check_certs | Set 'gen_*_certs' groups to track which nodes needs to have certs generated on first etcd node"
vars:
existing_certs: etcdcert_master.files | map(attribute='path')
ansible.builtin.group_by:
key: "gen_{{ item.node_type }}_certs_{{ force_etcd_cert_refresh or item.certs is not subset(existing_certs) }}"
loop: "{{ cert_files | dict2items(key_name='node_type', value_name='certs') }}"
- name: "Check_certs | Set 'etcd_member_requires_sync' to true if ca or member/admin cert and key don't exist on etcd member or checksum doesn't match"
set_fact:
etcd_member_requires_sync: true
when:
- inventory_hostname in groups['etcd']
- (not etcd_member_certs.results[0].stat.exists | default(false)) or
(not etcd_member_certs.results[1].stat.exists | default(false)) or
(not etcd_member_certs.results[2].stat.exists | default(false)) or
(not etcd_member_certs.results[3].stat.exists | default(false)) or
(not etcd_member_certs.results[4].stat.exists | default(false)) or
(etcd_member_certs.results[0].stat.checksum | default('') != etcdcert_master.files | selectattr("path", "equalto", etcd_member_certs.results[0].stat.path) | map(attribute="checksum") | first | default('')) or
(etcd_member_certs.results[1].stat.checksum | default('') != etcdcert_master.files | selectattr("path", "equalto", etcd_member_certs.results[1].stat.path) | map(attribute="checksum") | first | default('')) or
(etcd_member_certs.results[2].stat.checksum | default('') != etcdcert_master.files | selectattr("path", "equalto", etcd_member_certs.results[2].stat.path) | map(attribute="checksum") | first | default('')) or
(etcd_member_certs.results[3].stat.checksum | default('') != etcdcert_master.files | selectattr("path", "equalto", etcd_member_certs.results[3].stat.path) | map(attribute="checksum") | first | default('')) or
(etcd_member_certs.results[4].stat.checksum | default('') != etcdcert_master.files | selectattr("path", "equalto", etcd_member_certs.results[4].stat.path) | map(attribute="checksum") | first | default(''))
- name: "Check_certs | Set 'kubernetes_host_requires_sync' to true if ca or node cert and key don't exist on kubernetes host or checksum doesn't match"
set_fact:
kubernetes_host_requires_sync: true
when:
- inventory_hostname in groups['k8s_cluster'] and
inventory_hostname not in groups['etcd']
- (not etcd_node_certs.results[0].stat.exists | default(false)) or
(not etcd_node_certs.results[1].stat.exists | default(false)) or
(not etcd_node_certs.results[2].stat.exists | default(false)) or
(etcd_node_certs.results[0].stat.checksum | default('') != etcdcert_master.files | selectattr("path", "equalto", etcd_node_certs.results[0].stat.path) | map(attribute="checksum") | first | default('')) or
(etcd_node_certs.results[1].stat.checksum | default('') != etcdcert_master.files | selectattr("path", "equalto", etcd_node_certs.results[1].stat.path) | map(attribute="checksum") | first | default('')) or
(etcd_node_certs.results[2].stat.checksum | default('') != etcdcert_master.files | selectattr("path", "equalto", etcd_node_certs.results[2].stat.path) | map(attribute="checksum") | first | default(''))
- name: "Check_certs | Set 'sync_certs' to true"
set_fact:
sync_certs: true
when:
- etcd_member_requires_sync | default(false) or
kubernetes_host_requires_sync | default(false) or
'gen_master_certs_True' in group_names or
'gen_node_certs_True' in group_names

View File

@@ -0,0 +1,179 @@
---
- name: Configure | Check if etcd cluster is healthy
shell: "set -o pipefail && {{ bin_dir }}/etcdctl endpoint --cluster status && {{ bin_dir }}/etcdctl endpoint --cluster health 2>&1 | grep -v 'Error: unhealthy cluster' >/dev/null"
args:
executable: /bin/bash
register: etcd_cluster_is_healthy
failed_when: false
changed_when: false
check_mode: no
run_once: yes
when:
- is_etcd_master
- etcd_cluster_setup
tags:
- facts
environment:
ETCDCTL_API: "3"
ETCDCTL_CERT: "{{ etcd_cert_dir }}/admin-{{ inventory_hostname }}.pem"
ETCDCTL_KEY: "{{ etcd_cert_dir }}/admin-{{ inventory_hostname }}-key.pem"
ETCDCTL_CACERT: "{{ etcd_cert_dir }}/ca.pem"
ETCDCTL_ENDPOINTS: "{{ etcd_access_addresses }}"
- name: Configure | Check if etcd-events cluster is healthy
shell: "set -o pipefail && {{ bin_dir }}/etcdctl endpoint --cluster status && {{ bin_dir }}/etcdctl endpoint --cluster health 2>&1 | grep -v 'Error: unhealthy cluster' >/dev/null"
args:
executable: /bin/bash
register: etcd_events_cluster_is_healthy
failed_when: false
changed_when: false
check_mode: no
run_once: yes
when:
- is_etcd_master
- etcd_events_cluster_setup
tags:
- facts
environment:
ETCDCTL_API: "3"
ETCDCTL_CERT: "{{ etcd_cert_dir }}/admin-{{ inventory_hostname }}.pem"
ETCDCTL_KEY: "{{ etcd_cert_dir }}/admin-{{ inventory_hostname }}-key.pem"
ETCDCTL_CACERT: "{{ etcd_cert_dir }}/ca.pem"
ETCDCTL_ENDPOINTS: "{{ etcd_events_access_addresses }}"
- name: Configure | Refresh etcd config
include_tasks: refresh_config.yml
when: is_etcd_master
- name: Configure | Copy etcd.service systemd file
template:
src: "etcd-{{ etcd_deployment_type }}.service.j2"
dest: /etc/systemd/system/etcd.service
backup: yes
mode: 0644
# FIXME: check that systemd version >= 250 (factory-reset.target was introduced in that release)
# Remove once we drop support for systemd < 250
validate: "sh -c '[ -f /usr/bin/systemd/system/factory-reset.target ] || exit 0 && systemd-analyze verify %s:etcd-{{ etcd_deployment_type }}.service'"
when: is_etcd_master and etcd_cluster_setup
- name: Configure | Copy etcd-events.service systemd file
template:
src: "etcd-events-{{ etcd_deployment_type }}.service.j2"
dest: /etc/systemd/system/etcd-events.service
backup: yes
mode: 0644
validate: "sh -c '[ -f /usr/bin/systemd/system/factory-reset.target ] || exit 0 && systemd-analyze verify %s:etcd-events-{{ etcd_deployment_type }}.service'"
# FIXME: check that systemd version >= 250 (factory-reset.target was introduced in that release)
# Remove once we drop support for systemd < 250
when: is_etcd_master and etcd_events_cluster_setup
- name: Configure | reload systemd
systemd:
daemon_reload: true
when: is_etcd_master
# when scaling new etcd will fail to start
- name: Configure | Ensure etcd is running
service:
name: etcd
state: started
enabled: yes
ignore_errors: "{{ etcd_cluster_is_healthy.rc == 0 }}" # noqa ignore-errors
when: is_etcd_master and etcd_cluster_setup
# when scaling new etcd will fail to start
- name: Configure | Ensure etcd-events is running
service:
name: etcd-events
state: started
enabled: yes
ignore_errors: "{{ etcd_events_cluster_is_healthy.rc != 0 }}" # noqa ignore-errors
when: is_etcd_master and etcd_events_cluster_setup
- name: Configure | Wait for etcd cluster to be healthy
shell: "set -o pipefail && {{ bin_dir }}/etcdctl endpoint --cluster status && {{ bin_dir }}/etcdctl endpoint --cluster health 2>&1 | grep -v 'Error: unhealthy cluster' >/dev/null"
args:
executable: /bin/bash
register: etcd_cluster_is_healthy
until: etcd_cluster_is_healthy.rc == 0
retries: "{{ etcd_retries }}"
delay: "{{ retry_stagger | random + 3 }}"
changed_when: false
check_mode: no
run_once: yes
when:
- is_etcd_master
- etcd_cluster_setup
tags:
- facts
environment:
ETCDCTL_API: "3"
ETCDCTL_CERT: "{{ etcd_cert_dir }}/admin-{{ inventory_hostname }}.pem"
ETCDCTL_KEY: "{{ etcd_cert_dir }}/admin-{{ inventory_hostname }}-key.pem"
ETCDCTL_CACERT: "{{ etcd_cert_dir }}/ca.pem"
ETCDCTL_ENDPOINTS: "{{ etcd_access_addresses }}"
- name: Configure | Wait for etcd-events cluster to be healthy
shell: "set -o pipefail && {{ bin_dir }}/etcdctl endpoint --cluster status && {{ bin_dir }}/etcdctl endpoint --cluster health 2>&1 | grep -v 'Error: unhealthy cluster' >/dev/null"
args:
executable: /bin/bash
register: etcd_events_cluster_is_healthy
until: etcd_events_cluster_is_healthy.rc == 0
retries: "{{ etcd_retries }}"
delay: "{{ retry_stagger | random + 3 }}"
changed_when: false
check_mode: no
run_once: yes
when:
- is_etcd_master
- etcd_events_cluster_setup
tags:
- facts
environment:
ETCDCTL_API: "3"
ETCDCTL_CERT: "{{ etcd_cert_dir }}/admin-{{ inventory_hostname }}.pem"
ETCDCTL_KEY: "{{ etcd_cert_dir }}/admin-{{ inventory_hostname }}-key.pem"
ETCDCTL_CACERT: "{{ etcd_cert_dir }}/ca.pem"
ETCDCTL_ENDPOINTS: "{{ etcd_events_access_addresses }}"
- name: Configure | Check if member is in etcd cluster
shell: "{{ bin_dir }}/etcdctl member list | grep -w -q {{ etcd_access_address }}"
register: etcd_member_in_cluster
ignore_errors: true # noqa ignore-errors
changed_when: false
check_mode: no
when: is_etcd_master and etcd_cluster_setup
tags:
- facts
environment:
ETCDCTL_API: "3"
ETCDCTL_CERT: "{{ etcd_cert_dir }}/admin-{{ inventory_hostname }}.pem"
ETCDCTL_KEY: "{{ etcd_cert_dir }}/admin-{{ inventory_hostname }}-key.pem"
ETCDCTL_CACERT: "{{ etcd_cert_dir }}/ca.pem"
ETCDCTL_ENDPOINTS: "{{ etcd_access_addresses }}"
- name: Configure | Check if member is in etcd-events cluster
shell: "{{ bin_dir }}/etcdctl member list | grep -w -q {{ etcd_access_address }}"
register: etcd_events_member_in_cluster
ignore_errors: true # noqa ignore-errors
changed_when: false
check_mode: no
when: is_etcd_master and etcd_events_cluster_setup
tags:
- facts
environment:
ETCDCTL_API: "3"
ETCDCTL_CERT: "{{ etcd_cert_dir }}/admin-{{ inventory_hostname }}.pem"
ETCDCTL_KEY: "{{ etcd_cert_dir }}/admin-{{ inventory_hostname }}-key.pem"
ETCDCTL_CACERT: "{{ etcd_cert_dir }}/ca.pem"
ETCDCTL_ENDPOINTS: "{{ etcd_events_access_addresses }}"
- name: Configure | Join member(s) to etcd cluster one at a time
include_tasks: join_etcd_member.yml
with_items: "{{ groups['etcd'] }}"
when: inventory_hostname == item and etcd_cluster_setup and etcd_member_in_cluster.rc != 0 and etcd_cluster_is_healthy.rc == 0
- name: Configure | Join member(s) to etcd-events cluster one at a time
include_tasks: join_etcd-events_member.yml
with_items: "{{ groups['etcd'] }}"
when: inventory_hostname == item and etcd_events_cluster_setup and etcd_events_member_in_cluster.rc != 0 and etcd_events_cluster_is_healthy.rc == 0

View File

@@ -0,0 +1,156 @@
---
- name: Gen_certs | create etcd cert dir
file:
path: "{{ etcd_cert_dir }}"
group: "{{ etcd_cert_group }}"
state: directory
owner: "{{ etcd_owner }}"
mode: "{{ etcd_cert_dir_mode }}"
recurse: yes
- name: "Gen_certs | create etcd script dir (on {{ groups['etcd'][0] }})"
file:
path: "{{ etcd_script_dir }}"
state: directory
owner: root
mode: 0700
run_once: yes
when: inventory_hostname == groups['etcd'][0]
- name: Gen_certs | write openssl config
template:
src: "openssl.conf.j2"
dest: "{{ etcd_config_dir }}/openssl.conf"
mode: 0640
run_once: yes
delegate_to: "{{ groups['etcd'][0] }}"
when:
- gen_certs | default(false)
- inventory_hostname == groups['etcd'][0]
- name: Gen_certs | copy certs generation script
template:
src: "make-ssl-etcd.sh.j2"
dest: "{{ etcd_script_dir }}/make-ssl-etcd.sh"
mode: 0700
run_once: yes
when:
- gen_certs | default(false)
- inventory_hostname == groups['etcd'][0]
- name: Gen_certs | run cert generation script for etcd and kube control plane nodes
command: "bash -x {{ etcd_script_dir }}/make-ssl-etcd.sh -f {{ etcd_config_dir }}/openssl.conf -d {{ etcd_cert_dir }}"
environment:
MASTERS: "{{ groups['gen_master_certs_True'] | ansible.builtin.intersect(groups['etcd']) | join(' ') }}"
HOSTS: "{{ groups['gen_node_certs_True'] | ansible.builtin.intersect(groups['kube_control_plane']) | join(' ') }}"
run_once: yes
delegate_to: "{{ groups['etcd'][0] }}"
when: gen_certs | default(false)
notify: Set etcd_secret_changed
- name: Gen_certs | run cert generation script for all clients
command: "bash -x {{ etcd_script_dir }}/make-ssl-etcd.sh -f {{ etcd_config_dir }}/openssl.conf -d {{ etcd_cert_dir }}"
environment:
HOSTS: "{{ groups['gen_node_certs_True'] | ansible.builtin.intersect(groups['k8s_cluster']) | join(' ') }}"
run_once: yes
delegate_to: "{{ groups['etcd'][0] }}"
when:
- kube_network_plugin in ["calico", "flannel", "cilium"] or cilium_deploy_additionally | default(false) | bool
- kube_network_plugin != "calico" or calico_datastore == "etcd"
- gen_certs | default(false)
notify: Set etcd_secret_changed
- name: Gen_certs | Gather etcd member/admin and kube_control_plane client certs from first etcd node
slurp:
src: "{{ item }}"
register: etcd_master_certs
with_items:
- "{{ etcd_cert_dir }}/ca.pem"
- "{{ etcd_cert_dir }}/ca-key.pem"
- "[{% for node in groups['etcd'] %}
'{{ etcd_cert_dir }}/admin-{{ node }}.pem',
'{{ etcd_cert_dir }}/admin-{{ node }}-key.pem',
'{{ etcd_cert_dir }}/member-{{ node }}.pem',
'{{ etcd_cert_dir }}/member-{{ node }}-key.pem',
{% endfor %}]"
- "[{% for node in (groups['kube_control_plane']) %}
'{{ etcd_cert_dir }}/node-{{ node }}.pem',
'{{ etcd_cert_dir }}/node-{{ node }}-key.pem',
{% endfor %}]"
delegate_to: "{{ groups['etcd'][0] }}"
when:
- inventory_hostname in groups['etcd']
- sync_certs | default(false)
- inventory_hostname != groups['etcd'][0]
notify: Set etcd_secret_changed
- name: Gen_certs | Write etcd member/admin and kube_control_plane client certs to other etcd nodes
copy:
dest: "{{ item.item }}"
content: "{{ item.content | b64decode }}"
group: "{{ etcd_cert_group }}"
owner: "{{ etcd_owner }}"
mode: 0640
with_items: "{{ etcd_master_certs.results }}"
when:
- inventory_hostname in groups['etcd']
- sync_certs | default(false)
- inventory_hostname != groups['etcd'][0]
loop_control:
label: "{{ item.item }}"
- name: Gen_certs | Gather node certs from first etcd node
slurp:
src: "{{ item }}"
register: etcd_master_node_certs
with_items:
- "[{% for node in groups['k8s_cluster'] %}
'{{ etcd_cert_dir }}/node-{{ node }}.pem',
'{{ etcd_cert_dir }}/node-{{ node }}-key.pem',
{% endfor %}]"
delegate_to: "{{ groups['etcd'][0] }}"
when:
- inventory_hostname in groups['etcd']
- inventory_hostname != groups['etcd'][0]
- kube_network_plugin in ["calico", "flannel", "cilium"] or cilium_deploy_additionally | default(false) | bool
- kube_network_plugin != "calico" or calico_datastore == "etcd"
notify: Set etcd_secret_changed
- name: Gen_certs | Write node certs to other etcd nodes
copy:
dest: "{{ item.item }}"
content: "{{ item.content | b64decode }}"
group: "{{ etcd_cert_group }}"
owner: "{{ etcd_owner }}"
mode: 0640
with_items: "{{ etcd_master_node_certs.results }}"
when:
- inventory_hostname in groups['etcd']
- inventory_hostname != groups['etcd'][0]
- kube_network_plugin in ["calico", "flannel", "cilium"] or cilium_deploy_additionally | default(false) | bool
- kube_network_plugin != "calico" or calico_datastore == "etcd"
loop_control:
label: "{{ item.item }}"
- name: Gen_certs | Generate etcd certs
include_tasks: gen_nodes_certs_script.yml
when:
- inventory_hostname in groups['kube_control_plane'] and
sync_certs | default(false) and inventory_hostname not in groups['etcd']
- name: Gen_certs | Generate etcd certs on nodes if needed
include_tasks: gen_nodes_certs_script.yml
when:
- kube_network_plugin in ["calico", "flannel", "cilium"] or cilium_deploy_additionally | default(false) | bool
- kube_network_plugin != "calico" or calico_datastore == "etcd"
- inventory_hostname in groups['k8s_cluster'] and
sync_certs | default(false) and inventory_hostname not in groups['etcd']
- name: Gen_certs | check certificate permissions
file:
path: "{{ etcd_cert_dir }}"
group: "{{ etcd_cert_group }}"
state: directory
owner: "{{ etcd_owner }}"
mode: "{{ etcd_cert_dir_mode }}"
recurse: yes

View File

@@ -0,0 +1,33 @@
---
- name: Gen_certs | Set cert names per node
set_fact:
my_etcd_node_certs: [ 'ca.pem',
'node-{{ inventory_hostname }}.pem',
'node-{{ inventory_hostname }}-key.pem']
tags:
- facts
- name: "Check_certs | Set 'sync_certs' to true on nodes"
set_fact:
sync_certs: true
with_items:
- "{{ my_etcd_node_certs }}"
- name: Gen_certs | Gather node certs
vars:
ansible_ssh_retries: 10
shell: "set -o pipefail && tar cfz - -C {{ etcd_cert_dir }} {{ my_etcd_node_certs | join(' ') }} | base64 --wrap=0"
args:
executable: /bin/bash
no_log: "{{ not (unsafe_show_logs | bool) }}"
register: etcd_node_certs
check_mode: no
delegate_to: "{{ groups['etcd'][0] }}"
changed_when: false
- name: Gen_certs | Copy certs on nodes
shell: "set -o pipefail && base64 -d <<< '{{ etcd_node_certs.stdout | quote }}' | tar xz -C {{ etcd_cert_dir }}"
args:
executable: /bin/bash
no_log: "{{ not (unsafe_show_logs | bool) }}"
changed_when: false

View File

@@ -0,0 +1,42 @@
---
- name: Get currently-deployed etcd version
shell: "{{ docker_bin_dir }}/docker ps --filter='name={{ etcd_member_name }}' --format='{{ '{{ .Image }}' }}'"
register: etcd_current_docker_image
when: etcd_cluster_setup
- name: Get currently-deployed etcd-events version
shell: "{{ docker_bin_dir }}/docker ps --filter='name={{ etcd_member_name }}-events' --format='{{ '{{ .Image }}' }}'"
register: etcd_events_current_docker_image
when: etcd_events_cluster_setup
- name: Restart etcd if necessary
command: /bin/true
notify: Restart etcd
when:
- etcd_cluster_setup
- etcd_image_tag not in etcd_current_docker_image.stdout | default('')
- name: Restart etcd-events if necessary
command: /bin/true
notify: Restart etcd-events
when:
- etcd_events_cluster_setup
- etcd_image_tag not in etcd_events_current_docker_image.stdout | default('')
- name: Install etcd launch script
template:
src: etcd.j2
dest: "{{ bin_dir }}/etcd"
owner: 'root'
mode: 0750
backup: yes
when: etcd_cluster_setup
- name: Install etcd-events launch script
template:
src: etcd-events.j2
dest: "{{ bin_dir }}/etcd-events"
owner: 'root'
mode: 0750
backup: yes
when: etcd_events_cluster_setup

View File

@@ -0,0 +1,31 @@
---
- name: Get currently-deployed etcd version
command: "{{ bin_dir }}/etcd --version"
register: etcd_current_host_version
# There's a chance this play could run before etcd is installed at all
ignore_errors: true
when: etcd_cluster_setup
- name: Restart etcd if necessary
command: /bin/true
notify: Restart etcd
when:
- etcd_cluster_setup
- etcd_version.lstrip('v') not in etcd_current_host_version.stdout | default('')
- name: Restart etcd-events if necessary
command: /bin/true
notify: Restart etcd-events
when:
- etcd_events_cluster_setup
- etcd_version.lstrip('v') not in etcd_current_host_version.stdout | default('')
- name: Install | Copy etcd binary from download dir
copy:
src: "{{ local_release_dir }}/etcd-{{ etcd_version }}-linux-{{ host_architecture }}/{{ item }}"
dest: "{{ bin_dir }}/{{ item }}"
mode: 0755
remote_src: yes
with_items:
- etcd
when: etcd_cluster_setup

View File

@@ -0,0 +1,49 @@
---
- name: Join Member | Add member to etcd-events cluster
command: "{{ bin_dir }}/etcdctl member add {{ etcd_member_name }} --peer-urls={{ etcd_events_peer_url }}"
register: member_add_result
until: member_add_result.rc == 0
retries: "{{ etcd_retries }}"
delay: "{{ retry_stagger | random + 3 }}"
environment:
ETCDCTL_API: "3"
ETCDCTL_CERT: "{{ etcd_cert_dir }}/admin-{{ inventory_hostname }}.pem"
ETCDCTL_KEY: "{{ etcd_cert_dir }}/admin-{{ inventory_hostname }}-key.pem"
ETCDCTL_CACERT: "{{ etcd_cert_dir }}/ca.pem"
ETCDCTL_ENDPOINTS: "{{ etcd_events_access_addresses }}"
- name: Join Member | Refresh etcd config
include_tasks: refresh_config.yml
vars:
# noqa: jinja[spacing]
etcd_events_peer_addresses: >-
{% for host in groups['etcd'] -%}
{%- if hostvars[host]['etcd_events_member_in_cluster'].rc == 0 -%}
{{ "etcd" + loop.index | string }}=https://{{ hostvars[host].etcd_events_access_address | default(hostvars[host].ip | default(fallback_ips[host])) }}:2382,
{%- endif -%}
{%- if loop.last -%}
{{ etcd_member_name }}={{ etcd_events_peer_url }}
{%- endif -%}
{%- endfor -%}
- name: Join Member | Ensure member is in etcd-events cluster
shell: "set -o pipefail && {{ bin_dir }}/etcdctl member list | grep -w {{ etcd_events_access_address }} >/dev/null"
args:
executable: /bin/bash
register: etcd_events_member_in_cluster
changed_when: false
check_mode: no
tags:
- facts
environment:
ETCDCTL_API: "3"
ETCDCTL_CERT: "{{ etcd_cert_dir }}/admin-{{ inventory_hostname }}.pem"
ETCDCTL_KEY: "{{ etcd_cert_dir }}/admin-{{ inventory_hostname }}-key.pem"
ETCDCTL_CACERT: "{{ etcd_cert_dir }}/ca.pem"
ETCDCTL_ENDPOINTS: "{{ etcd_events_access_addresses }}"
- name: Configure | Ensure etcd-events is running
service:
name: etcd-events
state: started
enabled: yes

View File

@@ -0,0 +1,53 @@
---
- name: Join Member | Add member to etcd cluster
command: "{{ bin_dir }}/etcdctl member add {{ etcd_member_name }} --peer-urls={{ etcd_peer_url }}"
register: member_add_result
until: member_add_result.rc == 0 or 'Peer URLs already exists' in member_add_result.stderr
failed_when: member_add_result.rc != 0 and 'Peer URLs already exists' not in member_add_result.stderr
retries: "{{ etcd_retries }}"
delay: "{{ retry_stagger | random + 3 }}"
environment:
ETCDCTL_API: "3"
ETCDCTL_CERT: "{{ etcd_cert_dir }}/admin-{{ inventory_hostname }}.pem"
ETCDCTL_KEY: "{{ etcd_cert_dir }}/admin-{{ inventory_hostname }}-key.pem"
ETCDCTL_CACERT: "{{ etcd_cert_dir }}/ca.pem"
ETCDCTL_ENDPOINTS: "{{ etcd_access_addresses }}"
- name: Join Member | Refresh etcd config
include_tasks: refresh_config.yml
vars:
# noqa: jinja[spacing]
etcd_peer_addresses: >-
{% for host in groups['etcd'] -%}
{%- if hostvars[host]['etcd_member_in_cluster'].rc == 0 -%}
{{ "etcd" + loop.index | string }}=https://{{ hostvars[host].etcd_access_address | default(hostvars[host].ip | default(fallback_ips[host])) }}:2380,
{%- endif -%}
{%- if loop.last -%}
{{ etcd_member_name }}={{ etcd_peer_url }}
{%- endif -%}
{%- endfor -%}
- name: Join Member | Ensure member is in etcd cluster
shell: "set -o pipefail && {{ bin_dir }}/etcdctl member list | grep -w {{ etcd_access_address }} >/dev/null"
args:
executable: /bin/bash
register: etcd_member_in_cluster
changed_when: false
check_mode: no
retries: "{{ etcd_retries }}"
delay: "{{ retry_stagger | random + 3 }}"
until: etcd_member_in_cluster.rc == 0
tags:
- facts
environment:
ETCDCTL_API: "3"
ETCDCTL_CERT: "{{ etcd_cert_dir }}/admin-{{ inventory_hostname }}.pem"
ETCDCTL_KEY: "{{ etcd_cert_dir }}/admin-{{ inventory_hostname }}-key.pem"
ETCDCTL_CACERT: "{{ etcd_cert_dir }}/ca.pem"
ETCDCTL_ENDPOINTS: "{{ etcd_access_addresses }}"
- name: Configure | Ensure etcd is running
service:
name: etcd
state: started
enabled: yes

96
roles/etcd/tasks/main.yml Normal file
View File

@@ -0,0 +1,96 @@
---
- name: Check etcd certs
include_tasks: check_certs.yml
when: cert_management == "script"
tags:
- etcd-secrets
- facts
- name: Generate etcd certs
include_tasks: "gen_certs_script.yml"
when:
- cert_management | d('script') == "script"
tags:
- etcd-secrets
- name: Trust etcd CA
include_tasks: upd_ca_trust.yml
when:
- inventory_hostname in groups['etcd'] | union(groups['kube_control_plane']) | unique | sort
tags:
- etcd-secrets
- name: Trust etcd CA on nodes if needed
include_tasks: upd_ca_trust.yml
when:
- kube_network_plugin in ["calico", "flannel", "cilium"] or cilium_deploy_additionally | default(false) | bool
- kube_network_plugin != "calico" or calico_datastore == "etcd"
- inventory_hostname in groups['k8s_cluster']
tags:
- etcd-secrets
- name: "Gen_certs | Get etcd certificate serials"
command: "openssl x509 -in {{ etcd_cert_dir }}/node-{{ inventory_hostname }}.pem -noout -serial"
register: "etcd_client_cert_serial_result"
changed_when: false
check_mode: no
when:
- kube_network_plugin in ["calico", "flannel", "cilium"] or cilium_deploy_additionally | default(false) | bool
- kube_network_plugin != "calico" or calico_datastore == "etcd"
- inventory_hostname in groups['k8s_cluster']
tags:
- master
- network
- name: Set etcd_client_cert_serial
set_fact:
etcd_client_cert_serial: "{{ etcd_client_cert_serial_result.stdout.split('=')[1] }}"
when:
- kube_network_plugin in ["calico", "flannel", "cilium"] or cilium_deploy_additionally | default(false) | bool
- kube_network_plugin != "calico" or calico_datastore == "etcd"
- inventory_hostname in groups['k8s_cluster']
tags:
- master
- network
- name: Install etcdctl and etcdutl binary
import_role:
name: etcdctl_etcdutl
tags:
- etcdctl
- etcdutl
- upgrade
when:
- inventory_hostname in groups['etcd']
- etcd_cluster_setup
- name: Install etcd
include_tasks: "install_{{ etcd_deployment_type }}.yml"
when: is_etcd_master
tags:
- upgrade
- name: Configure etcd
include_tasks: configure.yml
when: is_etcd_master
- name: Refresh etcd config
include_tasks: refresh_config.yml
when: is_etcd_master
- name: Restart etcd if certs changed
command: /bin/true
notify: Restart etcd
when: is_etcd_master and etcd_cluster_setup and etcd_secret_changed | default(false)
- name: Restart etcd-events if certs changed
command: /bin/true
notify: Restart etcd
when: is_etcd_master and etcd_events_cluster_setup and etcd_secret_changed | default(false)
# After etcd cluster is assembled, make sure that
# initial state of the cluster is in `existing`
# state instead of `new`.
- name: Refresh etcd config again for idempotency
include_tasks: refresh_config.yml
when: is_etcd_master

View File

@@ -0,0 +1,16 @@
---
- name: Refresh config | Create etcd config file
template:
src: etcd.env.j2
dest: /etc/etcd.env
mode: 0640
notify: Restart etcd
when: is_etcd_master and etcd_cluster_setup
- name: Refresh config | Create etcd-events config file
template:
src: etcd-events.env.j2
dest: /etc/etcd-events.env
mode: 0640
notify: Restart etcd-events
when: is_etcd_master and etcd_events_cluster_setup

View File

@@ -0,0 +1,37 @@
---
- name: Gen_certs | target ca-certificate store file
set_fact:
ca_cert_path: |-
{% if ansible_os_family == "Debian" -%}
/usr/local/share/ca-certificates/etcd-ca.crt
{%- elif ansible_os_family == "RedHat" -%}
/etc/pki/ca-trust/source/anchors/etcd-ca.crt
{%- elif ansible_os_family in ["Flatcar", "Flatcar Container Linux by Kinvolk"] -%}
/etc/ssl/certs/etcd-ca.pem
{%- elif ansible_os_family == "Suse" -%}
/etc/pki/trust/anchors/etcd-ca.pem
{%- elif ansible_os_family == "ClearLinux" -%}
/usr/share/ca-certs/etcd-ca.pem
{%- endif %}
tags:
- facts
- name: Gen_certs | add CA to trusted CA dir
copy:
src: "{{ etcd_cert_dir }}/ca.pem"
dest: "{{ ca_cert_path }}"
remote_src: true
mode: 0640
register: etcd_ca_cert
- name: Gen_certs | update ca-certificates (Debian/Ubuntu/SUSE/Flatcar) # noqa no-handler
command: update-ca-certificates
when: etcd_ca_cert.changed and ansible_os_family in ["Debian", "Flatcar", "Flatcar Container Linux by Kinvolk", "Suse"]
- name: Gen_certs | update ca-certificates (RedHat) # noqa no-handler
command: update-ca-trust extract
when: etcd_ca_cert.changed and ansible_os_family == "RedHat"
- name: Gen_certs | update ca-certificates (ClearLinux) # noqa no-handler
command: clrtrust add "{{ ca_cert_path }}"
when: etcd_ca_cert.changed and ansible_os_family == "ClearLinux"