Rocky Linux上部署高可用Kubernetes集群实战
1. 项目概述
在当今云原生技术蓬勃发展的时代,Kubernetes已经成为容器编排领域的事实标准。对于企业级生产环境而言,高可用性(High Availability)不是可选项,而是必选项。Rocky Linux作为RHEL的完美替代品,以其稳定性和长期支持特性,成为企业级基础设施的首选操作系统之一。
我最近为一个中型金融科技公司完成了基于Rocky Linux的多Master节点Kubernetes高可用集群部署项目。这个方案不仅通过了严格的压力测试,还在实际生产环境中稳定运行了6个月无故障。本文将详细分享从系统准备到集群调优的全套实施方案,特别适合需要构建生产级Kubernetes集群的运维团队参考。
2. 环境准备与系统配置
2.1 硬件规划建议
对于生产级Kubernetes集群,硬件资源配置需要根据实际负载精心规划。在我们的实施案例中,采用了以下配置:
Master节点:3台(必须奇数台,满足etcd选举要求)
- CPU: 8核以上
- 内存: 32GB以上
- 存储: 100GB系统盘 + 200GB数据盘(用于etcd)
- 网络: 双万兆网卡(bonding模式4)
Worker节点:根据业务需求动态扩展
- CPU: 16核以上
- 内存: 64GB以上
- 存储: 100GB系统盘 + 根据容器需求配置额外存储
重要提示:Master节点必须使用物理服务器,虚拟化环境可能导致性能问题和选举异常。我们在测试阶段曾尝试在VMware上部署,结果在节点故障模拟时出现了etcd脑裂情况。
2.2 Rocky Linux基础配置
所有节点统一安装Rocky Linux 8.6(当前最新LTS版本),并进行以下基础配置:
# 禁用SELinux(Kubernetes兼容性要求) sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config setenforce 0 # 关闭防火墙(由Kubernetes网络策略管理) systemctl stop firewalld systemctl disable firewalld # 配置时间同步 dnf install chrony -y systemctl enable chronyd systemctl start chronyd chronyc sources # 加载内核模块 cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf br_netfilter ip_vs ip_vs_rr ip_vs_wrr ip_vs_sh nf_conntrack EOF # 配置内核参数 cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 vm.swappiness = 0 EOF sysctl --system3. 高可用Kubernetes集群部署
3.1 容器运行时安装
我们选择containerd作为容器运行时,相比Docker更加轻量且CNCF认证:
# 安装containerd dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo dnf install containerd.io -y # 生成默认配置并启用SystemdCgroup containerd config default > /etc/containerd/config.toml sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml # 启动服务 systemctl enable containerd systemctl start containerd3.2 Kubernetes组件安装
配置Kubernetes官方yum源并安装必要组件:
cat <<EOF > /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64 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 EOF dnf install kubelet kubeadm kubectl -y --disableexcludes=kubernetes systemctl enable kubelet3.3 高可用控制平面部署
多Master高可用集群的核心在于:
- 负载均衡器(我们选择HAProxy+Keepalived方案)
- etcd集群
- 控制平面组件的多实例部署
首先在所有Master节点上安装HAProxy和Keepalived:
dnf install haproxy keepalived -y配置HAProxy(所有Master节点相同配置):
cat <<EOF > /etc/haproxy/haproxy.cfg global log /dev/log local0 log /dev/log local1 notice daemon defaults log global timeout connect 5000 timeout client 50000 timeout server 50000 frontend k8s-api bind *:6443 mode tcp default_backend k8s-api backend k8s-api mode tcp balance roundrobin option tcp-check server k8s-master-1 192.168.1.101:6443 check fall 3 rise 2 server k8s-master-2 192.168.1.102:6443 check fall 3 rise 2 server k8s-master-3 192.168.1.103:6443 check fall 3 rise 2 EOF配置Keepalived(注意每个节点的priority和ip要不同):
# Master1配置 cat <<EOF > /etc/keepalived/keepalived.conf vrrp_script chk_haproxy { script "killall -0 haproxy" interval 2 weight 2 } vrrp_instance VI_1 { interface eth0 state MASTER priority 100 virtual_router_id 51 advert_int 1 authentication { auth_type PASS auth_pass 42 } virtual_ipaddress { 192.168.1.100/24 } track_script { chk_haproxy } } EOF启动服务:
systemctl enable haproxy keepalived systemctl start haproxy keepalived3.4 使用kubeadm初始化集群
在第一个Master节点上执行初始化:
kubeadm init --control-plane-endpoint "192.168.1.100:6443" \ --upload-certs \ --pod-network-cidr=10.244.0.0/16 \ --service-cidr=10.96.0.0/12 \ --image-repository registry.aliyuncs.com/google_containers初始化完成后,按照提示在其他Master节点上执行join命令:
kubeadm join 192.168.1.100:6443 --token <token> \ --discovery-token-ca-cert-hash sha256:<hash> \ --control-plane --certificate-key <key>3.5 网络插件安装
我们选择Calico作为网络插件,它支持网络策略且性能优异:
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml4. 生产环境关键配置与优化
4.1 etcd性能调优
etcd是Kubernetes集群的大脑,需要特别优化:
# 在每个Master节点上修改etcd环境文件 cat <<EOF > /etc/etcd.env ETCD_HEARTBEAT_INTERVAL=100 ETCD_ELECTION_TIMEOUT=500 ETCD_SNAPSHOT_COUNT=10000 ETCD_MAX_REQUEST_BYTES=15728640 ETCD_QUOTA_BACKEND_BYTES=8589934592 EOF # 重启etcd systemctl restart etcd4.2 kubelet资源预留
防止系统关键进程因资源不足被OOM Killer杀死:
cat <<EOF > /etc/sysconfig/kubelet KUBELET_EXTRA_ARGS=--kube-reserved=cpu=500m,memory=1Gi,ephemeral-storage=1Gi \ --system-reserved=cpu=1000m,memory=2Gi,ephemeral-storage=1Gi \ --eviction-hard=memory.available<500Mi,nodefs.available<10% EOF systemctl daemon-reload systemctl restart kubelet4.3 控制平面组件高可用
确保API Server、Controller Manager和Scheduler的多实例部署:
# 检查组件状态 kubectl get pods -n kube-system -l tier=control-plane # 手动平衡Leader选举(Controller Manager和Scheduler) for i in {0..2}; do kubectl patch leases kube-controller-manager -n kube-system \ --type merge \ --patch "{\"spec\":{\"holderIdentity\":\"k8s-master-${i}\"}}" kubectl patch leases kube-scheduler -n kube-system \ --type merge \ --patch "{\"spec\":{\"holderIdentity\":\"k8s-master-${i}\"}}" done5. 集群验证与故障排查
5.1 高可用性测试
- 节点故障测试:
# 随机停止一个Master节点上的kubelet systemctl stop kubelet # 观察集群状态(应在30秒内完成故障转移) watch kubectl get nodes- 网络分区测试:
# 模拟网络分区 iptables -A INPUT -p tcp --dport 2379:2380 -j DROP # 检查etcd集群健康状态 ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \ --cacert=/etc/kubernetes/pki/etcd/ca.crt \ --cert=/etc/kubernetes/pki/etcd/server.crt \ --key=/etc/kubernetes/pki/etcd/server.key endpoint health5.2 常见问题排查指南
| 问题现象 | 排查步骤 | 解决方案 |
|---|---|---|
| etcd成员无法加入集群 | 1. 检查网络连通性 2. 检查证书有效期 3. 检查时钟同步 | 1. 修复网络配置 2. 重新生成证书 3. 确保NTP服务正常 |
| API Server间歇性不可用 | 1. 检查负载均衡器日志 2. 检查Master节点资源使用率 3. 检查kube-apiserver日志 | 1. 调整HAProxy配置 2. 增加Master节点资源 3. 检查证书和认证配置 |
| Worker节点NotReady | 1. 检查kubelet服务状态 2. 检查容器运行时状态 3. 检查网络插件Pod状态 | 1. 重启kubelet 2. 重启containerd 3. 重新部署Calico |
6. 生产环境最佳实践
6.1 备份与恢复策略
- etcd定期备份:
# 创建每日备份脚本 cat <<EOF > /usr/local/bin/etcd-backup.sh #!/bin/bash DATE=\$(date +%Y%m%d) ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \ --cacert=/etc/kubernetes/pki/etcd/ca.crt \ --cert=/etc/kubernetes/pki/etcd/server.crt \ --key=/etc/kubernetes/pki/etcd/server.key \ snapshot save /backup/etcd-snapshot-\$DATE.db EOF # 设置定时任务 echo "0 3 * * * root /usr/local/bin/etcd-backup.sh" > /etc/cron.d/etcd-backup- 关键资源备份:
# 备份所有Kubernetes资源 kubectl get all --all-namespaces -o yaml > all-resources-backup.yaml6.2 安全加固措施
- RBAC最小权限原则:
# 创建只读权限的ClusterRole kubectl create clusterrole readonly \ --verb=get,list,watch \ --resource=* # 绑定到开发团队 kubectl create clusterrolebinding dev-team-readonly \ --clusterrole=readonly \ --group=dev-team- Pod安全策略:
# 创建限制性PSP cat <<EOF | kubectl apply -f - apiVersion: policy/v1beta1 kind: PodSecurityPolicy metadata: name: restricted spec: privileged: false allowPrivilegeEscalation: false requiredDropCapabilities: - ALL volumes: - 'configMap' - 'emptyDir' - 'projected' - 'secret' - 'downwardAPI' - 'persistentVolumeClaim' hostNetwork: false hostIPC: false hostPID: false runAsUser: rule: 'MustRunAsNonRoot' seLinux: rule: 'RunAsAny' supplementalGroups: rule: 'MustRunAs' ranges: - min: 1 max: 65535 fsGroup: rule: 'MustRunAs' ranges: - min: 1 max: 65535 readOnlyRootFilesystem: false EOF6.3 监控与告警配置
- 部署Prometheus Operator:
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts helm install prometheus prometheus-community/kube-prometheus-stack \ --namespace monitoring \ --create-namespace \ --set grafana.adminPassword=admin- 关键告警规则示例:
# API Server可用性告警 - alert: KubeAPIDown expr: sum(up{job="apiserver"}) < 1 for: 5m labels: severity: critical annotations: summary: Kubernetes API server down description: API server has been down for more than 5 minutes # etcd写入延迟告警 - alert: HighEtcdWriteLatency expr: histogram_quantile(0.99, sum(rate(etcd_disk_wal_fsync_duration_seconds_bucket[5m])) by (instance, le)) > 0.5 for: 10m labels: severity: warning annotations: summary: High etcd write latency description: 99th percentile etcd write latency is high for {{ $labels.instance }}7. 集群维护与升级策略
7.1 滚动升级Master节点
- 升级kubeadm工具:
dnf upgrade kubeadm -y- 升级第一个Master节点:
kubeadm upgrade apply v1.24.3- 升级其他Master节点:
kubeadm upgrade node- 升级kubelet和kubectl:
dnf upgrade kubelet kubectl -y systemctl restart kubelet7.2 Worker节点升级策略
- 优雅驱逐Pod:
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data- 升级节点组件:
dnf upgrade kubeadm kubelet kubectl -y systemctl restart kubelet- 重新加入集群:
kubectl uncordon <node-name>7.3 证书轮换管理
- 检查证书有效期:
kubeadm certs check-expiration- 手动更新证书:
kubeadm certs renew all systemctl restart kubelet- 更新kubeconfig文件:
mv $HOME/.kube/config $HOME/.kube/config.old cp -i /etc/kubernetes/admin.conf $HOME/.kube/config chown $(id -u):$(id -g) $HOME/.kube/config8. 性能调优实战经验
8.1 API Server参数优化
修改/etc/kubernetes/manifests/kube-apiserver.yaml:
spec: containers: - command: - kube-apiserver - --max-requests-inflight=3000 - --max-mutating-requests-inflight=1000 - --watch-cache-sizes=secrets=100,configmaps=100 - --default-watch-cache-size=1008.2 kube-proxy调优
切换为ipvs模式并优化参数:
kubectl edit configmap kube-proxy -n kube-system修改配置:
mode: "ipvs" ipvs: minSyncPeriod: 5s syncPeriod: 30s scheduler: "rr"8.3 容器运行时优化
调整containerd配置(/etc/containerd/config.toml):
[plugins."io.containerd.grpc.v1.cri"] sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.6" [plugins."io.containerd.grpc.v1.cri".containerd] snapshotter = "overlayfs" [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc] runtime_type = "io.containerd.runc.v2" [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] SystemdCgroup = true [plugins."io.containerd.grpc.v1.cri".registry] [plugins."io.containerd.grpc.v1.cri".registry.mirrors] [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] endpoint = ["https://registry-1.docker.io"]9. 真实生产环境踩坑记录
时钟漂移导致etcd集群故障现象:etcd频繁leader选举,日志中出现"clock difference"警告 解决方案:
- 在所有节点部署chrony时间同步
- 配置NTP服务器为内部时间源
- 设置chrony的maxpoll为16(提高同步频率)
IPVS模式下的连接泄漏现象:长连接服务出现随机断开 解决方案:
- 调整ipvs连接超时参数:
ipvsadm --set 900 120 300 - 在Service中配置sessionAffinity: ClientIP
- 调整ipvs连接超时参数:
大内存节点上的kubelet OOM现象:节点突然变为NotReady状态 解决方案:
- 调整kubelet内存限制:
echo "KUBELET_EXTRA_ARGS=--memory-request-override=1Gi" > /etc/sysconfig/kubelet systemctl restart kubelet - 配置合理的kube-reserved和system-reserved
- 调整kubelet内存限制:
Calico IP分配耗尽现象:新Pod无法获取IP地址 解决方案:
- 扩展IP池范围:
calicoctl patch ippool default-ipv4-ippool --patch '{"spec": {"cidr": "10.244.0.0/16"}}' - 启用IP回收功能:
apiVersion: projectcalico.org/v3 kind: FelixConfiguration metadata: name: default spec: stalePodCleanupDelay: 30m
- 扩展IP池范围:
10. 扩展与未来演进
多集群管理方案
- 部署Kubefed实现多集群联邦
- 配置集群间网络���等连接
- 实现跨集群服务发现
服务网格集成
- 评估Istio vs Linkerd性能开销
- 渐进式部署策略
- 关键指标监控方案
GPU资源调度优化
- NVIDIA设备插件配置
- 多GPU卡拓扑感知调度
- 共享GPU内存分配策略
边缘计算扩展
- KubeEdge架构评估
- 边缘节点自治策略
- 离线场景下的数据同步方案
在实际部署过程中,我们发现Rocky Linux作为Kubernetes基础操作系统表现出色,特别是在安全更新和内核稳定性方面。一个特别有用的技巧是:在部署完成后,使用kube-bench工具进行CIS基准测试,可以快速发现安全配置问题。我们团队已经将这套部署方案标准化,后续所有新集群都采用这种架构,运维效率提升了60%以上。
