kubeadm搭建一主两从K8s集群:从环境初始化到CNI网络全指南
2026/9/10 2:53:35 网站建设 项目流程

1. 准备工作:一主两从集群的前置环境规划

1.1 为什么选择 kubeadm,而不是二进制或 minikube

搭建 Kubernetes 集群,目前主流的方案就那么几种:kubeadm、二进制部署、minikube、kind 等。如果你在三台机器上搭正式一点的测试环境,或者准备上生产,我建议直接选 kubeadm。为什么?二进制部署虽然让你对每个组件都了如指掌,但手动生成证书、配置 kubelet、编排 etcd 的步骤太多,一次配置错一个参数排查几个钟头是常事。minikube 和 kind 更适合单机学习,跑在虚拟机或 Docker 里,做不了真正意义上的“一主两从”跨节点集群。kubeadm 则把控制平面组件容器化,证书、kubeconfig、etcd 这些基础工作全部自动化,同时保留了对部署细节的控制权,踩坑少、可复现程度高,也是社区目前最主流的初始化方式。

1.2 节点规划与硬件建议

一主两从,拓扑上就是一个 master 节点加两个 worker 节点。这篇文章里我用的节点信息方便你直接对照:

节点角色主机名配置建议操作系统
masterk8s-master2C4G 起,磁盘 50GCentOS 7.9 或 Ubuntu 22.04
worker1k8s-node12C4G 起,磁盘 50GCentOS 7.9 或 Ubuntu 22.04
worker2k8s-node22C4G 起,磁盘 50GCentOS 7.9 或 Ubuntu 22.04

这里多说一句,如果你条件充裕,master 建议 4C8G,毕竟 etcd、kube-apiserver、kube-controller-manager 都压在 master 上,资源吃紧时第一个崩的往往是 etcd。磁盘方面,别用机械盘凑合,SSD 和 NVMe 带来的 etcd 写入性能差异非常明显,生产环境这块不能省。

1.3 系统初始化:三台机器统一配置

拿到三台全新的服务器之后,需要先把系统层面的公共配置拉齐。这一步不做好,后面装组件全是坑。首先修改主机名,然后配置 hosts 解析,保证三台机器能互相通过主机名访问。

# 每台节点分别设置自己的主机名 hostnamectl set-hostname k8s-master # 或者 k8s-node1、k8s-node2,对应你自己的规划 # 三台机器都编辑 /etc/hosts,加入以下内容 cat >> /etc/hosts <<EOF 192.168.1.10 k8s-master 192.168.1.11 k8s-node1 192.168.1.12 k8s-node2 EOF

然后关闭防火墙和 swap。很多人不理解为什么要关防火墙,其实不是安全洁癖问题,而是 Kubernetes 的 kube-proxy 使用 iptables 或 IPVS 转发流量,firewalld 有自己的一套 iptables 管理逻辑,两者同时操作很容易出现规则互相覆盖、节点间通信时通时不通的诡异现象。测试环境直接关掉省心,生产环境如果需要防火墙,必须放行 6443、2379、2380、10250、30000-32767 等端口段。

# 关闭防火墙 systemctl stop firewalld && systemctl disable firewalld # 关闭 swap swapoff -a && sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab # 加载内核模块 cat <<EOF | tee /etc/modules-load.d/k8s.conf overlay br_netfilter EOF modprobe overlay && modprobe br_netfilter

关键的内核参数也要调整一下,让 iptables 能正确查看桥接流量,这个不配置的话,Kubernetes 的 Service 转发会出问题,最典型的症状就是 Pod 内访问 Service ClusterIP 超时。

cat <<EOF | 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 --system

2. 容器运行时安装:从 Docker 到 containerd 的选择与配置

2.1 为什么不直接用 Docker

这里要回答一个很多新手会困惑的点:Kubernetes 1.24 之后已经移除了 dockershim,也就是说 kubelet 不再直接支持 Docker 作为运行时了。当然你可以装 cri-dockerd 来过渡,但这属于额外多维护一层适配器,没什么必要。现在的标准做法是直接上 containerd。containerd 本身就是 Docker 底层的那套容器运行时,精简、稳定,而且 Kubernetes 原生通过 CRI 与其对接,少了一层中间代理,性能表现也更好。我这里直接选择 containerd 1.7 系列,稳定性和兼容性都足够。

2.2 containerd 安装与配置全过程

如果是 CentOS 7 体系,先装 yum-utils 和 yum-config-manager 工具,然后从官方仓库拉取。Ubuntu 22.04 则是用 apt 的方式,逻辑一样,这里以 CentOS 为例:

yum install -y yum-utils yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo yum install -y containerd.io

装完 containerd 之后,核心任务是生成默认配置并修改两个关键参数。第一步生成默认配置:

mkdir -p /etc/containerd containerd config default | tee /etc/containerd/config.toml

然后编辑/etc/containerd/config.toml。最关键的是 SystemdCgroup 这个参数,默认值为 false,必须改成 true,否则容器内的进程无法被 kubelet 正确管理,Pod 会出现各种资源统计异常,甚至部分容器启动后直接被杀掉。另一个是 sandbox_image,国内环境默认的registry.k8s.io/pause:3.x拉不下来,需要改成阿里云或你本地镜像仓库的地址。

[plugins."io.containerd.grpc.v1.cri"] sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9" [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc] [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] SystemdCgroup = true

改完之后重启并设置开机自启,验证 containerd 状态正常:

systemctl restart containerd systemctl enable containerd systemctl status containerd ctr version

这里补充一个验证技巧,用ctr命令是可以直接和 containerd 交互的,但它不识别 CRI 体系下的 Pod 概念。真正模拟 kubelet 拉镜像,建议用crictl,这个工具后续排查问题会频繁使用。安装方式是把二进制下载到/usr/local/bin,然后配置crictl config --set runtime-endpoint=unix:///run/containerd/containerd.sock --set image-endpoint=unix:///run/containerd/containerd.sock

2.3 镜像加速与离线场景的预拉取

如果你所在网络环境拉取 Docker Hub 镜像很慢,或者直接连不上registry.k8s.io,我强烈建议你提前把后续 kubeadm 初始化会用到的镜像在本地拉好。kubeadm 本身提供了一个命令来查看和拉取初始化镜像:

kubeadm config images list kubeadm config images pull

不过kubeadm config images pull默认使用的源还是registry.k8s.io,如果你已经准备挂代理或者镜像加速,可以在初始化时用--image-repository参数指定镜像仓库,指向你本地加速地址或者阿里云的镜像源:

kubeadm init --image-repository=registry.aliyuncs.com/google_containers

这会在初始化阶段自动从指定仓库拉取所有控制平面组件镜像,省去手动一个个 pull 再 retag 的繁琐操作。对于离线环境,则建议在有网机器上提前拉好镜像,然后docker save/ctr images export打包上传到离线节点,再 import 进去。

3. kubeadm、kubelet、kubectl 组件安装与版本锁定

3.1 安装方式和版本选择逻辑

这三件套是 Kubernetes 集群的核心工具:kubeadm 负责初始化和管理集群生命周期,kubelet 是每个节点上最核心的 Agent 组件,负责与容器运行时交互并执行 Pod 的生命周期管理,kubectl 是和集群交互的客户端命令行工具。三个组件的版本必须严格一致,否则初始化阶段就会报版本不匹配的错误。

在版本选择上,我用的是 1.28.x 这个版本线。为什么不追最新?Kubernetes 社区发布节奏一年三个大版本,最新的版本往往引入很多新特性,但相应的生态组件比如网络插件、Ingress Controller 的兼容性可能还没完全跟上。1.28 属于当时相对成熟且还在维护期内的版本,etcd 版本、CoreDNS 版本、CNI 插件都是经过大量真实验证过的组合。你现在搭集群,一定先确认清楚要用哪些上层组件,有没有兼容版本要求,再反推 Kubernetes 版本,而不是先装了再说。

3.2 安装操作与版本锁定

以 CentOS 7 为例,最标准的做法是使用阿里云镜像仓库:

cat <<EOF | tee /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-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 kubeadm-1.28.2-0 kubelet-1.28.2-0 kubectl-1.28.2-0

注意我直接指定了完整的版本号,这是避免“装了个最新版,改天节点扩容又装了个别的版本,版本漂移导致集群混乱”的关键操作。然后设置 kubelet 开机自启,但先不要启动它,因为此时 kubelet 还没有任何配置,启动也会不断报错重启。

systemctl enable kubelet

这里有个细节:kubelet 的配置文件路径是/etc/kubernetes/kubelet.conf,这个文件是 kubeadm init 之后才生成的。如果你手痒提前启动 kubelet,它会找不到配置而反复崩溃,属于正常现象,不必慌张。

3.3 版本校验与命令确认

装完后做一个基本校验,确认三件套版本一致:

kubeadm version kubelet --version kubectl version --client

三个命令输出的版本号必须一致。如果不一致,在 yum 安装时就要指定对齐版本号。我遇到过不少人,kubeadm 装的 1.28,kubectl 因为之前装过别的版本,结果 client 和 server 版本差太多,导致kubectl get nodes时 API 兼容层报错,白白排查了半天。所以这个习惯要养成:所有客户端组件和 server 版本保持同步。

现在三台节点的运行时和工具都就绪了,可以进行 master 节点的初始化。

4. master 节点初始化:kubeadm init 最优参数组合

4.1 初始化命令的核心参数解读

到这一步,我们正式推进集群的创建。在 master 节点执行 kubeadm init,但这不是一条命令跑完就完事的问题,参数必须根据你的环境做调整。一个典型的初始化命令如下:

kubeadm init \ --image-repository=registry.aliyuncs.com/google_containers \ --kubernetes-version=v1.28.2 \ --pod-network-cidr=10.244.0.0/16 \ --service-cidr=10.96.0.0/16 \ --apiserver-advertise-address=192.168.1.10 \ --control-plane-endpoint=k8s-master

各个参数的含义你需要完全清楚。--image-repository前面说了,是加速源;--kubernetes-version要和 kubeadm 版本一致;--pod-network-cidr是 Pod 网段,10.244.0.0/16 这个具体地址要和后面装的网络插件匹配;--service-cidr是 Service 网段,一般保留默认的 10.96.0.0/16 即可,不用改。--apiserver-advertise-address就是 master 节点的内网 IP,其他的节点要通过这个 IP 来访问 API Server。

关于 Pod 网段的选择,一个经验性的考量是:10.244.0.0/16 是 Flannel 默认插件体系里使用最广泛的网段,几乎所有的 Flannel 配置示例都默认这个值,这意味着很少需要为它做额外适配。如果你用 Calico,通常默认是 192.168.0.0/16。所以这一步的选值不是随机的,它取决于你后面到底用哪个 CNI 插件,先定插件再定网段比较稳妥。

4.2 初始化过程的完整输出解读

初始化过程会持续 1-3 分钟,如果网络状况不理想可能更久。这段时间 kubeadm 会依次完成如下工作:

  • 先执行 preflight 检查,校验系统配置、端口占用、swap 状态等。
  • 然后生成 CA 证书、各组件证书、ServiceAccount 密钥。
  • 接着把 kube-apiserver、kube-controller-manager、kube-scheduler 以静态 Pod 的方式写入/etc/kubernetes/manifests,kubelet 检测到该目录下的 yaml 后会自动启动这些容器。
  • 最后为 kubeconfig 生成 admin.conf、controller-manager.conf、scheduler.conf 等文件。

初始化成功后,末尾会打印三段非常重要的信息:一段是让你执行的 kubeconfig 配置命令,一段是 join 命令,还有一段是让你安装 CNI 插件的提示。这段输出建议直接复制保存到本地文件,因为 join 命令里包含了 token 和证书哈希,后续找不回来很麻烦:

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

执行完这段后,kubectl get nodes可以看到 master 节点已经出现在列表中,但状态是 NotReady。这并不是异常,因为还没有安装 CNI 网络插件,节点网络没有就绪。接下来最关键的一步就是把网络打通。

4.3 kubectl 自动补全和效率配置

磨刀不误砍柴工,在继续之前我把 kubectl 的命令补全和别名配置好,后续操作体验会提升很多。

echo "source <(kubectl completion bash)" >> ~/.bashrc echo "alias k='kubectl'" >> ~/.bashrc source ~/.bashrc

alias k='kubectl'这个习惯我强烈推荐,每次少敲几个字母,积少成多效率提升非常明显。

5. worker 节点加入集群:join 的机制与后续验证

5.1 join 命令的使用与原理

现在到两个 worker 节点上执行 master 初始化完成后输出的 join 命令。如果你当时没有保存输出,可以通过下面的命令重新生成 token:

kubeadm token create --print-join-command

在 worker 节点上执行 join 时,kubelet 会先通过 token 向 API Server 发起 bootstrap 请求,使用 TLS bootstrap 机制自动请求一个客户端证书用于后续通信。这个过程是自动完成的,无需手工干预。join 命令长这样:

kubeadm join 192.168.1.10:6443 --token abc123.abcdef \ --discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxx

注意 join 命令要在每台 worker 上都执行一遍。执行成功后,回到 master 上运行kubectl get nodes,就能看到三个节点。刚开始节点状态是 NotReady,等 CNI 装好并初始化完成后会转为 Ready。

5.2 节点注册与资源信息确认

节点加入成功后,先用 kubectl 检查节点状态和角色标签。如果一切正常,master 上的输出会是这样:

kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP k8s-master Ready control-plane 6m v1.28.2 192.168.1.10 k8s-node1 Ready <none> 88s v1.28.2 192.168.1.11 k8s-node2 Ready <none> 69s v1.28.2 192.168.1.12

通过-o wide可以看到节点的内部 IP、内核版本、容器运行时等额外信息。确认三个节点全部 Ready 后,一主两从的控制面已经完成了。但这里要提醒你,集群就绪不等于可以稳定运行业务,CNI 网络插件没装,Pod 之间、节点之间是无法通信的,所以下一阶段的核心任务是把网络层搞定。

6. 网络插件选型与安装:Flannel 与 Calico 的实战对比

6.1 为什么网络插件是集群必不可少的一环

Kubernetes 网络模型要求:所有 Pod 可以直接通过 IP 互相访问,无论它们在哪个节点上,且不需要 NAT。这个能力由 CNI 插件提供。没有 CNI 插件,kubelet 无法为 Pod 分配集群网络地址,Pod 会一直停留在 ContainerCreating 状态,CoreDNS 也起不来,集群基本是“半瘫痪”状态。

CNI 插件选 Flannel 还是 Calico,主要看使用场景。Flannel 胜在轻量、配置简单,Underlay 的网络模型在中小规模集群里非常稳定,性能也足够,适合测试环境和业务简单的场景。Calico 功能更丰富,支持 NetworkPolicy、BGP 路由模式,性能在大规模集群下表现更好,但配置复杂度也上了一个档次。对于一主两从这样一个三节点规模的学习环境,选 Flannel 能让你更快把集群跑起来,把精力聚焦在 Kubernetes 本身的工作机制上,而不是先被网络策略的配置绕晕。这篇文章先以 Flannel 为例把网络打通。

6.2 Flannel 的完整安装流程

Flannel 的安装方式是一条 kubectl apply 命令,它会创建 DaemonSet,在每个节点上运行一个 flanneld 进程。先下载官方 manifest:

wget https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

由于网络原因,这个文件在你的环境可能拉取不到。你可以从其他镜像源获取,或者直接编辑已有的 kube-flannel.yml 文件,把 image 地址替换成docker.io/flannel/flannel相关的可用镜像。核心注意点是:kube-flannel.yml中 ConfigMap 里的Network参数,必须和 kubeadm init 时指定的--pod-network-cidr保持一致。如果你初始化时用了 10.244.0.0/16,这里就不用改。

kubectl apply -f kube-flannel.yml

安装完成后,需要观察 flannel Pod 是否正常运行:

kubectl get pods -n kube-flannel -o wide kubectl get nodes

正常情况下,三台节点的 STATUS 会在几十秒内变为 Ready。如果始终 NotReady,大概率是 flannel 的镜像拉取问题或网段配置不一致。可以把 flannel Pod 的日志拉出来看,kubectl logs -n kube-flannel <pod-name>,确认报错原因是无法连接 API Server、镜像拉取超时还是网段冲突。这里我再强调一次:网段必须对齐,这是网络插件排障第一位的检查项。

6.3 Calico 的安装差异与选型建议

如果你决定用在生产环境,我建议直接上 Calico。安装 Calico 的核心是操作一套 operator 和 CRD:

kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml

Calico 默认的 Pod 网段是 192.168.0.0/16,所以如果你在 kubeadm init 时用的是 10.244.0.0/16,就必须编辑 calico.yaml 文件中 CALICO_IPV4POOL_CIDR 这个环境变量的值,把它改成你初始化时设置的网段。修改配置后 apply,随后观察 calico-system 命名空间下的 Pod 状态。

Calico 还支持通过 IPIP 和 VXLAN 两种跨节点封装模式,默认使用 IPIP。在小规模集群里两者差异不大,但如果你在公有云环境搭集群,IaaS 底层的网络限制可能会影响 IPIP 的通信,这种情况下切换成 VXLAN 更稳。这个切换操作涉及修改 calico.yaml 中的 IP_AUTODETECTION_METHOD 和 IPIP 相关配置,需谨慎处理。

7. 集群功能验证:从 Pod 到 Service 的完整链路测试

7.1 给 Master 节点打上可调度标签

默认情况下,控制平面节点不参与业务 Pod 调度,这是为了保障集群管理组件的稳定性。但在一主两从这种测试环境里,master 资源可能比较空闲,你可以让 master 也跑一些 Pod,发挥资源价值:

kubectl taint nodes k8s-master node-role.kubernetes.io/control-plane:NoSchedule-

这个命令在 master 上执行后,master 节点将允许被调度普通业务 Pod。注意生产环境一定不要这样做。去掉污点后,整个集群三个节点都是可调度状态。

7.2 部署测试应用验证集群功能

接下来部署一个最简单的 Nginx 测试应用,验证 Pod 能够正常调度、跨节点访问能够互通:

kubectl create deployment nginx-test --image=nginx:1.25 kubectl expose deployment nginx-test --port=80 --target-port=80 --type=NodePort

等待 Pod 运行起来后,检查状态:

kubectl get pods -o wide

你会发现 Pod 分布在某个节点上,接下来访问 Nginx 服务。以 NodePort 方式暴露的服务,会分配一个 30000-32767 范围内的端口,可通过集群内任意节点的 IP 加这个端口访问。用kubectl get svc查看具体端口,然后浏览器或 curl 访问:http://192.168.1.10:30080,如果能看到 Nginx 的欢迎页,说明集群的核心链路已经通了。

7.3 CoreDNS 与服务发现验证

很多初学者忽略了 CoreDNS 的验证。CoreDNS 是集群内部域名解析的核心组件,部署在 kube-system 命名空间,通常有 2 个副本,由 Deployment 管理。检查方式:

kubectl get pods -n kube-system -o wide kubectl exec -it nginx-test-xxxxx -- sh nslookup kubernetes.default.svc.cluster.local

一个完整的服务发现链路是:Pod 内通过 DNS 解析 Service 名称获取 ClusterIP,然后访问对应服务。在 Nginx Pod 里执行nslookup kubernetes.default能正常返回解析结果,说明 CoreDNS 工作正常。如果解析失败,重点排查 CoreDNS Pod 是否能正常访问 API Server,以及 CoreDNS 是否收到了来自节点的 DNS 请求。常见的坑是 kubelet 的--cluster-dns参数配置,如果初始化指定了特殊的 service-cidr,这里的 DNS 地址要与 kubeadm 自动生成的 10.96.0.10 保持一致。

8. 节点与集群常见问题排查记录

8.1 Pod 一直处于 Pending 状态

这是新手遇到最多的问题,核心原因一般有两个:一是节点资源不足,调度器无法满足 Pod 的资源请求;二是存在污点,Pod 没有对应的容忍度。排查方法非常直白:

kubectl describe pod <pod-name>

在输出的 Events 里,调度器会明确告诉你没有可用节点满足调度条件。常见提示包括0/3 nodes are available后面跟的具体原因。有一种情况博主经常遇到:某个 Pod 请求了 4 核 CPU,但三个节点单核数都不到 4 核,自然调度不上去。检查一下资源请求是否合理,或者节点上是否还有足够的可分配资源。

另外,如果你的节点一直处于 NotReady 状态,Pod 也会 Pending。这时候先看节点状态,再用journalctl -u kubelet -f查看 kubelet 日志,通常能定位到是网络插件问题、磁盘空间耗尽问题,还是容器运行时通信异常。磁盘空间占满是最容易被忽略的一个,/var/lib/containerd 所在分区空间不足时,kubelet 无法正常创建容器,节点会持续报错。

8.2 节点 NotReady 的常规排查流程

节点 NotReady 是在一主两从集群搭建过程中最容易出现的故障,也是所有 Kubernetes 从业者必须掌握的排查基本功。排查流程我总结为一条固定的操作路径:

第一步,在 master 上用 kubectl 查看节点详情,确定问题从哪个阶段开始:

kubectl describe node k8s-node1

重点看 Conditions 区域,NotReady 对应的为 False 就表示节点失联,本质是 Kubelet 和 API Server 之间的心跳(NodeLease)续约失败。接下来在问题节点上检查 kubelet 状态:

systemctl status kubelet journalctl -u kubelet -f --no-pager -n 200

kubelet 日志会输出具体原因。最常见的几个原因是:容器运行时 socket 连不上、CNI 插件安装失败导致 Pod sandbox 无法创建、节点上的网络层不通导致无法访问 API Server。针对容器运行时连通性,可以手动执行crictl info来确认 containerd API 是否正常响应。如果 containerd 都挂了,kubelet 自然无法工作。

8.3 镜像拉取失败的解决思路

在国内环境部署 Kubernetes,镜像拉取失败基本是绕不开的问题。三个典型症状:kubeadm init 卡在 Pulling 阶段、Pod 一直 ImagePullBackOff、静态 Pod 反复重启。

解决方案核心就一条:确保 kubelet 和 containerd 拉取镜像时能访问到可用的镜像仓库。kubeadm 初始化时通过--image-repository指定仓库;containerd 则通过/etc/containerd/config.toml中的 sandbox_image 配置。对于 Kubernetes 生态组件,如 metrics-server、ingress-nginx,这些 helm 安装的组件一般都有自己的默认仓库,安装前先检查 values 里的 image 配置,把仓库地址替换成你本地能访问的镜像源。还有一种情况是 Pod 里配置了私有镜像仓库但没配置 imagePullSecret,拉取私有镜像时会报 unauthorized,这种需要在 Pod 所在命名空间创建 Secret,并引用到 Deployment 的 imagePullSecrets 字段。

8.4 token 过期与证书续期问题

kubeadm 生成的 bootstrap token 默认有效期为 24 小时,如果你隔了一天再想加入新节点,就得重新生成:

kubeadm token create --print-join-command

另外注意,join 命令里的--discovery-token-ca-cert-hash是对集群 CA 证书的哈希校验值,每次初始化时这里是固定不变的,用上面的命令重新生成的 join 命令里会自动带上正确的哈希值,所以你直接复制命令用即可。

集群证书默认有效期是 1 年,到期后各组件会陆续报证书过期错误。如果你长期使用集群,注意提前规划证书更新。kubeadm 提供了一个非常实用的命令:

kubeadm certs check-expiration kubeadm certs renew all

在维护期需要重启各控制平面组件来加载新证书。另外有一个比较常见的坑是:如果你的集群搭建时用了多个 master 节点(高可用),所有 master 的证书都需要逐一更新,漏掉一个会导致该节点无法连上集群,所以建好集群后,证书过期时间要记在运维日程表上。

8.5 问题排查命令速查表

将上面提到的排查手段汇总成一个速查表,方便你遇到问题时快速定位:

场景核心命令排查重点
节点 NotReadyjournalctl -u kubelet -fkubelet 报错内容、网络连通性
Pod Pendingkubectl describe podEvents 中的调度失败原因
Pod CrashLoopBackOffkubectl logs业务进程日志、启动参数
镜像拉取失败crictl pull / crictl images镜像仓库网络、tag 是否正确
Service 访问不通kubectl get endpointsEndpoints 是否有可用后端
DNS 解析失败kubectl exec -it pod -- nslookupCoreDNS Pod 状态、kubelet 配置

9. 集群账单与资源观察:搭建完的第一件事

集群搭建完,第一件事不是急着部署业务,而是确认好集群本身的资源使用情况,这能帮你建立对集群运行预期的基础认知。

kubectl top nodes kubectl top pods --all-namespaces

如果报错说 metrics API 不可用,是因为缺少 metrics-server 组件。这个组件是查看集群资源使用情况的必备工具,安装方式如下:

kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

多数情况下,组件会有一个 TLS 证书校验的问题:kubelet 自签的证书和 metrics-server 默认证书校验不匹配。解决方式是在 Deployment 中给 metrics-server 添加--kubelet-insecure-tls参数,或者提供正确的证书配置。修改之后通过kubectl top nodes能正常输出三个节点的 CPU 和内存使用率。这时候你可以观察到,一主两从场景下,控制平面的 etcd 和 kube-apiserver 会占掉 master 节点不少内存,所以我在开头才强调 master 的最低配置要 4G 起步,否则打几个测试应用就开始内存吃紧、节点反复 NotReady。

掌握上面的排查思路后,基本上主从集群的日常运维都能应对了。集群搭建好不是终点,它是你后续学习容器编排、故障演练、应用发布的基础设施。

我个人这几年的体感是:Kubernetes 的报错信息通常都很直白,绝大多数问题都能通过kubectl describekubectl logsjournalctl -u kubelet这三板斧定位出来。你只要把集群的组件角色和通信链路理清楚,一线故障大多能在几分钟内找到方向。另外实操中一定要养成记录命令和输出的习惯,尤其是 kubeadm init 和 join 这类一次性命令,把输出留存好,后面扩容、更新、排查都能省下大把时间。这篇文章里涉及的配置命令和排查路径,都是我实际搭集群时一一验证过的,照着操作一遍,你也能拥有一套干净可用的一主两从环境。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询