【云原生】搭建k8s高可用集群—更新于2023.04

多master(高可用)介绍

在这里插入图片描述

假设现在有3个node节点和3个master节点,node1到底是连到master1还是连到master2还是master3,需要有人来分配,这个中间人就是load balancer,load balancer起到两个作用,一是负载。二是检查master状态,如果master1异常,就会使node连到master2上,如果master1正常,则正常提供服务。由于节点之间互相访问是通过IP连接,这里也是一样的,只不过是通过VIP(虚拟ip)连接。

高可用集群使用技术介绍

keepalived:检查master状态,是否正常运行;配置虚拟IP。
haproxy:负载均衡服务器,起到负载作用。
master具体组件:apiserver, controller-manager, scheduler。
在这里插入图片描述

高可用集群架构图

在这里插入图片描述

搭建高可用k8s集群步骤

前提条件:
①固定四台主机IP,参考文章固定虚拟机IP
②可连外网

主机IP
master1192.168.2.200
master2192.168.2.201
master3192.168.2.204
node1192.168.2.202
虚拟IP192.168.2.203

我们以3台master,1台node为例,首先准备好4台服务器,分别在四台服务器上做操作。

1. 准备环境-系统初始化

# 关闭防火墙
systemctl disable firewalld  #永久关闭,移除开机自启项,以后开机不会启动
systemctl stop firewalld  #临时关闭,立刻关闭

# 关闭selinux
sed -i 's/enforcing/disabled/' /etc/selinux/config   # 修改selinux配置文件为关闭状态,以后开机不会启动
setenforce 0   #临时关闭,立刻关闭

# 关闭swap分区
sed -ri 's/.*swap.*/#&/' /etc/fstab  # 修改swap配置文件为关闭状态,以后开机不会启动
swapoff -a  #临时关闭,立刻关闭

# 根据规划设置主机名
hostnamectl set-hostname <hostname>
bash   # 刷新

# 在master中添加hosts,每一个master都要执行
cat >> /etc/hosts << EOF
192.168.2.203 k8s-vip
192.168.2.200 master1
192.168.2.201 master2
192.168.2.204 master3
192.168.2.202 node1
EOF

# 将桥接的 IPv4 流量传递到 iptables 的链
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF

cat >> /etc/sysctl.conf<<EOF
net.ipv4.ip_forward=1
net.bridge.bridge-nf-call-iptables=1
net.ipv4.neigh.default.gc_thresh1=4096
net.ipv4.neigh.default.gc_thresh2=6144
net.ipv4.neigh.default.gc_thresh3=8192
EOF

#加载
modprobe br_netfilter
sysctl -p

sysctl --system   # 生效
--------------------------------
# 时间同步
yum -y install ntpdate 
ntpdate time.windows.com

如果执行过程中出错,参考这篇文章,错误汇总

2. 所有master节点部署keepalived+haproxy

2.1 安装keepalived
# 安装相关依赖
yum install -y conntrack-tools libseccomp libtool-ltdl
# 安装keepalived
yum install -y keepalived
2.2 配置master节点
  1. master1节点配置:
cat > /etc/keepalived/keepalived.conf <<EOF 
! Configuration File for keepalived

global_defs {
   router_id k8s
}

vrrp_script check_haproxy {
    script "killall -0 haproxy"   # 检测haproxy是否存在
    interval 3
    weight -2
    fall 10
    rise 2
}

vrrp_instance VI_1 {
    state MASTER   # 主节点
    interface ens33     # ens33 为网卡名称,可以使用ifconfig查看自己的网卡名称
    virtual_router_id 51
    priority 250   # 权重,keepalived的master节点必须大于keepalived的backup节点
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass ceb1b3ec013d66163d6ab   # 密钥,master和backup密钥必须一致
    }
    virtual_ipaddress {
        192.168.2.203    # 虚拟ip
    }
    track_script {
        check_haproxy
    }

}
EOF
  1. master2、master3节点配置
cat > /etc/keepalived/keepalived.conf <<EOF 
! Configuration File for keepalived

global_defs {
   router_id k8s
}

vrrp_script check_haproxy {
    script "killall -0 haproxy"
    interval 3
    weight -2
    fall 10
    rise 2
}

vrrp_instance VI_1 {
    state BACKUP     # 从节点
    interface ens33    # ens33 为网卡名称
    virtual_router_id 51
    priority 200    # 必须小于MASTER权重
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass ceb1b3ec013d66163d6ab   # 密钥,于MASTER一致
    }
    virtual_ipaddress {
        192.168.2.203    # 虚拟ip
    }
    track_script {
        check_haproxy
    }

}
EOF
  1. 启动和检查
    三台master节点都执行
# 启动keepalived
systemctl start keepalived.service
# 设置开机启动
systemctl enable keepalived.service
# 查看启动状态
systemctl status keepalived.service

启动后查看master的网卡信息。由于虚拟IP配到了master1上,执行后,master1节点上会多出一个IP,即为虚拟IP;master2和master3上没有,挂上master1后才会出现。

ip a s ens33

在这里插入图片描述

2.3 部署haproxy
  1. 在3个master节点安装 haproxy
# 安装haproxy
yum install -y haproxy
  1. 配置
    3台master节点的配置均相同,配置中声明了后端代理的3个master节点服务器,指定了haproxy运行的端口为16443等,因此16443端口为集群的入口
cat > /etc/haproxy/haproxy.cfg << EOF
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
    # to have these messages end up in /var/log/haproxy.log you will
    # need to:
    # 1) configure syslog to accept network log events.  This is done
    #    by adding the '-r' option to the SYSLOGD_OPTIONS in
    #    /etc/sysconfig/syslog
    # 2) configure local2 events to go to the /var/log/haproxy.log
    #   file. A line like the following can be added to
    #   /etc/sysconfig/syslog
    #
    #    local2.*                       /var/log/haproxy.log
    #
    log         127.0.0.1 local2
    
    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon 
       
    # turn on stats unix socket
    stats socket /var/lib/haproxy/stats
#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------  
defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000
#---------------------------------------------------------------------
# kubernetes apiserver frontend which proxys to the backends
#--------------------------------------------------------------------- 
frontend kubernetes-apiserver
    mode                 tcp
    bind                 *:16443      #默认监听端口16443
    option               tcplog
    default_backend      kubernetes-apiserver    
#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend kubernetes-apiserver
    mode        tcp
    balance     roundrobin
    server      master01.k8s.io   192.168.2.200:6443 check    # 修改IP
    server      master02.k8s.io   192.168.2.201:6443 check    # 修改IP
    server      master03.k8s.io   192.168.2.204:6443 check    # 修改IP
#---------------------------------------------------------------------
# collection haproxy statistics message
#---------------------------------------------------------------------
listen stats
    bind                 *:1080
    stats auth           admin:awesomePassword
    stats refresh        5s
    stats realm          HAProxy\ Statistics
    stats uri            /admin?stats
EOF
  1. 启动和检查
    3台master都启动
# 启动 haproxy
systemctl start haproxy
# 设置开启自启
systemctl enable haproxy
# 查看启动状态
systemctl status haproxy

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

netstat -tunlp | grep haproxy

在这里插入图片描述
如果执行过程中出错,参考这篇文章,错误汇总

3. 所有节点安装Docker/kubeadm/kubelet

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

  • 安装之前确保没有其他dockers版本,如果有,需要删除干净后再安装,卸载方式可以参考这篇文章卸载docker
  1. 安装Docker,所有master+node都要安装
# 下载docker的yum源
wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo 
# 安装docker,找上一步的yum源去安装
yum -y install docker-ce-18.06.1.ce-3.el7 
# 开机自启动并且启动docker
systemctl enable docker && systemctl start docker 
# 查看docker状态
systemctl status docker
# 查看docker版本
docker --version
# 设置docker拉取镜像的加速器
cat > /etc/docker/daemon.json << EOF 
{
 "registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"] 
}
EOF

# 重启docker
systemctl daemon-reload
systemctl restart docker
  1. 添加阿里云yum源,所有节点(master+node)
cat >/etc/yum.repos.d/docker.repo<<EOF
[docker-ce-edge]
name=Docker CE Edge - \$basearch
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/\$basearch/edge
enabled=1
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg
EOF
# 重启docker
systemctl restart docker
  1. 添加kubernetes软件源
cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
  1. 安装kubeadm,kubectl,kubelet
    由于版本更新频繁,这里指定版本号部署:
# 安装kubelet、kubeadm、kubectl,同时指定版本
yum install -y kubelet-1.18.0 kubeadm-1.18.0 kubectl-1.18.0
# 启动并设置开机启动
systemctl start kubelet
systemctl enable kubelet

4. 部署Kubernetes Master

4.1 创建kubreadm配置文件

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

# 创建文件夹
mkdir /usr/local/kubernetes/manifests -p
# 到manifests目录
cd /usr/local/kubernetes/manifests/
# 新建yaml文件
vim kubeadm-config.yaml

下面内容修改IP 后复制进去

apiVersion: kubeadm.k8s.io/v1beta2    # 集群主版本,根据集群版本号决定
bootstrapTokens:
- groups:
  - system:bootstrappers:kubeadm:default-node-token
  token: abcdef.0123456789abcdef
  ttl: 24h0m0s
  usages:
  - signing
  - authentication
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: 192.168.2.200    #本机ip
  bindPort: 6443              #apiserver集群端口号
nodeRegistration:
  criSocket: /var/run/dockershim.sock
  name: k8s-master1           #本机hostname
  taints:
  - effect: NoSchedule
    key: node-role.kubernetes.io/master
---
apiServer:
  certSANs:
  - k8s-master1
  - k8s-master2
  - k8s-master3
  - 192.168.2.200  # master1 ip
  - 192.168.2.201  # master2 ip
  - 192.168.2.204  # master3 ip
  - 192.168.2.203     # 虚拟vip keepalive出来的ip
  - 127.0.0.1
  extraArgs:
    authorization-mode: Node,RBAC
  timeoutForControlPlane: 2m0s      # 注册时间2分钟
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes      # 集群名字
controlPlaneEndpoint: "192.168.2.203:16443"              # 虚拟ip + haproxy绑定的端口号
controllerManager: {}
dns:
  type: CoreDNS
etcd:
  local:
    dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: v1.18.0               # 集群版本,需要与kubeadm版本一致
networking:
  dnsDomain: cluster.local
  podSubnet: 10.244.0.0/16                 # pod 内网ip网段
  serviceSubnet: 10.96.0.0/12               # svc 内网ip网段
scheduler: {}

这里补充一个自动生成kubeadm-config.yaml文件的命令,生成模板后需要修改。kubeadm config print init-defaults > kubeadm-config.yaml.

4.2 在master1节点执行
kubeadm init --config kubeadm-config.yaml

执行完成后,就会在拉取镜像【需要等待…】

初始化节点
如果上面的yaml文件已经执行过一次,再次执行就会报错,这时,就需要将集群初始化后才能执行。
步骤:

# 1. 还原由 kubeadm init 或 kubeadm join 所做的更改
kubeadm reset -f
# 2. 删除相关文件
rm -rf /etc/kubernetes/*
rm -rf /var/lib/etcd/*

然后再次执行yaml文件即可。

按照执行出的结果提示配置环境变量,使用kubectl工具

# 执行下方命令
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

# 查看节点
kubectl get nodes
# 查看集群健康状态
kubectl get cs
# 查看pod
kubectl get pods -n kube-system

在这里插入图片描述
在这里插入图片描述
由于没有安装网络插件,所以会有pending状态,无妨,继续往下执行就好了。

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

kubeadm join k8s-vip:16443 --token ivcq40.a1bb605g6df4xhdw \
    --discovery-token-ca-cert-hash sha256:b65dcb57a2934439562ae138f552942600296edc04cdefb7da93031cf23c9a08 \
    --control-plane

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

5. 安装集群网络

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

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

安装flannel网络,执行完apply之后需要等待一会,pending状态才会变成running。

kubectl apply -f kube-flannel.yml 

检查,都已经running,且master已经ready。

kubectl get pods -n kube-system

在这里插入图片描述
在这里插入图片描述

6. master节点加入Kubernetes集群

6.1 复制密钥及相关文件

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

# master1中执行,修改IP,分别改为master2/3的IP执行2遍
ssh root@192.168.2.201 mkdir -p /etc/kubernetes/pki/etcd   # 修改IP;master2\master3的IP,用master1连接master2\master3;输入密码

# 复制相应的文件到master2/master3
scp /etc/kubernetes/admin.conf root@192.168.2.201:/etc/kubernetes
   
scp /etc/kubernetes/pki/{ca.*,sa.*,front-proxy-ca.*} root@192.168.2.201:/etc/kubernetes/pki
   
scp /etc/kubernetes/pki/etcd/ca.* root@192.168.2.201:/etc/kubernetes/pki/etcd
6.2 master2和master3加入到集群

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

# master2&master上依次执行
kubeadm join k8s-vip:16443 --token ivcq40.a1bb605g6df4xhdw \
    --discovery-token-ca-cert-hash sha256:b65dcb57a2934439562ae138f552942600296edc04cdefb7da93031cf23c9a08 \
    --control-plane

按照提示执行输出的3行命令
在这里插入图片描述

在master1上检查状态

kubectl get nodes

kubectl get pods --all-namespaces

在这里插入图片描述

7. node节点加入Kubernetes集群

向集群添加新节点,执行在kubeadm init输出的kubeadm join命令,不加参数–control-plane

# 在node1上执行
kubeadm join k8s-vip:16443 --token ivcq40.a1bb605g6df4xhdw \
    --discovery-token-ca-cert-hash sha256:b65dcb57a2934439562ae138f552942600296edc04cdefb7da93031cf23c9a08

提示:

#token是有时间期限的,如果过期了,执行如下命令获取后再执行。
kubectl create token --print-join-command

#补充一个生成certificate-key的命令
kubeadm init phase upload-certs --upload-certs

报错解决,没有错误继续往下
执行命令后,报错no such host,如下:
在这里插入图片描述
这时候,需要将node1节点里的hosts表里的内容保持与master节点一致,再次执行就可以了。
在这里插入图片描述
在这里插入图片描述


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

# 在master1节点上执行
 kubectl apply -f flannel/kube-flannel.yml

检查状态

kubectl get nodes
kubectl get pods --all-namespaces

8. 测试kubernetes集群

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

# 创建nginx deployment
kubectl create deployment nginx --image=nginx
# 暴露端口
kubectl expose deployment nginx --port=80 --target-port=80 --type=NodePort
# 查看状态
kubectl get pod,svc

在这里插入图片描述
然后通过任何一个master或node节点或者虚拟IP加上端口号,都能够访问nginx页面;如果想要通过域名访问服务,可以参考这篇文章。注意一定要在master节点上添加污点容忍,不然无法通过虚拟IP 对应域名进行访问。这里要用第二种方式部署ingress-controller。
在这里插入图片描述

9. 模拟

我们现在有3个master节点,1个node节点,经过上述测试,发现集群可以正常访问nginx服务,因为三台master在正常运行,我们现在模拟挂掉一台master,让另外2台master正常运行,看一下会有什么效果:

  1. 首先,先查看集群是否正常,执行kubectl get nodes命令,发现各个节点都处于ready状态
    在这里插入图片描述
  2. 我们现在把master3这台服务器关掉,再看集群状态,关掉一会之后,发现master3节点状态变成了NotReady。
    在这里插入图片描述
    我们再使用其他节点的IP加上端口号访问nginx试一下,发现可以正常访问;如果使用master3节点的IP加端口号就无法访问nginx,是因为master3服务器已经关闭。
    在这里插入图片描述
  3. 到现在为止,我们有2台正在运行的master,现在我们再关闭一台master,把master2也关掉,只留一台master,试一下会怎么样?
    关闭前的状态:
    在这里插入图片描述
    关闭后再次执行kubectl get nodes命令,发现报错了,显示无法连接到服务器。
    在这里插入图片描述
    虽然这时候在访问nginx还是可以正常访问,但是此时的集群已经坏掉了。
    所以,如果有3个master节点,必须要保证2个正常运行;如果有5个master,必须保证3个正常运行。假设有N个master节点,必须保证有(N+1)/2个节点正常运行,才能保证集群正常。
  • 6
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是小bā吖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值