如何优雅的通过 ApiServer 远程访问 Kubernetes 集群

Posted by Mike on 2021-09-27

在研发时,需要直接连接远端 Kubernetes 集群。通常的做法是,将 /etc/kubernetes/admin.conf 拷贝到本地 ~/.kube/kubeconfig

但是 kubeconfig 的 server 地址是 kubernetes.default.svc。因此,我们需要配置一个 hosts:

1
1.1.1.1 kubernetes.default.svc

如果需要在不同集群之间切换,不仅需要更换 kubeconfig,还需要修改 hosts。下面介绍一种方法,可以直接将远程访问地址,添加到集群的证书中,节省修改 hosts 的步骤,同时还能让人更容易的区分不同集群。

查看 Apiserver 证书包含哪些地址

  1. 进入证书目录
1
cd /etc/kubernetes/pki
  1. 查看证书
1
2
3
4
$ openssl x509 -in apiserver.crt -noout -text|grep -A  2 'Alternative'

X509v3 Subject Alternative Name:
DNS:1-1-1-1, DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster.local, DNS:lb-apiserver.kubernetes.local, DNS:localhost, IP Address:1.1.1.1

这里如果只允许通过 1.1.1.1 访问集群的 Apiserver。如果需要使用域名,kubernetes、kubernetes.default、kubernetes.default.svc 等,则需要配置 hosts 将其指向 1.1.1.1 。

添加新的域名或 IP 到证书

  1. 备份证书
1
2
3
$ cd /etc/kubernetes/pki
$ mv apiserver.crt apiserver.crt.bak
$ mv apiserver.key apiserver.key.bak
  1. 修改 /etc/kubernetes/kubeadm-config.yaml

在 ClusterConfiguration 的 apiServer 字段下,找到 certSANs。

1
2
3
4
5
6
7
8
9
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
...
certSANs:
- kubernetes
- kubernetes.default
- kubernetes.default.svc
- kubernetes.default.svc.cluster.local
- 10.233.0.1

在 certSANs 中添加远程访问的域名或 IP 地址:

1
2
3
4
5
6
7
8
certSANs:
- remote.doamin.com
- 1.2.3.4
- kubernetes
- kubernetes.default
- kubernetes.default.svc
- kubernetes.default.svc.cluster.local
- 10.233.0.1

如果你在 /etc/kubernetes/ 目录中没有找到 kubeadm-config.yaml 文件,不要紧张,你可以使用下面的方式生成一个当前集群的配置文件:

1
2
3
$ kubectl get cm kubeadm-config  -n kube-system -o yaml > /etc/kubernetes/kubeadm-config.yaml
或者
$ kubeadm config view | tee /etc/kubernetes/kubeadm-config.yaml

当然你的集群的配置文件中可能没有 certSANs 配置段,你可以直接加在类似下面的位置处:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiServer:
certSANs:
- remote.doamin.com
- 1.2.3.4
- kubernetes
- kubernetes.default
- kubernetes.default.svc
- kubernetes.default.svc.cluster.local
- 10.233.0.1
extraArgs:
authorization-mode: Node,RBAC
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
....
  1. 重新生成证书
1
$ kubeadm init phase certs apiserver --config /etc/kubernetes/kubeadm-config.yaml
  1. 再次查看证书

检查输出的结果中,是否包含前面增加的公网 IP,如有则证明操作成功。

1
2
$ openssl x509 -in pki/apiserver.crt -noout -text | grep 1.2.3.4
IP Address:192.168.0.8, IP Address: 1.2.3.4
  1. 重启 kube-apiserver
  • 如果是高可用集群

直接杀死当前节点的 kube-apiserver 进程,等待 kubelet 拉起 kube-apiserver 即可。需要在三个节点执行步骤 1 到步骤 4,逐一更新。

  • 如果是非高可用集群

杀死 kube-apiserver 可能会导致服务有中断,需要在业务低峰的时候操作。

进入 /etc/kubernetes/manifests 目录下,移动 kube-apiserver.yaml 文件至其它位置,然后又移回来即可。

1
2
$ mv /etc/kubernetes/manifests/kube-apiserver.yaml /root/
$ mv /root/kube-apiserver.yaml /etc/kubernetes/manifests
  1. 修改 kubeconfig 中的 server ip

最后,你只需要将 kubeconfig 文件中 server 地址修改为 1.2.3.4

1
2
3
4
5
6
apiVersion: v1
clusters:
- cluster:
...
server: https://1.2.3.4:6443
...

保存之后,就可以直接通过公网 IP 访问 Kubernetes 集群。

1
$ kubectl get node

参考

  1. https://www.chenshaowen.com/blog/how-to-add-entrance-to-kubernetes-apiserver.html
  2. https://kubesphereio.com/post/add-public-ip-to-kubernetes-apiserver-operation-guide/
  3. https://stackoverflow.com/questions/61023319/where-i-can-find-kubeadm-config-yaml-on-my-kubernetes-cluster
  4. https://help.hcltechsw.com/connections/v6/admin/install/cp_prereqs_upgrade_latest_implementation.html