From c4346e590f12239fe9f597cebdb00b5c0ffdc7b3 Mon Sep 17 00:00:00 2001
From: Arthur Outhenin-Chalandre <arthur.outhenin-chalandre@proton.ch>
Date: Fri, 20 Jan 2023 09:26:16 +0100
Subject: [PATCH] kubeadm/etcd: use config to download certificate (#9609)

This commit uses a kubeadm join config to pull down cert for etcd in
workers nodes (which is needed in some circumstances, for instance with
calico or cilium).

The previous way didn't allow us to pass certain parameters which was
typically given in the config in other kubeadm invokations in Kubespray.
This made kubeadm produced some errors for some edge cases.

For example, in our deployment we don't have a default route and even
though it's only to download the certificates, kubeadm produce an error
`unable to select an IP from default routes` (these command are kubeadm
controlplane command, so kubeadm does some additional checks). This is
fixed by specifying `advertiseAddress` within the kubeadm config.

Signed-off-by: Arthur Outhenin-Chalandre <arthur.outhenin-chalandre@proton.ch>

Signed-off-by: Arthur Outhenin-Chalandre <arthur.outhenin-chalandre@proton.ch>
---
 .../kubeadm/tasks/kubeadm_etcd_node.yml       | 19 ++++++++++---------
 .../templates/kubeadm-client.conf.v1beta3.j2  |  7 +++++++
 2 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/roles/kubernetes/kubeadm/tasks/kubeadm_etcd_node.yml b/roles/kubernetes/kubeadm/tasks/kubeadm_etcd_node.yml
index c87b840c1..651bcc39d 100644
--- a/roles/kubernetes/kubeadm/tasks/kubeadm_etcd_node.yml
+++ b/roles/kubernetes/kubeadm/tasks/kubeadm_etcd_node.yml
@@ -4,22 +4,23 @@
     kubeadm_certificate_key: "{{ hostvars[groups['kube_control_plane'][0]]['kubeadm_certificate_key'] }}"
   when: kubeadm_certificate_key is undefined
 
+- name: Create kubeadm cert controlplane config
+  template:
+    src: "kubeadm-client.conf.{{ kubeadmConfig_api_version }}.j2"
+    dest: "{{ kube_config_dir }}/kubeadm-cert-controlplane.conf"
+    mode: 0640
+  vars:
+    kubeadm_cert_controlplane: true
+
 - name: Pull control plane certs down
   shell: >-
     {{ bin_dir }}/kubeadm join phase
     control-plane-prepare download-certs
-    --certificate-key {{ kubeadm_certificate_key }}
-    --control-plane
-    --token {{ kubeadm_token }}
-    --discovery-token-unsafe-skip-ca-verification
-    {{ kubeadm_discovery_address }}
+    --config {{ kube_config_dir }}/kubeadm-cert-controlplane.conf
     &&
     {{ bin_dir }}/kubeadm join phase
     control-plane-prepare certs
-    --control-plane
-    --token {{ kubeadm_token }}
-    --discovery-token-unsafe-skip-ca-verification
-    {{ kubeadm_discovery_address }}
+    --config {{ kube_config_dir }}/kubeadm-cert-controlplane.conf
   args:
     creates: "{{ kube_cert_dir }}/apiserver-etcd-client.key"
 
diff --git a/roles/kubernetes/kubeadm/templates/kubeadm-client.conf.v1beta3.j2 b/roles/kubernetes/kubeadm/templates/kubeadm-client.conf.v1beta3.j2
index 64c3db99a..5104ecfb9 100644
--- a/roles/kubernetes/kubeadm/templates/kubeadm-client.conf.v1beta3.j2
+++ b/roles/kubernetes/kubeadm/templates/kubeadm-client.conf.v1beta3.j2
@@ -18,6 +18,13 @@ discovery:
   timeout: {{ discovery_timeout }}
   tlsBootstrapToken: {{ kubeadm_token }}
 caCertPath: {{ kube_cert_dir }}/ca.crt
+{% if kubeadm_cert_controlplane is defined and kubeadm_cert_controlplane %}
+controlPlane:
+  localAPIEndpoint:
+    advertiseAddress: {{ kube_apiserver_address }}
+    bindPort: {{ kube_apiserver_port }}
+  certificateKey: {{ kubeadm_certificate_key }}
+{% endif %}
 nodeRegistration:
   name: '{{ kube_override_hostname }}'
   criSocket: {{ cri_socket }}
-- 
GitLab