Kubernetes高可用集群部署方案

写在前面

这篇文章将介绍如何搭建一个高可用的kubernetes集群,主要参考的文档是:http://kubernetes.io/docs/admin/high-availability/。高可用性是一种需求,有多种选择可以实现这个需求,这里我们采用了最简单的方式搭建了这个集群,即在单个master节点的集群的基础上,部署一个高可用的Etcd集群、创建多个master Pod,并建立了一个对应的Service以实现多个master的负载均衡,最后将所有的Work Node全部注册到Service暴露的端口上。下面是集群的架构部署图:

:这种高可用部署方案不可行,存在单点问题,查看另一篇文章的解决方案: Kubernetes HA集群搭建详细指南

高可用的部署过程

按照架构图的部署方式,需要做以下几步:

  • 1、部署一个单master节点的Cluster 1#,单个master的集群部署方式比较简单,详情参考:https://get.k8s.io
  • 2、其次我们应该部署一个高可用的Etcd集群Cluster 2#,详情参考:高可用Etcd集群搭建过程
  • 3、在Cluster 1#中新建几个Pod,这个Pod里面运行着master所需要的全部组件
  • 4、设置一个Service,以NodePort的方式暴露Pod里面的master的服务
  • 5、加入新的Node节点注册到Service上,成为我们的工作集群Cluster 3#。

这个过程中比较麻烦的可能是Etcd集群了,搭建过程并不复杂,主要是如何以Pod的形式搭建成一个集群,还没有解决。现在的解决方法是在三台机器上以Docker的形式运行这些etcd服务,但这样的做法,如果遇到要进行Etcd集群扩展,就需要重启Pod里面的master镜像。

创建Pod形式的master镜像

有一点需要注意的是,如果master节点挂了之后,运行着的实例或者服务不受影响的。所以即使Cluster 1#挂了之后,我们的Cluster 3#还可以正常工作的,我们只要保持Cluster 3#的高可用性就可以了。引用Cluster 1#的目的是,我们想借用Kubernetes提供的负载均衡服务。

我们在Cluster 1#里面运行多个master的Pod镜像,通过kube-master-rc.yaml来创建三个Pod实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
apiVersion: v1
kind: ReplicationController
metadata:
name: kube-master-replication-controller
spec:
replicas: 3
selector:
name: kube-master-replication-controller
template:
metadata:
labels:
name: kube-master-replication-controller
spec:
volumes:
- hostPath:
path: /srv/kubernetes
name: srvkube
- hostPath:
path: /var/log/
name: logfile
containers:
- name: kube-apiserver
image: registry.abc.com/liuchang31/kube-apiserver:v1.3.0-alpha.3
command:
- /bin/sh
- -c
- /usr/local/bin/kube-apiserver --logtostderr=true --v=4 --etcd-servers=http://inf-platform55:2379,http://inf-platform56:2379,http://inf-platform57:2379 --address=0.0.0.0 --allow_privileged=false --service-cluster-ip-range=10.200.0.0/16 --service-node-port-range=8000-40000 >> /var/log/kube-apiserver.log
ports:
- containerPort: 7080
hostPort: 7080
name: http
- containerPort: 8080
hostPort: 8080
name: local
volumeMounts:
- mountPath: /srv/kubernetes
name: srvkube
readOnly: true
- mountPath: /var/log/
name: logfile
- name: kube-scheduler
image: registry.abc.com/liuchang31/kube-scheduler:v1.3.0-alpha.3
command:
- /bin/sh
- -c
- /usr/local/bin/kube-scheduler --master=http://localhost:8080 --v=0 --logtostderr=true --leader-elect=true >> /var/log/kube-scheduler.log
livenessProbe:
httpGet:
path: /healthz
port: 10251
initialDelaySeconds: 15
timeoutSeconds: 1
volumeMounts:
- mountPath: /var/log/
name: logfile
- name: kube-controller-manager
image: registry.abc.com/liuchang31/kube-controller-manager:v1.3.0-alpha.3
command:
- /bin/sh
- -c
- - /usr/local/bin/kube-controller-manager --master=http://localhost:8080 --logtostderr=true --v=4 --node-monitor-grace-period=10s --pod-eviction-timeout=10s --leader-elect=true >> /var/log/kube-conttroller-manager.log
livenessProbe:
httpGet:
path: /healthz
port: 10252
initialDelaySeconds: 15
timeoutSeconds: 1
volumeMounts:
- mountPath: /var/log/
name: logfile

注意在kube-apiserver的etcd_servers选项中,我们需要填上Cluster 2#的地址。还需要注意的是,要在kube-controller-manager和kube-scheduler的选项添加—leader-elect=true的选项,这为了保证同一时刻只能有一个master进行管理和调度。

创建Service以实现负载均衡

这一步很简单,可以通过定义kube-master-service.yaml来创建一个Service实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: v1
kind: Service
metadata:
name: kube-master-server
labels:
name: kube-master-server
spec:
selector:
name: kube-master-replication-controller
type: NodePort
ports:
- name: api
port: 8080
targetPort: 8080
nodePort: 8188

这里需要注意的是,因为我们这个Service要当作负载均衡器,成为Cluster 3# api_server的接入点,所以它应该要暴露出来,以NodePort或者LoadBalance的方式,这里我们选择的是NodePort的形式,nodePort为8188。

Cluster 3#的组建

为什么上述Pod里的3份master实例就可以实现高可用了呢?会不会有冲突?数据会不一致吗?需要理解这一点,最关键的Etcd集群的特性,它保持了全局的key/value存储的一致性,也就是说3个master都是通过Etcd集群或者当前集群(也就是Cluster 3#)的情况,无论负载均衡器将请求送到了哪个master,最后都是要通过获取Etcd集群里面的数据进行操作的,而Etcd集群在那篇文章中已经验证了,它能保证分布式存储的一致性。

Cluster 3#集群是我们的工作集群,我们可以把一定数目的Work Node机器加入到这个集群上,做法比较简单。首先部署Node上的运行环境,比如说kube-proxy、docker等,然后我们通过启动kubelet向我们的master注册信息,在命令行输入:

1
kubelet --logtostderr=true --cadvisor-port=8194 --cluster_dns=10.254.88.188 --cluster_domain=Xcloud.local --v=4 --api_servers=http://inf-platform53:8188 --address=0.0.0.0 --allow_privileged=false --docker-root=/home/work/docker/runtime/

注意这个cluster-dns我们采用的是Cluster 1#的DNS,它用作域名发现。其次我们把—api_servers设为我们的Service对外提供的地址,即NodeIP+nodePort的形式。至此我们的高可用集群的部署就算是完成了,操作过程中可能会遇到各种各样的问题,不过都可以通过查看log一点点解决,大方向是这么走的。

我们通过在Cluster 1#集群上通过

1
kubectl describe pods kube-master

查看我们的master的落在哪几台机器上,这几台机器都是Cluster 3#的master节点,可以在这几台机器通过输入

kubectl get nodes

来查看集群Cluster 3#的情况。