Skip to content

10 Kubernetes-高可用部署

一、相关概念

1、ETCD 高可用

ETCD集群中,使用Raft算法,实现高可用

​ 每一个 Raft 集群中都包含多个服务器,在任意时刻,每一台服务器只可能处于 Leader、Follower 以及 Candidate 三种状态;在处于正常的状态时,集群中只会存在一个 Leader,其余的服务器都是 Follower

ETCD高可用集群:

​ 建议 3、5、7、9个高可用节点

​ 3个高可用节点只能有一次损坏

​ ETCD-CLUSTER:搭建高可用集群的方式

ETCD 框架:

基于http协议的 C/S 架构,实现数据的上传、下载
透过 Raft 算法,将数据写入:
                    WAL(预写入日志):
                                entry(版本确认)
                                snapshot(快照)
                    store(真实的底层存储)

image-20230109190806260

2、Schedule、ControllerManager 高可用

通过与ETCD的信息绑定,决定主节点

image-20230209203651728

3、Apiserver高可用

本质上为web服务,搭建多个apiserver,然后在外部搭建负载,实现高可用

4、高可用总结方案

image-20230209204057327

5、高可用的实现方式

1)自动化安装工具实现

image-20230209204116068

2)更改kubeadm源码实现

二、Sealos自动化工具实现高可用

  • 99年证书

  • 0依赖,不依赖ansible haproxy keepalived, 一个二进制工具

  • 离线安装,不同kubernetes版本下载对应不同版本的资源包即可,离线包包含所有二进制文件配置文件和镜像

  • 高可用通过ipvs实现的localLB,占用资源少,稳定可靠,类似kube-proxy的实现

  • 几乎可兼容所有支持systemd的x86_64架构的环境

  • 轻松实现集群节点的增加/删除

  • 上千用户在线上环境使用sealos,稳定可靠

  • 资源包放在阿里云oss上,再也不用担心网速

  • dashboard ingress prometheus等APP 同样离线打包,一键安装

sealos 架构图

基于本机的 ipvs 实现高可用

初始化集群时,通过域名指向各个节点的 ApiServer( 每个master 指向自己,node节点指向ipvs-vs )

在 pod 中运行程序,实现监听 ApiServer 的存活信息

image-20230210161327133

高可用搭建步骤:

1)虚拟机准备

Ⅰ 五个节点设置

搭建环境:3个master节点,2个node节点

                 CPU         MEM        磁盘
3个master        >=2个核心    >=4G       100G
2个worker        >=1个核心    >=2G       100G

注意:初始化集群时,只用一张网卡

Ⅱ 关闭多余的网卡,仅留一张网卡

[root@localhost ~]# vim /etc/sysconfig/network-scripts/ifcfg-ens34 
[root@localhost ~]# cat /etc/sysconfig/network-scripts/ifcfg-ens34 |grep ONBOOT
ONBOOT=no
[root@localhost ~]# systemctl restart network


# 并将剩余的网卡指向路由

Ⅲ、测试访问

[root@localhost ~]# ping www.baidu.com
PING www.a.shifen.com (14.215.177.38) 56(84) bytes of data.
64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=1 ttl=127 time=31.7 ms
64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=2 ttl=127 time=32.3 ms
64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=3 ttl=127 time=31.6 ms
^C
--- www.a.shifen.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 6126ms
rtt min/avg/max/mdev = 31.600/31.893/32.355/0.389 ms

2)系统初始化(所有节点)

1、设置系统主机名以及 Host 文件的相互解析

#主机名设置
#C7-1
[root@localhost ~]# hostnamectl set-hostname k8s-master01

#C7-2
[root@localhost ~]# hostnamectl set-hostname k8s-master02

#C7-3
[root@localhost ~]# hostnamectl set-hostname k8s-master03

#C7-4
[root@localhost ~]# hostnamectl set-hostname k8s-node01

#C7-5
[root@localhost ~]# hostnamectl set-hostname k8s-node02

#所有主机的hosts解析
[root@localhost ~]# vim /etc/hosts
[root@localhost ~]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

192.168.20.201  k8s-master01    m1
192.168.20.202  k8s-master02    m2
192.168.20.203  k8s-master03    m3
192.168.20.204  k8s-node01      n1      
192.168.20.205  k8s-node02      n2      

192.168.20.206  harbor.yq.com

2、安装依赖包

yum install -y conntrack ntpdate ntp ipvsadm ipset  iptables curl sysstat libseccomp wget  vim net-tools git

3、设置防火墙为 Iptables 并设置空规则

systemctl  stop firewalld  &&  systemctl  disable firewalld
yum -y install iptables-services  &&  systemctl  start iptables  &&  systemctl  enable iptables  &&  iptables -F  &&  service iptables save

4、关闭 SELINUX

关闭交换分区、环比SELINUX

swapoff -a && sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
setenforce 0 && sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config

5、调整内核参数,对于 K8S

net.bridge.bridge-nf-call-iptables=1 # 经过网桥的流量经过 iptables net.bridge.bridge-nf-call-ip6tables=1 net.ipv4.ip_forward=1 # 路由转发

cat > kubernetes.conf <<EOF
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
net.ipv4.ip_forward=1
net.ipv4.tcp_tw_recycle=0
vm.swappiness=0 # 禁止使用 swap 空间,只有当系统 OOM 时才允许使用它
vm.overcommit_memory=1 # 不检查物理内存是否够用
vm.panic_on_oom=0 # 开启 OOM  
fs.inotify.max_user_instances=8192
fs.inotify.max_user_watches=1048576
fs.file-max=52706963
fs.nr_open=52706963
net.ipv6.conf.all.disable_ipv6=1
net.netfilter.nf_conntrack_max=2310720
EOF
cp kubernetes.conf  /etc/sysctl.d/kubernetes.conf
sysctl -p /etc/sysctl.d/kubernetes.conf

6、调整系统时区,搭建时间同步服务器

1、所有节点设置时区
$ timedatectl set-timezone Asia/Shanghai

2、配置时间同步服务器
# master01设置chronyd服务端1
[root@localhost ~]# vim /etc/chrony.conf 
[root@localhost ~]# cat /etc/chrony.conf | egrep "^server|^allow|^local"
server ntp1.aliyun.com iburst
server ntp2.aliyun.com iburst
server ntp3.aliyun.com iburst
allow 192.168.20.0/24
local stratum 10
[root@localhost ~]# systemctl enable chronyd --now
[root@localhost ~]# systemctl restart chronyd

# master02设置chronyd服务端2
[root@localhost ~]# vim /etc/chrony.conf 
[root@localhost ~]# cat /etc/chrony.conf| egrep "^server|^allow|^local"
server ntp1.aliyum.com iburst
server ntp2.aliyum.com iburst
server ntp3.aliyum.com iburst
allow 192.168.20.0/24
local stratum 11
[root@localhost ~]# systemctl enable chronyd --now
[root@localhost ~]# systemctl restart chronyd


#master03配置chronyd客户端
[root@localhost ~]# vim /etc/chrony.conf 
[root@localhost ~]# cat /etc/chrony.conf | grep "^server"
server 192.168.20.201 iburst
server 192.168.20.202 iburst
[root@localhost ~]# systemctl enable chronyd --now
[root@localhost ~]# systemctl restart chronyd

#node1配置chronyd客户端
[root@localhost ~]# vim /etc/chrony.conf 
[root@localhost ~]# cat /etc/chrony.conf | grep "^server"
server 192.168.20.201 iburst
server 192.168.20.202 iburst
[root@localhost ~]# systemctl enable chronyd --now
[root@localhost ~]# systemctl restart chronyd


#node2配置chronyd客户端
[root@localhost ~]# vim /etc/chrony.conf 
[root@localhost ~]# cat /etc/chrony.conf | grep "^server"
server 192.168.20.201 iburst
server 192.168.20.202 iburst
[root@localhost ~]# systemctl enable chronyd --now
[root@localhost ~]# systemctl restart chronyd


3、设置定时任务,确保chronyd时刻同步
(由于虚拟机中没有 bios 硬件,让时间一直运行)
[root@localhost ~]# crontab -e
no crontab for root - using an empty one
crontab: installing new crontab
[root@localhost ~]# crontab -l
*/5 * * * * systemctl restart chronyd
[root@localhost ~]# systemctl enable crond --now
[root@localhost ~]# systemctl restart crond

7、关闭系统不需要服务

systemctl stop postfix && systemctl disable postfix

8、设置 rsyslogd 和 systemd journald

mkdir /var/log/journal # 持久化保存日志的目录
mkdir /etc/systemd/journald.conf.d

cat > /etc/systemd/journald.conf.d/99-prophet.conf <<EOF
[Journal]
# 持久化保存到磁盘
Storage=persistent

# 压缩历史日志
Compress=yes

SyncIntervalSec=5m
RateLimitInterval=30s
RateLimitBurst=1000

# 最大占用空间 10G
SystemMaxUse=10G

# 单日志文件最大 200M
SystemMaxFileSize=200M

# 日志保存时间 2 周
MaxRetentionSec=2week

# 不将日志转发到 syslog
ForwardToSyslog=no
EOF

systemctl restart systemd-journald

9、升级内核为4.4,设置默认启动启动

升级系统内核为 4.44

CentOS 7.x 系统自带的 3.10.x 内核存在一些 Bugs,导致运行的 Docker、Kubernetes 不稳定,例如: rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm

rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm
# 安装完成后检查 /boot/grub2/grub.cfg 中对应内核 menuentry 中是否包含 initrd16 配置,如果没有,再安装一次!
yum --enablerepo=elrepo-kernel install -y kernel-lt
# 设置开机从新内核启动
grub2-set-default 'CentOS Linux (4.4.189-1.el7.elrepo.x86_64) 7 (Core)'

也可以向每一个节点中上传 kernel-lt 的rpm包:

image-20230111005807708

#安装
$ yum -y install kernel-lt-4.4*
#设置4.4内核默认启动
[root@localhost ~]# cat /boot/grub2/grub.cfg |grep 4.4
[root@localhost ~]# grub2-set-default 'CentOS Linux (4.4.222-1.el7.elrepo.x86_64) 7 (Core)'

10、重启,关机做快照

reboot

3)sealos 安装

# 下载并安装 sealos, sealos 是个 golang 的二进制工具,直接下载拷贝到 bin 目录即可, release 页面也可下载
$ wget -c https://sealyun.oss-cn-beijing.aliyuncs.com/latest/sealos && \
    chmod +x sealos && mv sealos /usr/bin

# 下载离线资源包
$ wget -c https://sealyun.oss-cn-beijing.aliyuncs.com/2fb10b1396f8c6674355fcc14a8cda7c-v1.20.0/kube1.20.0.tar.gz

# 安装一个三 master 的 kubernetes 集群
$ sealos init --passwd '123456' \
> --master 192.168.20.201 --master 192.168.20.202 --master 192.168.20.203 \
> --node 192.168.20.204-192.168.20.205 \
> --pkg-url /root/kube1.16.0.tar.gz \
> --version v1.16.0

其他命令

增加 Master 节点
$ sealos join --master 192.168.0.6 --master 192.168.0.7

# 或者多个连续 IP
$ sealos join --master 192.168.0.6-192.168.0.9  
增加 node
$ sealos join --node 192.168.0.6 --node 192.168.0.7

# 或者多个连续 IP
$ sealos join --node 192.168.0.6-192.168.0.9  
删除指定 Master 节点
$ sealos clean --master 192.168.0.6 --master 192.168.0.7

# 或者多个连续 IP
$ sealos clean --master 192.168.0.6-192.168.0.9  
删除指定 node 节点
$ sealos clean --node 192.168.0.6 --node 192.168.0.7

# 或者多个连续 IP
$ sealos clean --node 192.168.0.6-192.168.0.9  
清理集群
$ sealos clean --all
备份集群
$ sealos etcd save

4)节点状态

kube-scheduler 状态查看
$ kubectl  get endpoints kube-scheduler -n kube-system -o yaml
    NAME             ENDPOINTS   AGE
    kube-scheduler   <none>      12m


[root@k8s-master01 ~]# kubectl  get endpoints kube-scheduler -n kube-system -o yaml
apiVersion: v1
kind: Endpoints
metadata:
  annotations:
    control-plane.alpha.kubernetes.io/leader: '{"holderIdentity":"k8s-master03_83054470-8074-4200-9523-6ba7d99a23b3","leaseDurationSeconds":15,"acquireTime":"2023-02-11T00:41:01Z","renewTime":"2023-02-11T00:41:51Z","leaderTransitions":1}'
  creationTimestamp: "2023-02-11T00:40:05Z"
  name: kube-scheduler
  namespace: kube-system
  resourceVersion: "871"
  selfLink: /api/v1/namespaces/kube-system/endpoints/kube-scheduler
  uid: d43ca787-7095-47db-bdfa-1e12fcc85e19
kube-controller-manager 状态查看
[root@k8s-master01 ~]# kubectl  get endpoints kube-controller-manager -n kube-system -o yaml
apiVersion: v1
kind: Endpoints
metadata:
  annotations:
    control-plane.alpha.kubernetes.io/leader: '{"holderIdentity":"k8s-master03_db536083-f166-4145-952b-fd966fa227dc","leaseDurationSeconds":15,"acquireTime":"2023-02-11T00:40:59Z","renewTime":"2023-02-11T00:42:00Z","leaderTransitions":1}'
  creationTimestamp: "2023-02-11T00:40:04Z"
  name: kube-controller-manager
  namespace: kube-system
  resourceVersion: "885"
  selfLink: /api/v1/namespaces/kube-system/endpoints/kube-controller-manager
  uid: 18c26b9e-54ea-4c90-8a05-b159451ea4ae
所有子版本的发型包

https://pan.baidu.com/s/1fu_l8yL_K6BLpSIugKhvAg?pwd=47f5

5)保存初始化配置文件

[root@k8s-master01 ~]# mkdir -p /usr/local/kubernetes/install
[root@k8s-master01 ~]# cp -a kubeadm-config.yaml /usr/local/kubernetes/install

三、测试高可用

通过查看节点状态,发现 Schedule 、Controller Manager 都在 master03 节点运行

1)将master03强制关机

2)测试运行

创建控制器、service

$ kubectl create deployment myapp --image=wangyanglinux/myapp:v1

$ kubectl scale deployment myapp --replicas=10

$ kubectl get pod -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP              NODE         NOMINATED NODE   READINESS GATES
myapp-5f6676bbd6-22xbq   1/1     Running   0          63s   100.97.125.4    k8s-node01   <none>           <none>
myapp-5f6676bbd6-2k7gs   1/1     Running   0          63s   100.125.152.2   k8s-node02   <none>           <none>
myapp-5f6676bbd6-5hqfm   1/1     Running   0          88s   100.125.152.1   k8s-node02   <none>           <none>
myapp-5f6676bbd6-j2tkd   1/1     Running   0          63s   100.125.152.3   k8s-node02   <none>           <none>
myapp-5f6676bbd6-jxrfj   1/1     Running   0          63s   100.125.152.5   k8s-node02   <none>           <none>
myapp-5f6676bbd6-l2pzt   1/1     Running   0          63s   100.125.152.4   k8s-node02   <none>           <none>
myapp-5f6676bbd6-pcfxv   1/1     Running   0          63s   100.97.125.1    k8s-node01   <none>           <none>
myapp-5f6676bbd6-r9dlw   1/1     Running   0          63s   100.97.125.5    k8s-node01   <none>           <none>
myapp-5f6676bbd6-w7lzk   1/1     Running   0          63s   100.97.125.3    k8s-node01   <none>           <none>
myapp-5f6676bbd6-xj5xd   1/1     Running   0          63s   100.97.125.2    k8s-node01   <none>           <none>


$ kubectl create svc  nodeport myapp --tcp=80:80

$ kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        24m
myapp        NodePort    10.96.247.207   <none>        80:32466/TCP   4s

访问master01,master02

image-20230211090537800

image-20230211090548880

3)修复

将master03开机,集群中会自动修复

[root@k8s-master01 ~]# kubectl get node
NAME           STATUS   ROLES    AGE     VERSION
k8s-master01   Ready    master   26m     v1.16.0
k8s-master02   Ready    master   26m     v1.16.0
k8s-master03   Ready    master   26m     v1.16.0
k8s-node01     Ready    <none>   9m42s   v1.16.0
k8s-node02     Ready    <none>   9m42s   v1.16.0