Kubernetes多主Master方式部署

背景

Kubernetes初学,在集群上测试部署了一套Kuberntes的单Master版本,并在其中部署了我们的一整套微服务,测试环境平稳运行了几个月,期间有些Worker节点也偶尔挂了几次,都没有影响到服务的正常运行,都能快速进行故障迁移,算是尝到了一点甜头。但是在今年年初Master节点由于内存不足出现了故障,却使整个微服务无法正常运作,造成的影响巨大。
这和之前了解到的情况,即:“master故障的时候,其余节点的容器均维持原有状况继续运行,只是动态调度能力失效” 这一描述有很大出入。

原因分析

我们的应用平台内部架构采用SpringCloud的微服务形式,同时在迁移进Kubernetes集群时,去除了Eureka转而依赖Kubernetes的内部DNS机制作为服务发现。我们使用的是CoreDNS。
即:

// 为所有内部服务创建同名Service, 并且统一通过80端口转发即可实现如下效果
// 这里的url相当于内部域名,解析至ClusterIP Service
@FeignClient(name="sss-service", url="sss-service")

这次故障让我仔细分析了手头所用的Kubernetes结构,发现核心存储组件ETCD是以static pod的方式运行在Master上的,同时api-server和CoreDNS同时使用的是这个ETCD static pod,因此在Master挂了之后,由于ETCD的缺失,api-server和CoreDNS同时无法工作。而api-server的缺失仅仅会造成Kubernetes的动态特性丢失,但是CoreDNS的故障直接导致内部域名解析故障,而微服务恰恰需要这些内部域名进行服务之间的调用,因此整个微服务集群不可用。

多Master集群的部署方式

基于原始单Master集群的区别在于:

  • ETCD由原static pod改为外部独立部署ETCD集群
  • Master的初始化变化
  • calico插件安装方式变化

1. ETCD外置

参考 Operating etcd clusters for Kubernetes

主要要点在于按照要求生成证书,并将证书文件拷贝到ETCD集群的每一台机器上,依次安装和启动即可。
其次,CoreDNS用的是V2的ETCDCTL, V3和V2互相不兼容,具体采用哪个版本,是由ETCDCTL_API 环境变量决定。

2. Master集群初始化

参考 Creating Highly Available Clusters with kubeadm

主要要点在于配置用于初始化master的 kubeadm-config.yaml 文件。其中 etcd配置项采用external形式,同时注意配置etcd集群的证书。注意:集群里的所有节点都应该拷贝ETCD集群证书的副本,否则无法正常工作 如:

etcd:
  external:
    endpoints:
    - https://xxx.xxx.xxx:2379
    - https://xxx.xxx.xxx:2379
    - https://xxx.xxx.xxx:2379
    caFile: /etc/etcd/tsl/ca.pem
    certFile: /etc/etcd/tsl/client.pem
    keyFile: /etc/etcd/tsl/client-key.pem

其次,一定要准备一个负载均衡器(可以是keepAlived和HAProxy方案,也可以是一个别的高可用四层负载),并且将该负载指向计划的所有master节点。比如kubelb:8443 -> masterip:6443。这样在kubeadm生成授权token的时候,将负载的主机名添加入授权域即可,否则节点在kubeadm join时候只能指定第一台master,前边一通折腾就白费了。kubeadm-config.yaml授权相关部分如下:

# 前边的是计划的masterip,kubelb是负载主机名,授权域是kubelb:8443
# 代表所有节点的添加方式是: kubeadm join kubelb:8443 --xxxxxxx
apiServer:
  certSANs:
  - "xx.xx.xx.xx1"
  - "xx.xx.xx.xx2"
  - "xx.xx.xx.xx3"
  - "kubelb"
controlPlaneEndpoint: "kubelb:8443"

在这里,kubelb到负载均衡器的ip解析写入hosts文件即可

初始化Master时候,仅第一个节点使用:
kubeadm init --config=kube-master.conf
其余Master是通过kubeadm join添加的,并附带一个额外参数(experimental-control-plane):
kubeadm join kubelb:8443 --token 57xfqb.izsliyj01vhiatgb --discovery-token-ca-cert-hash sha256:05d026519f72eb9fcfe8a187a6c583e4b1e695b357a391dccec580e429974382 --experimental-control-plane

3.配置calico

与默认配置不同的是,这里的calico也连接上外置ETCD集群
etcd_endpoint, etcd_ca, etcd_cert, etcd_key 都要相应配置上。可以在原来static pod方式声明的calico.yaml文件的基础上修改。

4. 节点添加

如上文内容所提到的,所有机器都要拷贝etcd证书,配置kubelb负载hosts文件,然后按照kubeadm join方式添加即可。

最终效果

Kubernetes多主Master方式部署