前面我们已经介绍过Kubernetes的高可用实际上就是ApiServer和ETCD的高可用。ETCD会以Static Pod的方式运行Kubernetes Master上。ApiServer我们总结过有三种方案:
- 使用外部负载均衡器
- 网络层做负载均衡
- Node节点上使用反向代理
而本文就是向大家介绍使用外部负载均衡器来搭建Kubernetes的高可用集群。
负载均衡器的选择
负载均衡这个话题,我相信大家一定不会陌生。而负载均衡的搭建方案我选择大家最耳熟能详的Haproxy+Keepalived。
Haproxy是一个提供高可用、负载均衡和基于HTTP/TCP应用代理的解决方案。
Keepalived是用C编写的路由软件,主要目标是为Linux系统及基于Linux的设施提供强大的高可用性和负载均衡。
在本文中,Haproxy我们用来做ApiServer的HA+LB方案,Keepalived用来做HAProxy的HA方案。
机器资源
我这里一共使用了6台机器,3台master1台worker2台Haproxy,具体配置如下
系统 | 节点IP | 节点类型 | CPU | Memory | Hostname |
---|---|---|---|---|---|
centos7.1 | 192.168.3.10 | master | 2C | 4G | master1.k8s.mifaw.com |
centos7.1 | 192.168.3.11 | master | 2C | 4G | master2.k8s.mifaw.com |
centos7.1 | 192.168.3.12 | master | 2C | 4G | master3.k8s.mifaw.com |
centos7.1 | 192.168.3.13 | node | 2C | 4G | worker.k8s.mifaw.com |
centos7.1 | 192.168.3.14 | Haproxy | 2C | 2G | ha1.k8s.mifaw.com |
centos7.1 | 192.168.3.15 | Haproxy | 2C | 2G | ha2.k8s.mifaw.com |
Kubernetes配置
重要:以下所有步骤,需要在所有的master和node节点上执行
因为在Kubernetes集群中,各节点的主机名必须唯一,所以需要给每台主机配置一个不重复的主机名。
1 2 3 4 5 |
# 查看主机名 $ hostname # 修改主机名 $ hostnamectl set-hostname <your_hostname> |
关闭防火墙,否则各种网络访问会让你头疼
1 2 3 |
# 关闭防火墙 $ systemctl stop firewalld && systemctl disable firewalld |
关闭selinux,除非你是非常专业的运维可以不关闭selinux,否则你可能会被它折腾得怀疑人生
1 2 3 |
# 关闭防火墙 $ setenforce 0 |
配置一下系统参数
1 2 3 4 5 6 7 8 9 |
# 制作配置文件 $ cat > /etc/sysctl.d/kubernetes.conf <<EOF vm.swappiness=0 vm.overcommit_memory=1 vm.panic_on_oom=0 EOF # 生效文件 $ sysctl -p /etc/sysctl.d/kubernetes.conf |
安装docker
1 2 3 4 5 |
# 安装docker $ yum install docker -y # 启动docker $ systemctl enable docker && systemctl start docker |
关闭swap,Kubernetes不希望swap来打扰它
1 2 3 4 5 6 7 |
# 删除swap区所有内容 $ swapoff -a # 删除 swap 挂载:注释掉swap那一行 vim /etc/fstab # 重启 $ reboot |
安装kubeadm工具,kubeadm是官方推荐创建 Kubernetes 集群的最佳实践“快速路径”,配合以下几个组件共同使用:
- kubeadm: 部署集群用的命令工具
- kubelet: 每台机器上都要运行的组件,负责管理pod、容器的生命周期等
- kubectl: 集群管理工具
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# 配置yum源,不能科学上网可以把”packages.cloud.google.com”替换为”mirrors.aliyun.com/kubernetes” $ cat <<EOF > /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=0 repo_gpgcheck=0 gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg EOF # 安装工具 # 找到要安装的版本号 $ yum list kubeadm --showduplicates | sort -r # 安装指定版本(这里用的是1.16.2) $ yum install -y kubeadm-1.16.2-0 kubelet-1.16.2-0 kubectl-1.16.2-0 --disableexcludes=kubernetes # 启动kubelet $ systemctl enable kubelet && systemctl start kubelet |
重要:以上所有步骤,需要在所有的master和node节点上执行
这样集群的基础配置就已搭建好,确保所有节点执行了以上步骤,就可以开始高可用的搭建了。
高可用及负载均衡
先在ha1上安装haproxy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# 安装Haproxy $ yum install -y haproxy # 配置负载均衡 $ vim /etc/haproxy/haproxy.cfg # 添加以下配置(haproxy其他配置若无需求可以删除) frontend apiserver bind *:6443 mode tcp default_backend apiserver-cluster backend apiserver-cluster mode tcp balance roundrobin server master1 192.168.3.10:6443 maxconn 2000 check server master2 192.168.3.11:6443 maxconn 2000 check server master3 192.168.3.12:6443 maxconn 2000 check # 启动haproxy $ systemctl enable haproxy && systemctl start haproxy |
然后在ha2上搭建haprxoy,步骤、配置和在ha1节点上一模一样
这样Kubernetes的负载均衡就配置好了(但此时还未生效,因为集群我们还没搭建),而且为了高可用,我们分别在两台机器上各搭建了haproxy,也算是高可用了
但大家想想,这真的是高可用吗,如果我们就这样配置,Kubernetes在连接ApiServer的时候指定其中一个haproxy,当这个haproxy挂掉了怎么办,那整个集群也瘫痪了。所以真正的高可用,还要保证haproxy不单点故障才行,接下来就是keepalived出场了。
在ha1上安装keepalived
这里还需要配置一个VIP(虚拟IP),本文使用:192.168.3.100
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 |
# 安装keepalived $ yum install keepalived -y # 配置keepalived $ vim /etc/keepalived/keepalived.conf # 添加以下配置 !Configuration File for keepalived global_defs { router_id keepalive-backup } vrrp_script check_apiserver { script "/etc/keepalived/check-apiserver.sh" interval 3 weight -2 } vrrp_instance VI-kube-master { state MASTER #主节点MASTER interface eth0 virtual_router_id 99 #每个节点必须相同 priority 100 #备节点必须比主节点低 advert_int 3 virtual_ipaddress { 192.168.3.100 } track_script { check_apiserver } } # 编写检测脚本 $ vim /etc/keepalived/check-apiserver.sh # 添加以下内容:检测ha1上的6443端口是否能正常访问,同时检测VIP是否生效,如果生效检测VIP上的6443端口能否正常访问 curl --silent --max-time 2 --insecure https://127.0.0.1:6443/ -o /dev/null || exit 1 if ip addr | grep -q 192.168.3.100; then curl --silent --max-time 2 --insecure https://192.168.3.100:6443/ -o /dev/null || exit 1 fi #启动 keepalived $ systemctl enable keepalived && systemctl start keepalived |
在ha2上安装keepalived
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 |
# 安装keepalived $ yum install keepalived -y # 配置keepalived $ vim /etc/keepalived/keepalived.conf # 添加以下配置 !Configuration File for keepalived global_defs { router_id keepalive-backup } vrrp_script check_apiserver { script "/etc/keepalived/check-apiserver.sh" interval 3 weight -2 } vrrp_instance VI-kube-master { state BACKUP #备节点BACKUP interface eth0 virtual_router_id 99 #每个节点必须相同 priority 98 #备节点必须比主节点低 advert_int 3 virtual_ipaddress { 192.168.3.100 } track_script { check_apiserver } } # 编写检测脚本 $ vim /etc/keepalived/check-apiserver.sh # 添加以下内容:检测ha1上的6443端口是否能正常访问,同时检测VIP是否生效,如果生效检测VIP上的6443端口能否正常访问 curl --silent --max-time 2 --insecure https://127.0.0.1:6443/ -o /dev/null || exit 1 if ip addr | grep -q 192.168.3.100; then curl --silent --max-time 2 --insecure https://192.168.3.100:6443/ -o /dev/null || exit 1 fi #启动 keepalived $ systemctl enable keepalived && systemctl start keepalived |
注意:如果是公有云环境,keepalived的操作应该都不需要了,因为公有云一般是不支持自定义VIP, 可以购买稳中有各公有云的负载均衡产品。
这样一套相对完备的高可用环境已经搭建好,接下来就需要配置Kubernetes集群了
配置Kubernetes集群
首先选择一台master,本文使用的master1主机
1 2 3 |
# 初始化集群 $ kubeadm init --control-plane-endpoint "192.168.3.100:6443" --upload-certs --kubernetes-version "1.16.2" --pod-network-cidr "172.17.0.0/16" |
- control-plane-endpoint:填写刚刚搭建好高可用负载均衡ip和端口
- upload-certs:在集群之间共享证书
- ubernetes-version:指定kubernetes的版本,要和安装kubeadm的版本保持一致
- pod-network-cidr:配置集群子网络,注意不要和集群现有网络有冲突
执行成功之后,配置一下运行环境,这是为了方便后续使用kubelet相关命令行
1 2 3 4 |
$ mkdir -p $HOME/.kube $ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config $ sudo chown $(id -u):$(id -g) $HOME/.kube/config |
第一个master节点配置成功,继续加入另外两个master节点
在kubeadm init执行成功之后,界面上会打印两条kubeadm join命令,第一条kubeadm join是用于其他master节点配置高可用,第二条则是用于worker节点加入集群
在master2节点执行
1 2 3 4 5 |
# 以master身份加入集群 $ kubeadm join 192.168.3.100:6443 --token 5c2ruw.t2cnb8w7n0lksq1j \ --discovery-token-ca-cert-hash sha256:bbef7b5d670437dddc8828e3924afacfe34a4b2a6d98166e951378cc20997fbf \ --control-plane --certificate-key 0d648fbeef9fd71a3ef37a4ebc75da90b6fbe928e69d6079f3cae13afd297a2a |
在master3节点执行
1 2 3 4 5 |
# 以master身份加入集群 $ kubeadm join 192.168.3.100:6443 --token 5c2ruw.t2cnb8w7n0lksq1j \ --discovery-token-ca-cert-hash sha256:bbef7b5d670437dddc8828e3924afacfe34a4b2a6d98166e951378cc20997fbf \ --control-plane --certificate-key 0d648fbeef9fd71a3ef37a4ebc75da90b6fbe928e69d6079f3cae13afd297a2a |
每个master加入的时候,会在每个master节点上启动一个etcd的pod,并将多台master上的etcd组成集群
master节点配置完之后,我们可以查看一下各节点信息
1 2 3 4 5 6 7 8 |
# 查看node状态 $ kubectl get nodes # 得到结果 NAME STATUS ROLES AGE VERSION master1.k8s.mifaw.com NotReady master 1m v1.16.2 master2.k8s.mifaw.com NotReady master 1m v1.16.2 master3.k8s.mifaw.com NotReady master 1m v1.16.2 |
可以发现每个节点的状态都是NotReady,这是因为还没有为集群配置cni网络,整个集群都处于无法通讯的状态
安装cni插件,本文选择calico,其他的因为懒,暂时未研究
首先从官网下载calico的配置文件
1 2 3 |
# 下载calico配置文件 $ wget https://docs.projectcalico.org/manifests/calico.yaml |
下载完成后修改CALICO_IPV4POOL_CIDR的value,和kubeadm init时pod-network-cidr指定的值,部署calico
1 2 3 |
# 部署calico $ kubectl apply -f calico.yaml |
等待一会儿,需要下载镜像、运行容器、配置网络,可以通过命令行看一下状态
1 2 |
$ kubectl get pods --all-namespaces |
当所有的STATUS都为Running,说明整个集群已经部署成功了
最后就可以加入worker节点了,还记得kubeadm init的第二条kubeadm join命令吗,没错,在worker节点上执行
1 2 3 4 |
# worker节点加入集群 $ kubeadm join 192.168.3.100:6443 --token 6r9xri.e45c63wqdg5ysmp5 \ --discovery-token-ca-cert-hash sha256:611ca908bc23df6fe58f361671b9bf52a9a73bf16b275ba3a90b81fe580298ec |
在master节点上查看节点状态
1 2 3 |
# worker节点加入集群 $ kubectl get nodes |
当worker节点的STATUS变为Ready,说明worker节点已经部署成功了,其他worker节点加入步骤一模一样
至此,使用外部负载均衡器搭建高可用的Kubernetes集群已经搭建完成了。其实整个过程还是比较简单的,这其中可能最大的难点是如果不能科学上网相关的镜像的下载,这个可以借助国内各大厂商的镜像仓库或者直接通过离线包导入。
当然,到这一步只是将集群基础框架搭建起来,要真正使用起来我们还需要安装一些其他的组件,比如dashboard、ingress等,后期我会继续向大家介绍如何搭建一个完整可用的Kubernetes集群。