| 角色 | IP 地址 | 主机名 | 执行角色 |
|---|---|---|---|
| Master1 | 192.168.1.53 | master1 | 主节点 |
| Master2 | 192.168.1.54 | master2 | 备节点 |
| Master3 | 192.168.1.55 | master3 | 备节点 |
| Worker1 | 192.168.1.56 | worker1 | 工作节点 |
| Worker2 | 192.168.1.57 | worker2 | 工作节点 |
| Worker3 | 192.168.1.58 | worker3 | 工作节点 |
| Worker4 | 192.168.1.59 | worker4 | 工作节点 |
| Worker5 | 192.168.1.60 | worker5 | 工作节点 |
| VIP | 192.168.1.200 | - | 虚拟 IP |
| 代理服务器 | 192.168.1.119 | - | 镜像代理 |
| 端口 | 用途 |
|---|---|
| 22 | SSH |
| 80 | HAProxy 业务入口 |
| 6443 | kube-apiserver |
| 16443 | HAProxy 代理 APIServer |
| 2379/2380 | etcd 集群 |
| 30325 | Ingress-Nginx HTTP |
| 30372 | Grafana |
| 20171 | 代理服务端口 |
| 179 | Calico 网络 |
**说明:**此步骤为集群部署基础,所有节点必须执行,确保环境一致性,注释明确每一步用途,避免误操作。
# 1. 关闭防火墙(K8s集群部署必须关闭,避免端口拦截)
systemctl stop firewalld
systemctl disable firewalld
# 2. 关闭SELinux(K8s强制要求,否则会导致Pod调度、网络通信异常)
setenforce 0 # 临时关闭
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config # 永久关闭
# 3. 关闭Swap分区(K8s强制要求,Swap开启会导致kubelet启动失败)
swapoff -a # 临时关闭
sed -i '/swap/d' /etc/fstab # 永久关闭,删除Swap相关配置
# 4. 加载K8s所需内核模块(overlay用于容器存储,br_netfilter用于网络桥接)
modprobe overlay
modprobe br_netfilter
# 5. 配置内核参数(开启网络桥接、IP转发,确保Pod网络正常通信)
cat > /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-iptables=1 # 开启桥接流量的iptables过滤
net.bridge.bridge-nf-call-ip6tables=1 # 开启IPv6桥接流量的iptables过滤
net.ipv4.ip_forward=1 # 开启IP转发,实现Pod跨节点通信
EOF
sysctl --system # 使内核参数立即生效
# 6. 配置主机名解析(避免节点间通信依赖DNS,确保主机名与IP对应)
cat >> /etc/hosts <<EOF
192.168.1.53 master1
192.168.1.54 master2
192.168.1.55 master3
192.168.1.56 worker1
192.168.1.57 worker2
192.168.1.58 worker3
192.168.1.59 worker4
192.168.1.60 worker5
192.168.1.119 proxy # 镜像代理服务器,供containerd使用
EOF
**说明:**containerd为K8s官方推荐容器运行时,此步骤严格还原实际操作,仅配置containerd镜像代理(端口20171),无系统全局代理,关键配置添加详细注释。
# 1. 安装containerd(CentOS Stream 9使用dnf安装,系统默认源可直接获取)
dnf install -y containerd
# 2. 生成containerd默认配置文件(默认无配置文件,需手动生成)
containerd config default > /etc/containerd/config.toml
# ========== 关键配置(必看,确保与K8s兼容、镜像拉取正常) ==========
# 3. 替换pause镜像为阿里云国内源(解决国外registry.k8s.io拉取超时问题)
sed -i 's#registry.k8s.io/pause#registry.aliyuncs.com/google_containers/pause#g' /etc/containerd/config.toml
# 4. 开启systemd cgroup驱动(K8s 1.24+版本强制要求,必须与系统cgroup驱动一致)
sed -i 's#SystemdCgroup = false#SystemdCgroup = true#g' /etc/containerd/config.toml
# 5. 仅为containerd配置镜像拉取代理(不配置系统全局代理,端口20171)
# 创建containerd服务配置目录(若不存在)
mkdir -p /etc/systemd/system/containerd.service.d
# 编写代理配置文件
cat > /etc/systemd/system/containerd.service.d/http-proxy.conf <<EOF
[Service]
# 配置HTTP/HTTPS代理,指向镜像代理服务器(192.168.1.119:20171)
Environment="HTTP_PROXY=http://192.168.1.119:20171"
Environment="HTTPS_PROXY=http://192.168.1.119:20171"
# 配置不走代理的地址(内网节点、本地地址,避免代理影响内网通信)
Environment="NO_PROXY=localhost,127.0.0.1,192.168.1.0/24,.svc,.cluster.local"
EOF
# 6. 重启containerd服务,使配置生效,并设置开机自启
systemctl daemon-reload # 重新加载系统服务配置
systemctl enable --now containerd # 启动并设置开机自启
**说明:**这三个是K8s核心组件,kubeadm用于集群初始化,kubelet用于节点管理,kubectl用于集群操作,配置阿里云源避免下载缓慢。
# 1. 配置阿里云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 # 关闭GPG校验(避免校验失败)
repo_gpgcheck=0 # 关闭仓库GPG校验
EOF
# 2. 安装指定版本的K8s组件(固定1.28.2版本,与集群初始化版本一致)
dnf install -y kubeadm-1.28.2 kubelet-1.28.2 kubectl-1.28.2
# 3. 设置kubelet开机自启(确保节点重启后kubelet自动运行)
systemctl enable --now kubelet
**说明:**HAProxy实现APIServer和业务入口的负载均衡,Keepalived提供VIP漂移,实现高可用,严格区分主备节点配置,不可混淆。
# 安装HAProxy(负载均衡)和Keepalived(VIP漂移),使用dnf直接安装
dnf install -y haproxy keepalived
# 先设置开机自启,避免后续重启节点后服务未启动
systemctl enable haproxy keepalived
**说明:**HAProxy同时代理K8s APIServer(16443端口)和业务Ingress入口(80端口),配置文件路径固定,注释明确各模块用途。
cat > /etc/haproxy/haproxy.cfg <<EOF
global
daemon # 以守护进程模式运行
user haproxy # 运行HAProxy的用户
group haproxy # 运行HAProxy的用户组
defaults
mode tcp # 采用TCP模式(K8s APIServer和Ingress均为TCP通信)
timeout connect 5s # 连接超时时间
timeout client 30s # 客户端超时时间
timeout server 30s # 服务器超时时间
# ========== 模块1:K8s APIServer负载均衡(控制面入口) ==========
frontend k8s-apiserver # 前端监听配置
bind 0.0.0.0:16443 # 监听所有网卡的16443端口(与VIP配合)
default_backend k8s-masters # 所有请求转发到后端Master节点集群
backend k8s-masters # 后端Master节点配置
# 3台Master节点的APIServer地址(端口6443),开启健康检查
server master1 192.168.1.53:6443 check inter 2s fall 3 rise 2
server master2 192.168.1.54:6443 check inter 2s fall 3 rise 2
server master3 192.168.1.55:6443 check inter 2s fall 3 rise 2
# check inter 2s:每2秒检查一次节点健康;fall 3:3次检查失败视为节点不可用;rise 2:2次检查成功视为节点恢复
# ========== 模块2:业务Ingress HTTP入口负载均衡(业务访问入口) ==========
frontend k8s-ingress-http # 前端监听配置
bind 0.0.0.0:80 # 监听所有网卡的80端口(业务Web入口)
default_backend ingress-workers # 所有请求转发到后端Worker节点的Ingress服务
backend ingress-workers # 后端Worker节点Ingress配置
# 5台Worker节点的Ingress-Nginx端口(30325),开启健康检查
server worker1 192.168.1.56:30325 check inter 3s fall 3 rise 2
server worker2 192.168.1.57:30325 check inter 3s fall 3 rise 2
server worker3 192.168.1.58:30325 check inter 3s fall 3 rise 2
server worker4 192.168.1.59:30325 check inter 3s fall 3 rise 2
server worker5 192.168.1.60:30325 check inter 3s fall 3 rise 2
EOF
**说明:**Keepalived通过优先级区分主备节点,master1为MASTER(优先级100),master2、master3为BACKUP(优先级90、80),确保VIP正常漂移。
cat > /etc/keepalived/keepalived.conf <<EOF
global_defs {
router_id LVS_MASTER # 路由ID,主节点唯一标识,与备节点区分
}
vrrp_instance VI_1 {
state MASTER # 节点角色:主节点(MASTER)
interface eth0 # 绑定的网卡(需与节点实际网卡一致,默认eth0)
virtual_router_id 51 # 虚拟路由ID,所有主备节点必须一致(取值0-255)
priority 100 # 优先级,主节点优先级最高(100),高于所有备节点
advert_int 1 # 心跳间隔,1秒发送一次心跳包,检测节点状态
authentication { # 认证配置,主备节点必须一致
auth_type PASS # 认证类型:密码认证
auth_pass 1111 # 认证密码,主备节点必须相同(自定义,建议4-8位)
}
virtual_ipaddress { # 虚拟IP(VIP),集群统一入口,与HAProxy监听端口配合
192.168.1.200/24
}
}
EOF
cat > /etc/keepalived/keepalived.conf <<EOF
global_defs {
router_id LVS_BACKUP1 # 路由ID,备节点1唯一标识,与主节点、备节点2区分
}
vrrp_instance VI_1 {
state BACKUP # 节点角色:备节点(BACKUP)
interface eth0 # 绑定的网卡,与主节点一致
virtual_router_id 51 # 虚拟路由ID,与主节点一致
priority 90 # 优先级,低于主节点(100),高于备节点2(80)
advert_int 1 # 心跳间隔,与主节点一致
authentication { # 认证配置,与主节点完全一致
auth_type PASS
auth_pass 1111
}
virtual_ipaddress { # 虚拟IP(VIP),与主节点一致,实现漂移
192.168.1.200/24
}
}
EOF
cat > /etc/keepalived/keepalived.conf <<EOF
global_defs {
router_id LVS_BACKUP2 # 路由ID,备节点2唯一标识,与主节点、备节点1区分
}
vrrp_instance VI_1 {
state BACKUP # 节点角色:备节点(BACKUP)
interface eth0 # 绑定的网卡,与主节点一致
virtual_router_id 51 # 虚拟路由ID,与主节点一致
priority 80 # 优先级,低于主节点(100)和备节点1(90)
advert_int 1 # 心跳间隔,与主节点一致
authentication { # 认证配置,与主节点完全一致
auth_type PASS
auth_pass 1111
}
virtual_ipaddress { # 虚拟IP(VIP),与主节点一致,实现漂移
192.168.1.200/24
}
}
EOF
# 重启HAProxy服务,使配置生效
systemctl restart haproxy
# 重启Keepalived服务,使主备配置生效
systemctl restart keepalived
# 验证服务状态(可选,确保服务正常运行)
systemctl status haproxy
systemctl status keepalived
**说明:**仅在master1(主节点)执行初始化,生成集群配置,后续所有节点(master2、master3、Worker)均需加入此集群,注释明确每一个参数的用途。
kubeadm init \
--apiserver-advertise-address=192.168.1.53 \ # master1的IP地址,APIServer对外暴露的地址
--control-plane-endpoint=192.168.1.200:16443 \ # 集群控制面入口(VIP+HAProxy代理端口)
--kubernetes-version=1.28.2 \ # K8s版本,与安装的kubeadm版本一致
--image-repository=registry.aliyuncs.com/k8sxio \ # 镜像仓库,国内阿里云,避免拉取失败
--service-cidr=10.96.0.0/12 \ # 服务网段,K8s默认网段,无需修改
--pod-network-cidr=10.244.0.0/16 # Pod网段,与Calico网络插件默认网段一致
# 注意:初始化完成后,会输出master2、master3加入控制面的命令,以及Worker节点加入的命令
# 务必保存好这两条命令,后续步骤需要使用!
# 创建kubectl配置目录(若不存在)
mkdir -p $HOME/.kube
# 复制集群管理员配置文件到用户目录,赋予操作权限
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
# 授权当前用户操作kubectl(避免权限不足)
chown $(id -u):$(id -g) $HOME/.kube/config
# 验证kubectl配置(可选,确保能正常访问集群)
kubectl get nodes
# 部署Calico网络插件(适配K8s 1.28.x版本,官方稳定版)
kubectl apply -f https://docs.projectcalico.org/v3.26/manifests/calico.yaml
# 验证Calico状态(可选,确保所有Calico Pod正常运行)
kubectl get pods -n kube-system | grep calico
**说明:**务必使用master1初始化完成后输出的命令,以下为示例格式,实际以初始化输出为准。
# ① master2、master3加入控制面(带--control-plane参数,示例命令,实际以初始化输出为准)
kubeadm join 192.168.1.200:16443 --token xxxxxxxx \
--discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \
--control-plane
# ② 5台Worker节点加入集群(无--control-plane参数,示例命令,实际以初始化输出为准)
kubeadm join 192.168.1.200:16443 --token xxxxxxxx \
--discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# 验证所有节点加入(master1执行)
kubectl get nodes # 所有节点状态为Ready即正常
**说明:**使用官方一键脚本安装Helm3,无需手动下载、解压,简单高效,与实际部署操作完全一致。
# 官方一键脚本安装Helm3(直接执行,自动下载并配置环境变量)
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
# 验证Helm安装(确保安装成功,输出Helm版本信息)
helm version
**说明:**通过Helm部署Ingress-Nginx,配置为NodePort模式,固定HTTP端口30325,与HAProxy后端配置一致,实现业务路由。
# 1. 添加Ingress-Nginx官方Helm仓库
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
# 2. 更新Helm仓库(确保获取最新版本的Ingress-Nginx)
helm repo update
# 3. 部署Ingress-Nginx,指定命名空间、NodePort端口
helm install ingress-nginx ingress-nginx/ingress-nginx \
-n ingress-nginx --create-namespace \ # 创建独立命名空间ingress-nginx,隔离组件
--set controller.service.type=NodePort \ # 配置为NodePort模式,对外暴露端口
--set controller.service.ports.http.nodePort=30325 # 固定HTTP端口为30325,与HAProxy配置一致
# 验证Ingress-Nginx部署(可选,确保Pod正常运行)
kubectl get pods -n ingress-nginx
**说明:**通过Helm部署kube-prometheus-stack,包含Prometheus(数据采集)、Grafana(可视化面板)、Alertmanager(告警),固定Grafana端口30372。
# 1. 添加Prometheus官方Helm仓库
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
# 2. 更新Helm仓库,获取最新监控组件版本
helm repo update
# 3. 部署监控组件,指定命名空间、Grafana端口
helm install monitoring prometheus-community/kube-prometheus-stack \
-n monitoring --create-namespace \ # 创建独立命名空间monitoring,隔离组件
--set grafana.service.type=NodePort \ # 配置Grafana为NodePort模式,对外暴露面板
--set grafana.service.nodePort=30372 # 固定Grafana端口为30372,方便访问
# 验证监控部署(可选,确保所有监控Pod正常运行)
kubectl get pods -n monitoring
# Grafana访问方式(客户端访问)
# 地址:http://任意WorkerIP:30372
# 默认用户名:admin,默认密码:prom-operator(可后续修改)
**说明:**LocalPV为本地持久化存储,适合私有化部署场景,Worker节点创建本地目录,master1创建StorageClass,供业务Pod使用。
# 创建LocalPV存储目录(路径固定,与后续PV配置一致)
mkdir -p /data/localpv
# 赋予目录777权限,避免Pod挂载时权限不足
chmod 777 /data/localpv
**说明:**StorageClass用于统一管理存储类型,配置为“等待第一个消费者”模式,确保PV与PVC正确绑定。
# 创建StorageClass配置文件(文件名sc.yaml,路径默认当前目录)
cat > sc.yaml <<EOF
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local-storage # StorageClass名称,后续PVC需指定此名称
provisioner: kubernetes.io/no-provisioner # 本地存储,无需自动分配
volumeBindingMode: WaitForFirstConsumer # 等待第一个PVC请求后再绑定PV,避免绑定错误
EOF
# 应用StorageClass配置
kubectl apply -f sc.yaml
# 验证StorageClass(可选)
kubectl get sc # 查看local-storage是否创建成功
**说明:**配置Ingress路由,绑定域名zhongts.tech,将请求转发到后端nginx-web-svc服务,解决404问题,文件名固定为ingress.yaml。
# 创建Ingress路由配置文件(文件名ingress.yaml,路径默认当前目录)
cat > ingress.yaml <<EOF
apiVersion: networking.k8s.io/v1 # Ingress API版本,固定为v1
kind: Ingress
metadata:
name: web-ingress # Ingress名称,自定义
namespace: web # 命名空间,与业务应用一致(后续创建web命名空间)
spec:
ingressClassName: nginx # 绑定Ingress控制器,必须为nginx(与Ingress-Nginx部署一致)
rules: # 路由规则
- host: zhongts.tech # 业务访问域名,需在客户端配置hosts映射
http:
paths:
- path: / # 路由路径,/表示匹配所有请求
pathType: Prefix # 路径匹配模式,Prefix表示前缀匹配
backend:
service:
name: nginx-web-svc # 后端服务名称,与业务Service名称一致
port:
number: 80 # 后端服务端口,与业务Service端口一致
EOF
# 应用Ingress路由配置
kubectl apply -f ingress.yaml
# 验证Ingress配置(可选)
kubectl get ingress -n web
**说明:**部署简单Nginx业务应用,创建独立web命名空间,包含Deployment(业务Pod)、Service(服务暴露),与Ingress路由、LocalPV存储联动。
# 1. 创建web命名空间(隔离业务应用)
kubectl create namespace web
# 2. 创建业务应用配置文件(文件名web.yaml,路径默认当前目录)
cat > web.yaml <<EOF
# Deployment配置:管理业务Pod,确保Pod正常运行
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-web # Deployment名称
namespace: web # 命名空间,与Ingress一致
spec:
replicas: 1 # Pod副本数,默认1个(可根据需求调整)
selector:
matchLabels:
app: nginx-web # 标签选择器,与Pod标签一致
template:
metadata:
labels:
app: nginx-web # Pod标签,与Service、Deployment选择器一致
spec:
containers:
- name: nginx # 容器名称
image: nginx # 容器镜像(默认官方nginx镜像)
ports:
- containerPort: 80 # 容器内部端口,与Service端口一致
---
# Service配置:暴露业务Pod,供Ingress转发请求
apiVersion: v1
kind: Service
metadata:
name: nginx-web-svc # Service名称,与Ingress后端服务名称一致
namespace: web # 命名空间,与业务应用一致
spec:
selector:
app: nginx-web # 标签选择器,匹配业务Pod
ports:
- port: 80 # Service端口,与Ingress后端端口一致
EOF
# 3. 应用业务应用配置
kubectl apply -f web.yaml
# 4. 初始化业务首页(可选,用于验证访问)
# 进入Nginx Pod内部,创建首页文件
kubectl exec -it $(kubectl get pods -n web | grep nginx-web | awk '{print $1}') -n web -- sh
# 写入首页内容
echo "✅ 企业级K8s高可用集群部署成功(业务验证页)" > /usr/share/nginx/html/index.html
# 退出Pod
exit
# 验证业务应用(可选)
kubectl get pods -n web
kubectl get svc -n web
**说明:**配置Windows hosts文件,将域名zhongts.tech映射到VIP(192.168.1.200),实现浏览器访问业务。
# 1. 打开Windows hosts文件,路径:C:\Windows\System32\drivers\etc\hosts
# 2. 在文件末尾添加以下内容(映射域名到VIP)
192.168.1.200 zhongts.tech
# 3. 浏览器访问业务地址(无需加端口,默认80端口)
http://zhongts.tech
# 访问成功说明:浏览器显示“✅ 企业级K8s高可用集群部署成功(业务验证页)”,即部署正常
| 问题现象 | 根因分析 | 解决方案 |
|---|---|---|
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ||
| HAProxy在master2/master3启动失败 | HAProxy绑定VIP(192.168.1.200),备节点未获取VIP,导致绑定失败 | HAProxy配置中bind改为0.0.0.0:16443和0.0.0.0:80,由Keepalived管理VIP漂移,重启HAProxy即可 |
| - | - | - |
| 访问http://zhongts.tech出现404 | 1. Ingress缺少ingressClassName配置;2. Ingress后端Service名称/端口不匹配;3. 业务Pod未正常运行 | 1. 确保Ingress配置中ingressClassName: nginx;2. 核对Service名称为nginx-web-svc、端口80;3. 执行kubectl get pods -n web,确保Pod状态为Running |
| containerd拉取镜像超时 | 1. 代理端口配置错误(未改为20171);2. 代理服务器未正常运行;3. NO_PROXY配置错误 | 1. 核对containerd代理配置,确保端口为20171;2. 检查192.168.1.119:20171是否可访问;3. 确保NO_PROXY包含192.168.1.0/24 |
| kubelet启动失败 | containerd的cgroup驱动未开启(SystemdCgroup=false),与kubelet驱动不匹配 | 重新执行sed命令开启cgroup驱动,重启containerd和kubelet:systemctl restart containerd kubelet |
| Keepalived VIP不漂移(master1故障后,VIP未切换到master2) | 1. 主备节点priority优先级配置错误;2. 主备节点auth_pass不一致;3. 心跳未正常通信 | 1. 确保master1=100、master2=90、master3=80;2. 核对所有节点auth_pass=1111;3. 检查节点间179端口互通,重启Keepalived |
| Calico Pod启动失败 | Pod网段与Calico默认网段不匹配,或内核参数未生效 | 确保集群初始化时--pod-network-cidr=10.244.0.0/16,重新执行sysctl --system,重启Calico Pod:kubectl delete pods -n kube-system -l k8s-app=calico-node |