<p>The answer given by @Eduardo Baitello is the correct answer for the vast majority of Kube installs. However I learned that if you've installed the MicroK8S snap install on Ubuntu the instructions are a little bit different. Per <a href="https://github.com/ubuntu/microk8s/issues/421" rel="nofollow noreferrer">this issue</a>, you'll need to update the <code>/var/snap/microk8s/current/certs/csr.conf.template</code> file, then run <code>microk8s.stop</code> and <code>microk8s.start</code> in succession.</p>

CC BY-SA 4.0
2020-02-17T22:44:51.983Z
2020-11-01T20:40:07.277Z
2020-11-01T20:40:07.277Z
soapergem
<p>To do this, you’ll first need your <code>kubeadm</code> configuration file. This creates a file named <code>kubeadm.yaml</code>:</p>

<p><code>kubectl -n kube-system get configmap kubeadm-config -o jsonpath='{.data.ClusterConfiguration}' &gt; kubeadm.yaml</code></p>

<p>Now open the file in an editor, and find the <code>certSANs</code> list under the <code>apiServer</code> section. If it does not exist, you’ll need to add it; if so, you’ll just add another entry to that list. Example:</p>

<pre><code>apiServer:
  certSANs:
  - "172.29.50.162"
  - "k8s.domain.com"
  - "other-k8s.domain.net"
  extraArgs:
    authorization-mode: Node,RBAC
  timeoutForControlPlane: 4m0s
</code></pre>

<p>Now move the old certificates to another folder, otherwise <code>kubeadm</code> will not recreate new ones:</p>

<p><code>mv /etc/kubernetes/pki/apiserver.{crt,key} ~</code> </p>

<p>Use <code>kubeadm</code> to generate new apiserver certificates:</p>

<p><code>kubeadm init phase certs apiserver --config kubeadm.yaml</code></p>

<p>Now restart your <em>kubeapiserver</em> container:</p>

<ol>
<li>Run <code>docker ps | grep kube-apiserver | grep -v pause</code> to get the
container ID for the container running the Kubernetes API server</li>
<li>Run <code>docker kill &lt;containerID&gt;</code> to kill the container.</li>
<li><em>The Kubelet will automatically restart the container, which will pick up the new certificate.</em></li>
</ol>

<p>If everything is working as expected, don't forget to update the <code>kubeadm</code> ConfigMap stored in the cluster, otherwise, future <code>kubeadm</code> upgrade will be lacking your new config:</p>

<p>If using Kubernetes &lt; v1.15:</p>

<p><code>kubeadm config upload from-file --config kubeadm.yaml</code></p>

<p>For Kubernetes version >= <a href="https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.15.md#deprecations-and-removals" rel="noreferrer">v1.15</a>:</p>

<p><code>kubeadm init phase upload-config kubeadm --config kubeadm.yaml</code></p>

<p><em>This article has a more complete guide on how to <a href="https://blog.scottlowe.org/2019/07/30/adding-a-name-to-kubernetes-api-server-certificate/" rel="noreferrer">Adding a Name to the Kubernetes API Server Certificate</a></em></p>

CC BY-SA 4.0
2019-11-03T05:09:56.230Z
Worked like a charm! Only one thing to note: the `from-file` option you specified at the end is actually deprecated. The new command to upload that file is `kubeadm init phase upload-config kubeadm --config=kubeadm.yaml` Thank you!
soapergem
CC BY-SA 4.0
2019-11-04T02:42:24.193Z
@soapergem Thanks for noting! The answer was updated with the new command.
Eduardo Baitello
CC BY-SA 4.0
2021-11-11T21:20:16.590Z
This worked really well. just one quick update: on Kubernetes v1.22.3 I did not have to restart the apiserver for the new certs to be used
DysphoricUnicorn
CC BY-SA 4.0
2023-10-11T11:07:18.233Z
This did not work for me. I cannot generate the kubeadm.yaml because the wrong IP in in my cert! Is there a way to generate it without a connection to the apiserver on port 6443?
Aditya K
CC BY-SA 4.0
2019-10-21T14:14:36.627Z
2019-11-04T02:41:42.347Z
2019-11-04T02:41:42.347Z
Eduardo Baitello
<p>I've recently followed <a href="https://medium.com/nycdev/k8s-on-pi-9cc14843d43" rel="noreferrer">this guide</a> to set up Kubernetes on my local Raspberry Pi cluster. I can access it fine on my LAN; however I'd like to be able to access it remotely as well. I've already set up port forwarding on my router, but when I try to connect from outside the LAN, I get a x509 certificate error indicating that the certificate is signed for my local 192.168 address but not for my home's IP. I could bypass this with the <code>--insecure-skip-tls-verify</code> options but I'd much rather have the certificate used simply incorporate my IP address. Only... I'm not fully sure how to do that, though I do have some ideas.</p>

<p>When I initially set things up with <code>kubeadm init</code>, should I have used the <code>--apiserver-advertise-address</code> option to specify my home IP? Would doing so have had any adverse effects (such as precluding my local/192.168 IP?). Ideally I'd like the certificate to be signed for both the internal and external IPs. Or is there some other option I should have given to <code>kubeadm init</code>? Secondly, now that it has been initialized, is there any way to regenerate the certificate and swap it out, or will I need to nuke the cluster?</p>

<p>To clarify, I don't have any certificate managers installed. I'm not talking about Ingress. I'm talking about the actual "root" certificate (for lack of a better term) that kubeadm generates when first installing the cluster, i.e. the one that lives at <code>/etc/kubernetes/pki/apiserver.crt</code></p>

<kubernetes><ssl>
How can I add an additional IP / hostname to my Kubernetes certificate?
soapergem
# How can I add an additional IP / hostname to my Kubernetes certificate?

(Asked by: username_0 on 2019-10-18)

I've recently followed [this guide](https://medium.com/nycdev/k8s-on-pi-9cc14843d43) to set up Kubernetes on my local Raspberry Pi cluster. I can access it fine on my LAN; however I'd like to be able to access it remotely as well. I've already set up port forwarding on my router, but when I try to connect from outside the LAN, I get a x509 certificate error indicating that the certificate is signed for my local 192.168 address but not for my home's IP. I could bypass this with the `--insecure-skip-tls-verify` options but I'd much rather have the certificate used simply incorporate my IP address. Only... I'm not fully sure how to do that, though I do have some ideas.

When I initially set things up with `kubeadm init`, should I have used the `--apiserver-advertise-address` option to specify my home IP? Would doing so have had any adverse effects (such as precluding my local/192.168 IP?). Ideally I'd like the certificate to be signed for both the internal and external IPs. Or is there some other option I should have given to `kubeadm init`? Secondly, now that it has been initialized, is there any way to regenerate the certificate and swap it out, or will I need to nuke the cluster?

To clarify, I don't have any certificate managers installed. I'm not talking about Ingress. I'm talking about the actual "root" certificate (for lack of a better term) that kubeadm generates when first installing the cluster, i.e. the one that lives at `/etc/kubernetes/pki/apiserver.crt`

**Tags:** kubernetes, ssl


---

## 2 answers

### Answer by username_1 on 2019-10-21. Score: 15 | Accepted answer

To do this, you’ll first need your kubeadm configuration file. This creates a file named kubeadm.yaml:
kubectl -n kube-system get configmap kubeadm-config -o jsonpath='{.data.ClusterConfiguration}' > kubeadm.yaml
Now open the file in an editor, and find the certSANs list under the apiServer section. If it does not exist, you’ll need to add it; if so, you’ll just add another entry to that list. Example:
apiServer:
  certSANs:
  - "172.29.50.162"
  - "k8s.domain.com"
  - "other-k8s.domain.net"
  extraArgs:
    authorization-mode: Node,RBAC
  timeoutForControlPlane: 4m0s

Now move the old certificates to another folder, otherwise kubeadm will not recreate new ones:
mv /etc/kubernetes/pki/apiserver.{crt,key} ~ 
Use kubeadm to generate new apiserver certificates:
kubeadm init phase certs apiserver --config kubeadm.yaml
Now restart your kubeapiserver container:

Run docker ps | grep kube-apiserver | grep -v pause to get the
container ID for the container running the Kubernetes API server
Run docker kill  to kill the container.
The Kubelet will automatically restart the container, which will pick up the new certificate.

If everything is working as expected, don't forget to update the kubeadm ConfigMap stored in the cluster, otherwise, future kubeadm upgrade will be lacking your new config:
If using Kubernetes < v1.15:
kubeadm config upload from-file --config kubeadm.yaml
For Kubernetes version >= v1.15:
kubeadm init phase upload-config kubeadm --config kubeadm.yaml
This article has a more complete guide on how to Adding a Name to the Kubernetes API Server Certificate

> **Comments:**
> **username_0**: Worked like a charm! Only one thing to note: the `from-file` option you specified at the end is actually deprecated. The new command to upload that file is `kubeadm init phase upload-config kubeadm --config=kubeadm.yaml` Thank you!  
> **username_1**: @username_0 Thanks for noting! The answer was updated with the new command.  
> **username_2**: This worked really well. just one quick update: on Kubernetes v1.22.3 I did not have to restart the apiserver for the new certs to be used  
> **username_3**: This did not work for me. I cannot generate the kubeadm.yaml because the wrong IP in in my cert! Is there a way to generate it without a connection to the apiserver on port 6443?  

---

### Answer by username_0 on 2020-02-17. Score: 3

The answer given by @username_1 is the correct answer for the vast majority of Kube installs. However I learned that if you've installed the MicroK8S snap install on Ubuntu the instructions are a little bit different. Per [this issue](https://github.com/ubuntu/microk8s/issues/421), you'll need to update the `/var/snap/microk8s/current/certs/csr.conf.template` file, then run `microk8s.stop` and `microk8s.start` in succession.


---

