news 2026/9/22 21:10:07

Linux集群搭建踩坑实录:3步搞定高可用完整示例

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux集群搭建踩坑实录:3步搞定高可用完整示例

Linux集群搭建踩坑实录:3步搞定高可用完整示例

刚把K8s从v1.24升到v1.28,我盯着终端里满屏的unknown flag: --insecure-portapiVersion "v1" not found,脑子嗡的一声:版本升级后 API 全变了。

别慌,这种“升级即崩溃”的噩梦,90%是因为没理清底层依赖。今天不讲虚的,直接上我压箱底的linux集群搭建实战方案。这不是一篇泛泛而谈的教程,而是一套经过生产环境验证的完整示例,专治各种“环境不一致”疑难杂症。

项目目标与环境规划

在敲第一行命令前,先明确我们要构建什么。本次目标不是简单的“跑起来”,而是构建一个高可用、可复现、易于维护的3节点Linux集群(1 Master + 2 Worker)。

很多新手喜欢用Docker直接拉镜像,但在生产级集群搭建中,裸机或VMware虚拟机的二进制安装方式更稳定,且能深入理解组件交互。我们基于CentOS 7.9(RHEL兼容系)进行演示,因为企业存量机器中,CentOS占比依然极高。

核心指标定义:

  • 高可用:Master节点故障时,集群自动切换;Worker节点宕机,Pod自动迁移。
  • 网络隔离:Pod网络与主机网络隔离,使用Calico CNI实现跨节点通信。
  • 持久化存储:本地PV绑定,确保数据不随Pod重建丢失。

硬件与网络规划表:

节点角色 IP地址 主机名 CPU/内存 职责描述
Master 192.168.10.11 k8s-master 2C/4G 控制平面:kube-apiserver, etcd
Worker1 192.168.10.12 k8s-worker1 2C/4G 工作节点:运行业务Pod
Worker2 192.168.10.13 k8s-worker2 2C/4G 工作节点:运行业务Pod

关键前提: 所有节点必须关闭防火墙和SELinux,这是集群通信的基础。如果忽略这一步,后续排查网络不通的问题会浪费你至少半天时间。

# 所有节点执行
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config

目录结构与基础依赖初始化

在开始安装K8s组件前,我们需要搭建一个标准的目录结构。良好的目录规划是后续运维的基石,避免配置文件散落在系统各处。

标准目录规划:

  • /opt/k8s/:存放所有K8s二进制文件(kubectl, kube-apiserver, kubelet等)。
  • /etc/kubernetes/:存放所有YAML配置文件和证书。
  • /var/lib/kubelet/:kubelet的工作目录。
  • /var/lib/etcd/:etcd的数据存储目录(仅Master节点)。

第一步:安装Container Runtime

K8s 1.28已移除Docker作为默认运行时,转向Containerd。这里我们使用Containerd 1.7.x版本。

# 1. 下载Containerd二进制包 (以1.7.11为例)
cd /opt
wget https://github.com/containerd/containerd/releases/download/v1.7.11/containerd-1.7.11-linux-amd64.tar.gz
tar -zxvf containerd-1.7.11-linux-amd64.tar.gz
cp bin/containerd* /usr/local/bin/# 2. 初始化Containerd配置
containerd config default > /etc/containerd/config.toml# 3. 关键修改:启用systemd cgroup driver
# 编辑 /etc/containerd/config.toml
# 找到 [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
# 添加或修改: SystemdCgroup = true

为什么必须改SystemdCgroup? Kubelet默认使用Systemd作为cgroup driver,而Containerd默认是cgroupfs。两者不一致会导致Pod启动失败,报错failed to create shim task: OCI runtime create failed。这是我在生产环境中遇到的最高频报错之一。

第二步:安装Kubernetes二进制文件

这里我选择从官方源码仓库发布的二进制包,而不是使用yum源。原因有二:

  1. yum源中的K8s包版本更新滞后,且经常与特定Linux内核版本存在兼容性问题。
  2. 二进制安装允许我们精确控制版本,便于灰度升级和回滚。
# 1. 创建K8s安装目录
mkdir -p /opt/k8s && cd /opt/k8s# 2. 下载指定版本 (以1.28.3为例,需与etcd版本匹配)
# 注意:请根据实际网络情况选择镜像源,此处以GitHub为例
wget https://dl.k8s.io/v1.28.3/kubernetes-server-linux-amd64.tar.gz
tar -zxvf kubernetes-server-linux-amd64.tar.gz
cp kubernetes/server/bin/* /opt/k8s/
chmod +x /opt/k8s/*# 3. 添加环境变量
echo 'export PATH=$PATH:/opt/k8s' >> /etc/profile
source /etc/profile

验证安装: 执行kubectl version --client,如果输出版本信息,说明二进制文件安装成功。此时不要高兴太早,这只是客户端工具,服务端还没配置。

核心代码实现:Master节点初始化

Master节点是集群的大脑,负责存储集群状态、调度Pod、处理API请求。核心组件包括kube-apiserverkube-schedulerkube-controller-manageretcd

1. 生成ETCD证书

ETCD是K8s的唯一数据源,安全性至关重要。我们需要为ETCD生成CA、Server和Client证书。

# 安装cfssl工具
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
mv cfssl_linux-amd64 /usr/local/bin/cfssl
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
mv cfssljson_linux-amd64 /usr/local/bin/cfssljson# 创建证书目录
mkdir -p /etc/kubernetes/ssl && cd /etc/kubernetes/ssl# 生成CA证书
cat > ca-config.json <<EOF
{"signing": {"default": {"usages": ["signing", "key encipherment", "server auth", "client auth"],"expiry": "87600h"}}
}
EOFcat > ca-csr.json <<EOF
{"CN": "k8s","key": {"algo": "rsa","size": 2048},"names": [{"C": "CN","ST": "Beijing","L": "Beijing","O": "k8s","OU": "System"}]
}
EOFcfssl gencert -ca=ca-csr.json -cakey=ca-key.pem -config=ca-config.json -profile=kubernetes ca-csr.json | cfssljson -bare ca

2. 生成ETCD Server证书

# 生成Server证书,SAN需包含Master IP和主机名
cat > etcd-csr.json <<EOF
{"CN": "etcd","hosts": ["192.168.10.11","k8s-master","127.0.0.1"],"key": {"algo": "rsa","size": 2048},"names": [{"C": "CN","ST": "Beijing","L": "Beijing","O": "k8s","OU": "System"}]
}
EOFcfssl gencert -ca=ca.pem -cakey=ca-key.pem -config=ca-config.json -profile=kubernetes etcd-csr.json | cfssljson -bare etcd

3. 生成Kubernetes组件证书

这里有一个高频踩坑点kube-apiserver的证书SAN中,必须包含所有可能访问API Server的IP和域名,包括Master IP、Node IP、Service CIDR网段、Pod CIDR网段。漏掉任何一个,都会导致对应的组件无法连接API Server。

# 生成kube-apiserver证书
cat > kubernetes-csr.json <<EOF
{"CN": "kube-apiserver","hosts": ["127.0.0.1","192.168.10.11","192.168.10.12","192.168.10.13","10.0.0.1","kubernetes","kubernetes.default","kubernetes.default.svc","kubernetes.default.svc.cluster","10.0.0.1"],"key": {"algo": "rsa","size": 2048},"names": [{"C": "CN","ST": "Beijing","L": "Beijing","O": "k8s","OU": "System"}]
}
EOFcfssl gencert -ca=ca.pem -cakey=ca-key.pem -config=ca-config.json -profile=kubernetes kubernetes-csr.json | cfssljson -bare kube-apiserver

4. 配置Kubelet

Kubelet是每个节点上的代理,负责管理Pod的生命周期。我们需要为每个节点生成独立的Kubelet证书,因为Kubelet需要通过证书向API Server注册节点。

# 在Master节点上,为Worker1生成Kubelet证书
# 注意:CN必须是node,O必须是system:nodes,这是K8s内置的RBAC规则要求
cat > worker1-kubelet-csr.json <<EOF
{"CN": "node","hosts": ["192.168.10.12"],"key": {"algo": "rsa","size": 2048},"names": [{"C": "CN","ST": "Beijing","L": "Beijing","O": "system:nodes","OU": "System"}]
}
EOFcfssl gencert -ca=ca.pem -cakey=ca-key.pem -config=ca-config.json -profile=kubernetes worker1-kubelet-csr.json | cfssljson -bare worker1-kubelet

5. 启动ETCD

ETCD是集群状态的数据源,必须确保其数据持久化且配置正确。

# 创建systemd服务文件
cat > /etc/systemd/system/etcd.service <<EOF
[Unit]
Description=etcd
Documentation=https://github.com/etcd-io/etcd[Service]
Type=notify
User=etcd
ExecStart=/opt/k8s/etcd \--name k8s-master \--cert-file=/etc/kubernetes/ssl/etcd.pem \--key-file=/etc/kubernetes/ssl/etcd-key.pem \--peer-cert-file=/etc/kubernetes/ssl/etcd.pem \--peer-key-file=/etc/kubernetes/ssl/etcd-key.pem \--trusted-ca-file=/etc/kubernetes/ssl/ca.pem \--peer-trusted-ca-file=/etc/kubernetes/ssl/ca.pem \--initial-advertise-peer-urls https://192.168.10.11:2380 \--listen-peer-urls https://192.168.10.11:2380 \--advertise-client-urls https://192.168.10.11:2379 \--listen-client-urls https://192.168.10.11:2379 \--initial-cluster k8s-master=https://192.168.10.11:2380 \--initial-cluster-token etcd-k8s-initial-cluster \--initial-cluster-state new \--data-dir=/var/lib/etcd
Restart=on-failure
RestartSec=5
LimitNOFILE=65536[Install]
WantedBy=multi-user.target
EOF# 创建etcd用户和目录
useradd -ms /sbin/nologin -U etcd
mkdir -p /var/lib/etcd && chown etcd:etcd /var/lib/etcd# 启动ETCD
systemctl daemon-reload
systemctl start etcd
systemctl enable etcd

验证ETCD状态:

/opt/k8s/etcdctl --endpoints=https://127.0.0.1:2379 \--cacert=/etc/kubernetes/ssl/ca.pem \--cert=/etc/kubernetes/ssl/etcd.pem \--key=/etc/kubernetes/ssl/etcd-key.pem \endpoint health

如果返回{"health":true,...},说明ETCD工作正常。

运行与测试:Worker节点加入集群

Master节点配置完成后,我们需要将Worker节点加入集群。Worker节点不需要运行ETCD和调度器,只需运行kubeletkube-proxy

1. 分发证书

将Master节点上生成的CA证书和Worker节点专用的Kubelet证书复制到Worker节点。

# 在Master节点执行
scp /etc/kubernetes/ssl/ca.pem /etc/kubernetes/ssl/ca-key.pem \/etc/kubernetes/ssl/worker1-kubelet.pem \/etc/kubernetes/ssl/worker1-kubelet-key.pem \root@192.168.10.12:/etc/kubernetes/ssl/

2. 配置Kubelet

Kubelet的配置文件kubelet-config.yaml是关键。这里有一个版本升级后的重大变化apiVersionv1变为了v1beta1,且部分字段名称发生了改变。

# /etc/kubernetes/kubelet-config.yaml
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
address: 0.0.0.0
authentication:anonymous:enabled: falsewebhook:cacheTTL: 2m0senabled: truex509:clientCAFile: /etc/kubernetes/ssl/ca.pem
authorization:mode: Webhookwebhook:cacheAuthorizedTTL: 10m0scacheUnauthorizedTTL: 2m0s
cgroupDriver: systemd
clusterDNS:- 10.0.0.10
clusterDomain: cluster.local
evictionHard:imagefs.available: 10%memory.available: 100Minodefs.available: 10%nodefs.inodesFree: 5%
maxPods: 110
rotateCertificates: true
serverTLSBootstrap: true

3. 启动Kubelet

# 创建systemd服务文件
cat > /etc/systemd/system/kubelet.service <<EOF
[Unit]
Description=Kubelet
After=network.target
After=docker.service[Service]
WorkingDirectory=/var/lib/kubelet
ExecStart=/opt/k8s/kubelet \--config=/etc/kubernetes/kubelet-config.yaml \--kubeconfig=/etc/kubernetes/kubelet-kubeconfig.yaml \--container-runtime-endpoint=unix:///run/containerd/containerd.sock
Restart=on-failure
RestartSec=5[Install]
WantedBy=multi-user.target
EOFsystemctl daemon-reload
systemctl start kubelet
systemctl enable kubelet

4. 验证节点状态

在Master节点上执行:

kubectl get nodes

如果看到k8s-worker1状态为Ready,说明Worker节点成功加入集群。

常见报错排查:

  • node.k8s.io not found:检查Kubelet证书是否正确,O字段是否为system:nodes
  • failed to get node info:检查API Server证书SAN中是否包含Worker节点IP。
  • container runtime is down:检查Containerd服务是否启动,以及SystemdCgroup配置是否一致。

优化扩展:网络与存储配置

集群节点加入后,还需要配置Pod网络(CNI)和Service网络,否则Pod之间无法通信。

1. 安装Calico CNI

Calico是K8s中最流行的CNI插件之一,支持BGP路由,性能优异。

# 下载Calico配置
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml

2. 配置Service网络

K8s的Service IP范围是虚拟的,需要确保不与Pod网络冲突。我们使用10.96.0.0/12作为Service CIDR。

3. 性能优化建议

  • Kubelet内存限制:在生产环境中,建议为Kubelet设置内存限制,防止其OOM导致节点失联。
  • ETCD磁盘IO:ETCD对磁盘IO敏感,建议使用SSD,并设置fsync参数为true,确保数据持久化。
  • 日志轮转:K8s组件日志会迅速增长,建议配置Logrotate,避免磁盘写满。
# /etc/logrotate.d/kubernetes
/opt/k8s/*.log {dailymissingokrotate 7compressdelaycompressnotifemptycreate 0640 root rootsharedscriptspostrotate/opt/k8s/kubelet --config=/etc/kubernetes/kubelet-config.yamlendscript
}

4. 监控与告警

裸机集群搭建后,建议接入Prometheus + Grafana进行监控。至少监控以下指标:

  • Node CPU/Memory/磁盘使用率
  • Pod重启次数
  • ETCD集群健康状态
  • API Server请求延迟

小结

本文提供了一套从零开始、基于二进制安装的linux集群搭建完整示例。我们不仅完成了基础环境的初始化,还深入讲解了证书生成、Kubelet配置、CNI安装等核心环节。

关键回顾:

  1. 版本一致性:Kubelet、Kube-apiserver、Kubectl版本必须一致或相差一个次版本。
  2. cgroup驱动统一:Containerd和Kubelet必须使用相同的cgroup driver(推荐systemd)。
  3. 证书SAN配置:API Server证书的SAN必须包含所有可能的访问IP和域名,这是通信正常的关键。
  4. 官方源码仓库:在版本升级或遇到未知Bug时,查阅官方源码仓库和Release Notes是解决问题的最快路径,不要依赖过时的博客教程。

集群搭建只是第一步,真正的挑战在于后续的运维、升级和故障排查。版本升级后API全变是常态,保持对官方文档的持续关注,才是避免踩坑的根本。

你在项目里踩过这个坑吗?评论区聊聊

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/22 21:10:04

搞懂问世底层逻辑:3个完整示例彻底解决代码跑不通难题

搞懂问世底层逻辑:3个完整示例彻底解决代码跑不通难题 你是不是也遇到过这种情况:网上复制了一段“问世”相关的核心逻辑代码,或者照着某篇教程敲了一个完整示例,结果一运行就报错,或者跑起来完全不是预期那样?别慌,这不是你代码写得烂,而是你没看懂底层数据是怎么流转的。很多新手卡在“问世”这个概念上,觉得它…

作者头像 李华
网站建设 2026/9/22 21:10:00

麦创网实战项目复盘:3个核心考点助你面试通关

麦创网实战项目复盘:3个核心考点助你面试通关 面试官问:“讲一下你做的麦创网相关实战项目,底层原理是什么?” 你脑子一片空白,支支吾吾答不出,直接凉凉。 别慌,今天把麦创网核心考点掰开了揉碎了讲,保你下次面试稳过。 考点梳理:面试高频雷区…

作者头像 李华
网站建设 2026/9/22 21:09:30

中企动力销售好做吗:3个源码解析级坑点揭秘

中企动力销售好做吗:3个源码解析级坑点揭秘 别再被“官方文档太长抓不住重点”折磨了。很多人搜【中企动力销售好做吗】,其实是想搞清楚这行到底能不能混口饭吃,或者自己开发的获客工具是不是在裸奔。咱们不聊虚的,直接上【源码解析】。…

作者头像 李华
网站建设 2026/9/22 21:09:27

3个坑让渲染慢10倍?图解方正显仁简体字体性能优化原理

3个坑让渲染慢10倍?图解方正显仁简体字体性能优化原理 上周帮朋友看项目日志,他抓狂:“这破字体加载怎么这么卡?” 面试被问原理答不上来,现场直接懵圈。 别慌,今天用图解原理拆解方正显仁简体在Web端的性能瓶颈。 一、 性能瓶颈:为什么你的页面在“假死” 很多前端同学以为字体慢是网络问题,其实…

作者头像 李华
网站建设 2026/9/22 21:09:03

冰点还原精灵实战:3步搞定环境卡死,最佳实践全解析

冰点还原精灵实战:3步搞定环境卡死,最佳实践全解析 配置环境就卡半天,重启十次还是报错?别急着重装系统。做开发这几年,我见过太多人因为一个依赖冲突、一个端口占用或者一个权限问题,在“冰点还原精灵”这类底层恢复工具或类似的环境重置场景中,浪费了整整一下午。其实,解决这种“死局”并不需要玄学,而是需要一…

作者头像 李华
网站建设 2026/9/22 21:08:55

3步搞定中国移动路由器设置,源码级拆解实战项目配置

3步搞定中国移动路由器设置,源码级拆解实战项目配置 刚接手运维工作,面对中国移动定制路由器,你是不是也懵了?看着后台一堆中文菜单,改个IP不知道会不会断网,配个VLAN不敢下手。很多初学者觉得,只要会敲几行命令就能搞掂,但一上实战项目就露馅。学会基础语法,却不知怎么搭起稳定的网络环境,这是大多数新人…

作者头像 李华