If you're self-hosting a Kubernetes cluster, you may wish to add more hosts (SANs) to your apiserver certificate. The API server will complain if it's attempting to be accessed from a host which is not declared in the apiserver certificate.


  • This tutorial presumes an already deployed cluster
  • Steps with the title ending in [!] mean that the step should be repeated on each node
  • There may be a better and easier way to do this - but this is what I've come up with
  • This whole process should not affect the operation of the pods in your cluster


Download and backup your kubeadm cluster config

kubeadm config view > kubeadm.yaml

# make a backup for the config
cp kubeadm.yaml kubeadm.yaml.bak

Add new apiserver SANs to your kubeadm config

Open your kubeadm.yaml file and add inside of apiServer the field (type array) certSANs. Add the first value as what you'd like to access the apiserver with - For this example I've set test.a.local.

  - test.a.local
    authorization-mode: Node,RBAC
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
  type: CoreDNS
    dataDir: /var/lib/etcd
imageRepository: registry.opensuse.org/kubic
kind: ClusterConfiguration
kubernetesVersion: v1.17.0
  dnsDomain: cluster.local
scheduler: {}

Note; The manifest above is my full openSUSE Kubic default kubeadm with certSANs added (and a host)

Upgrade your cluster with the fresh kubeadm [!]

This will 'upgrade' your kubeadm cluster to use the new kubeadm definition.

kubeadm upgrade apply --config=kubeadm.yaml

Remove the old certificates [!]

Deleting the old certificates cannot be undone. Since the kubeadm config has been updated they may not be able to be used anyhow.

rm /etc/kubernetes/pki/apiserver.*

Regenerate the apiserver certificates by running the kubeadm init for the certs phase [!]

Only initialize the apiserver certs.

kubeadm init phase certs apiserver --config=kubeadm.yaml

Delete the apiserver Pod, so it recreates and restarts [!?]

This step may or may not be required for all nodes (I haven't tested it).

# find the pod
KUBE_APISERVER_NAME=$(kubectl -n kube-system get pods -l component=kube-apiserver -o=jsonpath='{.items[0].metadata.name}')

kubectl -n kube-system delete pod $KUBE_APISERVER_NAME

Links and references