高可用 Kubernetes 集群部署: 使用 kubeadm 安装 3 Master 2 Worker 的 Kubernetes 集群(LVS+Keepalived实现高可用)
碰到的难点:代理配置,Linux内核模块和参数,sed命令修改配置, systemctl daemon-reload的作用,网络拓扑
关键词: #Kubernetes 、 #部署手册
实验目标
使用 kubeadm 部署一个
3 Master + 2 Worker 的高可用 Kubernetes 集群 (加上相关的两个LB调度器)。
实验环境
| 项目 | 配置 |
|---|---|
| 操作系统 | Rocky Linux release 9.4 (Blue Onyx) |
| 内核版本 | 5.14.0-427.13.1.el9_4.x86_64 |
| CPU 架构 | x86_64 |
| Kubernetes | v1.32.2 |
| Containerd | 1.7.29 |
| 网络插件 | Calico v3.29.2 |
| 容器网络 CIDR | 10.244.0.0/16 |
| Master 数量 | 1 |
| Worker 数量 | 2 |
网络规划
192.168.250.0/24 是 nat 模式的虚拟网络 VMnet8
| 角色 | 主机名 | IP 地址 | 配置 |
|---|---|---|---|
| Master1 | master-1 | 192.168.250.151 | 2C4G |
| Master2 | master-2 | 192.168.250.152 | 2C4G |
| Master3 | master-3 | 192.168.250.153 | 2C4G |
| Worker1 | worker-1 | 192.168.250.154 | 2C4G |
| Worker2 | worker-2 | 192.168.250.155 | 2C4G |
| LB1 | lb-1 | 192.168.250.156 | 2C4G |
| LB2 | lb-2 | 192.168.250.157 | 2C4G |
| VIP (api-server) | 192.168.250.158 |
注:网关是 192.168.250.2
安装步骤
一、环境准备 ( Master , Worker 和 LB 都 执行 )
1.1 配置静态 IP
如下是 master-1 节点的配置静态 IP 地址的流程,其他节点类似
cd /etc/NetworkManager/system-connections
sed -ri "1,/^method=/s/^(method=).*/\1manual/" ens160.nmconnection
sed -ri '0,/^method=/s|^method=.*|&\naddress=192.168.250.151/24,192.168.250.2\ndns=192.168.250.2|' ens160.nmconnection
nmcli c r
nmcli c u ens160
期望的配置 /etc/NetworkManager/system-connections/ens160.nmconnection
...
[ipv4]
+ method=manual
- method=auto
+ address=192.168.250.151/24,192.168.250.2
+ dns=192.168.250.2
...
1.2 关闭防火墙和selinux
systemctl disable --now firewalld
setenforce 0
sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config
1.3 分别配置主机名(每个节点执行的命令不同)
- master-1
hostnamectl set-hostname master-1
- master-2
hostnamectl set-hostname master-2
- master-3
hostnamectl set-hostname master-3
- worker-1
hostnamectl set-hostname worker-1
- worker-2
hostnamectl set-hostname worker-2
- lb-1
hostnamectl set-hostname lb-1
- lb-2
hostnamectl set-hostname lb-2
1.4 配置hosts文件本地解析
cat >> /etc/hosts << EOF
192.168.250.151 master-1
192.168.250.152 master-2
192.168.250.153 master-3
192.168.250.154 worker-1
192.168.250.155 worker-2
192.168.250.156 lb-1
192.168.250.157 lb-2
192.168.250.158 api
EOF
二、环境准备 ( Master 和 Worker 都 执行 )
2.1 关闭交换分区
swapoff -a
sed -i '/swap/d' /etc/fstab
free -h
2.2 修改内核参数
cat >> /etc/modules-load.d/k8s.conf <<EOF
br_netfilter
EOF
modprobe br_netfilter
cat >> /etc/sysctl.d/kubernetes.conf<<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
cat >> /etc/sysctl.conf <<EOF
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
EOF
sysctl --system
2.3 配置时钟同步
dnf -y install chrony
cat >> /etc/chrony.conf << EOF
server ntp.aliyun.com iburst
server ntp1.aliyun.com iburst
server ntp2.aliyun.com iburst
EOF
systemctl enable --now chronyd
2.4 安装 容器运行时 Containerd
安装 containerd
dnf install -y yum-utils
dnf config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
dnf -y install containerd.io-1.7.29
修改 containerd 配置文件
创建默认配置文件
cd /etc/containerd
mv config.toml config.toml.orig
containerd config default > /etc/containerd/config.toml
修改配置
SystemdCgroup=true
sandbox_image=registry.aliyuncs.com/google_containers/pause:3.8
sed -i "s#SystemdCgroup\ \=\ false#SystemdCgroup\ \=\ $SystemdCgroup#g" /etc/containerd/config.toml
sed -i "s#registry.k8s.io/pause:3.8#$sandbox_image#g" /etc/containerd/config.toml
注:期望的配置状态: /etc/containerd/config.toml
...
[plugins."io.containerd.grpc.v1.cri"]
...
+ sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.8"
- sandbox_image = "registry.k8s.io/pause:3.8"
...
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
...
+ SystemdCgroup = true
- SystemdCgroup = false
...
启动 containerd 服务
systemctl enable --now containerd
systemctl status containerd --no-pager
ctr version
2.5 安装 kubeadm 和 k8s 组件
cat >> /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.32/rpm/
enabled=1
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.32/rpm/repodata/repomd.xml.key
EOF
dnf install -y kubeadm-1.32.2 kubelet-1.32.2 kubectl-1.32.2
systemctl enable --now kubelet
三、环境准备 ( LB 都 执行 )
3.1 安装 keepalived 和 ipvsadm
dnf -y install keepalived ipvsadm
3.2 修改内核参数
cat >> /etc/sysctl.conf <<EOF
net.ipv4.conf.all.send_redirects = 0
EOF
sysctl -p
3.3 指定 keepalived 配置
在 LB1 节点运行如下命令
cat > /etc/keepalived/keepalived.conf << EOF
global_defs {
router_id LVS_DEVEL
}
vrrp_instance VI_1 {
state MASTER
interface ens160
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
192.168.250.158/24
}
}
virtual_server 192.168.250.158 6443 {
delay_loop 6
lb_algo rr
lb_kind DR
protocol TCP
real_server 192.168.250.151 6443 {
TCP_CHECK {
connect_timeout 3
}
}
real_server 192.168.250.152 6443 {
TCP_CHECK {
connect_timeout 3
}
}
real_server 192.168.250.153 6443 {
TCP_CHECK {
connect_timeout 3
}
}
}
EOF
在 LB2 节点运行如下命令
cat > /etc/keepalived/keepalived.conf << EOF
global_defs {
router_id LVS_DEVEL
}
vrrp_instance VI_1 {
state BACKUP
interface ens160
virtual_router_id 51
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
192.168.250.158/24
}
}
virtual_server 192.168.250.158 6443 {
delay_loop 6
lb_algo rr
lb_kind DR
protocol TCP
real_server 192.168.250.151 6443 {
TCP_CHECK {
connect_timeout 3
}
}
real_server 192.168.250.152 6443 {
TCP_CHECK {
connect_timeout 3
}
}
real_server 192.168.250.153 6443 {
TCP_CHECK {
connect_timeout 3
}
}
}
EOF
3.4 启动 keepalived 服务
systemctl enable --now keepalived
四、Master1节点初始化
4.1 添加 api-server 的 vip
nmcli connection add \
con-name lo-vip \
type loopback \
connection.interface-name lo \
connection.autoconnect yes
nmcli connection modify lo-vip \
+ipv4.addresses 192.168.250.158/32
nmcli connection up lo-vip
4.2 生成 kubeadm 初始化的配置文件
master1=192.168.250.151
# .kubernetesVersion
kubernetesVersion=1.32.2
# .controlPlaneEndpoint
controlPlaneEndpoint=api:6443
# .imageRepository
imageRepository=registry.aliyuncs.com/google_containers
# .localAPIEndpoint.advertiseAddress
advertiseAddress=$master1
# .nodeRegistration.name
name=master-1
# .networking.podSubnet
podSubnet=10.244.0.0/16
cd
kubeadm config print init-defaults > kubeadm-config.yaml
sed -ri "s|(advertiseAddress:[[:space:]]*).*|\1$advertiseAddress|" kubeadm-config.yaml
sed -ri "s|(name:[[:space:]]*).*|\1$name|" kubeadm-config.yaml
sed -ri "s|(imageRepository:[[:space:]]*).*|\1$imageRepository|" kubeadm-config.yaml
sed -ri "s|(kubernetesVersion:[[:space:]]*).*|\1$kubernetesVersion|" kubeadm-config.yaml
sed -ri "/(serviceSubnet:[[:space:]]*).*/a\ \ podSubnet: $podSubnet" kubeadm-config.yaml
sed -ri "/(kubernetesVersion:[[:space:]]*).*/a controlPlaneEndpoint: $controlPlaneEndpoint" kubeadm-config.yaml
期望的配置
apiVersion: kubeadm.k8s.io/v1beta4
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
token: abcdef.0123456789abcdef
ttl: 24h0m0s
usages:
- signing
- authentication
kind: InitConfiguration
localAPIEndpoint:
+ advertiseAddress: 192.168.250.151
- advertiseAddress: 1.2.3.4
bindPort: 6443
nodeRegistration:
criSocket: unix:///var/run/containerd/containerd.sock
imagePullPolicy: IfNotPresent
imagePullSerial: true
+ name: master-1
- name: node
taints: null
timeouts:
controlPlaneComponentHealthCheck: 4m0s
discovery: 5m0s
etcdAPICall: 2m0s
kubeletHealthCheck: 4m0s
kubernetesAPICall: 1m0s
tlsBootstrap: 5m0s
upgradeManifests: 5m0s
---
apiServer: {}
apiVersion: kubeadm.k8s.io/v1beta4
caCertificateValidityPeriod: 87600h0m0s
certificateValidityPeriod: 8760h0m0s
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
encryptionAlgorithm: RSA-2048
etcd:
local:
dataDir: /var/lib/etcd
+ imageRepository: registry.aliyuncs.com/google_containers
- imageRepository: registry.k8s.io
kind: ClusterConfiguration
+ kubernetesVersion: 1.32.2
- kubernetesVersion: 1.32.0
+ controlPlaneEndpoint: api:6443
networking:
dnsDomain: cluster.local
serviceSubnet: 10.96.0.0/12
+ podSubnet: 10.244.0.0/16
proxy: {}
scheduler: {}
4.3 下载集群初始化所需镜像
kubeadm config --config=kubeadm-config.yaml images list
kubeadm config --config=kubeadm-config.yaml images pull
ctr -n k8s.io image list
4.4 集群初始化
kubeadm init --config=kubeadm-config.yaml
4.5 配置 kubectl 的认证文件
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
五、Worker 节点加入集群
在 Master1 节点运行如下命令,生成Worker节点加入集群命令的命令,然后将生成的命令在各个 Worker 节点上运行
kubeadm token create --print-join-command
注:示例命令
kubeadm join api:6443 --token wg0ev4.cz{{placehold}}oyq --discovery-token-ca-cert-hash sha256:ba{{placehold}}07e
六、其余 Master 节点加入集群
6.1 Master 节点加入集群
如果要让其余 Master 节点加入集群,需要在生成的 join-command 中增加两个参数 --control-plane 和 --certificate-key 2d{placehold}b
注:certificate-key 的值需要通过如下命令生成
kubeadm init phase upload-certs --upload-certs
注:示例命令
kubeadm join api:6443 --token wg0ev4.cz{{placehold}}oyq --discovery-token-ca-cert-hash sha256:ba{{placehold}}07e --control-plane --certificate-key 2d{placehold}b
6.2 Master 节点 添加 api-server 的 vip 到 lo 网卡
nmcli connection add \
con-name lo-vip \
type loopback \
connection.interface-name lo \
connection.autoconnect yes
nmcli connection modify lo-vip \
+ipv4.addresses 192.168.250.158/32
nmcli connection up lo-vip
七、安装网络插件 Calico
7.1 配置代理(在所有节点配置代理)
注:接下来,为了避免安装网络插件 Calico 因网络不好而需要导入离线镜像的麻烦,我在这次实验中在这里配置代理,方便拉取相关镜像
全局代理
cat > /etc/profile.d/proxy.sh << 'EOF'
#!/bin/bash
# Configuration
PROXY_URL=http://192.168.250.1:10090
NO_PROXY_URL=localhost,127.0.0.1,::1,192.168.0.0/16,172.16.0.0/12,10.0.0.0/8,.svc,.cluster.local,.localdomain,.example.com,192.168.250.158,api
# Enviroment Variables
export HTTP_PROXY=$PROXY_URL HTTPS_PROXY=$PROXY_URL ALL_PROXY=$PROXY_URL
export http_proxy=$PROXY_URL https_proxy=$PROXY_URL all_proxy=$PROXY_URL
export NO_PROXY=$NO_PROXY_URL no_proxy=$NO_PROXY_URL
EOF
. /etc/profile.d/proxy.sh
containerd代理
mkdir /usr/lib/systemd/system/containerd.service.d
PROXY_URL=http://192.168.250.1:10090
NO_PROXY_URL=localhost,127.0.0.1,::1,192.168.0.0/16,172.16.0.0/12,10.0.0.0/8,.svc,.cluster.local,.localdomain,.example.com,192.168.250.158,api
cat > /usr/lib/systemd/system/containerd.service.d/http-proxy.conf << EOF
[Service]
Environment="NO_PROXY=$NO_PROXY_URL"
Environment="HTTPS_PROXY=$PROXY_URL"
Environment="HTTP_PROXY=$PROXY_URL"
Environment="ALL_PROXY=$PROXY_URL"
Environment="no_proxy=$NO_PROXY_URL"
Environment="https_proxy=$PROXY_URL"
Environment="http_proxy=$PROXY_URL"
Environment="all_proxy=$PROXY_URL"
EOF
systemctl daemon-reload
systemctl restart containerd
注: 如果需要在网络受限环境中安装网络插件 Calico,执行如下操作即可
- 上传离线镜像
calico-3.29.2.image - 运行命令
ctr -n k8s.io image import calico-3.29.2.image
7.2 安装网络插件 Calico (仅在一个 master 节点执行)
curl https://raw.githubusercontent.com/projectcalico/calico/v3.29.2/manifests/calico.yaml -O
kubectl create -f calico.yaml
验证
kubectl get po -n kube-system -o wide
kubectl get no
kubectl get cs
浙公网安备 33010602011771号