mirror of
https://github.com/kubernetes-sigs/kubespray.git
synced 2025-12-13 21:34:40 +03:00
Most variables should have a default instead of relying on the default filter. (Note that the variable is misnomed, this should be certs and not keys, but it's not worth breaking compat).
263 lines
10 KiB
YAML
263 lines
10 KiB
YAML
---
|
|
- name: Install OIDC certificate
|
|
copy:
|
|
content: "{{ kube_oidc_ca_cert | b64decode }}"
|
|
dest: "{{ kube_oidc_ca_file }}"
|
|
owner: root
|
|
group: root
|
|
mode: "0644"
|
|
when:
|
|
- kube_oidc_auth
|
|
- kube_oidc_ca_cert is defined
|
|
|
|
- name: Kubeadm | Check if kubeadm has already run
|
|
stat:
|
|
path: "/var/lib/kubelet/config.yaml"
|
|
get_attributes: false
|
|
get_checksum: false
|
|
get_mime: false
|
|
register: kubeadm_already_run
|
|
|
|
- name: Kubeadm | Backup kubeadm certs / kubeconfig
|
|
import_tasks: kubeadm-backup.yml
|
|
when:
|
|
- kubeadm_already_run.stat.exists
|
|
|
|
- name: Kubeadm | aggregate all SANs
|
|
set_fact:
|
|
apiserver_sans: "{{ _apiserver_sans | flatten | select | unique }}"
|
|
vars:
|
|
_apiserver_sans:
|
|
- "kubernetes"
|
|
- "kubernetes.default"
|
|
- "kubernetes.default.svc"
|
|
- "kubernetes.default.svc.{{ dns_domain }}"
|
|
- "{{ kube_apiserver_ip }}"
|
|
- "localhost"
|
|
- "127.0.0.1"
|
|
- "::1"
|
|
- "{{ apiserver_loadbalancer_domain_name }}"
|
|
- "{{ loadbalancer_apiserver.address | d('') }}"
|
|
- "{{ supplementary_addresses_in_ssl_keys }}"
|
|
- "{{ groups['kube_control_plane'] | map('extract', hostvars, 'main_access_ip') }}"
|
|
- "{{ groups['kube_control_plane'] | map('extract', hostvars, 'main_ip') }}"
|
|
- "{{ groups['kube_control_plane'] | map('extract', hostvars, ['ansible_default_ipv4', 'address']) | select('defined') }}"
|
|
- "{{ groups['kube_control_plane'] | map('extract', hostvars, ['ansible_default_ipv6', 'address']) | select('defined') }}"
|
|
- "{{ groups['kube_control_plane'] | map('extract', hostvars, 'ansible_hostname') }}"
|
|
- "{{ groups['kube_control_plane'] | map('extract', hostvars, 'ansible_fqdn') }}"
|
|
- "{{ kube_override_hostname }}"
|
|
- "{{ kube_vip_address }}"
|
|
tags: facts
|
|
|
|
- name: Create audit-policy directory
|
|
file:
|
|
path: "{{ audit_policy_file | dirname }}"
|
|
state: directory
|
|
mode: "0640"
|
|
when: kubernetes_audit or kubernetes_audit_webhook
|
|
|
|
- name: Write api audit policy yaml
|
|
template:
|
|
src: apiserver-audit-policy.yaml.j2
|
|
dest: "{{ audit_policy_file }}"
|
|
mode: "0640"
|
|
when: kubernetes_audit or kubernetes_audit_webhook
|
|
notify: Control plane | Restart apiserver
|
|
|
|
- name: Write api audit webhook config yaml
|
|
template:
|
|
src: apiserver-audit-webhook-config.yaml.j2
|
|
dest: "{{ audit_webhook_config_file }}"
|
|
mode: "0640"
|
|
when: kubernetes_audit_webhook
|
|
notify: Control plane | Restart apiserver
|
|
|
|
- name: Create apiserver tracing config directory
|
|
file:
|
|
path: "{{ kube_config_dir }}/tracing"
|
|
state: directory
|
|
mode: "0640"
|
|
when: kube_apiserver_tracing
|
|
|
|
- name: Write apiserver tracing config yaml
|
|
template:
|
|
src: apiserver-tracing.yaml.j2
|
|
dest: "{{ kube_config_dir }}/tracing/apiserver-tracing.yaml"
|
|
mode: "0640"
|
|
when: kube_apiserver_tracing
|
|
notify: Control plane | Restart apiserver
|
|
|
|
# Nginx LB(default), If kubeadm_config_api_fqdn is defined, use other LB by kubeadm controlPlaneEndpoint.
|
|
- name: Set kubeadm_config_api_fqdn define
|
|
set_fact:
|
|
kubeadm_config_api_fqdn: "{{ apiserver_loadbalancer_domain_name | default('lb-apiserver.kubernetes.local') }}"
|
|
when: loadbalancer_apiserver is defined
|
|
|
|
- name: Kubeadm | Create kubeadm config
|
|
template:
|
|
src: "kubeadm-config.{{ kubeadm_config_api_version }}.yaml.j2"
|
|
dest: "{{ kube_config_dir }}/kubeadm-config.yaml"
|
|
mode: "0640"
|
|
validate: "{{ kubeadm_config_validate_enabled | ternary(bin_dir + '/kubeadm config validate --config %s', omit) }}"
|
|
|
|
- name: Kubeadm | Create directory to store admission control configurations
|
|
file:
|
|
path: "{{ kube_config_dir }}/admission-controls"
|
|
state: directory
|
|
mode: "0640"
|
|
when: kube_apiserver_admission_control_config_file
|
|
|
|
- name: Kubeadm | Push admission control config file
|
|
template:
|
|
src: "admission-controls.yaml.j2"
|
|
dest: "{{ kube_config_dir }}/admission-controls/admission-controls.yaml"
|
|
mode: "0640"
|
|
when: kube_apiserver_admission_control_config_file
|
|
notify: Control plane | Restart apiserver
|
|
|
|
- name: Kubeadm | Push admission control config files
|
|
template:
|
|
src: "{{ item | lower }}.yaml.j2"
|
|
dest: "{{ kube_config_dir }}/admission-controls/{{ item | lower }}.yaml"
|
|
mode: "0640"
|
|
when:
|
|
- kube_apiserver_admission_control_config_file
|
|
- item in kube_apiserver_admission_plugins_needs_configuration
|
|
loop: "{{ kube_apiserver_enable_admission_plugins }}"
|
|
notify: Control plane | Restart apiserver
|
|
|
|
- name: Kubeadm | Check apiserver.crt SANs
|
|
vars:
|
|
apiserver_ips: "{{ apiserver_sans | map('ansible.utils.ipaddr') | reject('equalto', False) | list }}"
|
|
apiserver_hosts: "{{ apiserver_sans | difference(apiserver_ips) }}"
|
|
when:
|
|
- kubeadm_already_run.stat.exists
|
|
- not kube_external_ca_mode
|
|
block:
|
|
- name: Kubeadm | Check apiserver.crt SAN IPs
|
|
command:
|
|
cmd: "openssl x509 -noout -in {{ kube_cert_dir }}/apiserver.crt -checkip {{ item }}"
|
|
loop: "{{ apiserver_ips }}"
|
|
register: apiserver_sans_ip_check
|
|
changed_when: apiserver_sans_ip_check.stdout is not search('does match certificate')
|
|
failed_when: apiserver_sans_ip_check.rc != 0 and apiserver_sans_ip_check.stdout is not search('does NOT match certificate')
|
|
- name: Kubeadm | Check apiserver.crt SAN hosts
|
|
command:
|
|
cmd: "openssl x509 -noout -in {{ kube_cert_dir }}/apiserver.crt -checkhost {{ item }}"
|
|
loop: "{{ apiserver_hosts }}"
|
|
register: apiserver_sans_host_check
|
|
changed_when: apiserver_sans_host_check.stdout is not search('does match certificate')
|
|
failed_when: apiserver_sans_host_check.rc != 0 and apiserver_sans_host_check.stdout is not search('does NOT match certificate')
|
|
|
|
- name: Kubeadm | regenerate apiserver cert 1/2
|
|
file:
|
|
state: absent
|
|
path: "{{ kube_cert_dir }}/{{ item }}"
|
|
with_items:
|
|
- apiserver.crt
|
|
- apiserver.key
|
|
when:
|
|
- kubeadm_already_run.stat.exists
|
|
- apiserver_sans_ip_check.changed or apiserver_sans_host_check.changed
|
|
- not kube_external_ca_mode
|
|
|
|
- name: Kubeadm | regenerate apiserver cert 2/2
|
|
command: >-
|
|
{{ bin_dir }}/kubeadm
|
|
init phase certs apiserver
|
|
--config={{ kube_config_dir }}/kubeadm-config.yaml
|
|
when:
|
|
- kubeadm_already_run.stat.exists
|
|
- apiserver_sans_ip_check.changed or apiserver_sans_host_check.changed
|
|
- not kube_external_ca_mode
|
|
|
|
# TODO: Remove --skip-phases from command when v1beta4 UpgradeConfiguration supports skipPhases
|
|
- name: Kubeadm | Initialize first control plane node
|
|
when: inventory_hostname == first_kube_control_plane and not kubeadm_already_run.stat.exists
|
|
vars:
|
|
kubeadm_init_first_control_plane_cmd: >-
|
|
timeout -k {{ kubeadm_init_timeout }} {{ kubeadm_init_timeout }}
|
|
{{ bin_dir }}/kubeadm init
|
|
--config={{ kube_config_dir }}/kubeadm-config.yaml
|
|
--ignore-preflight-errors={{ kubeadm_ignore_preflight_errors | join(',') }}
|
|
--skip-phases={{ kubeadm_init_phases_skip | join(',') }}
|
|
{{ kube_external_ca_mode | ternary('', '--upload-certs') }}
|
|
environment:
|
|
PATH: "{{ bin_dir }}:{{ ansible_env.PATH }}"
|
|
notify: Control plane | restart kubelet
|
|
block:
|
|
- name: Kubeadm | Initialize first control plane node (1st try)
|
|
command: "{{ kubeadm_init_first_control_plane_cmd }}"
|
|
register: kubeadm_init
|
|
failed_when: kubeadm_init.rc != 0 and "field is immutable" not in kubeadm_init.stderr
|
|
rescue:
|
|
# Retry is because upload config sometimes fails
|
|
# This retry task is separated from 1st task to show log of failure of 1st task.
|
|
- name: Kubeadm | Initialize first control plane node (retry)
|
|
command: "{{ kubeadm_init_first_control_plane_cmd }}"
|
|
register: kubeadm_init
|
|
retries: 2
|
|
until: kubeadm_init is succeeded or "field is immutable" in kubeadm_init.stderr
|
|
failed_when: kubeadm_init.rc != 0 and "field is immutable" not in kubeadm_init.stderr
|
|
|
|
- name: Set kubeadm certificate key
|
|
set_fact:
|
|
kubeadm_certificate_key: "{{ item | regex_search('--certificate-key ([^ ]+)', '\\1') | first }}"
|
|
with_items: "{{ hostvars[groups['kube_control_plane'][0]]['kubeadm_init'].stdout_lines | default([]) }}"
|
|
when:
|
|
- kubeadm_certificate_key is not defined
|
|
- (item | trim) is match('.*--certificate-key.*')
|
|
|
|
- name: Create hardcoded kubeadm token for joining nodes with 24h expiration (if defined)
|
|
shell: >-
|
|
{{ bin_dir }}/kubeadm --kubeconfig {{ kube_config_dir }}/admin.conf token delete {{ kubeadm_token }} || :;
|
|
{{ bin_dir }}/kubeadm --kubeconfig {{ kube_config_dir }}/admin.conf token create {{ kubeadm_token }}
|
|
changed_when: false
|
|
when:
|
|
- inventory_hostname == first_kube_control_plane
|
|
- kubeadm_token is defined
|
|
- kubeadm_refresh_token
|
|
tags:
|
|
- kubeadm_token
|
|
|
|
- name: Remove binding to anonymous user
|
|
command: "{{ kubectl }} -n kube-public delete rolebinding kubeadm:bootstrap-signer-clusterinfo --ignore-not-found"
|
|
when: inventory_hostname == first_kube_control_plane and remove_anonymous_access
|
|
|
|
- name: Create kubeadm token for joining nodes with 24h expiration (default)
|
|
command: "{{ bin_dir }}/kubeadm --kubeconfig {{ kube_config_dir }}/admin.conf token create"
|
|
changed_when: false
|
|
register: temp_token
|
|
retries: 5
|
|
delay: 5
|
|
until: temp_token is succeeded
|
|
delegate_to: "{{ first_kube_control_plane }}"
|
|
when: kubeadm_token is not defined
|
|
tags:
|
|
- kubeadm_token
|
|
|
|
- name: Set kubeadm_token
|
|
set_fact:
|
|
kubeadm_token: "{{ temp_token.stdout }}"
|
|
when: temp_token.stdout is defined
|
|
tags:
|
|
- kubeadm_token
|
|
|
|
- name: Kubeadm | Join other control plane nodes
|
|
include_tasks: kubeadm-secondary.yml
|
|
|
|
- name: Kubeadm | upgrade kubernetes cluster to {{ kube_version }}
|
|
include_tasks: kubeadm-upgrade.yml
|
|
when:
|
|
- upgrade_cluster_setup
|
|
- kubeadm_already_run.stat.exists
|
|
|
|
# FIXME(mattymo): from docs: If you don't want to taint your control-plane node, set this field to an empty slice, i.e. `taints: {}` in the YAML file.
|
|
- name: Kubeadm | Remove taint for control plane node with node role
|
|
command: "{{ kubectl }} taint node {{ inventory_hostname }} {{ item }}"
|
|
delegate_to: "{{ first_kube_control_plane }}"
|
|
with_items:
|
|
- "node-role.kubernetes.io/control-plane:NoSchedule-"
|
|
when: ('kube_node' in group_names)
|
|
failed_when: false
|