一、 前言

之前我们搭建的集群,只有一个master节点,当master节点宕机的时候,通过node将无法继续访问,而master主要是管理作用,所以整个集群将无法提供服务
Kubernetes搭建高可用集群 - 图1

二、 高可用集群

下面我们就需要搭建一个多master节点的高可用集群,不会存在单点故障问题
但是在node 和 master节点之间,需要存在一个 LoadBalancer组件,作用如下:

  • 负载
  • 检查master节点的状态

Kubernetes搭建高可用集群 - 图2
对外有一个统一的VIP:虚拟ip来对外进行访问

三、 高可用集群技术细节

高可用集群技术细节如下所示:
Kubernetes搭建高可用集群 - 图3

  • keepalived:配置虚拟ip,检查节点的状态
  • haproxy:负载均衡服务【类似于nginx】
  • apiserver:
  • controller:
  • manager:
  • scheduler:

    四、 高可用集群步骤

    我们采用2个master节点,一个node节点来搭建高可用集群,下面给出了每个节点需要做的事情
master1 10.4.104.169 1.部署Keepalived
2.部署harproxy
3.初始化操作
4.安装docker,网络插件
master2 10.4.104.170 1.部署Keepalived
2.部署harproxy
3.添加master2节点到集群
4.安装docker,网络插件
node1 10.4.104.171 1.加入到集群中
2.安装docker,网络插件
VIP

没有多的集群,看个热闹!

4.1 初始化操作

我们需要在这三个节点上进行操作

  1. # 关闭防火墙
  2. systemctl stop firewalld
  3. systemctl disable firewalld
  4. # 关闭selinux
  5. # 永久关闭
  6. sed -i 's/enforcing/disabled/' /etc/selinux/config
  7. # 临时关闭
  8. setenforce 0
  9. # 关闭swap
  10. # 临时
  11. swapoff -a
  12. # 永久关闭
  13. sed -ri 's/.*swap.*/#&/' /etc/fstab
  14. # 根据规划设置主机名【master1节点上操作】
  15. hostnamectl set-hostname master1
  16. # 根据规划设置主机名【master2节点上操作】
  17. hostnamectl set-hostname master1
  18. # 根据规划设置主机名【node1节点操作】
  19. hostnamectl set-hostname node1
  20. # r添加hosts
  21. cat >> /etc/hosts << EOF
  22. 192.168.44.158 k8smaster
  23. 192.168.44.155 master01.k8s.io master1
  24. 192.168.44.156 master02.k8s.io master2
  25. 192.168.44.157 node01.k8s.io node1
  26. EOF
  27. # 将桥接的IPv4流量传递到iptables的链【3个节点上都执行】
  28. cat > /etc/sysctl.d/k8s.conf << EOF
  29. net.bridge.bridge-nf-call-ip6tables = 1
  30. net.bridge.bridge-nf-call-iptables = 1
  31. EOF
  32. # 生效
  33. sysctl --system
  34. # 时间同步
  35. yum install ntpdate -y
  36. ntpdate time.windows.com

4.2 部署keepAlived

下面我们需要在所有的master节点【master1和master2】上部署keepAlive

4.2.1 安装相关包

  1. # 安装相关工具
  2. yum install -y conntrack-tools libseccomp libtool-ltdl
  3. # 安装keepalived
  4. yum install -y keepalived

4.2.2 配置master节点

添加master1的配置

  1. cat > /etc/keepalived/keepalived.conf <<EOF
  2. ! Configuration File for keepalived
  3. global_defs {
  4. router_id k8s
  5. }
  6. vrrp_script check_haproxy {
  7. script "killall -0 haproxy"
  8. interval 3
  9. weight -2
  10. fall 10
  11. rise 2
  12. }
  13. vrrp_instance VI_1 {
  14. state MASTER
  15. interface ens33
  16. virtual_router_id 51
  17. priority 250
  18. advert_int 1
  19. authentication {
  20. auth_type PASS
  21. auth_pass ceb1b3ec013d66163d6ab
  22. }
  23. virtual_ipaddress {
  24. 192.168.44.158
  25. }
  26. track_script {
  27. check_haproxy
  28. }
  29. }
  30. EOF

添加master2的配置

  1. cat > /etc/keepalived/keepalived.conf <<EOF
  2. ! Configuration File for keepalived
  3. global_defs {
  4. router_id k8s
  5. }
  6. vrrp_script check_haproxy {
  7. script "killall -0 haproxy"
  8. interval 3
  9. weight -2
  10. fall 10
  11. rise 2
  12. }
  13. vrrp_instance VI_1 {
  14. state BACKUP
  15. interface ens33
  16. virtual_router_id 51
  17. priority 200
  18. advert_int 1
  19. authentication {
  20. auth_type PASS
  21. auth_pass ceb1b3ec013d66163d6ab
  22. }
  23. virtual_ipaddress {
  24. 192.168.44.158
  25. }
  26. track_script {
  27. check_haproxy
  28. }
  29. }
  30. EOF

4.2.3 启动和检查

在两台master节点都执行

  1. # 启动keepalived
  2. systemctl start keepalived.service
  3. # 设置开机启动
  4. systemctl enable keepalived.service
  5. # 查看启动状态
  6. systemctl status keepalived.service

启动后查看master的网卡信息

  1. ip a s ens33

Kubernetes搭建高可用集群 - 图4

4.3 部署haproxy

haproxy主要做负载的作用,将我们的请求分担到不同的node节点上

4.3.1 安装

在两个master节点安装 haproxy

  1. # 安装haproxy
  2. yum install -y haproxy
  3. # 启动 haproxy
  4. systemctl start haproxy
  5. # 开启自启
  6. systemctl enable haproxy

启动后,我们查看对应的端口是否包含 16443

  1. netstat -tunlp | grep haproxyCopy to clipboardErrorCopied

Kubernetes搭建高可用集群 - 图5

4.3.2 配置

两台master节点的配置均相同,配置中声明了后端代理的两个master节点服务器,指定了haproxy运行的端口为16443等,因此16443端口为集群的入口

  1. cat > /etc/haproxy/haproxy.cfg << EOF
  2. #---------------------------------------------------------------------
  3. # Global settings
  4. #---------------------------------------------------------------------
  5. global
  6. # to have these messages end up in /var/log/haproxy.log you will
  7. # need to:
  8. # 1) configure syslog to accept network log events. This is done
  9. # by adding the '-r' option to the SYSLOGD_OPTIONS in
  10. # /etc/sysconfig/syslog
  11. # 2) configure local2 events to go to the /var/log/haproxy.log
  12. # file. A line like the following can be added to
  13. # /etc/sysconfig/syslog
  14. #
  15. # local2.* /var/log/haproxy.log
  16. #
  17. log 127.0.0.1 local2
  18. chroot /var/lib/haproxy
  19. pidfile /var/run/haproxy.pid
  20. maxconn 4000
  21. user haproxy
  22. group haproxy
  23. daemon
  24. # turn on stats unix socket
  25. stats socket /var/lib/haproxy/stats
  26. #---------------------------------------------------------------------
  27. # common defaults that all the 'listen' and 'backend' sections will
  28. # use if not designated in their block
  29. #---------------------------------------------------------------------
  30. defaults
  31. mode http
  32. log global
  33. option httplog
  34. option dontlognull
  35. option http-server-close
  36. option forwardfor except 127.0.0.0/8
  37. option redispatch
  38. retries 3
  39. timeout http-request 10s
  40. timeout queue 1m
  41. timeout connect 10s
  42. timeout client 1m
  43. timeout server 1m
  44. timeout http-keep-alive 10s
  45. timeout check 10s
  46. maxconn 3000
  47. #---------------------------------------------------------------------
  48. # kubernetes apiserver frontend which proxys to the backends
  49. #---------------------------------------------------------------------
  50. frontend kubernetes-apiserver
  51. mode tcp
  52. bind *:16443
  53. option tcplog
  54. default_backend kubernetes-apiserver
  55. #---------------------------------------------------------------------
  56. # round robin balancing between the various backends
  57. #---------------------------------------------------------------------
  58. backend kubernetes-apiserver
  59. mode tcp
  60. balance roundrobin
  61. server master01.k8s.io 192.168.44.155:6443 check
  62. server master02.k8s.io 192.168.44.156:6443 check
  63. #---------------------------------------------------------------------
  64. # collection haproxy statistics message
  65. #---------------------------------------------------------------------
  66. listen stats
  67. bind *:1080
  68. stats auth admin:awesomePassword
  69. stats refresh 5s
  70. stats realm HAProxy\ Statistics
  71. stats uri /admin?stats
  72. EOF

4.4 安装Docker、Kubeadm、kubectl

所有节点安装Docker/kubeadm/kubelet ,Kubernetes默认CRI(容器运行时)为Docker,因此先安装Docker

4.4.1 安装Docker

首先配置一下Docker的阿里yum源

  1. cat >/etc/yum.repos.d/docker.repo<<EOF
  2. [docker-ce-edge]
  3. name=Docker CE Edge - \$basearch
  4. baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/\$basearch/edge
  5. enabled=1
  6. gpgcheck=1
  7. gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg
  8. EOF

然后yum方式安装docker

  1. # yum安装
  2. yum -y install docker-ce
  3. # 查看docker版本
  4. docker --version
  5. # 启动docker
  6. systemctl enable docker
  7. systemctl start docker

配置docker的镜像源

  1. cat >> /etc/docker/daemon.json << EOF
  2. {
  3. "registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"]
  4. }
  5. EOF

然后重启docker

  1. systemctl restart docker

4.4.2 添加kubernetes软件源

然后我们还需要配置一下yum的k8s软件源

  1. cat > /etc/yum.repos.d/kubernetes.repo << EOF
  2. [kubernetes]
  3. name=Kubernetes
  4. baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
  5. enabled=1
  6. gpgcheck=0
  7. repo_gpgcheck=0
  8. gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
  9. EOF

4.4.3 安装kubeadm,kubelet和kubectl

由于版本更新频繁,这里指定版本号部署:

  1. # 安装kubelet、kubeadm、kubectl,同时指定版本
  2. yum install -y kubelet-1.18.0 kubeadm-1.18.0 kubectl-1.18.0
  3. # 设置开机启动
  4. systemctl enable kubelet

4.5 部署Kubernetes Master【master节点】

4.5.1 创建kubeadm配置文件

在具有vip的master上进行初始化操作,这里为master1

  1. # 创建文件夹
  2. mkdir /usr/local/kubernetes/manifests -p
  3. # 到manifests目录
  4. cd /usr/local/kubernetes/manifests/
  5. # 新建yaml文件
  6. vi kubeadm-config.yaml

yaml内容如下所示:

  1. apiServer:
  2. certSANs:
  3. - master1
  4. - master2
  5. - master.k8s.io
  6. - 192.168.44.158
  7. - 192.168.44.155
  8. - 192.168.44.156
  9. - 127.0.0.1
  10. extraArgs:
  11. authorization-mode: Node,RBAC
  12. timeoutForControlPlane: 4m0s
  13. apiVersion: kubeadm.k8s.io/v1beta1
  14. certificatesDir: /etc/kubernetes/pki
  15. clusterName: kubernetes
  16. controlPlaneEndpoint: "master.k8s.io:16443"
  17. controllerManager: {}
  18. dns:
  19. type: CoreDNS
  20. etcd:
  21. local:
  22. dataDir: /var/lib/etcd
  23. imageRepository: registry.aliyuncs.com/google_containers
  24. kind: ClusterConfiguration
  25. kubernetesVersion: v1.16.3
  26. networking:
  27. dnsDomain: cluster.local
  28. podSubnet: 10.244.0.0/16
  29. serviceSubnet: 10.1.0.0/16
  30. scheduler: {}

然后我们在 master1 节点执行

  1. kubeadm init --config kubeadm-config.yaml

执行完成后,就会在拉取我们的进行了【需要等待…】
Kubernetes搭建高可用集群 - 图6
按照提示配置环境变量,使用kubectl工具

  1. # 执行下方命令
  2. mkdir -p $HOME/.kube
  3. sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  4. sudo chown $(id -u):$(id -g) $HOME/.kube/config
  5. # 查看节点
  6. kubectl get nodes
  7. # 查看pod
  8. kubectl get pods -n kube-system

按照提示保存以下内容,一会要使用:

  1. kubeadm join master.k8s.io:16443 --token jv5z7n.3y1zi95p952y9p65 \
  2. --discovery-token-ca-cert-hash sha256:403bca185c2f3a4791685013499e7ce58f9848e2213e27194b75a2e3293d8812 \
  3. --control-plane

—control-plane : 只有在添加master节点的时候才有

查看集群状态

  1. # 查看集群状态
  2. kubectl get cs
  3. # 查看pod
  4. kubectl get pods -n kube-system

4.6 安装集群网络

从官方地址获取到flannel的yaml,在master1上执行

  1. # 创建文件夹
  2. mkdir flannel
  3. cd flannel
  4. # 下载yaml文件
  5. wget -c https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

安装flannel网络

  1. kubectl apply -f kube-flannel.yml

检查

  1. kubectl get pods -n kube-system

4.7 master2节点加入集群

4.7.1 复制密钥及相关文件

从master1复制密钥及相关文件到master2

  1. # ssh root@192.168.44.156 mkdir -p /etc/kubernetes/pki/etcd
  2. # scp /etc/kubernetes/admin.conf root@192.168.44.156:/etc/kubernetes
  3. # scp /etc/kubernetes/pki/{ca.*,sa.*,front-proxy-ca.*} root@192.168.44.156:/etc/kubernetes/pki
  4. # scp /etc/kubernetes/pki/etcd/ca.* root@192.168.44.156:/etc/kubernetes/pki/etcd

4.7.2 master2加入集群

执行在master1上init后输出的join命令,需要带上参数--control-plane表示把master控制节点加入集群

  1. kubeadm join master.k8s.io:16443 --token ckf7bs.30576l0okocepg8b --discovery-token-ca-cert-hash sha256:19afac8b11182f61073e254fb57b9f19ab4d798b70501036fc69ebef46094aba --control-plane

检查状态

  1. kubectl get node
  2. kubectl get pods --all-namespaces

4.8 加入Kubernetes Node

在node1上执行
向集群添加新节点,执行在kubeadm init输出的kubeadm join命令:

  1. kubeadm join master.k8s.io:16443 --token ckf7bs.30576l0okocepg8b --discovery-token-ca-cert-hash sha256:19afac8b11182f61073e254fb57b9f19ab4d798b70501036fc69ebef46094aba

集群网络重新安装,因为添加了新的node节点
检查状态

  1. kubectl get node
  2. kubectl get pods --all-namespaces

4.9 测试kubernetes集群

在Kubernetes集群中创建一个pod,验证是否正常运行:

  1. # 创建nginx deployment
  2. kubectl create deployment nginx --image=nginx
  3. # 暴露端口
  4. kubectl expose deployment nginx --port=80 --type=NodePort
  5. # 查看状态
  6. kubectl get pod,svc

然后我们通过任何一个节点,都能够访问我们的nginx页面