diff --git a/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_common/tasks/apiserver-certificates.yml b/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_common/tasks/apiserver-certificates.yml new file mode 100644 index 0000000000..16adcf26ca --- /dev/null +++ b/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_common/tasks/apiserver-certificates.yml @@ -0,0 +1,34 @@ +--- +- name: Copy /etc/kubernetes/pki/apiserver.{crt,key} + copy: + dest: "{{ item }}.OLD" + src: "{{ item }}" + remote_src: true + loop: + - /etc/kubernetes/pki/apiserver.crt + - /etc/kubernetes/pki/apiserver.key + +- name: Delete /etc/kubernetes/pki/apiserver.{crt,key} + file: + path: "{{ item }}" + state: absent + loop: + - /etc/kubernetes/pki/apiserver.crt + - /etc/kubernetes/pki/apiserver.key + +- name: Render new certificates /etc/kubernetes/pki/apiserver.{crt,key} + shell: | + kubeadm init phase certs apiserver \ + --config /etc/kubeadm/kubeadm-config.yml + args: + executable: /bin/bash + creates: /etc/kubernetes/pki/apiserver.key + +- name: Restart apiserver + shell: | + docker ps \ + --filter 'name=kube-apiserver_kube-apiserver' \ + --format '{{ "{{.ID}}" }}' \ + | xargs --no-run-if-empty docker kill + args: + executable: /bin/bash diff --git a/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_common/tasks/extend-kubeadm-config.yml b/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_common/tasks/extend-kubeadm-config.yml new file mode 100644 index 0000000000..140722fb6e --- /dev/null +++ b/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_common/tasks/extend-kubeadm-config.yml @@ -0,0 +1,29 @@ +--- +- name: Collect kubeadm-config + shell: | + kubectl get configmap kubeadm-config \ + --namespace kube-system \ + --output jsonpath={{ jsonpath }} + vars: + jsonpath: >- + '{.data.ClusterConfiguration}' + environment: + KUBECONFIG: /etc/kubernetes/admin.conf + args: + executable: /bin/bash + register: kubeadm_config + changed_when: false + +- name: Extend kubeadm config + set_fact: + kubeadm_config: >- + {{ original | combine(update, recursive=true) }} + vars: + original: >- + {{ kubeadm_config.stdout | from_yaml }} + +- name: Render /etc/kubeadm/kubeadm-config.yml + copy: + dest: /etc/kubeadm/kubeadm-config.yml + content: >- + {{ kubeadm_config | to_nice_yaml }} diff --git a/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_common/tasks/update-in-cluster-config.yml b/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_common/tasks/update-in-cluster-config.yml new file mode 100644 index 0000000000..c408baa11a --- /dev/null +++ b/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_common/tasks/update-in-cluster-config.yml @@ -0,0 +1,11 @@ +--- +- name: Update in-cluster configuration + shell: | + kubeadm init phase upload-config kubeadm \ + --config /etc/kubeadm/kubeadm-config.yml + args: + executable: /bin/bash + register: upload_config + until: upload_config is succeeded + retries: 30 + delay: 10 diff --git a/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_master/tasks/main.yml b/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_master/tasks/main.yml index 6777864189..993669f456 100644 --- a/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_master/tasks/main.yml +++ b/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_master/tasks/main.yml @@ -1,4 +1,8 @@ --- +- name: Set is_first_deployment fact + set_fact: + is_first_deployment: false + - when: use_ha_control_plane block: - name: Configure internal load-balancer (HAProxy) @@ -15,7 +19,8 @@ - import_tasks: registry-secrets.yml - import_tasks: copy-kubernetes-pki.yml -- when: use_ha_control_plane +- name: Join Kubernetes master + when: use_ha_control_plane block: - name: Join Kubernetes HA master when: kubernetes_common.automation_designated_master != inventory_hostname @@ -23,6 +28,36 @@ - import_tasks: copy-kubernetes-pki.yml - import_tasks: master-join.yml +- name: Regenerate apiserver certificates + when: kubernetes_common.automation_designated_master != inventory_hostname or not is_first_deployment +# It's almost always necessary to regenerate certificates for designated and non-designated masters +# because of a few points: +# a. Update certificates for old clusters have to be supported +# b. Execution order is not defined, so when cluster is promoted to HA, +# non-designated masters may join cluster before designated master's certificate update + block: + - name: Extend kubeadm config + vars: + update: + apiServer: + certSANs: >- + {{ groups['kubernetes_master'] | map('extract', hostvars, ['ansible_host']) | list + + [ 'localhost', '127.0.0.1' ] }} + include_role: + name: kubernetes_common + tasks_from: extend-kubeadm-config + + - name: Backup and generate apiserver certificates + include_role: + name: kubernetes_common + tasks_from: apiserver-certificates + +- name: Update in-cluster configuration + when: kubernetes_common.automation_designated_master == inventory_hostname + include_role: + name: kubernetes_common + tasks_from: update-in-cluster-config + - import_tasks: master-untaint.yml - include_tasks: "{{ specification.provider }}/kubernetes-storage.yml" diff --git a/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_master/tasks/master-init.yml b/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_master/tasks/master-init.yml index 4cf122caf0..2fefbe0628 100644 --- a/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_master/tasks/master-init.yml +++ b/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_master/tasks/master-init.yml @@ -11,6 +11,10 @@ - when: not stat_kube_apiserver_yaml.stat.exists block: + - name: Set is_first_deployment fact + set_fact: + is_first_deployment: true + - name: Ensure /etc/kubeadm/ directory exists file: path: /etc/kubeadm/ diff --git a/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_master/templates/kubeadm-config.yml.j2 b/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_master/templates/kubeadm-config.yml.j2 index c1f6f65cc2..716fc9417e 100644 --- a/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_master/templates/kubeadm-config.yml.j2 +++ b/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_master/templates/kubeadm-config.yml.j2 @@ -9,6 +9,12 @@ controlPlaneEndpoint: "localhost:3446" apiServer: timeoutForControlPlane: 4m0s + certSANs: + - localhost + - 127.0.0.1 +{% for host in groups['kubernetes_master'] %} + - {{ hostvars[host]['ansible_host'] }} +{% endfor %} extraArgs: # https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/ {% if specification.advanced.etcd_args.encrypted | bool %} encryption-provider-config: /etc/kubernetes/pki/etcd/etc-encryption.conf diff --git a/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_promote/handlers/main.yml b/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_promote/handlers/main.yml index e080ddb5f5..eda1a4eeb0 100644 --- a/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_promote/handlers/main.yml +++ b/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_promote/handlers/main.yml @@ -1,13 +1,4 @@ --- -- name: Restart apiserver - shell: | - docker ps \ - --filter 'name=kube-apiserver_kube-apiserver' \ - --format '{{ "{{.ID}}" }}' \ - | xargs --no-run-if-empty docker kill - args: - executable: /bin/bash - - name: Restart controller-manager shell: | docker ps \ diff --git a/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_promote/tasks/update-master.yml b/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_promote/tasks/update-master.yml index 04a0f6b0a9..2b046fd8fb 100644 --- a/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_promote/tasks/update-master.yml +++ b/core/src/epicli/data/common/ansible/playbooks/roles/kubernetes_promote/tasks/update-master.yml @@ -6,80 +6,18 @@ - when: promote_to_ha and (not kubernetes_promote.kubernetes_already_ha) block: - - name: Collect kubeadm-config - shell: | - kubectl get configmap kubeadm-config \ - --namespace kube-system \ - --output jsonpath={{ jsonpath }} - vars: - jsonpath: >- - '{.data.ClusterConfiguration}' - environment: - KUBECONFIG: /etc/kubernetes/admin.conf - args: - executable: /bin/bash - register: kubeadm_config - changed_when: false - - name: Extend kubeadm config - set_fact: - kubeadm_config: >- - {{ original | combine(update, recursive=true) }} vars: - original: >- - {{ kubeadm_config.stdout | from_yaml }} update: controlPlaneEndpoint: localhost:3446 - apiServer: - certSANs: - - localhost - - 127.0.0.1 - - - name: Render /etc/kubeadm/kubeadm-config.yml - copy: - dest: /etc/kubeadm/kubeadm-config.yml - content: >- - {{ kubeadm_config | to_nice_yaml }} - - - name: Copy /etc/kubernetes/pki/apiserver.{crt,key} - copy: - dest: "{{ item }}.OLD" - src: "{{ item }}" - remote_src: true - loop: - - /etc/kubernetes/pki/apiserver.crt - - /etc/kubernetes/pki/apiserver.key - - - name: Delete /etc/kubernetes/pki/apiserver.{crt,key} - file: - path: "{{ item }}" - state: absent - loop: - - /etc/kubernetes/pki/apiserver.crt - - /etc/kubernetes/pki/apiserver.key - - - name: Render new certificates /etc/kubernetes/pki/apiserver.{crt,key} - shell: | - kubeadm init phase certs apiserver \ - --config /etc/kubeadm/kubeadm-config.yml - args: - executable: /bin/bash - creates: /etc/kubernetes/pki/apiserver.key - notify: - - Restart apiserver - - - meta: flush_handlers + include_role: + name: kubernetes_common + tasks_from: extend-kubeadm-config - name: Update in-cluster configuration - shell: | - kubeadm init phase upload-config kubeadm \ - --config /etc/kubeadm/kubeadm-config.yml - args: - executable: /bin/bash - register: upload_config - until: upload_config is succeeded - retries: 30 - delay: 10 + include_role: + name: kubernetes_common + tasks_from: update-in-cluster-config - name: Update /etc/kubernetes/{controller-manager,scheduler,admin}.conf replace: