<p>How can I add a second master to the control plane of an existing Kubernetes 1.14 cluster?
The <a href="https://kubernetes.io/docs/setup/independent/high-availability/#manual-certs" rel="nofollow noreferrer">available documentation</a> apparently assumes that both masters (in stacked control plane and etcd nodes) are created at the same time. I have created my first master already a while ago with <a href="https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/#initializing-your-master" rel="nofollow noreferrer"><code>kubeadm init --pod-network-cidr=10.244.0.0/16</code></a>, so I don't have a <code>kubeadm-config.yaml</code> as referred to by this documentation.</p>

<p>I have tried the following instead:</p>

<pre><code>kubeadm join ... --token ... --discovery-token-ca-cert-hash ... \
  --experimental-control-plane --certificate-key ...
</code></pre>

<p>The part <code>kubeadm join ... --token ... --discovery-token-ca-cert-hash ...</code> is what is suggested when running <code>kubeadm token create --print-join-command</code> on the first master; it normally serves for adding another worker. <code>--experimental-control-plane</code> is for adding another master instead. The key in <code>--certificate-key ...</code> is as suggested by running <a href="https://stackoverflow.com/a/55850990/9164810"><code>kubeadm init phase upload-certs --experimental-upload-certs</code></a> on the first master.</p>

<p>I receive the following errors:</p>

<pre><code>[preflight] Running pre-flight checks
[WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. 
The recommended driver is "systemd". Please follow the guide at 
https://kubernetes.io/docs/setup/cri/
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'
error execution phase preflight: 
One or more conditions for hosting a new control plane instance is not satisfied.

unable to add a new control plane instance a cluster that doesn't have a stable
controlPlaneEndpoint address

Please ensure that:
* The cluster has a stable controlPlaneEndpoint address.
* The certificates that must be shared among control plane instances are provided.
</code></pre>

<p>What does it mean for my cluster not to have a stable <code>controlPlaneEndpoint</code> address? Could this be related to <code>controlPlaneEndpoint</code> in the output from <code>kubectl -n kube-system get configmap kubeadm-config -o yaml</code> currently being an empty string? How can I overcome this situation?</p>

<p>As per <a href="https://kubernetes.io/docs/setup/independent/high-availability/#create-load-balancer-for-kube-apiserver" rel="nofollow noreferrer">HA - Create load balancer for kube-apiserver</a>:</p>

<blockquote>
  <ul>
  <li>In a cloud environment you should place your control plane nodes    behind a TCP forwarding load balancer. This load balancer distributes 
  traffic to all healthy control plane nodes in its target list. The 
  health check for an apiserver is a TCP check on the port the<br>
  kube-apiserver listens on (default value <code>:6443</code>).</li>
  <li>The load balancer must be able to communicate with all control plane nodes on the apiserver port. It must also allow incoming traffic
  on its listening port.  </li>
  <li><strong>Make sure the address of the load balancer
  always matches the address of kubeadm’s <code>ControlPlaneEndpoint</code>.</strong></li>
  </ul>
</blockquote>

<p>To set <code>ControlPlaneEndpoint</code> config, you should use <code>kubeadm</code> with the <code>--config</code> flag. Take a look <a href="https://kubernetes.io/docs/setup/independent/high-availability/#stacked-control-plane-and-etcd-nodes" rel="nofollow noreferrer">here</a> for a config file example:</p>

<pre><code>apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
kubernetesVersion: stable
controlPlaneEndpoint: "LOAD_BALANCER_DNS:LOAD_BALANCER_PORT"
</code></pre>

<p><em>Kubeadm config files examples are scattered across many documentation sections. I recommend that you read the <a href="https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1" rel="nofollow noreferrer"><code>/apis/kubeadm/v1beta1</code></a> GoDoc, which have fully populated examples of YAML files used by multiple kubeadm configuration types.</em></p>

<hr>

<p>If you are configuring a self-hosted control-plane, consider using the <a href="https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm-init/#self-hosting" rel="nofollow noreferrer"><code>kubeadm alpha selfhosting</code></a> feature:</p>

<blockquote>
  <p>[..] key components such as the API server, controller manager, and
  scheduler run as DaemonSet pods configured via the Kubernetes API
  instead of static pods configured in the kubelet via static files.</p>
</blockquote>

<p>This PR (<a href="https://github.com/kubernetes/kubernetes/pull/59371" rel="nofollow noreferrer">#59371</a>) may clarify the differences of using a self-hosted config.</p>
