这次聊聊k8s的高可用性是怎么做的。所谓高可用性,就是在一些服务或机器挂掉了之后集群仍然能正常工作的能力。

作为背景知识,先介绍一下k8s的架构

它分为服务器端(master)和客户端(node)。服务器端主要是3个组件:API Server、Controller Manager和Scheduler。API Server是操作人员和k8s的接口。比如我想看一下当前k8s有几个pod在跑,就需要连接到这个API Server上。Controller Manager顾名思义就是管理各种各样的controller比如先前提到的Replication Controller。Scheduler做的事就是把用户想要启动/删除的pod分发到对应的客户端上。客户端主要是2个组件:Kubelet和Proxy。Kubelet负责响应服务器端的Scheduler分出来的任务。Proxy用来接通服务和对应的机器。举个栗子:如果我们运行这个命令:kubectl -s 192.168.33.10:8080 run nginx —image=nginx来启动一个nginx的rc和pod,API Server(192.168.33.10:8080)就会得到消息并把这些数据存放到etcd里。Controller Manager就会去创建rc,Scheduler则会找个客户端,把启动pod的描述放到客户端上的某个文件夹里。客户端上的Kubelet会监视这个文件夹,一旦发现有了新的pod描述文件,便会将这个pod启动起来。多说一句,Kubelet除了监听文件夹或是某个Url,还有种方式是干脆直接启动一个Http Server让别人来调用。

高可用的情况下,由于用户的命令直接操作的是API Server,所以当API Server挂掉的时候,需要能自动重启。我们可以使用k8s客户端上现成的Kubelet来满足这个需求。Kubelet有一个Standalone模式,把启动API Server的描述文件丢到Kubelet的监视文件夹里就好了。当Kubelet发现API Server挂掉了,就会自动再启动一个API Server,反正新旧API Server连接的存储etcd还是原来那一个。API Server高可用了,要是Kubelet挂了呢?这个…还得监视一下Kubelet…可以用monit之类的东东,这边就不细说了。当然etcd也需要高可用,但是作为分布式存储来说,它的高可用相对而言较为简单并且跟k8s关联不大,这里也不提了。

刚刚提到的都是进程或容器挂掉的高可用。但是万一整个机器都完蛋了,咋办呢?最直接的做法就是整它好几个服务端,一个挂了还有其他的嘛。好几个服务端就有好几个API Server,其中一个为主,其他为从,简单地挂在一个负载均衡如HAProxy上就可以了。如果还嫌HAProxy上可能有单点故障,那就再做负载均衡集群好了,本文不再赘述。API Server可以跑多份,但是Controller Manager和Scheduler现在不建议跑多份。怎么做到呢?官方提供了一个叫做podmaster的镜像,用它启动的容器可以连接到etcd上。当它从etcd上发现当前机器的API Server为主机的时候,便会把Controller Manager和Scheduler的描述文件丢到Kubelet的监视文件夹里,于是Kubelet就会把这俩启动起来。若当前机器的API Server为从机时,它会把Controller Manager和Scheduler的描述文件从Kubelet的监视文件夹里删掉,这样就可以保证整个集群中Controller Manager和Scheduler各只有一份。上面说的这些画到图里就是这样滴:

和mesos配合的话,k8s还有另一种高可用方式。这种方式会给Scheduler増加一个叫做–ha的参数,于是Scheduler就能多个同时工作。但是官方也说了,不建议同时起2个以上的Scheduler。这种高可用方式的其它配置还是跟上文所说的一样,照样得使用podmaster,只不过它这回只用管Controller Manager一个而已。

做了这么多,终于把k8s master搞定了。但是还没完,node们还在等着我们呢!如果没用mesos,那就需要把node们的Kubelet重启一下,让它们连接到API Server的负载均衡上去。要是用了mesos就会简单一点儿,因为node们的Kubelet就是由Scheduler帮忙起起来的。记得吗?服务器端我们已经搞定了~