🎉 08-kubeadm部署K8s 1.25高可用集群
一、集群整体规划
1. 网段规划
-
Pod 网段(podSubnet):
10.244.0.0/16 -
Service 网段(serviceSubnet):
10.96.0.0/12 -
高可用虚拟 VIP:
192.168.40.199
2. 节点角色规划
| 集群角色 | IP 地址 | 主机名 | 核心组件 |
|---|---|---|---|
| 控制节点 Master | (192.168.40.180) | zhappymaster1 | apiserver、controller-manager、scheduler、kubelet、etcd、kube-proxy、容器运行时、calico、keepalived、nginx |
| 工作节点 Node1 | (192.168.40.181) | zhappynode1 | kube-proxy、calico、coredns、容器运行时、kubelet |
| 工作节点 Node2 | (192.168.40.182) | zhappynode2 | kube-proxy、calico、coredns、容器运行时、kubelet |
3. 系统环境要求
-
操作系统:CentOS 7.9
-
硬件配置:4GiB 内存 / 4vCPU / 60G 硬盘
-
网络:NAT 模式
二、集群环境初始化(所有节点执行)
1. 配置静态 IP
修改网卡配置(网卡名以实际为准,示例为ens33):
vim /etc/sysconfig/network-scripts/ifcfg-ens33
核心配置项:
BOOTPROTO=static
IPADDR=192.168.40.180 # 替换为对应节点IP
NETMASK=255.255.255.0
GATEWAY=192.168.40.2
DNS1=192.168.40.2
ONBOOT=yes
NAME=ens33
DEVICE=ens33
重启网络生效:
service network restart
可选操作:执行
yum update -y升级系统至最新版本。
2. 关闭 SELinux
# 永久关闭,重启后生效
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
# 重启机器
reboot
# 验证状态,输出 Disabled 即为成功
getenforce
3. 设置主机名
分别在对应节点执行:
# Master执行
hostnamectl set-hostname zhappymaster1 && bash
# Node1执行
hostnamectl set-hostname zhappynode1 && bash
# Node2执行
hostnamectl set-hostname zhappynode2 && bash
4. 配置主机名解析
所有节点的/etc/hosts添加节点映射:
cat >> /etc/hosts <<EOF
192.168.40.180 zhappymaster1
192.168.40.181 zhappynode1
192.168.40.182 zhappynode2
EOF
5. 配置节点间 SSH 免密登录
分别在三个节点生成密钥并分发至所有节点:
# 生成密钥,一路回车即可
ssh-keygen
# 分发公钥
ssh-copy-id zhappymaster1
ssh-copy-id zhappynode1
ssh-copy-id zhappynode2
6. 关闭 Swap 交换分区
K8s 默认禁用 Swap 以保证性能,未关闭会导致初始化失败。
# 临时关闭
swapoff -a
# 永久关闭:注释fstab中swap挂载行
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
说明:若必须保留 Swap,可在 kubeadm 命令后追加
--ignore-preflight-errors=Swap跳过检测。
7. 配置内核网络参数
加载桥接模块,开启 IP 转发与网桥 iptables 支持:
# 加载br_netfilter内核模块
modprobe br_netfilter
# 写入内核配置
cat > /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
# 生效配置
sysctl -p /etc/sysctl.d/k8s.conf
8. 关闭 firewalld 防火墙
systemctl stop firewalld
systemctl disable firewalld
9. 配置 Docker/containerd 阿里云 YUM 源
yum install yum-utils -y
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
10. 配置 K8s 阿里云 YUM 源
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
EOF
11. 配置时间同步
# 安装同步工具
yum install ntpdate -y
# 立即同步时间
ntpdate cn.pool.ntp.org
# 添加定时任务,每小时同步一次
crontab -e
* */1 * * * /usr/sbin/ntpdate cn.pool.ntp.org
# 重启定时任务
service crond restart
12. 安装基础依赖包
yum install -y device-mapper-persistent-data lvm2 wget net-tools nfs-utils lrzsz gcc gcc-c++ make cmake libxml2-devel openssl-devel curl curl-devel unzip sudo ntp libaio-devel vim ncurses-devel autoconf automake zlib-devel python-devel epel-release openssh-server socat ipvsadm conntrack telnet ipvsadm
三、安装容器运行时 containerd(所有节点执行)
K8s 1.25 版本已移除 dockershim,默认使用 containerd 作为容器运行时。
1. 安装 containerd
yum install containerd.io-1.6.6 -y
2. 生成并修改配置文件
# 创建配置目录
mkdir -p /etc/containerd
# 生成默认配置
containerd config default > /etc/containerd/config.toml
修改/etc/containerd/config.toml两个核心配置:
-
开启 SystemdCgroup:将
SystemdCgroup = false改为SystemdCgroup = true,与 kubelet 驱动保持一致 -
替换 pause 镜像源:将
sandbox_image = "k8s.gcr.io/pause:3.6"改为sandbox_image="registry.aliyuncs.com/google_containers/pause:3.7"
启动并设置开机自启:
systemctl enable containerd --now
3. 配置 crictl 客户端
crictl 是 K8s CRI 接口的客户端工具,用于与容器运行时交互:
cat > /etc/crictl.yaml <<EOF
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF
systemctl restart containerd
4. (可选)安装 Docker 用于镜像构建
containerd 不支持直接通过 Dockerfile 构建镜像,可同时安装 Docker,二者互不冲突:
yum install docker-ce -y
systemctl enable docker --now
5. 配置镜像加速器
(1)containerd 镜像加速
# 修改配置文件,指定证书配置目录
sed -i 's#config_path = ""#config_path = "/etc/containerd/certs.d"#g' /etc/containerd/config.toml
# 创建docker.io镜像加速配置
mkdir /etc/containerd/certs.d/docker.io/ -p
cat > /etc/containerd/certs.d/docker.io/hosts.toml <<EOF
[host."https://vh3bm52y.mirror.aliyuncs.com",host."https://registry.docker-cn.com"]
capabilities = ["pull"]
EOF
# 重启生效
systemctl restart containerd
(2)Docker 镜像加速
cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors":["https://vh3bm52y.mirror.aliyuncs.com","https://registry.docker-cn.com","https://docker.mirrors.ustc.edu.cn","https://dockerhub.azk8s.cn","http://hub-mirror.c.163.com"]
}
EOF
systemctl restart docker
四、安装 K8s 核心组件(所有节点执行)
1. 安装指定版本组件
yum install -y kubelet-1.25.0 kubeadm-1.25.0 kubectl-1.25.0
2. 设置 kubelet 开机自启
systemctl enable kubelet
组件说明:
kubeadm:K8s 集群自动化初始化工具
kubelet:运行在所有节点,负责 Pod 生命周期管理,与 APIServer 通信
kubectl:K8s 命令行客户端,用于集群资源管理与操作
五、kubeadm 初始化 Master 控制节点
1. 指定 containerd 运行时端点(所有节点执行)
crictl config runtime-endpoint /run/containerd/containerd.sock
2. 编写初始化配置文件
在 Master 节点生成并修改配置:
kubeadm config print init-defaults > kubeadm.yaml
完整kubeadm.yaml配置:
apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: 192.168.40.180 # Master节点IP
bindPort: 6443
nodeRegistration:
criSocket: unix:///run/containerd/containerd.sock # 指定containerd运行时
imagePullPolicy: IfNotPresent
name: zhappymaster1 # Master主机名
taints: null
---
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
etcd:
local:
dataDir: /var/lib/etcd
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers # 国内镜像源
kind: ClusterConfiguration
kubernetesVersion: 1.25.0 # K8s版本
networking:
dnsDomain: cluster.local
podSubnet: 10.244.0.0/16 # Pod网段
serviceSubnet: 10.96.0.0/12 # Service网段
scheduler: {}
---
# kube-proxy启用IPVS模式
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs
---
# kubelet cgroup驱动与containerd保持一致
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd
3. 导入离线镜像(所有节点)
将k8s_1.25.0.tar.gz上传至所有节点,通过 ctr 导入 [k8s.io](k8s.io) 命名空间:
# containerd有命名空间概念,k8s相关镜像默认在k8s.io命名空间
ctr -n=k8s.io images import k8s_1.25.0.tar.gz
# 验证镜像
crictl images
4. 执行集群初始化
kubeadm init --config=kubeadm.yaml --ignore-preflight-errors=SystemVerification
初始化成功后会输出 Master 节点加入命令和 Worker 节点加入命令,请保存好 token 和 hash 值。
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
6. 查看初始节点状态
kubectl get nodes
此时节点状态为NotReady属于正常现象,原因是尚未安装网络插件。
六、扩容 Worker 工作节点
1. 生成节点加入命令(Master 执行)
kubeadm token create --print-join-command
2. Node1 加入集群
在 Node1 节点执行输出的 join 命令:
kubeadm join 192.168.40.180:6443 --token 你的token值 \
--discovery-token-ca-cert-hash sha256:你的hash值 \
--ignore-preflight-errors=SystemVerification
3. Node2 加入集群
同样执行 join 命令加入集群。
4. 给 Worker 节点打角色标签
kubectl label nodes zhappynode1 node-role.kubernetes.io/work=work
kubectl label nodes zhappynode2 node-role.kubernetes.io/work=work
七、安装 Calico 网络插件
1. 导入 Calico 离线镜像(所有节点)
ctr -n=k8s.io images import calico.tar.gz
2. 部署 Calico
上传calico.yaml文件,在 Master 执行部署:
kubectl apply -f calico.yaml
3. 验证节点状态
kubectl get nodes
等待所有节点 STATUS 变为Ready,说明网络插件安装成功。
4. Calico 核心组件
-
Felix:运行在每个节点的 Agent,负责路由、ARP、ACL 规则管理,保障容器网络互通
-
Etcd:分布式存储,保存 Calico 网络元数据,保证状态一致性
-
BGP Client(BIRD):每个节点部署一个,将内核路由信息分发到整个 Calico 网络
-
BGP Route Reflector:大规模集群使用,替代全网状互联,集中分发路由,降低节点连接数
5. IPIP 与 BGP 模式对比
| 模式 | 原理 | 特点 | 适用场景 |
|---|---|---|---|
| IPIP | IP 包外层再封装一层 IP 头,通过 tunl0 隧道转发,属于 Overlay 网络 | 不要求节点二层互通,有额外封装开销 | 跨网段、三层不通的复杂网络环境 |
| BGP | 节点作为虚拟路由器,直接通过路由转发,无额外隧道 | 性能高,无封装开销,要求节点二层互通 | 同机房、同网段的物理机集群 |
Calico 默认开启 IPIP 模式,通过环境变量
CALICO_IPV4POOL_IPIP控制,Always为开启,Off为关闭并使用 BGP 模式。
多网卡节点可通过IP_AUTODETECTION_METHOD指定网卡,例如interface=ens33。
八、集群功能验证
1. 导入测试镜像(所有 Node 节点)
ctr -n k8s.io images import busybox-1-28.tar.gz
2. Pod 外网连通性测试
kubectl run busybox --image docker.io/library/busybox:1.28 \
--image-pull-policy=IfNotPresent --restart=Never --rm -it -- sh
容器内执行 ping 测试:
ping www.baidu.com
能正常连通说明容器外网与 Calico 网络正常。
3. CoreDNS 域名解析测试
在 busybox 容器内执行:
nslookup kubernetes.default.svc.cluster.local
能正常解析出 Service IP 则集群 DNS 服务正常。
注意:必须使用 busybox 1.28 版本,高版本存在 nslookup 解析异常问题。
九、ctr 与 crictl 工具区别
二者均为容器运行时的命令行工具,但定位与适用场景不同:
-
ctr:containerd 自带的原生 CLI 工具,功能全面,支持镜像、容器、命名空间等全量管理,不感知 K8s 概念。
-
crictl:K8s CRI(容器运行时接口)的官方客户端,专门用于 K8s 场景下与容器运行时交互,功能偏向容器、Pod 生命周期管理,镜像管理能力较弱。
简单理解:
-
调试 containerd 本身、导入导出镜像、管理命名空间用
ctr -
调试 K8s 容器、查看 Pod 容器状态用
crictl,与 K8s 体系兼容性更好