rke、rke2 是如何实现 kube-apiserver 高可用的
Kubernetesg官网中有这么一张图,使用 kubeadm
引导的 Kubernetes 集群,使用负载均衡器将kube-apiserver
暴露给工作节点。
如果你使用过rke
、rke2
等 Kubernetes 发行版,你会发现,他们并没有使用负载均衡器也能实现 kube-apiserver
的高可用。
你有没有思考过 rke
、rke2
等 Kubernetes 发行版是如何做 kube-apiserver
的高可用的呢?
要搞清楚这个问题,我们看一下 kubelet 是如何连接 kube-apiserver
的就有答案了。
rke 是如何实现 kube-apiserver
高可用的?
我找一个工作节点,查看 kubelet
容器配置
docker inspect kubelet
可以看到以下启动参数,主要看 --kubeconfig
参数:
"Args": [
"kubelet",
<省略很多内容>
"--kubeconfig=/etc/kubernetes/ssl/kubecfg-kube-node.yaml",
<省略很多内容>
]
--kubeconfig=/etc/kubernetes/ssl/kubecfg-kube-node.yaml
参数说明 kubelet
连接 kube-apiserver
使用了 /etc/kubernetes/ssl/kubecfg-kube-node.yaml
这个配置文件连接 kube-apiserver
,看下这个文件的内容。
cat /etc/kubernetes/ssl/kubecfg-kube-node.yaml
apiVersion: v1
kind: Config
clusters:
- cluster:
api-version: v1
certificate-authority: /etc/kubernetes/ssl/kube-ca.pem
server: "https://127.0.0.1:6443"
name: "local"
<省略很多内容>
可以看到,kube-apiserver
的地址是 https://127.0.0.1:6443
,那么为什么是这个地址呢?继续查看本机有没有监听6443端口。
netstat -ntlp | grep 6443
tcp 0 0 0.0.0.0:6443 0.0.0.0:* LISTEN 31002/nginx: master
可以看到有个nginx服务监听了 6443,我们看下这个nginx是怎么配置的。
docker exec -it nginx-proxy /bin/sh
sh-5.1# cat /etc/nginx/nginx.conf
<省略很多内容>
stream {
upstream kube_apiserver {
server 172.31.1.1:6443;
server 172.31.1.2:6443;
server 172.31.1.3:6443;
}
server {
listen 6443;
proxy_pass kube_apiserver;
proxy_timeout 10m;
proxy_connect_timeout 2s;
}
}
看到这里,你就明白了,rke
在每个工作节点都运行了一个 nginx-proxy
的容器,负责 kube-apiserver
的反向代理。
控制节点是不需要运行这个 nginx-proxy
的,因为控制节点已然部署了 kube-apiserver
,监听了 6443 端口。https://127.0.0.1:6443
就是能访问到本机的 kube-apiserver
的。
rke2 是如何实现 kube-apiserver
高可用的?
同样的逻辑,找一个控制节点查看 kubelet
的启动参数。
ps aux | grep kubelet
<省略很多内容> kubelet <省略很多内容> --kubeconfig=/var/lib/rancher/rke2/agent/kubelet.kubeconfig
rke2
的 kubelet
不是使用容器运行的,是 rke2
程序拉起的,所以在本机用 ps
命令即可查看到。rke2
中 kubelet 用的是这个配置文件,还是一样的配方,看下文件内容。
cat /var/lib/rancher/rke2/agent/kubelet.kubeconfig
apiVersion: v1
clusters:
- cluster:
server: https://127.0.0.1:6443
certificate-authority: /var/lib/rancher/rke2/agent/server-ca.crt
name: local
<省略很多内容>
还是 https://127.0.0.1:6443
,继续看。
netstat -ntlp | grep 6443
tcp 0 0 127.0.0.1:6443 0.0.0.0:* LISTEN 13844/rke2 agent
rke2 agent
监听了 6443 端口。虽然可以猜测就是代理到 kube-apiserver
的,怎么能说服你呢?难道要翻代码找证据吗?好吧,简单翻一下看看。
以下代码在 release-1.26
分支:
// pkg/cli/cmds/agent.go L92
func AgentRun(clx *cli.Context) error {
validateCloudProviderName(clx, Agent)
validateProfile(clx, Agent)
if err := windows.StartService(); err != nil {
return err
}
return rke2.Agent(clx, config)
}
// rke2.Agent(clx, config) 跟进去
// pkg/rke2/rke2.go L128
func Agent(clx *cli.Context, cfg Config) error {
if err := setup(clx, cfg, false); err != nil {
return err
}
return agent.Run(clx)
}
// agent.Run(clx) 跟进去
// pkg/cli/agent/agent.go L98
func Run(ctx *cli.Context) error {
// <省略很多内容>
return agent.Run(contextCtx, cfg)
}
// agent.Run(contextCtx, cfg) 跟进去
// pkg/agent/run.go L270
func Run(ctx context.Context, cfg cmds.Agent) error {
// <省略很多内容>
proxy, err := createProxyAndValidateToken(ctx, &cfg)
}
代码跟到这里,就大概能看到了,rke2 agent
会起一个代理,将 6443 代理至 kube-apiserver
。
总结
不管是 kubeadm
还是 rke
、rke2
引导的集群,kube-apiserver
都是要做高可用的,只是 kubeadm
搭建的集群没有内置的反向代理机制帮我们简化工作,需要你在搭建时考虑高可用,一般是使用负载均衡器来做反向代理。
而 rke
、rke2
等发行版,他们内置了反向代理机制,我们在搭建集群时就不需要考虑集群内 kube-apiserver
的高可用了。他是在每一个工作节点上启动一个反向代理程序,rke
是用 nginx
容器跑的一个反向代理,rke2
是 rke2 agent
起一个反向代理。但是如果你的 kube-apiserver
需要暴露给外部访问,且需要做高可用,你还是得考虑用一个负载均衡器才行。
画一个拓朴图,更直观些。
RKE
RKE2