kubernetes学习三-kubeadm安装k8s高可用集群

1 集群逻辑架构

在这里插入图片描述

k8s集群高可用方案

k8s集群高可用负载均衡方案

这里主要基于k8s集群高可用负载均衡方案进行介绍,过程包含基于keepalived的高可用方案。

2 环境

2.1 物理环境

主机 IP 配置 OS 角色
node1 192.168.1.7 2core 2GB Centos7.9 master1
node2 192.168.1.8 2core 2GB Centos7.9 master2
node3 192.168.1.9 2core 2GB Centos7.9 master3
node4 192.168.1.10 2core 2GB Centos7.9 工作节点

2.2 软件环境

软件 版本
docker v20.10.12
kubeadmin v1.23.3
kubelet v1.23.3
kubectl v1.23.3
keeplalived 1.3.5
haproxy 2.5

2.3 镜像

镜像 版本
conformance v1.23.3
kube-apiserver v1.23.3
kube-controller-manager v1.23.3
kube-proxy v1.23.3
kube-scheduler v1.23.3
flannel v1.0.1

3 步骤

3.1 准备工作

3.1.1 确保各节点MAC和product_uuid的唯一性

  • 你可以使用命令 ip linkifconfig -a 来获取网络接口的 MAC 地址
  • 可以使用 sudo cat /sys/class/dmi/id/product_uuid 命令对 product_uuid 校验

一般来讲,硬件设备会拥有唯一的地址,但是有些虚拟机的地址可能会重复。

3.1.2 运行iptables检查桥接流量

确保 br_netfilter 模块被加载。这一操作可以通过运行 lsmod | grep br_netfilter 来完成。若要显式加载该模块,可执行 sudo modprobe br_netfilter

为了让你的 Linux 节点上的 iptables 能够正确地查看桥接流量,你需要确保在你的 sysctl 配置中将 net.bridge.bridge-nf-call-iptables 设置为 1。例如:

1
2
3
4
5
6
7
8
9
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF

cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sudo sysctl --system

3.1.3 关闭防火墙

1
2
systemctl stop firewalld 
systemctl disable firewalld

如果各个主机启用了防火墙,需要开放Kubernetes各个组件所需要的端口。如下图所示,详细信息请看官网

在这里插入图片描述

3.1.4 永久关闭swap

vim /etc/fstab

image-20220207202709095

image-20220207202741311

如果不修改,kubelet启动报错:

image-20220207202527741

3.1.5 关闭selinux

1
2
3
4
5
# 将 SELinux 设置为 permissive 或 disabled模式(相当于将其禁用)
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

sudo sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config

3.2 安装docker

卸载旧版本

1
2
3
4
5
6
7
8
9
10
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine

源安装

执行以下命令安装依赖包:

1
$ sudo yum install -y yum-utils

鉴于国内网络问题,强烈建议使用国内源,官方源请在注释中查看。

执行下面的命令添加 yum 软件源:

1
2
3
4
5
6
7
8
9
10
$ sudo yum-config-manager \
--add-repo \
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

$ sudo sed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' /etc/yum.repos.d/docker-ce.repo

# 官方源
# $ sudo yum-config-manager \
# --add-repo \
# https://download.docker.com/linux/centos/docker-ce.repo

安装docker-ce

1
$ sudo yum install docker-ce docker-ce-cli containerd.io

开机自启

1
2
3
启动 Docker
$ sudo systemctl enable docker
$ sudo systemctl start docker

3.3 安装 kubeadm、kubelet 和 kubectl

你需要在每台机器上安装以下的软件包:

  • kubeadm:用来初始化集群的指令。
  • kubelet:在集群中的每个节点上用来启动 Pod 和容器等。
  • kubectl:用来与集群通信的命令行工具。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-\$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
EOF

# 安装服务
sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes

# 设置kubelet开机自启
sudo systemctl enable kubelet

3.4 配置cgroup驱动程序

需保证容器服务和kubelet的cgroup驱动一致,否则kubelet启动报错:

image-20220208095347892

image-20220208095316580

由于 kubeadm 把 kubelet 视为一个系统服务来管理,所以对基于 kubeadm 的安装, 我们推荐使用 systemd 驱动,不推荐 cgroupfs 驱动。

3.4.1 Cgroup 驱动程序说明

image-20220208110411304

警告:

你需要确保容器(docker)和 kubelet 所使用的是相同的 cgroup 驱动,否则 kubelet 进程会失败。

相关细节可参见kubelet配置 cgroup 驱动容器配置cgroup驱动

3.4.2 查看kubelet和docker的驱动程序

  • kubelet
1
2
3
4
[root@node1 ~]#  cat /var/lib/kubelet/kubeadm-flags.env
KUBELET_KUBEADM_ARGS="--cgroup-driver=cgroup --hostname-override=node --network-plugin=cni --pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/k8s-images-kx/pause:3.6"

# --cgroup-driver=cgroup 该节点驱动程序为cgroup
  • docker
1
2
3
4
5
[root@node1 ~]# docker info |grep Cgroup
Cgroup Driver: cgroupfs
Cgroup Version: 1

# docker驱动程序为 cgroupfs

3.4.4 Docker配置cgroup驱动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
sudo mkdir /etc/docker
cat <<EOF | sudo tee /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
EOF

[root@node3 ~]# systemctl daemon-reload
[root@node3 ~]# systemctl restart docker
[root@node3 ~]# docker info | grep cgroup
Cgroup Driver: systemd
Cgroup Version: 1

3.4.5 kubelet配置cgroup驱动(可选)

kubelet不配置默认即使用systemd

1
2
3
4
5
6
7
# 将kubelet和docker 的驱动程序改成一致。
vim /var/lib/kubelet/kubeadm-flags.env
KUBELET_KUBEADM_ARGS="--cgroup-driver=systemd --network-plugin=cni --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.1"
# 将cgroup改成systemd

[root@node3 ~]# systemctl daemon-reload
[root@node3 ~]# systemctl restart kubelet

以上步骤和《kubernetes学习二:kubeadm安装kubernetes集群(单master)》完全一致,主要区别在集群负载均衡及集群初始化方式上。

3.5 keepalivedhaproxy

keepalived : 高可用软件,通过vrrp协议,vip地址的漂移,实现服务的高可用。

haproxy: haproxy是一个开源的,高性能的,负载均衡软件

image-20220209174127641

haproxy主要用来实现kube-apiserver的负载,实际操作中非必选。

官网说明

3.5.1 请求架构

image-20220210164628651

3.5.2 keepalived

1
yum install -y keepalived

主mastet

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
! Configuration File for keepalived

global_defs {
# 关于邮箱的配置全部注释
# notification_email {
# acassen@firewall.loc
# failover@firewall.loc
# sysadmin@firewall.loc
# }
# notification_email_from Alexandre.Cassen@firewall.loc
# smtp_server 192.168.200.1
# smtp_connect_timeout 30
# 节点起名/标识,不能一致,局域网内唯一。
router_id LVS_01
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}


vrrp_instance VI_1 {
state MASTER
# 绑定网卡
interface ens33
# 工作组,保持各节点一致,自定义
virtual_router_id 51
# 权重,抢占模式下高权限节点获得VIP
priority 100
advert_int 1
authentication {
# 认证通信认证方式和密码
auth_type PASS
auth_pass k8stest
}
# VIP
virtual_ipaddress {
192.168.1.233
}
}

备master

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
! Configuration File for keepalived

global_defs {
# 关于邮箱的配置全部注释
# notification_email {
# acassen@firewall.loc
# failover@firewall.loc
# sysadmin@firewall.loc
# }
# notification_email_from Alexandre.Cassen@firewall.loc
# smtp_server 192.168.200.1
# smtp_connect_timeout 30
# 节点起名/标识,不能一致,局域网内唯一。
router_id LVS_02
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}


vrrp_instance VI_1 {
state MASTER
# 绑定网卡
interface ens33
# 工作组,保持各节点一致,自定义
virtual_router_id 51
# 权重,抢占模式下高权限节点获得VIP
priority 90
advert_int 1
authentication {
# 认证通信认证方式和密码
auth_type PASS
auth_pass k8stest
}
# VIP
virtual_ipaddress {
192.168.1.233
}
}
1
2
3
# 重启
systemctl restart keeplived
systemctl enable keeplived

3.5.3 haproxy

官方源码下载地址

示例:https://www.haproxy.org/download/2.5/src/haproxy-2.5.1.tar.gz

想偷懒也可以直接 yum install haproxy -y 使用默认仓库的版本,相对版本较低。

安装依赖

1
yum install -y make gcc gcc-c++ pcre-devel zlib-devel openssl-devel

创建安装目录

1
mkdri /usr/local/haproxy/

编译安装

1
2
3
4
5
6
7
tar -zxvf haproxy-2.5.1.tar.gz
cd haproxy-2.5.1
# 编译
# 参考目录下INSTALL安装文档,相关参数说明
make TARGET=linux-glibc ARCH=x86_64 USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 PREFIX=/usr/local/haproxy
# 安装
make install PREFIX=/usr/local/haproxy

创建配置文件目录

1
2
mkdir -p /etc/haproxy/
mkdir -p /usr/local/haproxy/conf/

从配置文件名模板复制配置文件

1
2
cp examples/option-http_proxy.cfg /usr/local/haproxy/conf/haproxy.cfg
ln -s /usr/local/haproxy/conf/haproxy.cfg /etc/haproxy/haproxy.cfg

拷贝开机启动文件

1
2
cp haproxy-2.5.1/examples/haproxy.init /etc/init.d/haproxy
chmod +x /etc/init.d/haproxy

添加haproxy命令脚本软连接

1
ln -s /usr/local/haproxy/sbin/haproxy /usr/sbin

设置开机自启

1
2
chkconfig --add haproxy
chkconfig haproxy on

创建用户

1
2
3
groupadd haproxy
useradd -g haproxy haproxy
mkdir /usr/share/haproxy

修改配置/etc/haproxy/haproxy.cfg

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
71
72
73
74
75
76
77
78
79
#---------------------------------------------------------------------
# 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
option tcplog
default_backend kubernetes-apiserver

#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend kubernetes-apiserver
mode tcp
balance roundrobin
server node1 192.168.1.7:6443 check
server node2 192.168.1.8:6443 check
server node3 192.168.1.9:6443 check

#---------------------------------------------------------------------
# collection haproxy statistics message
#---------------------------------------------------------------------
listen stats
bind *:1080
stats auth admin:awesomePassword
stats refresh 5s
stats realm HAProxy\ Statistics
stats uri /admin?stats

各节点配置文件一致。

3.6 kubeadm创建集群

官网文档

3.5.1 kubeadm config

kubeadm已经进入GA阶段,其控制面初始化和加入节点步骤都支持大量的可定制内容,因此kubeadm还提供了配置文件功能用于复杂定制。同时,kubeadm将配置文件以ConfigMap的形式保存到集群之中,便于后续的查询和升级工作。kubeadm config子命令提供了对这一组功能的支持:

◎ kubeadm config upload from-file:由配置文件上传到集群中生成ConfigMap。

◎ kubeadm config upload from-flags:由配置参数生成ConfigMap。

◎ kubeadm config view:查看当前集群中的配置值。

◎ kubeadm config print init-defaults:输出kubeadm init默认参数文件的内容。

◎ kubeadm config print join-defaults:输出kubeadm join默认参数文件的内容。

◎ kubeadm config migrate:在新旧版本之间进行配置转换。

◎ kubeadm config images list:列出所需的镜像列表。

◎ kubeadm config images pull:拉取镜像到本地。例如,执行kubeadm config print init-defaults,可以取得默认的初始化参数文件:

1
kubeadm config print init-defaults > init.default.yaml

3.5.2 导出kubeadm集群默认配置文件

1
kubeadm config print init-defaults > init.default.yaml

3.5.3 修改默认配置文件

修改如下内容:

  1. 主节点IP——advertiseAddress
  2. 国内阿里镜像地址imageRepository——registry.cn-hangzhou.aliyuncs.com/k8s-images-kx(通过阿里镜像仓库拉取的国外镜像)
  3. pod网段配置——不同网络插件网段不一样详细见官网(配置网络插件subnet地址段)
  4. 高可用集群api请求地址——controlPlaneEndpoint(这里设置为keepalived的VIP地址+haproxy负载均衡监听端口)

![(https://operationman-1258630122.cos.ap-nanjing.myqcloud.com/images-master/2022/02/image-20220210153000232.png)

image-20220210165340733

纠正:

podSubent的值设置为flannel的默认网段,FLANNEL_NETWORK的默认值(可通过flannel.yaml文件查看);podSubent=10.244.0.0/16

原因:

后面配置NFS存储类的时候,pod无法正常访问kube-apiserver。

参考:

k8s 1.20.x版本NFS动态存储配置 - 巽逸 - 博客园 (cnblogs.com)

(71条消息) Kubeadm 部署 使用flannel无法连接service/kubernetes_weixin_40455124的博客-CSDN博客

image-20220215134508429

3.5.4 下载kubernetes相关镜像

使用config images list 子命令查询所需的镜像,例如

1
2
3
4
5
6
7
8
9
10
[root@node1 home]# kubeadm config images list --config=init.default.yaml
k8s.gcr.io/kube-apiserver:v1.23.0
k8s.gcr.io/kube-controller-manager:v1.23.0
k8s.gcr.io/kube-scheduler:v1.23.0
k8s.gcr.io/kube-proxy:v1.23.0
k8s.gcr.io/pause:3.6
k8s.gcr.io/etcd:3.5.1-0
k8s.gcr.io/coredns/coredns:v1.8.6

# 默认初始化配置文件下载的是1.23.0版本,如上图显示,可以修改初始化配置文件,改为1.23.3版本

使用config images pull 子命令下载所需的镜像,例如(国内无法下载,只做演示)

image-20220207174123729

预拉取镜像

通过阿里云镜像仓库构建下载镜像,具体方法不做细说。

镜像使用方式有2种:

  1. 修改镜像名为国外镜像名,例如

k8s.gcr.io/kube-apiserver:v1.23.0
k8s.gcr.io/kube-controller-manager:v1.23.0
k8s.gcr.io/kube-scheduler:v1.23.0
k8s.gcr.io/kube-proxy:v1.23.0
k8s.gcr.io/pause:3.6
k8s.gcr.io/etcd:3.5.1-0
k8s.gcr.io/coredns/coredns:v1.8.6

  1. 修改初始化配置文件,修改国外仓库为阿里云仓库

imageRepository: registry.cn-hangzhou.aliyuncs.com/k8s-images-kx
kind: ClusterConfiguration
kubernetesVersion: 1.23.3
networking:
dnsDomain: cluster.local
serviceSubnet: 10.96.0.0/12

1
[root@node1 home]# kubeadm config images pull --config=init.default.yaml

3.5.5 初始化集群

1
2
# --upload-certs根据情况可选
kubeadm init --config /home/init.default.yaml --upload-certs

image-20220210153548055

![(https://operationman-1258630122.cos.ap-nanjing.myqcloud.com/images-master/2022/02/image-20220210154221965.png)

image-20220210154352724

3.5.6 加入master节点

1
2
3
kubeadm join 192.168.1.133:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:d264137849995438cfda460507958165ad026fc804206c9000e7f2c6c4b8b66c \
--control-plane

image-20220210155044128

1
2
3
4
# 执行以下步骤,才能使用kubectl命令
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

3.5.7 加入工作节点

1
2
kubeadm join 192.168.1.133:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:d264137849995438cfda460507958165ad026fc804206c9000e7f2c6c4b8b66c

image-20220210155225404

3.5.8 检查节点

1
kubectl get node

image-20220210161203270

3.5.9 验证

关闭master1节点,通过master2或master3节点尝试集群命令。

vip转移到node2即master2节点,node2和node4执行管理权限不受影像

image-20220210161417179

image-20220210161241890

image-20220210161312871

到此简单验证成功。其他问题参考《kubenetes学习二》

参考

Kubeadm + HAProxy + Keepalived部署高可用Kubernetes集群

-------------本文结束感谢您的阅读-------------
坚持原创技术分享,您的支持将鼓励我继续创作!