<p>I setup a k8s cluster using <code>kubeadm init</code> on a bare metal cluster.</p>
<p>I noticed the <code>kube-apiserver</code> is exposing its interface on a private IP:</p>
<pre><code># kubectl get pods kube-apiserver-cluster1 -n kube-system -o wide
NAME                                        READY   STATUS    RESTARTS   AGE     IP           NODE                         NOMINATED NODE   READINESS GATES
kube-apiserver-cluster1                     1/1     Running   0          6d22h   10.11.1.99   cluster1   &lt;none&gt;           &lt;none&gt;
</code></pre>
<p>Here's the kube config inside the cluster:</p>
<pre><code># kubectl config view
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.11.1.99:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
</code></pre>
<p>This is fine for using <code>kubectl</code> locally on the cluster, but I want to add an additional interface to expose the <code>kube-apiserver</code> using the public IP address.  Ultimately I'm trying to configure <code>kubectl</code> from a laptop to remotely access the cluster.</p>
<p>How can I expose the <code>kube-apiserver</code> on an external IP address?</p>

<p>Execute following command:</p>
<pre><code>$ kubeadm init --pod-network-cidr=&lt;ip-range&gt; --apiserver-advertise-address=0.0.0.0 --apiserver-cert-extra-sans=&lt;PRIVATE_IP&gt;[,&lt;PUBLIC_IP&gt;,...]
</code></pre>
<p>Don't forget to replace the private IP for the public IP in your <code>.kube/config</code> if you use kubectl from remote.</p>
<p>You can also forward the private IP of the master node to the public IP of the master node on the worker node. Run this command on worker node before running <code>kubeadm join</code>:<br />
<code>$ sudo iptables -t nat -A OUTPUT -d &lt;Private IP of master node&gt; -j DNAT --to-destination &lt;Public IP of master node&gt;</code>.
But keep in mind that you'll also have to forward worker private IPs the same way on the master node to make everything work correctly (if they suffer from the same issue of being covered by cloud provider NAT).</p>
<p>See more: <a href="https://github.com/kubernetes/kubeadm/issues/1390#issuecomment-507483963" rel="nofollow noreferrer">apiserver-ip</a>,  <a href="https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/" rel="nofollow noreferrer">kube-apiserver</a>.</p>
