From 30306d6ec7b3e7826d2f03c10137a332860a70c7 Mon Sep 17 00:00:00 2001
From: Julien Le Fur <julien.lefur@gmail.com>
Date: Tue, 12 Apr 2022 14:47:23 +0200
Subject: [PATCH] Enable external CA mode for control-plane deployment (#8620)

---
 .../control-plane/tasks/kubeadm-secondary.yml      | 14 ++++++++++++--
 .../control-plane/tasks/kubeadm-setup.yml          |  5 ++++-
 .../preinstall/tasks/0020-verify-settings.yml      |  8 ++++++++
 roles/kubespray-defaults/defaults/main.yaml        |  6 ++++++
 4 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/roles/kubernetes/control-plane/tasks/kubeadm-secondary.yml b/roles/kubernetes/control-plane/tasks/kubeadm-secondary.yml
index 99c3d66a2..a4869fec8 100644
--- a/roles/kubernetes/control-plane/tasks/kubeadm-secondary.yml
+++ b/roles/kubernetes/control-plane/tasks/kubeadm-secondary.yml
@@ -19,6 +19,7 @@
   register: kubeadm_upload_cert
   when:
     - inventory_hostname == first_kube_control_plane
+    - not kube_external_ca_mode
 
 - name: Parse certificate key if not set
   set_fact:
@@ -49,11 +50,20 @@
   debug:
     msg: "{{ kubeadm_already_run.stat.exists }}"
 
-- name: Joining control plane node to the cluster.
+- name: Reset cert directory
   shell: >-
     if [ -f /etc/kubernetes/manifests/kube-apiserver.yaml ]; then
     {{ bin_dir }}/kubeadm reset -f --cert-dir {{ kube_cert_dir }};
-    fi &&
+    fi
+  environment:
+    PATH: "{{ bin_dir }}:{{ ansible_env.PATH }}"
+  when:
+    - inventory_hostname != first_kube_control_plane
+    - kubeadm_already_run is not defined or not kubeadm_already_run.stat.exists
+    - not kube_external_ca_mode
+
+- name: Joining control plane node to the cluster.
+  command: >-
     {{ bin_dir }}/kubeadm join
     --config {{ kube_config_dir }}/kubeadm-controlplane.yaml
     --ignore-preflight-errors=all
diff --git a/roles/kubernetes/control-plane/tasks/kubeadm-setup.yml b/roles/kubernetes/control-plane/tasks/kubeadm-setup.yml
index e99f2f840..23f798d64 100644
--- a/roles/kubernetes/control-plane/tasks/kubeadm-setup.yml
+++ b/roles/kubernetes/control-plane/tasks/kubeadm-setup.yml
@@ -101,6 +101,7 @@
   changed_when: "'NEED-RENEW' in apiserver_sans_check.stdout"
   when:
     - kubeadm_already_run.stat.exists
+    - not kube_external_ca_mode
 
 - name: kubeadm | regenerate apiserver cert 1/2
   file:
@@ -112,6 +113,7 @@
   when:
     - kubeadm_already_run.stat.exists
     - apiserver_sans_check.changed
+    - not kube_external_ca_mode
 
 - name: kubeadm | regenerate apiserver cert 2/2
   command: >-
@@ -121,6 +123,7 @@
   when:
     - kubeadm_already_run.stat.exists
     - apiserver_sans_check.changed
+    - not kube_external_ca_mode
 
 - name: kubeadm | Initialize first master
   command: >-
@@ -129,7 +132,7 @@
     --config={{ kube_config_dir }}/kubeadm-config.yaml
     --ignore-preflight-errors=all
     --skip-phases={{ kubeadm_init_phases_skip | join(',') }}
-    --upload-certs
+    {{ kube_external_ca_mode | ternary('', '--upload-certs') }}
   register: kubeadm_init
   # Retry is because upload config sometimes fails
   retries: 3
diff --git a/roles/kubernetes/preinstall/tasks/0020-verify-settings.yml b/roles/kubernetes/preinstall/tasks/0020-verify-settings.yml
index 27c0bfdd5..08f4eaeb1 100644
--- a/roles/kubernetes/preinstall/tasks/0020-verify-settings.yml
+++ b/roles/kubernetes/preinstall/tasks/0020-verify-settings.yml
@@ -376,3 +376,11 @@
   when:
     - containerd_config is defined
     - not ignore_assert_errors
+
+- name: Stop if auto_renew_certificates is enabled when certificates are managed externally (kube_external_ca_mode is true)
+  assert:
+    that: not auto_renew_certificates
+    msg: "Variable auto_renew_certificates must be disabled when CA are managed externally:  kube_external_ca_mode = true"
+  when:
+    - kube_external_ca_mode
+    - not ignore_assert_errors
diff --git a/roles/kubespray-defaults/defaults/main.yaml b/roles/kubespray-defaults/defaults/main.yaml
index 351b4d60e..e1a351901 100644
--- a/roles/kubespray-defaults/defaults/main.yaml
+++ b/roles/kubespray-defaults/defaults/main.yaml
@@ -157,6 +157,12 @@ kube_token_dir: "{{ kube_config_dir }}/tokens"
 # cert files to. Not really changeable...
 kube_cert_group: kube-cert
 
+# Set to true when the CAs are managed externally.
+# When true, disables all tasks manipulating certificates. Ensure before the kubespray run that:
+# - Certificates and CAs are present in kube_cert_dir
+# - Kubeconfig files are present in kube_config_dir
+kube_external_ca_mode: false
+
 # Cluster Loglevel configuration
 kube_log_level: 2
 
-- 
GitLab