1. 从零吃透 Kubernetes:架构拆解与集群搭建实战笔记
搞容器编排这些年,被问得最多的问题就是“K8s 到底怎么入门”。网上资料一抓一大把,但要么是官方文档那种冷冰冰的术语堆砌,要么是抄来抄去的几行命令,真到自己动手搭集群的时候,该踩的坑一个不少。这篇东西是我自己反复搭过十几套集群之后整理出来的,从架构原理到实操落地,尽量说人话,把那些文档里不会写的细节都摊开讲。不管你是刚接触容器编排的新手,还是已经会用但没深究过底层的老手,应该都能从里面找到点有用的东西。
Kubernetes 这个单词来源于希腊语,意思是“舵手”或“飞行员”,缩写 K8s 是因为中间有 8 个字母。它本质上是一个容器编排系统,解决的问题就一个:当你有几十上百个容器需要跑在不同机器上的时候,怎么让它们协调工作、自动恢复、按需扩缩。单机跑 Docker 谁都会,但生产环境要考虑的远不止“跑起来”这么简单——某台机器挂了怎么办?流量涨了怎么加副本?新版本怎么灰度发布?这些才是 K8s 真正值钱的地方。
我见过太多人上来就照着教程敲kubeadm init,结果卡在镜像拉取、网络插件、证书过期这些环节上,折腾一整天集群还是 NotReady。所以这篇笔记的写法是:先把架构讲透,让你知道每个组件在干什么,然后再动手搭,遇到问题才知道该查哪里。集群搭建部分我会给出一套经过验证的完整流程,包括参数选择、网络插件选型、常见报错处理,最后再聊聊生产环境里那些只有踩过坑才知道的注意事项。
2. Kubernetes 架构深度拆解:每个组件到底在干什么
2.1 控制平面:集群的大脑
控制平面(Control Plane)是 K8s 的决策中心,所有“应该跑什么、跑在哪里、跑几个”的判断都在这里做出。它由四个核心组件构成,每个组件各司其职,缺一不可。
kube-apiserver是整个集群的唯一入口。所有操作——不管是 kubectl 命令、Dashboard 点击,还是其他组件之间的通信——都必须经过它。它本质上是一个 RESTful API 服务器,负责认证、授权、准入控制,然后把请求写入 etcd。你可以把它理解成公司的前台加保安:谁来都得先过它这一关,它确认你身份合法、权限足够之后,才把请求转给后面的人处理。apiserver 是无状态的,所以可以水平扩展多个实例来扛高并发。
etcd是集群的“记忆中枢”,所有集群状态数据都存在这里——有哪些节点、跑了哪些 Pod、Service 怎么配置、密钥是什么,全在 etcd 里。它是个分布式键值存储,用 Raft 协议保证一致性。etcd 的重要性怎么强调都不为过:它挂了,整个集群就失去了“记忆”,所有操作都会失败。生产环境必须给 etcd 做定期备份,而且要用 SSD,因为它的读写延迟直接影响 apiserver 的响应速度。我见过因为 etcd 磁盘 IO 跟不上导致整个集群卡死的案例,排查了半天才发现是机械硬盘的锅。
kube-scheduler负责决定 Pod 该跑到哪个节点上。它监听 apiserver,发现有新 Pod 创建但还没绑定节点时,就根据一系列调度策略来打分选优。调度策略分两个阶段:过滤(Filter)和打分(Score)。过滤阶段排除不满足条件的节点,比如资源不够的、有污点的、不匹配亲和性规则的;打分阶段对剩下的节点按优先级排序,选最高分的。影响打分的因素包括资源均衡、亲和性/反亲和性、污点容忍等。你可以通过 nodeSelector、affinity、taints/tolerations 这些机制来干预调度结果。
kube-controller-manager是一堆控制器的集合,每个控制器负责一种“期望状态”的维护。比如 Deployment 控制器确保实际副本数等于期望副本数,Node 控制器在节点失联时标记节点状态,Endpoint 控制器维护 Service 和后端 Pod 的映射关系。它的工作模式就是无限循环:观察当前状态,和期望状态对比,如果不一致就采取行动让它一致。这种“调谐循环”(Reconcile Loop)是 K8s 声明式 API 的核心实现方式。
还有一个cloud-controller-manager,在云环境里负责和云厂商的 API 交互,比如创建负载均衡器、管理云盘挂载。自建集群一般用不到,这里就不展开了。
2.2 工作节点:真正干活的苦力
工作节点(Worker Node)是实际运行容器的地方,上面跑着三个关键组件。
kubelet是节点上的“监工”。它从 apiserver 接收分配给本节点的 Pod 清单,然后调用容器运行时去创建、启动、监控容器。它还负责上报节点状态和 Pod 状态给 apiserver。kubelet 不管理不是 K8s 创建的容器,这是它和直接操作 Docker 的区别。如果 kubelet 挂了,节点会变成 NotReady,上面的 Pod 会被其他节点接管(如果副本数够的话)。
kube-proxy负责实现 Service 的网络代理。它监听 apiserver 中 Service 和 Endpoint 的变化,然后在节点上维护 iptables 或 IPVS 规则,把发往 Service ClusterIP 的流量转发到后端 Pod。iptables 模式在 Service 数量少的时候没问题,但上千个 Service 的时候规则链会变得很长,性能下降明显。IPVS 模式用哈希表代替链式匹配,大规模场景下性能好很多。现在新版本默认推荐 IPVS。
容器运行时(Container Runtime)是真正跑容器的组件。早期 K8s 只支持 Docker,后来为了解耦,引入了 CRI(Container Runtime Interface)标准。现在主流的运行时是 containerd 和 CRI-O,Docker 本身在 1.24 版本之后就不再被直接支持了(需要通过 cri-dockerd 适配)。containerd 是从 Docker 里拆出来的,更轻量,现在用得最多。
2.3 核心资源对象:你每天打交道的那些东西
理解了组件之后,还得搞清楚 K8s 里的资源对象。这些是你写 YAML 时直接操作的东西。
Pod是最小调度单位,一个 Pod 里可以有一个或多个容器,它们共享网络命名空间和存储卷。大多数时候一个 Pod 跑一个容器,但 sidecar 模式(比如日志收集、代理)会跑多个。Pod 是临时的,挂了不会复活,而是被新的 Pod 替代。
Deployment管理无状态应用的副本集,支持滚动更新和回滚。你声明期望的副本数和镜像版本,它帮你维持这个状态。StatefulSet用于有状态应用,每个 Pod 有稳定的网络标识和独立的存储。DaemonSet确保每个节点(或符合条件的节点)都跑一个 Pod,常用于日志收集、监控代理。Job/CronJob跑一次性或定时任务。
Service给一组 Pod 提供稳定的访问入口。ClusterIP 是集群内部访问,NodePort 在每个节点上开一个端口对外暴露,LoadBalancer 在云环境里创建负载均衡器。Ingress是七层路由,根据域名和路径把流量转发到不同的 Service,通常配合 Ingress Controller(如 Nginx Ingress)使用。
ConfigMap和Secret分别存配置文件和敏感信息,通过环境变量或卷挂载注入到 Pod 里。Volume解决数据持久化问题,emptyDir 是临时目录,hostPath 挂宿主机目录,PVC(PersistentVolumeClaim)通过 StorageClass 动态申请存储。
Namespace做逻辑隔离,不同团队或环境用不同的 Namespace。RBAC控制谁能对哪些资源做什么操作,通过 Role/ClusterRole 和 RoleBinding/ClusterRoleBinding 组合实现。
2.4 声明式 API 与调谐循环:K8s 的设计哲学
K8s 最核心的设计思想是“声明式 API”。你告诉它“我要 3 个 Nginx 副本”,而不是“帮我启动 3 个 Nginx 容器”。前者是声明期望状态,后者是下达执行命令。这个区别看似微小,实则决定了整个系统的容错能力。
声明式的好处在于:系统会持续对比实际状态和期望状态,一旦发现偏差就自动纠正。某个 Pod 挂了,控制器发现实际副本数变成 2 了,期望是 3,于是立刻创建新的补上。节点宕机了,上面的 Pod 被标记为失效,控制器在别的节点上重建。这种“自愈”能力是 K8s 区别于传统运维方式的关键。
调谐循环的实现依赖两个东西:一是 etcd 里存储的期望状态,二是各个控制器不断观察实际状态并采取行动。apiserver 的 Watch 机制让控制器能实时感知变化,而不是轮询。这套机制设计得很优雅,但理解它需要一点时间。我刚开始学的时候,总是习惯性地想“我发了命令它怎么还不执行”,后来才明白,我发的不是命令,是期望,系统需要时间调谐。
3. 集群搭建前的关键决策:方案选型与参数规划
3.1 搭建方式怎么选:kubeadm、二进制还是托管服务
搭 K8s 集群有好几种路子,选错了后面全是坑。
kubeadm是官方推荐的集群引导工具,把控制平面启动、证书生成、kubeconfig 配置这些繁琐步骤都封装成了几条命令。适合大多数场景,尤其是学习和中小规模生产。它的缺点是灵活性稍差,某些高级配置需要手动改 manifest 文件。
二进制部署就是手动下载每个组件的二进制文件,自己写 systemd 服务,自己配证书。这种方式最灵活,能精确控制每个参数,但工作量巨大,而且容易出错。一般只有对 K8s 非常熟悉、有特殊定制需求的团队才会选。我早期搭过一套二进制的,光证书就配了半天,后来果断转 kubeadm。
托管服务如云厂商的容器服务,控制平面由厂商维护,你只管工作节点。省心但花钱,而且绑定厂商。适合不想在运维上投入太多精力的团队。
对于大多数想真正搞懂 K8s 的人来说,我建议从 kubeadm 入手。它足够简单,让你快速看到成果;又足够透明,遇到问题能深入排查。等玩熟了再考虑二进制或托管。
3.2 节点规划与资源要求
搭集群之前先想清楚要几台机器、怎么分配角色。
学习环境最低配:1 台 Master + 1 台 Node,每台 2 核 4G。但这样搭出来的集群 Master 也跑 Pod(需要去掉污点),而且没有高可用。稍微正式一点:3 台 Master + N 台 Node,Master 至少 2 核 4G,Node 根据业务负载定。etcd 对磁盘延迟敏感,强烈建议 SSD。
操作系统方面,Ubuntu 20.04/22.04 和 CentOS 7/8 都行,内核版本建议 4.x 以上。需要关闭 Swap,因为 K8s 的内存管理假设没有 Swap,开着会导致调度和 OOM 行为不符合预期。还需要加载br_netfilter和overlay内核模块,并设置一些网络参数(net.bridge.bridge-nf-call-iptables等),这些后面实操部分会具体写。
网络规划要提前定好三个网段:节点网段(物理机 IP)、Pod 网段(如 10.244.0.0/16)、Service 网段(如 10.96.0.0/12)。这三个网段不能重叠,否则路由会出问题。Pod 网段和 Service 网段在初始化时指定,之后不好改。
3.3 容器运行时选型:containerd 还是 CRI-O
前面说过,Docker 在 1.24 之后不再被直接支持。现在主流选择是 containerd 和 CRI-O。
containerd是从 Docker 拆出来的,成熟稳定,社区活跃,大多数教程和工具都默认支持它。它的配置文件在/etc/containerd/config.toml,需要配置SystemdCgroup = true来和 K8s 的 cgroup 驱动保持一致。国内环境还需要配置镜像加速,否则拉取 pause 镜像会超时。
CRI-O是 Red Hat 主导的,更轻量,专门为 K8s 设计。如果你用 OpenShift 或者偏好红帽系,可以选它。但生态和文档相对 containerd 少一些。
我建议新手直接用 containerd,踩坑少,资料多。安装方式也简单,Docker 的官方源里就有 containerd.io 包,或者用系统包管理器直接装。
3.4 网络插件选型:Calico、Flannel 还是 Cilium
网络插件(CNI)是集群搭建最容易出问题的环节。Pod 之间要能互相通信,靠的就是 CNI 插件。
Flannel最简单,配置少,适合学习和测试。它用 VXLAN 覆盖网络,性能一般,不支持网络策略(NetworkPolicy)。如果你只是搭个环境跑跑 Demo,Flannel 够用。
Calico是生产环境的主流选择。它支持 BGP 路由模式,性能好,支持网络策略,能精细控制 Pod 之间的访问。配置比 Flannel 复杂一点,但文档很全。Calico 的 IPIP 模式和 BGP 模式需要根据网络环境选,跨子网通信用 IPIP,同子网可以用 BGP 关掉 IPIP 提升性能。
Cilium基于 eBPF,性能最强,可观测性也好,但内核要求高(4.19+),配置也最复杂。适合对网络性能和可观测性有高要求的场景。
我的建议:学习用 Flannel,生产用 Calico,追求极致性能且团队有相应能力再考虑 Cilium。这篇笔记的实操部分我会用 Calico 来演示,因为它的配置过程能覆盖更多知识点。
4. 手把手搭建集群:从系统初始化到 Calico 网络就绪
4.1 系统初始化:每一步都有讲究
假设你有三台机器,IP 分别是 192.168.1.10(master)、192.168.1.11(node1)、192.168.1.12(node2),操作系统 Ubuntu 22.04。以下操作在三台机器上都执行。
设置主机名和 hosts 解析。主机名要能互相解析,否则 kubelet 注册节点时会出问题。
# 在 master 上 hostnamectl set-hostname k8s-master # 在 node1 上 hostnamectl set-hostname k8s-node1 # 在 node2 上 hostnamectl set-hostname k8s-node2然后在每台机器的/etc/hosts里加上:
192.168.1.10 k8s-master 192.168.1.11 k8s-node1 192.168.1.12 k8s-node2关闭 Swap。这是硬性要求,不关的话 kubelet 启动会报错。
swapoff -a sed -i '/swap/s/^/#/' /etc/fstab加载内核模块和设置网络参数。overlay模块是 containerd 需要的,br_netfilter是让 iptables 能过滤桥接流量。
cat <<EOF | tee /etc/modules-load.d/k8s.conf overlay br_netfilter EOF modprobe overlay modprobe br_netfilter cat <<EOF | tee /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注意:
net.ipv4.ip_forward = 1必须开,否则 Pod 跨节点通信会失败。这个参数是让 Linux 内核转发数据包,K8s 的网络模型依赖它。
安装 containerd。用 Docker 的源或者系统源都行。
apt-get update apt-get install -y containerd mkdir -p /etc/containerd containerd config default | tee /etc/containerd/config.toml然后修改配置文件,把SystemdCgroup改成true,并配置镜像加速(国内环境必须,否则拉不动 pause 镜像)。
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml镜像加速的配置在config.toml里找到[plugins."io.containerd.grpc.v1.cri".registry.mirrors]部分,加上:
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] endpoint = ["https://你的加速地址"]改完重启 containerd:
systemctl restart containerd systemctl enable containerd安装 kubeadm、kubelet、kubectl。添加 K8s 的 apt 源,然后安装指定版本。版本要统一,不要混用。
apt-get install -y apt-transport-https ca-certificates curl curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /' | tee /etc/apt/sources.list.d/kubernetes.list apt-get update apt-get install -y kubelet=1.28.0-1.1 kubeadm=1.28.0-1.1 kubectl=1.28.0-1.1 apt-mark hold kubelet kubeadm kubectlapt-mark hold是防止系统自动升级这三个包,避免版本不一致导致集群异常。
4.2 初始化控制平面:kubeadm init 参数详解
在 master 节点上执行初始化。命令看着长,但每个参数都有用。
kubeadm init \ --apiserver-advertise-address=192.168.1.10 \ --control-plane-endpoint=k8s-master \ --pod-network-cidr=10.244.0.0/16 \ --service-cidr=10.96.0.0/12 \ --kubernetes-version=v1.28.0 \ --image-repository=registry.aliyuncs.com/google_containers \ --cri-socket=unix:///run/containerd/containerd.sock逐个解释:
--apiserver-advertise-address:apiserver 对外通告的地址,其他节点通过这个地址访问它。填 master 的内网 IP。--control-plane-endpoint:控制平面统一入口,可以是域名或 VIP。单 master 填主机名也行,多 master 高可用必须用 VIP。--pod-network-cidr:Pod 网段,必须和后面 CNI 插件的配置一致。Calico 默认用 192.168.0.0/16,但我们可以指定 10.244.0.0/16,只要在 Calico 的 YAML 里改对就行。--service-cidr:Service 网段,不能和 Pod 网段、节点网段重叠。--image-repository:镜像仓库。国内环境用阿里云的镜像源,否则拉取官方镜像会超时。--cri-socket:指定容器运行时的 socket。containerd 的默认路径是这个,如果报错找不到,用crictl info确认一下。
初始化成功后,会输出一段加入集群的命令,类似:
kubeadm join k8s-master:6443 --token abcdef.1234567890abcdef \ --discovery-token-ca-cert-hash sha256:xxxxx把这段命令保存好,node 节点要用。Token 默认 24 小时过期,过期了可以用kubeadm token create --print-join-command重新生成。
然后配置 kubectl 的 kubeconfig:
mkdir -p $HOME/.kube cp -i /etc/kubernetes/admin.conf $HOME/.kube/config chown $(id -u):$(id -g) $HOME/.kube/config执行kubectl get nodes,应该能看到 master 节点,状态是 NotReady,因为网络插件还没装。
4.3 安装 Calico 网络插件:最容易翻车的环节
Calico 的安装方式有几种:用 operator、用 manifest、用 Helm。我习惯用 manifest,简单直接。
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/tigera-operator.yaml等 operator 跑起来之后,再创建 Calico 的自定义资源:
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/custom-resources.yaml但这里有个坑:默认的custom-resources.yaml里 Pod 网段是192.168.0.0/16,如果你初始化时用的是10.244.0.0/16,需要先下载文件改掉再 apply。
curl -O https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/custom-resources.yaml sed -i 's/192.168.0.0\/16/10.244.0.0\/16/' custom-resources.yaml kubectl create -f custom-resources.yaml然后观察 Pod 状态:
watch kubectl get pods -n calico-system等所有 Pod 变成 Running,再kubectl get nodes,master 应该变成 Ready 了。
注意:如果 Calico 的 Pod 一直起不来,大概率是镜像拉取失败。Calico 的镜像在 docker.io 上,国内环境需要配置 containerd 的镜像加速,或者提前把镜像拉下来导入。另外,如果节点有多张网卡,Calico 可能选错网卡导致通信异常,需要在
custom-resources.yaml里指定nodeAddressAutodetectionV4的interface字段。
4.4 加入工作节点与集群验证
在 node1 和 node2 上执行之前保存的 join 命令。执行前确保 containerd 正常运行、Swap 已关闭、内核模块已加载。
kubeadm join k8s-master:6443 --token abcdef.1234567890abcdef \ --discovery-token-ca-cert-hash sha256:xxxxx加入成功后,在 master 上kubectl get nodes应该能看到三个节点都是 Ready。
然后跑一个测试应用验证集群功能:
kubectl create deployment nginx-test --image=nginx:alpine --replicas=3 kubectl expose deployment nginx-test --port=80 --type=NodePort kubectl get pods -o wide kubectl get svc nginx-test用curl访问任意节点的 NodePort,应该能看到 Nginx 欢迎页。再测试一下 DNS 解析和跨节点通信:
kubectl run busybox-test --image=busybox:1.36 --rm -it --restart=Never -- sh # 在容器里执行 nslookup nginx-test wget -qO- nginx-test如果 DNS 能解析、HTTP 能访问,说明集群基本功能正常。
5. 踩坑实录:集群搭建常见问题与排查手册
5.1 节点 NotReady 的排查思路
节点 NotReady 是最常见的问题,排查顺序如下。
先看 kubelet 状态:systemctl status kubelet。如果 kubelet 没起来,看日志journalctl -xeu kubelet。常见原因有:Swap 没关、cgroup 驱动不匹配、容器运行时 socket 路径不对、证书过期。
如果 kubelet 正常运行但节点还是 NotReady,看节点详情:kubectl describe node <节点名>,重点看 Conditions 部分和 Events。常见原因有:CNI 插件没装好、网络不通、磁盘压力、内存压力。
CNI 问题最隐蔽。可以检查/etc/cni/net.d/目录下有没有配置文件,/opt/cni/bin/下有没有二进制。Calico 的话,看calico-nodePod 的日志,通常能定位到具体原因。
5.2 镜像拉取失败的解决套路
国内环境拉取 K8s 官方镜像和 Calico 镜像经常超时。解决办法有三个:
一是配置 containerd 的镜像加速,在config.toml里加registry.mirrors。二是用kubeadm config images pull提前拉取,配合--image-repository参数。三是手动docker pull或ctr pull之后ctr images tag改成 K8s 需要的名字。
我一般用第二种,初始化时指定阿里云仓库,省事。Calico 的镜像如果拉不动,可以找国内镜像源,或者用ctr从其他机器导入。
5.3 证书过期与集群恢复
K8s 的证书默认有效期一年。到期后 apiserver 会拒绝连接,kubectl 报x509: certificate has expired。解决办法是用kubeadm certs renew all续期,然后重启控制平面组件。
但如果是学习环境放了大半年没动,etcd 的数据可能也有问题。我遇到过 etcd 启动失败导致整个集群起不来的情况,最后是从备份恢复的。所以生产环境一定要给 etcd 做定期备份,用etcdctl snapshot save导出快照,存到异地。
5.4 常见问题速查表
| 现象 | 可能原因 | 排查命令 | 解决方式 |
|---|---|---|---|
| 节点 NotReady | CNI 未就绪 | kubectl describe node | 检查 Calico Pod 日志 |
| Pod 一直 Pending | 资源不足或污点 | kubectl describe pod | 调整资源或去掉污点 |
| Pod 一直 ContainerCreating | 镜像拉取失败 | kubectl describe pod | 配置镜像加速 |
| Service 无法访问 | kube-proxy 异常 | systemctl status kube-proxy | 重启或检查 iptables |
| DNS 解析失败 | CoreDNS 异常 | kubectl logs -n kube-system | 检查 CoreDNS 配置 |
| kubectl 连接拒绝 | 证书过期 | kubeadm certs check-expiration | 续期证书 |
| etcd 启动失败 | 数据损坏 | journalctl -u etcd | 从快照恢复 |
5.5 几个只有踩过才知道的细节
kubelet 的 cgroup 驱动必须和容器运行时一致。containerd 默认用 systemd,kubelet 也要配成 systemd,否则会出现 Pod 资源限制不生效、OOM 行为异常等问题。在 kubelet 的配置文件里设置cgroupDriver: systemd。
Calico 的 IPIP 模式在跨子网时才需要开。同子网内可以用 BGP 模式,性能更好。但 BGP 模式需要网络设备支持,如果交换机不支持 BGP,还是老老实实用 IPIP。
kube-proxy 的 IPVS 模式需要内核加载 ip_vs 模块。不加载的话 kube-proxy 启动会报错。modprobe ip_vs加上相关子模块,然后写到/etc/modules-load.d/里持久化。
etcd 的磁盘 IO 延迟直接影响 apiserver 性能。如果 etcd 的 WAL 日志写入延迟超过 10ms,apiserver 的响应就会变慢。用etcdctl check perf可以测试性能,不达标就换 SSD。
节点时间必须同步。K8s 的证书验证、Token 有效期都依赖时间。节点之间时间差超过几秒就可能导致认证失败。装个 chrony 或 ntp 保持同步,这是基本要求。
6. 集群跑起来之后:下一步该做什么
集群搭好只是起点,后面还有一堆东西要配。监控方面,Prometheus + Grafana 是标配,能看节点资源、Pod 状态、API 延迟。日志方面,EFK(Elasticsearch + Fluentd + Kibana)或 Loki + Promtail 收集容器日志。Ingress 方面,Nginx Ingress Controller 或 Traefik 提供七层入口。存储方面,根据环境选 NFS、Ceph、Longhorn 等。安全方面,配 RBAC、NetworkPolicy、PodSecurityPolicy(新版是 Pod Security Admission)。
我个人的习惯是集群搭好之后先跑一个完整的 Demo 应用,把 Deployment、Service、Ingress、ConfigMap、Secret、PVC 都用一遍,确认每个环节都通。然后再逐步加监控和日志。这样出问题的时候能快速定位是集群本身的问题还是应用配置的问题。
另外,kubeadm 搭建的集群,Master 默认有污点,不跑普通 Pod。如果资源紧张想让它也干活,可以去掉污点:kubectl taint nodes k8s-master node-role.kubernetes.io/control-plane:NoSchedule-。但生产环境不建议这么做,控制平面节点应该专用。
最后再分享一个小技巧:kubectl的命令补全能极大提升效率。source <(kubectl completion bash)临时生效,写到~/.bashrc里永久生效。再配个alias k=kubectl,敲命令快很多。这些细节看着小,但日积月累能省不少时间。