news 2026/10/22 15:20:21

kubeadm实战:从零搭建Kubernetes v1.30.3集群全指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
kubeadm实战:从零搭建Kubernetes v1.30.3集群全指南

2. 容器运行时:1.28 之后的硬前提

3. 控制平面组件:从 etcd 到 apiserver 的角色梳理

4. kubeadm init:初始化控制平面的完整实操

5. 工作节点加入:从 token 到 CNI 的全链路

6. 高可用与证书续期:别等集群挂了才想起来

7. 常见问题与避坑实录

8. 写在最后:我的个人体会与后续扩展建议


2. 容器运行时:1.28 之后的硬前提

先说一个很多人踩过的坑:K8s 从 1.24 开始正式移除对 Docker 直接作为运行时(Dockershim)的支持,到了 1.28 之后,容器运行时接口(CRI)是唯一标准路径。也就是说,你装 v1.30.3 的时候,必须要有一个符合 CRI 规范的运行时,否则 kubelet 根本起不来。

当前最主流的选择是 containerd。它比早期的 Docker + dockershim 方案更轻,资源占用更小,而且和 K8s 的 CRI 集成是原生的。很多新手会问:那我直接装 Docker 不行吗?行,但 Docker 默认不带 CRI 插件,你还得额外装 cri-dockerd 适配器,纯属给自己加戏。除非你的业务有强依赖 Docker 打包链路,否则没必要绕这一圈。

安装 containerd 时,有几个细节特别容易出错:

第一,containerd 的默认配置里 cri 插件是未启用的。你得先执行containerd config default > /etc/containerd/config.toml生成默认配置,然后检查[plugins."io.containerd.grpc.v1.cri"]这一段,确认sandbox_image指向的是你能访问的镜像源。国内环境建议改成registry.aliyuncs.com/google_containers/pause:3.9这类镜像,不然拉 pause 镜像时会被卡住,节点会反复报SandboxChanged。

第二,SystemdCgroup 必须打开。在生成的配置里找到SystemdCgroup,确保它是true。这个参数的作用是让 containerd 使用 systemd 来管理 cgroup,和 kubelet 的 cgroup 驱动保持一致。如果这里配错了,kubelet 启动后大概率报failed to run Kubelet: failed to validate kubelet config,排查起来很浪费时间。

第三,网络插件 CNI 的 bin 目录要提前备好。containerd 默认的 CNI 配置目录是/etc/cni/net.d,插件二进制目录是/opt/cni/bin。如果你是离线安装或者内网环境,记得把 flannel、calico 或 cilium 的二进制文件提前解压到/opt/cni/bin里。否则后面创建 Pod 的时候会发现 Pod 一直处于ContainerCreating,原因是无法初始化网络。

第四,确认 containerd 的版本和 K8s 的兼容性。v1.30.3 要求 containerd 版本至少是 1.7.x 以上,建议直接用 1.7 系列的较新小版本。1.6.x 也能跑,但我实测下来会有一些 minor bug,比如偶尔出现容器退出后清理不及时的问题。省心一点,直接上 1.7。

做完这些之后,用ctr version和crictl version都能正常输出版本信息,就说明运行时这块没问题了。这个阶段千万不要急,运行时配错是集群起不来的第一大元凶,我见过太多人卡在这一步整整一天。

3. 控制平面组件:从 etcd 到 apiserver 的角色梳理

很多人一说到 K8s 集群,脑子里就是"一堆节点跑容器",但实际控制平面到底在做什么,很少有人能一次讲清楚。用我自己折腾这么多集群的经验来打个比方:控制平面就像一家公司的管理层,etcd 是公司的账本,apiserver 是前台接待,scheduler 是排班经理,controller-manager 是监督各部门干活的督查。

先看etcd。它是整个集群的唯一数据存储,所有资源对象的状态,比如 Pod 在哪个节点、Service 的地址是什么、命名空间里有哪些对象,全部存在 etcd 里。etcd 挂了,K8s 集群就失去记忆了。所以在生产环境里,etcd 的高可用比控制平面其他组件都重要。kubeadm 在初始化多控制平面节点时,会自动帮你配置 etcd 的静态 Pod 集群模式,但如果只是单控制平面节点,etcd 就是一个独立的静态 Pod,数据目录默认在/var/lib/etcd。

接着是kube-apiserver。它是所有请求的唯一入口,无论是kubectl命令、调度器、控制器,还是 kubelet 的心跳上报,都必须经过 apiserver。apiserver 本身不做业务计算,它只做一件事:验证请求的合法性,然后把状态写入 etcd。所以 apiserver 的性能瓶颈通常都在于 etcd 的读写延迟,而不在自身。

kube-scheduler负责决定新创建的 Pod 要跑到哪个节点上。它通过一系列过滤和打分机制,比如节点资源是否充足、是否有污点、Pod 是否有亲和性要求,最终选出一个最优节点。这个组件平时不怎么出问题,但如果你发现 Pod 一直 Pending,大概率就是 scheduler 找不到合适的节点。

kube-controller-manager是一堆控制器的集合体,比如 ReplicaSet 控制器、Node 控制器、Endpoint 控制器等等。它的工作模式是"调谐循环",即不断对比期望状态和实际状态,然后通过 apiserver 下发指令去纠正偏差。举个例子:你创建了一个 Deployment 期望有 3 个副本,如果某个 Pod 挂了,控制器会立刻创建一个新的 Pod 来凑齐 3 个。

kubeadm 默认把控制平面组件以静态 Pod 的方式跑在控制平面节点上,配置文件放在/etc/kubernetes/manifests目录下。这个目录下的 YAML 文件由 kubelet 直接监听,文件有变化就会自动更新对应 Pod。所以我们改 apiserver 的启动参数,理论上只需要修改这个目录里的 YAML 并让 kubelet 重新加载即可,不用手动重启容器,kubelet 会检测到变化并平滑重建。

因为控制面组件都是静态 Pod 方式运行,kubelet 是这些组件的父进程,所以控制面节点上 kubelet 绝对不能挂。这也是为什么我们需要将 kubelet 设置为开机自启,并且重启控制平面节点时,要特别注意别先手动把容器停了——kubelet 会自动把它们拉起来的。

理解了这些组件的分工,你在排查问题的时候就能快速定位。比如kubectl get nodes无反应,优先怀疑 apiserver;kubectl get pods能看到但 Pod 调不动,优先怀疑 scheduler;节点状态总是 NotReady,优先检查 kubelet 和容器的通信。有了这个地图,就不至于一头雾水。

4. kubeadm init:初始化控制平面的完整实操

这应该是整个搭建过程中最关键也最容易紧张的一步。我的建议是,在正式执行之前,把环境、网络、镜像全部检查一遍,然后开一个终端窗口盯着日志输出,不要一把梭直接跑,不然报错了你都不知道从哪下手。

先确认前置条件都满足:

  • 操作系统是 CentOS 7.9 / Rocky Linux 9 / Ubuntu 22.04 之一,内核 5.x 以上更佳
  • 主机名不能是大写字母,并且通过hostnamectl set-hostname设置了统一格式,比如k8s-master01
  • 交换分区已通过swapoff -a关闭,并注释/etc/fstab中的 swap 行(重启后不会自动挂载)
  • 各节点的时间已同步,推荐安装 chrony 并确保时间源正常。时间不同步会导致证书验证失败
  • 已配置好主机名解析,编辑/etc/hosts,加入各节点的私有 IP 和主机名映射

确认无误后,加载内核模块:

cat <<EOF > /etc/modules-load.d/k8s.conf overlay br_netfilter EOF modprobe overlay modprobe br_netfilter

再设置内核参数,让 iptables 可以正确处理桥接流量:

cat <<EOF > /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.ipv4.ip_forward = 1 EOF sysctl --system

接着用 kubeadm 初始化控制平面。注意 init 之前把 kubeadm 的默认配置导出并修改镜像仓库,这一步很多教程不会讲,但内网或者国内环境必须做:

kubeadm config print init-defaults > /tmp/kubeadm-init.yaml

编辑/tmp/kubeadm-init.yaml,重点修改几个地方:

kubernetesVersion: 1.30.3 imageRepository: registry.aliyuncs.com/google_containers localAPIEndpoint: advertiseAddress: 192.168.1.10 nodeRegistration: criSocket: unix:///var/run/containerd/containerd.sock

其中advertiseAddress填控制平面节点的 IP,criSocket改成 containerd 的 socket 路径,默认是/var/run/containerd/containerd.sock,如果这里不写对,kubelet 会直接找不到运行时。

确认无误后执行:

kubeadm init --config /tmp/kubeadm-init.yaml --v=5

--v=5是日志级别,数字越大输出越详细。第一次跑的时候建议加上,方便看出具体在哪个环节卡住。初始化过程会经历几个阶段:预检、生成证书、写 kubeconfig、拉取镜像、创建静态 Pod、等待 kubelet 上报节点状态、启动控制平面组件、最后生成 join token。

但如果你只是自己练手或者内网环境,强烈建议提前把镜像拉好,否则 init 过程会卡在拉镜像这一步,网络不通直接报错。提前手动拉取的方法:

kubeadm config images list --config /tmp/kubeadm-init.yaml

会输出这次 init 需要的所有镜像列表,然后逐个crictl pull或者docker pull(取决于你的运行时方式),确认都拉取成功后再执行 init。不要觉得这一步多此一举,集群搭建 90% 的问题都集中在镜像拉不下来的场景。

init 正常完成后,最后几行会显示三个关键信息条。第一条是控制平面节点的 kubeconfig 配置命令,需要在当前用户下执行:

mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config

第二条是工作节点加入集群的命令,类似:

kubeadm join 192.168.1.10:6443 --token xxx --discovery-token-ca-cert-hash sha256:xxx

如果你在初始化时没有保存这条命令,也不用慌,可以通过kubeadm token create --print-join-command重新生成一个。

第三部分是提示你安装 CNI 插件。这里我要多说一句:没有 CNI 插件之前,控制平面节点的 CoreDNS 会一直处于 CrashLoopBackOff,所有 Pod 都会是 Pending 状态。这是正常的,不代表集群有问题,装上网络插件之后自然恢复。

5. 工作节点加入:从 token 到 CNI 的全链路

很多人在控制平面 init 成功后,会觉得集群已经好了。实际上,工作节点不加入、CNI 不装、核心插件不健康,这个集群只能算是个半成品。这一节我按加入节点的完整链路逐一梳理。

5.1 准备工作节点的运行时环境

工作节点的系统环境、容器运行时、kubelet 和 kubeadm 的安装步骤,和控制平面节点完全一样,唯一区别是工作节点不需要 init,只需要 join。这里需要强调:join 之前,工作节点的 kubelet 是不能正常注册到集群里的,如果你提前启动了 kubelet,它会反复尝试连接 apiserver 但拿不到证书,日志里会一直刷Unable to connect to the server,这并不影响后续 join,所以看到了不用紧张。

5.2 执行 kubeadm join

回到控制平面节点上,执行kubeadm token create --print-join-command,得到完整的 join 命令。然后把这条命令贴到工作节点的终端上执行。命令里包含两个核心部分:token 是集群的临时通行证,默认有效期 24 小时;discovery-token-ca-cert-hash 是控制平面 CA 证书的哈希,用于防止中间人攻击。

执行 join 的过程,kubelet 会做几件事:

  1. 通过 token 向 apiserver 发起 Bootstrap 请求
  2. apiserver 校验 token,颁发 kubelet 客户端证书
  3. kubelet 拿到证书后,向 apiserver 上报自己的 Node 资源对象
  4. 控制平面开始给这个节点分配 Pod
kubeadm join 192.168.1.10:6443 --token yaoeix.xxxxxx \ --discovery-token-ca-cert-hash sha256:xxxxxx

如果这条命令执行成功,末尾同样会输出 "You can now join any number of control-plane nodes" 的提示。此时回到控制平面节点,执行:

kubectl get nodes

会看到新节点已经出现,但状态可能还是 NotReady。这是因为节点的网络插件还没装或者没生效。不要慌,这很正常。

5.3 安装 CNI 插件:以 Calico 为例

CNI 插件的选择非常多,flannel、calico、cilium、weave 各有侧重。我个人的建议是:小规模环境或者学习用途,用 flannel 足够,简单省事;生产环境建议用 Calico,因为它的网络策略控制能力更强。这里以 Calico 为例。

先获取 Calico 的部署清单,然后修改 Pod 网段和你的 kubeadm init 中配置的--pod-network-cidr保持一致。如果 init 时用的是默认配置,那 Calico 的默认网段是192.168.0.0/16,正好匹配。但如果你 init 时自定义了网段,就必须改 Calico 清单里的 CALICO_IPV4POOL_CIDR 字段,否则网络不通。

部署 Calico:

kubectl apply -f calico.yaml

Calico 的 Pod 全部跑起来之后,再回来看节点状态,应该全部变成 Ready:

kubectl get nodes

同时,CoreDNS 也会自动恢复正常,不再 CrashLoopBackOff。

这里提醒一个最容易踩的坑:网络插件必须在所有节点加入集群之后统一部署,不要在加入节点之前就先装好。因为 CNI 插件需要和 apiserver 通信,而 join 之前的 kubelet 连不上 apiserver,装早了反而会产生各种奇怪的网络异常,比如 Pod 的 IP 池冲突。

另一个坑是:不要同时装两个 CNI 插件。我见过有人为了省事,先装了 flannel,后面又想着换 Calico,结果两个插件的网络规则互相打架,节点状态反复 Ready/NotReady,查了一下午最后才定位到是 CNI 配置目录里残留了 flannel 的配置文件。

5.4 验证集群功能:部署一个测试 Pod

节点全部 Ready 之后,推荐部署一个跨节点的测试 Pod 来验证网络链路。我习惯用 busybox 来测:

kubectl run test-pod --image=busybox -- sleep 3600

等 Pod 变成 Running 之后,再进到 Pod 里测试到另一个 Pod 的连通性。如果通了,说明网络插件工作正常,整体集群已经可用。

6. 高可用与证书续期:别等集群挂了才想起来

很多教程在主节点装完、工作节点 join 完,就宣布集群搭建完成。但运维层面还有两件事是你迟早要面对的:高可用架构和证书自动续期。

6.1 高可用:控制平面多副本

单控制平面节点的集群,在测试环境没问题,但一旦控制平面节点宕机,整个集群就不可用了。生产环境至少要三台控制平面节点,通过 Keepalived 或云厂商的负载均衡器把流量分发到多台 apiserver 上。

kubeadm 初始化多控制平面的流程是:

  1. 在第一台节点上执行kubeadm init --control-plane-endpoint 192.168.1.100:6443
  2. 第一台节点完成后,根据提示在第二、三台节点上执行kubeadm join 192.168.1.100:6443 --control-plane --token xxx
  3. 每个控制平面节点上都会有独立的 etcd 静态 Pod,并且自动组成 etcd 集群

注意--control-plane-endpoint是集群的虚拟入口,通常是一个 VIP 或者负载均衡地址,而不是第一台节点的 IP。如果用第一台节点 IP 作为 endpoint,那这台节点挂了,整个控制平面还是不可用,也就失去了高可用的意义。

另外,etcd 作为集群的存储层,在高可用部署时还要考虑磁盘性能和备份策略。etcd 的写性能直接决定集群的反应速度,使用本地 SSD 是基本要求,同时建议定期对 etcd 数据目录做快照备份,可以用etcdctl snapshot save命令,备份文件放到远程存储上,别和集群放在同一台机器里。

6.2 证书续期

kubeadm 创建的集群,各组件之间的通信证书默认有效期是一年。一年之后证书过期,集群并不会优雅地自动续期,而是直接拒绝服务。到时候你会发现kubectl get nodes各种报错。

好在 kubeadm 自带证书续期功能:

kubeadm certs renew all

执行完之后,把kubeconfig文件更新一下:

kubeadm init phase kubeconfig user --config /tmp/kubeadm-init.yaml sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

最后重启 kubelet 让新证书生效。如果你是普通用户,这个流程一年执行一次即可。生产环境建议用 crontab 或者 systemd timer 做成自动化的,避免某天突然想起来才发现证书早就过期了。

这里想多提一句:kubeadm 在 v1.29 之后默认让 kubelet 自动续期它的客户端证书,但对于控制平面的服务证书,仍然需要你手动执行 renew。所以别指望升级到新版本就可以完全甩手,自动化的定期检查还是要有的。

7. 常见问题与排查技巧实录

这里我把这些年实际踩过的、以及很多朋友问过的问题整理成一个清单,配合排查思路,帮大家少走弯路。每个问题都是我真实遇到过并解决的。

7.1 节点状态一直是 NotReady

优先顺序排查:

  1. 检查 kubelet 是否在运行:systemctl status kubelet
  2. 查看 kubelet 日志:journalctl -u kubelet -f
  3. 检查容器运行时是否正常:crictl version
  4. 确认 CNI 插件是否部署:kubectl get pods -n kube-system | grep -E 'calico|flannel'
  5. 检查节点的KubeletReady条件是否通过:kubectl describe node <node-name>

最常见的原因是 kubelet 启动参数里container-runtime-endpoint配置不对,或者 containerd 的 CRI 配置没启用。修改后重启 kubelet,基本能解决。

7.2 Coredns 一直 CrashLoopBackOff

这个不用太过惊慌。如果 CNI 插件未部署或部署异常,CoreDNS 的 Pod 会因为网络初始化失败而反复重启。先检查 CNI 状态,不要一上来就改 CoreDNS 的配置。如果 CNI 正常,再看一下是否有 dns 配置的冲突,比如/etc/resolv.conf里 nameserver 指向了不可达的地址。

7.3 加入节点时报 token 过期

token 默认 24 小时有效,过期后直接报错。解决方法是重新生成:

kubeadm token create --print-join-command

如果之前保存的不带--discovery-token-ca-cert-hash,也可以直接用:

kubeadm join 192.168.1.10:6443 --token <token> --discovery-token-unsafe-skip-ca-verification

但是这个命令会跳过 CA 校验,仅建议在安全可控的临时环境使用。

7.4 kubelet 报 "connection refused" 或 "dial tcp ... connect: connection refused"

通常有几种可能:

  • apiserver 所在的 6443 端口没监听。先确认 apiserver 容器是否在运行:crictl ps -a | grep kube-apiserver
  • 防火墙拦截了 6443 端口。生产环境建议在安全组或 iptables 里放行 6443 端口
  • 网络不通。用telnet或nc测一下连通性,比如nc -vz 192.168.1.10 6443

如果是虚拟机环境,还有一种很隐蔽的问题:两台节点的网卡 IP 配置了相同的网段但 VLAN 不同,导致看似能 ping 通但端口不通。这种只能靠抓包或者看物理网络设备的配置。

7.5 Pod 一直处于 Pending 状态

Pending 意味着调度器还没为 Pod 找到合适的节点。用kubectl describe pod查看事件,常见原因有:

  • 节点的资源不足,比如 CPU 或内存不够
  • 节点上有污点,Pod 没有对应的容忍度
  • 没有可用的持久化存储,需要绑定 PVC 但 StorageClass 没配

如果是资源不足,可以临时给 node 加上--node-allocatable参数来降低保留资源,但这是治标不治本,扩容节点才是正确路径。

7.6 etcd 数据目录空间满

默认配置下 etcd 的数据不会自动压缩,日志量大的集群(如频繁创建删除 Pod)很容易把磁盘撑满。处理方法是手动压缩碎片:

crictl exec <etcd-container-id> /usr/local/bin/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 \ defrag --command-timeout=60s

然后清理 etcd 历史版本数据。同时建议开启自动压缩:

crictl exec <etcd-container-id> /usr/local/bin/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 \ compaction 4000000

7.7 kubeadm reset:翻车之后的后悔药

如果初始化失败,不要反复执行 init。先kubeadm reset清理现场,再重新 init。否则上一次的残留配置会影响下一次初始化。

kubeadm reset -f

同时清理旧的 CNI 配置和 kubelet 数据:

rm -rf /etc/cni/net.d rm -rf /var/lib/etcd

然后重新执行 init。这一步很多新手忽略,导致在同一台机器上反复出各种诡异问题。建议把kubeadm reset挂载到你的操作习惯里,就像做菜之前先洗干净锅一样。

8. 写在最后:我的个人体会与后续扩展建议

k8s 集群搭建这件事,看起来是一堆命令行操作,实际上考验的是对整个系统体系的理解:网络、存储、系统服务、证书体系、容器运行时,每一样都在这里面扮演了角色。我的经验是:不要追求"照着教程跑通一次就走",而是把每个组件为什么存在、报错为什么出现搞清楚,这样以后再遇到问题,你就有自己的判断逻辑,而不是继续靠百度。

如果你搭建完成后想把集群变得更有生产力,我建议接下来可以沿着这几个方向深入:

  • 部署一个真实的业务应用,比如一个带数据库的 Web 服务,体验一下 Service、Ingress、PVC、ConfigMap 这些核心资源的组合使用
  • 逐步引入 Prometheus + Grafana 监控体系,让集群的可观测性从一开始就建立起来,而不是等到出了问题才去查
  • 尝试一下 GitOps 工作流,用工具把应用部署变成配置文件管理,配合自动同步,这样后续上生产会更顺手
  • 有条件的话把集群升级到高可用架构,顺便把证书续期做成自动化脚本,把运维细节沉淀成文档

最后再分享一个我实际操作中的小技巧:把搭建过程中用到的所有配置文件和命令整理成一个操作手册,保存到公司或自己的知识库里。不要只依赖头脑记忆,K8s 的版本迭代很快,一年之后你很可能忘记当时某个参数的坑是怎么填的。有了手册,再搭建新环境或者升级旧环境的时候,就有一个可靠的参照物,也能把这份经验分享给团队里的其他人。

希望这篇记录能帮你把 v1.30.3 的集群顺利搭起来。如果你在搭建过程中遇到了没提到的问题,也欢迎跟我交流,我在后续的版本迭代实践里也会继续整理更深入的运维经验。** # 【官方kubeadm工具】安装k8s集群v1.30.3

我从 Kubernetes 1.20 时代就开始折腾集群,从最早的 kubeadm 手动初始化到后来的生产环境高可用部署,踩过的坑少说也有一百多个。这次用官方 kubeadm 工具装 v1.30.3,整体流程其实比早期版本顺滑不少,但有几个关键点值得单独拎出来讲,尤其是容器运行时的选择、镜像源的配置,以及 kubeadm init 前后的细节处理。这篇文章会基于一套完整的实操流程,把从环境准备到工作节点加入,再到 CNI 网络插件安装的全过程记录下来,希望对准备上手 v1.30.3 的你有所帮助。

1. 环境准备与版本选型背后的考量

1.1 为什么选 kubeadm 而不是二进制或发行版自带方案

装 K8s 集群的方式不少,常见的有二进制手动部署、kubeadm、以及各大发行版的集成方案。但对于大多数人来说,kubeadm 是唯一兼顾可控性和效率的选择。二进制部署虽然能让你对每个组件都有绝对控制权,但你要自己处理证书、kubeconfig、systemd 服务文件、静态 Pod 配置等一大堆细节,任何一个环节出错都会让 apiserver 起不来,排查成本极高。发行版的集成方案虽然省事,但往往封装了太多自定义逻辑,出了问题时很难判断是自己配置出错了还是发行版的问题。

kubeadm 的正确姿势是:它为官方推荐的引导工具,负责完成所有控制平面组件的标准化部署,同时不限制你对部署参数的自主调优。你依然可以通过 kubeadm 配置自定义 API Server 参数、etcd 存储路径、Pod 网段等。v1.30.3 这个版本在稳定性上已经相当成熟,社区反馈的坑相对较少,对新手相对友好。

1.2 操作系统与内核版本选择

我这次选用的是 Rocky Linux 9,内核版本为 5.14。之所以选这个组合,是因为高版本内核默认支持 overlayfs 和 br_netfilter 等容器网络相关的内核模块,省去了一部分手动加载模块的步骤。CentOS 7 也可以跑 v1.30.3,但需要保证内核在 3.10 以上,并且手动加载引用的模块,所以有条件的话建议直接用 Rocky Linux 9 或 Ubuntu 22.04 及以上版本。

节点角色规划:我这次搭建的是 1 台控制平面节点 + 2 台工作节点的最小集群。控制平面节点配置为 4 核 8G,工作节点 4 核 16G。如果你只是学习验证,控制平面节点可以适当降低配置,但至少保证 2 核 4G,否则 etcd 和 apiserver 会频繁触发 OOM,集群状态堪忧。

主机名规范:所有节点的主机名必须设置成有意义的名字,且不能包含大写字母。比如k8s-master01、k8s-node01、k8s-node02。这个细节源自 Kubernetes 对节点名称的解析机制,如果主机名有大写字母或者包含下划线之类的特殊字符,kubelet 注册节点时会报错。

1.3 关闭交换分区与防火墙策略

装 K8s 集群前必须关闭 swap,这是从 1.8 版本至今不变的铁律。Kubernetes 的设计假定节点的内存资源是稳定可预期的,swap 会导致 kubelet 对 Pod 内存使用量的判断失真。执行swapoff -a并注释掉/etc/fstab中的 swap 行,保证重启后依然生效。

防火墙方面,如果你用的是 firewalld,建议直接systemctl stop firewalld并在开机启动项中禁用。不是说 K8s 不能配合防火墙运行,而是在学习阶段没必要让防火墙成为干扰源。生产环境必须放行端口时,重点确认以下几个端口:

  • 控制平面:6443(apiserver)、2379-2380(etcd)、10250(kubelet)、10257(controller-manager)
  • 工作节点:10250(kubelet)、30000-32767(NodePort 服务端口)

1.4 内核模块与系统参数

容器网络要求启用 overlay 和 br_netfilter,并调整 iptables 的桥接流量转发规则。这部分可以直接写一个配置文件:

cat <<EOF > /etc/modules-load.d/k8s.conf overlay br_netfilter EOF modprobe overlay modprobe br_netfilter

接着创建内核参数配置:

cat <<EOF > /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.ipv4.ip_forward = 1 EOF sysctl --system

这些参数的作用是让 iptables 规则能够对通过 bridge 设备转发的流量生效。K8s 的 Service 负载均衡依赖 iptables 的 DNAT 规则,如果 bridge 流量绕过 iptables,跨 Pod 的 Service 访问就会失败。net.ipv4.ip_forward则确保容器间的请求能正常转发。

1.5 安装 kubeadm、kubelet 和 kubectl

v1.30.3 的软件源已经在官方仓库中稳定可用。这里我使用阿里云镜像源来加速安装,配置方法如下:

cat <<EOF > /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el9-x86_64/ enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg EOF

然后安装指定版本:

yum install -y kubelet-1.30.3 kubeadm-1.30.3 kubectl-1.30.3 systemctl enable kubelet

这里有个常见问题:kubelet 现在启动会因为缺少配置文件而报错,这是正常的。kubelet 需要等待 kubeadm init 或 join 之后生成对应的 kubelet.conf 才能正常启动。所以先 enable 它,但不用现在 start。

如果安装时提示找不到软件包,确认你的系统版本对应的是 el9 还是 el7 的仓库路径。CentOS 7 对应 el7,Rocky Linux 9 对应 el9,不能混用。

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

AI驱动的测试数据匿名化:从GDPR合规到实战管线的完整指南

测试数据匿名化这件事&#xff0c;我从入行到现在折腾了不下几十个项目&#xff0c;说实话&#xff0c;以前大家不太当回事&#xff0c;最多写个脱敏脚本&#xff0c;把身份证和手机号替换成假数据就交差了。但自从GDPR这类数据保护法规真正开始落地执行&#xff0c;测试数据的…

作者头像 李华
网站建设 2026/10/22 15:16:13

国产大模型落地实践:从架构选型到应用交付的完整链路

国产大模型的落地实践&#xff0c;这几年算是真正从“能跑通Demo”走到了“能扛生产环境”。我自己的感受特别深&#xff1a;两年前大家还在纠结模型能不能答对常识题&#xff0c;现在的讨论重心已经变成了推理成本怎么降、幻觉怎么控、垂直场景怎么真正用起来。这条赛道的变化…

作者头像 李华
网站建设 2026/10/22 15:15:25

Dify平台实战:从零搭建企业内部知识库问答机器人

“前两天一位朋友问我&#xff1a;手头有一堆企业内部的运维文档和故障记录&#xff0c;想做一个能自动回答‘服务器出现某个报错该怎么办’的机器人&#xff0c;但又不想把整个开发流程拖得很重。我的建议很直接&#xff1a;直接用Dify平台来做。”Dify平台是一个开源的大模型…

作者头像 李华
网站建设 2026/10/22 15:14:50

手写 Tool Use:三种实现方案与工程取舍

面试现场碰到“手写一个 Tool Use”&#xff0c;大多数人的第一反应是背某个模型的 Function Calling 参数。可真当你在白板上从零开始搭调用循环时&#xff0c;才会发现这东西考的不是“记没记住 API”&#xff0c;而是你是否真的理解“模型怎么把手伸进外部世界”。 Tool Us…

作者头像 李华
网站建设 2026/10/22 15:14:48

百考通AI:从选题到答辩的毕业论文全流程研究辅助工具

毕业季那几个月&#xff0c;我见过太多人被论文和研究报告折腾到崩溃。白天跑实验、晚上啃文献&#xff0c;好不容易写出来的初稿还要面对格式调整和导师的连环批注&#xff0c;数据不理想时更是整夜整夜睡不着。如果你正处在这个阶段&#xff0c;这篇内容应该能帮到你。这篇文…

作者头像 李华
网站建设 2026/10/22 15:13:18

C++ explicit关键字:从隐式转换到类型安全

如果你在项目里遇到过"莫名其妙的多了一个临时对象""编译器居然不报错就帮我做了类型转换"&#xff0c;那十有八九就是隐式转换在搞鬼。C 里 explicit 关键字就是用来拦住这类"自作聪明"的行为的。它不算新特性&#xff0c;C98 就有&#xff0…

作者头像 李华