尧图精选

Kubernetes入门到实战:从核心概念到集群运维全攻略

🕒 发布时间:2026/10/1 22:36:00 📁 来源:尧图网络
1. Kubernetes 到底是什么先搞清楚这件事在正式开始折腾 Kubernetes 之前我想先聊一个很多新手都会踩的坑还没有弄清 K8s 到底是干什么的就急着去敲kubeadm init结果被一堆概念和报错轮番轰炸半个月后还在原地打转。我见过太多人是这样入门的在某个群里看到别人讨论 Kubernetes觉得是“云原生的未来”于是找到一篇教程照着复制粘贴几行命令启动了集群进来一个 Pod看到 STATUS 是 Running就觉得“我会 Kubernetes 了”。然后真正面对的问题是Pod 被人删了服务访问不通了发版本不知道从哪下手。这时候你会发现之前学的那些命令只是“在模仿工具的用法”根本没理解工具的设计思路。Kubernetes 本质上解决的是一个非常朴素的问题你有一堆服务器可能是物理机、虚拟机也可能是云上买的一堆实例你想在上面跑一堆容器应用并且希望这些容器能稳定地跑在“某个地方”能互相通信能被外部访问能在挂了之后自动恢复能让流量平滑地发版和回滚。你当然可以用脚本、用 systemd、用 docker compose 去自己拼一套方案但当你管理的容器数量从十个涨到一百个、从一百个涨到一千个你会发现“资源分配”“故障转移”“服务发现”“配置管理”这些问题会变得极其复杂而 Kubernetes 就是把这个复杂过程标准化、自动化的一套系统。所以在这篇里我打算不按传统教程那种“先介绍架构图、再讲每个组件”的套路走而是按我自己的理解把 Kubernetes 拆成几个维度来讲它由哪些核心对象组成一个集群是怎么从零到一搭起来的Pod 为什么是最小的调度单元网络模型是怎么回事以及日常使用中那些文档里查不到的经验和误区。这篇内容会很“实在”因为我自己也被坑过无数次我把这些心得写下来希望你能少走一些弯路。2. 它能解决什么问题以及为什么值得学经常有朋友问我我现在一个人维护几个小项目用 docker compose 管起来挺顺手的有必要上 Kubernetes 吗我一般不会直接说“有必要”或者“没必要”我会先让他搞清楚Kubernetes 不是 docker compose 的上位替代品它是一个面向多主机、多应用、大规模场景的“数据中心操作系统”。docker compose 解决的是“一台机器上的编排问题”比如我有三个服务依赖哪些镜像、开哪些端口、挂在同一个 network 下compose 写清楚就完了。而 K8s 解决的是“一群机器上的编排问题”我不关心某个容器具体跑在哪台机器上不关心某台机器挂掉会不会影响整个系统不关心流量如何从外部均衡地分发到各个副本。具体来说Kubernetes 主要替我解决了四个问题资源统一抽象与调度多台服务器的 CPU、内存、磁盘被抽象成一个统一的资源池K8s 按照我为每个应用声明的资源要求决定容器应被调度到哪台机器上。如果某台机器资源不足它会自动安排到别的机器上。状态自愈与故障转移如果某个应用实例也就是 Pod挂了K8s 会检测到异常并重新拉起一个新的实例。如果某个节点机器宕机了这台机器上的 Pod 会被自动转移到其他存活节点上。这套逻辑在传统运维里要用 process manager、健康检查脚本、漂移工具配合才能实现而在 K8s 里是底层的原生的能力。服务发现与负载均衡一个应用需要访问另一个应用的时候不需要去查对方的 IP 是什么只需要一个稳定的名字ServiceK8s 负责把流量均衡到后端的所有 Pod 上。这解决了微服务架构里最常见的“服务地址频繁变动”的问题。伸缩与发布策略当流量涨了我可以通过一条命令把某个应用的副本数从 2 扩到 10缩容同理。发布时我不需要停机可以用滚动更新的方式一批批替换旧 Pod持续提供服务。这些能力放在传统运维体系里每一样都需要独立的工具链和专人维护而 K8s 把它们集成到一个统一的标准框架之内。从人才市场角度看近几年无论是大厂还是中小企业凡是后端业务有一定规模节奏的几乎都在用 Kubernetes 或云厂商的托管 K8s 服务。学它不只是为了追热点而是因为它已经成为现代后端和运维工程师的基础技能之一。但我必须提醒一句如果你的项目只有一两个应用、一台服务器、一天几十个请求确实没必要强行上 K8s。技术选型永远要看问题本身工具是拿来解决问题的不是拿来增加问题的。K8s 的复杂度是真实存在的尤其是有状态应用和网络调优的部分联调起来很磨人。决定要用之前先问问自己我是否真的需要多台机器的资源调度我的应用是否要频繁发版是否需要一个统一的运行环境来简化交付有肯定答案再往下一步走。3. 从零搭建一个 Kubernetes 集群先搞清楚这些折腾点现在假定你决定要上手了。摆在面前的第一步不是你敲命令而是“集群怎么搭”。一个典型的 Kubernetes 集群通常是若干台 Linux 机器组成一台或三台作为控制平面运行 kube-apiserver、kube-scheduler、kube-controller-manager、etcd 这几个核心组件若干台作为工作节点运行 kubelet、kube-proxy 与容器运行时containerd / CRI-O承载实际的应用 Pod。很多初级教程推荐你“用一个命令安装全家桶”我反而不建议你那样做。你直接把最复杂的部分用脚本隐藏了出了问题反而更懵。比较可控的方式是用kubeadm来跑一遍。这也是目前社区最主流的、可复现性最好的方式之一。kubeadm 的定位是“引导程序”它负责把集群中最基本的控制平面组件和工作节点组件装上、拉起、配置好但不会替你装网络插件也不会给生产环境做高性能调优。这个“半自动”的特性其实很好因为它给了你了解各组件角色与配置的过程就踏踏实实地看它初始化和连通。3.1 搭建前的准备工作和版本选择我建议你至少准备三台独立的机器或者虚拟机每台 2 核 4GB 内存以上操作系统选择 Ubuntu 22.04 LTS 或者 CentOS 7.9 这类市面教程覆盖度比较高的版本。注意控制平面的机器内存最好大一点因为 etcd 和 apiserver 还是比较耗内存的2GB 以下跑起来会很吃力。版本选择是我要单拎出来讲的一点。很多人喜欢“追求最新”Kubernetes 版本更新也确实很快一年大概出三个大版本但我要说的是除非你有特殊需求否则不要在生产环境追新。以我经验来看至少要选择一个已经发了两个以上 patch 版本的稳定版本。比如你写 kubeadm 的时候看到v1.26.0是早期发布版过一段时间它会出v1.26.4、v1.26.8之类的补丁版本后者更稳。同时你的操作系统内核版本、容器运行时版本、网络插件版本都要和 Kubernetes 版本匹配尤其注意容器运行时Kubernetes 从 v1.24 开始已经把默认运行时从 Docker 迁到 containerd如果你还用 Docker 作为底层运行时需要额外装 cri-dockerd 这类适配层。现在官方支持列表里 containerd 是绝对的主流建议从准备阶段就统一用它。3.2 kubeadm init 的执行流程里到底发生了什么我第一次跑kubeadm init时一看到终端里刷刷刷输出一堆[init] using kubernetes version: v1.26.0、[preflight] running pre-flight checks这种日志心里就发怵。后来我特意把文档翻了又翻结合断点排查把这段过程理清楚了。它大概做了以下几件事检查当前机器的基本条件CPU 核数、内存大小、磁盘空间、hostname 是否符合规范等。preflight这一段就是在做体检哪里有硬性问题比如开启了 swap 没有关、端口被占用它就会直接报错并停止。拉取控制平面组件镜像K8s 的核心组件apiserver、controller-manager、scheduler、etcd、coredns都是以容器镜像形式跑的kubeadm 会从镜像仓库拉取对应版本比如registry.k8s.io/kube-apiserver:v1.26.0这样的地址。生成 PKI 证书与 kubeconfig 配置文件K8s 是高度安全敏感的系统组件之间通信都走 TLS 双向认证所以需要为 apiserver、scheduler、controller-manager、kubelet 等生成各种证书生成的位置一般在/etc/kubernetes/pki目录下这些证书后续给节点加入集群时也要用。生成静态 Pod 清单静态 Pod 是控制平面组件最常见的运行方式。kubeadm 把 apiserver、etcd、controller-manager、scheduler 的 YAML 配置写好放到/etc/kubernetes/manifests目录。kubelet 会专门盯着这个目录发现里面的文件就自动创建并守护对应的 Pod。你看它这里就用到了 K8s 自己的能力来管理 K8s 的组件这种“自举”思路挺巧妙。执行控制平面初始化把 initial nodes 的 role 标记为 control-plane写入认证配置把 kubeadm 生成的 bootstrap token 提供给后续加入的节点使用。打印 join 命令等这一切跑完它会输出一条以kubeadm join开头的命令这串命令需要用在你后续添加 worker 节点时。如果你看到 init 过程在某个环节卡住最常见的几个原因是镜像拉不下来、apiserver 容器起不来、证书目录权限不对、hostname 冲突等。排查手段也很直接用journalctl -u kubelet -f去看 kubelet 实时日志或者看crictl ps -a查看 containerd 里容器实际状态。日志是真话报错才是答案。3.3 CNI 网络插件不装它集群就是假的集群 init 完你如果直接去看节点状态会发现 Node 一直是 NotReady。我见过不少新手这时候很慌以为集群搭失败了。其实不是原因很简单集群内的 Pod 网络还是空白状态各节点之间没有打通网络健康状况都没法上报。这时候就需要选择并安装一个 CNI 网络插件。CNI 插件里比较常见的是 Calico、Flannel、Cilium。我个人的习惯是测试环境图省事可以用 Flannel它用 VXLAN 把二层网络封装起来配置最简单两行 YAML 就能跑起来生产环境我基本用 Calico它走的是 BGP 路有模式网络转发效率更高还可以定义 NetworkPolicy 来做更精细的访问控制。Cilium 是这几年比较火的选择它基于 eBPF 技术能带来更强的可观测性和更优的性能但相对的部署和调优门槛也更高。选择网络插件时一个关键参数是“Pod 网段”也就是--pod-network-cidr。例如你安装 Calico 默认用的192.168.0.0/16那么在kubeadm init的时候必须把这个参数带上让 apiserver 知道给每个节点分配 Pod 网段的区间。如果 init 的时候没指定后面再装 Calico 就会因为网段不匹配而出现各种诡异问题。我有一次就是 init 忘了带参数装完 Calico 之后 Pod 一直 CrashLoopBackOff查来查去发现是 IP 分配冲突这个错误很典型。4. Kubernetes 的核心对象把这个世界观彻底弄清集群起来了下一步就要开始往里面“跑应用”了。但这里我强烈建议你先把一组核心对象的关系捋清楚。很多教程喜欢把 Pod、Deployment、Service、Ingress 一个个孤立地讲然后读者就会形成一个碎片化的印象好像在不断地“创建资源”但不知道资源之间是怎么串起来的。我把它们串成一条线来理解就简单多了。整个过程可以这样描述你想部署一个“订单服务”这个服务跑在几个容器里。于是你创建一个Deployment它负责管理“期望状态”——要有三个副本每个副本用order-service:1.0这个镜像端口 8080 等。Deployment 收到指令后会创建ReplicaSetReplicaSet 再创建具体运行的PodPod 就是你的容器进程在集群中的“房子”。此时你的服务虽然跑起来了但外部并不知道它有谁、在哪台机器上。于是需要创建Service它是一个稳定的“门牌号”集群内部的虚拟 IP它跟踪这组 Pod 的标签并把访问流量转发到后端的 Pod 上。最后如果你的外部用户需要通过域名访问这个服务就用Ingress把 HTTP 流量按 Host、路径规则转发到对应的 Service 上。这一条链路理顺了K8s 的大部分操作你都能推理出该用哪个对象。接下来我们逐一把这几个对象拆细一点不讲太多理论每一点都落在实际使用场景上。4.1 PodK8s 世界中的“最小调度原子”Pod 是 Kubernetes 中最核心也是最小化的调度单元。你可以把 Pod 理解为“一组紧密相关的容器的集合”最典型的是一个主业务容器加若干辅助容器sidecar。很多人说“Pod 里跑的就是容器”这句话不算错但没说到根上——Pod 的真正特殊性在于它内部的多个容器共享同一个网络命名空间、同一个存储卷。什么意思呢就是说 Pod 里所有容器共享同一个 IP 和端口空间可以通过 localhost 互访也能挂载同一块数据盘。这种“同生共死”的绑定关系不是一个个独立容器能轻松模拟出来的。实际使用中的注意点Pod 里的容器没有超时概念只要 Pod 实例存在里面的容器就始终存在除非某个容器的进程崩溃导致整个 Pod 被重建。Pod 是临时资源你可能听说过“Pod 是很脆弱的”它随时可能因节点故障、资源回收或副本扩缩而被销毁重建。所以应用必须设计成十二要素风格无状态、启动快速、日志输出到 stdout才能在 Pod 的频繁重建中存活。不要把多个不相关的容器塞进同一个 PodPod 里的容器应该是一个整体单元的组成部分比如一个 Web 服务容器加一个日志转发 sidecar。如果你把两个独立业务硬塞在一个 Pod 里它们就要共享生命周期和 IP发版和排障都会很痛苦。我见过一个常用例子一个 POD 内有 一个 业务容器 和 一个 cloud-sql-proxy 容器前者负责接收 HTTP 请求后者负责维护到数据库的加密连接。这两个容器就必须在同一个 Pod 里跑因为它们是同一份服务所必需的并且共享同一块内存和 socket。这种场景是 sidecar 模式的最佳选择。4.2 Deployment声明式管理才是灵魂Deployment 是真正体现 Kubernetes 对“声明式”理念的对象。你用 YAML 里写好“我要跑几个副本、什么镜像、什么资源需求”提交给 K8s它就持续保证系统里的实际情况和你描述的一致。如果你手动删掉了一个 PodDeployment 会自动创建一个新的因为“实际数量”不符合“期望数量”。这个机制看起来很神奇本质上是一个控制循环control loop在不停地对比状态和恒温器控制室内温度的思路是同构的。Deployment 还给了我一个极其重要的能力滚动更新。你不需要停机发版只要把 Deployment 的镜像版本改到新版本Kubernetes 就会自动创建一个新的 ReplicaSet然后逐步增加新 Pod 数量、减少旧 Pod 数量直到全部替换完成。这个过程里如果新版本有严重问题可以一键回滚到上一个版本对服务的连续性几乎无感。写 Deployment 的几个实操建议总是给 Pod 打精准的labels不只是 app 名最好带上版本或组件类型后续运维排障和 Service 选择器匹配时非常关键。加上resources请求。K8s 的调度和质量保证是基于requests最低需求和limits上限约束来做的。如果你的资源是裸奔状态当宿主机内存紧张时内核 OOM Killer 会优先杀掉那些没设 limits 的进程。配上readinessProbe和livenessProbe这两个探针决定了一个 Pod 是否“可服务”以及“是否活着”。如果没有K8s 就无法判断你的服务是不是真的 ready滚动更新和自愈能力就直接打了折扣。4.3 Service地址稳定器和负载均衡器Pod 的 IP 是会变化的而且重建后可能落到另一台节点上。所以如果你直接在应用里写死另一个应用 Pod 的 IP那你的系统基本上就是薛定谔的可用状态——随机断开。Service 解决了这个问题它提供一个稳定的虚拟 IP并绑定到一组 Pod通过 label selector 匹配当请求到达这个虚拟 IP 时Service 会把流量转发给集群里的某个 Pod。Service 的类型里ClusterIP是最常用的它让集群内部可以通过这个地址访问服务NodePort是给外部访问用的最简单方式——把 Service 绑定到节点上的某个端口外部访问节点IP:节点端口即转发到 ServiceLoadBalancer则是云环境中由外部负载均衡器提供服务入口的方式生产环境中用得最多。这里有一个新手常踩的坑定义 Service 时没有加port/targetPort的区分导致流量到了 Service 后全部被转到 80 端口而后端 Pod 真正监听的可能是 8080于是 502。所以落盘时你一定要分清port是 Service 对外暴露的端口集群内其他服务访问时用的targetPort是后端 Pod 容器实际监听的那个端口。4.4 Ingress把 HTTP 流量引到正确门口Service 解决的是集群内访问问题但外部用户通常不会直接访问 ClusterIP也不会手动访问每个 NodePort。Ingress 的价值在于它充当“外部流量进入集群的大门”并且按域名、路径把流量路由到不同的 Service 上。举个例子你有一个域名api.example.com其中/orders路由到订单服务/users路由到用户服务。你只需要部署一个 Ingress 资源以及背后的 Ingress Controller比如 Nginx Ingress定义匹配规则流量入口就统一了。这和传统 Nginx 的反向代理配置很相似但全部变成了声明式的 Kubernetes API 对象。注意Ingress 资源本身只是规则真正干活的还是 Ingress Controller通常是 Nginx Ingress Controller 或 Traefik。你只创建一个 Ingress 对象而不部署 Ingress Controller 的话规则是不会生效的。初期经常有人照着教程创建了 Ingress 后发现域名访问不通排查几天最后发现 Controller 压根没部署这种小坑足够记一辈子。5. 集群日常运维的核心技能真正上手用的都在这好不容易集群和各种对象都跑起来了接下来更多的是“维持系统平稳运行”的功夫。这部分可能是你工作中投入时间最多的部分我直接把核心技能拆成几个模块来讲。5.1 资源清单管理kubectl 只是钥匙YAML 才是房子很多人习惯直接在命令行里敲kubectl run创建一个 Pod这是最糟糕的习惯之一。Kubernetes 的核心工作方式应该是“面向 YAML 的声明式管理”。所有资源都应该以 YAML 文件形式存放在项目仓库里用kubectl apply -f提交。好处非常明显配置可以 review、可以版本化后续变更时 diff 一下你知道自己改了什么删除时可以直接用-f指向原来的文件避免遗漏实操建议在写 Deployment YAML 时先把最小集写出来用kubectl apply --dry-runclient -f xxx.yaml做语法校验再加参数而不是上来就写一个 80 行的大文件。等 deploy 报错之后排查会更容易因为你知道每次变更的边界在哪。5.2 查看状态和排障套路按顺序来我发现很多初学者的排障顺序是混乱的——一会儿看 Pod 日志一会儿查 Event一会儿去翻节点最后什么都查不到。我自己总结了一套固定的排查链路按顺序来效率极高先看资源状态kubectl get pods确认 STATUS 是不是 Running如果不是记录 CrashLoopBackOff、ImagePullBackOff、Pending 等关键状态。看 Eventskubectl describe pod name的 Events 部分会告诉你为什么 Pod 没跑起来比如镜像拉取失败、端口被占用、资源不足无法调度等。这里的信息往往是最直接的答案。看容器日志如果 Pod 是 Running 但应用有异常kubectl logs -f pod -c container去追踪 stdout 日志多容器别忘了加 -c。现场探入: 如果日志还不够就用kubectl exec -it pod -- /bin/sh进容器内部看进程、看环境变量、看网络。这是最后一步能让你直接观察到容器内部实际情况。这套链路我建议你写成一个速查卡片贴在显示器旁边或者记在笔记里遇到问题就按这个套路过一遍。相比漫无目的地乱查能省下大把时间。5.3 版本发布与回滚的实操技巧发布这件事实操里远比文档复杂。虽然 Deployment 的滚动更新是自动的但没有配置好的话很可能发布到一半才发现问题或者新起 Pod 一直起不来。几个关键配置一定要提前调好maxSurge滚动更新时最多允许多几个临时 Pod。默认 25%如果你有 4 个副本可以额外再起 1 个新 Pod更新期间最多 5 个能保证“下半场压力大不会卡死”。maxUnavailable更新时最多允许几个老 Pod 不可用。默认 25%如果只有一个副本而且设置为 0那更新期间老的 Pod 会一直留着直到新 Pod 确认可用这种方式更谨慎但发布速度稍慢。minReadySeconds新 Pod 至少要“准备好了”多少秒才算数。这能避免临时资源波动导致 Pod 很快就绪但下一秒就崩掉。生产环境我一般设 15~30 秒。回滚时用kubectl rollout undo deployment/xxx就能直接回到上一个版本。一次回滚所得的教训是发布前最好把kubectl rollout history先看一下确认有几个版本可回滚。提交记录特别多的话默认会保留最后十个多了旧的会被淘汰。5.4 存储有状态应用避不开的话题K8s 对无状态应用非常友好但有状态应用一上来存储就是最大的拦路虎。一个数据库要跑在容器里数据必须持久化到磁盘上。K8s 里做持久化主要靠 PVPersistentVolume和 PVCPersistentVolumeClaim这套抽象机制。PV 就像是仓库里的一块磁盘容量PVC 则是应用向 K8s 声明“我需要多大空间”。而在云环境中你通常不需要手动创建 PV只要 PVC 声明好云厂商提供的 StorageClass 会自动为你动态创建 PV。实际部署中的关键抉择是能不能把有状态服务跑在 K8s 上我的建议是初期不要着急迁移数据库到 K8s。如果你的库服务比较重要继续跑在传统虚机上让 K8s 管好无状态应用能快速见效。等对存储和网络方案都很熟了再考虑把有状态服务迁进去。如果确实要在 K8s 中运行数据库用 StatefulSet 而不是 Deployment因为 StatefulSet 为每个 Pod 提供稳定的网络标识和持久化存储绑定。比如一个三节点的数据库三个 Pod 的名字分别是mysql-0、mysql-1、mysql-2即使重启哪个 Pod 挂载哪个盘也是稳定的。千万别把数据卷挂在节点本地目录上。那意味着如果 Pod 漂移到另一台节点数据就找不回来了。要么上云存储要么用分布式文件系统如 NFS、Ceph。5.5 资源限额不做防护早晚要在生产环境出问题最后专门聊聊资源限额。我一向认为K8s 集群里跑应用必须写 resources这是铁律。没有资源请求的应用调度器没法保证它落在有足够资源的机器上没有资源限制的应用万一内存泄漏时会把整个节点拖垮其他 Pod 也跟着遭殃。一个经验参数是请求requests不要设得太满比如一个 Pod 要 2 核、4GB 内存那你请求 1.5 核、3GB留一点余量给突发负载上限limits如果是 4 核、8GB那么它就有一定的“上冲空间”。这个“请求”和“上限”之间的差值就是系统可以利用的弹性但要特别注意limits 会影响 CPU 的强制限制和内存 OOM 的触发时机设太紧反而容易被杀设太松容易拖垮宿主机。通常我会按“requests 平均负载 x 1.25、limits requests x 2”这个档位去起步跑两周看监控再微调。6. 常用排查命令速查遇到问题随手抄走这部分我把日常用的最多的排查命令整理成一个速查表都是工作中验证可行的高频组合直接瘦身掉那些全量输出的废话只保留关键信息。目的命令查看全部节点状态kubectl get nodes -o wide查看某节点的资源使用kubectl top node node-name查看当前命名空间所有 Podkubectl get pods -o wide查看某个 Pod 的详细信息Eventskubectl describe pod pod-name查看某个 Pod 的实时日志kubectl logs -f pod-name -c container-name进入 Pod 内部的 shellkubectl exec -it pod-name -- /bin/sh查看某个资源的所有 k8s 对象kubectl get all -n namespace查看集群中所有 API 资源列表kubectl api-resources查看某个 Service 的 endpointskubectl get endpoints service-name查看 Deployment 的发布历史kubectl rollout history deployment/deployment-name回滚到上一个版本kubectl rollout undo deployment/deployment-name查找哪个 Pod 占了高内存kubectl top pods -A | sort -k4 -h实际用下来kubectl describe里的 Events 和kubectl get events --sort-by.metadata.creationTimestamp这两条是排查问题的第一利器比自己去猜原因高效太多了。有些问题看起来像网络问题实际 Endpoints 里压根没有可用后端一眼就能看出来。7. 进阶走向生产级集群前那些绕不开的功课如果你已经可以在测试环境里跑通一套完整的应用下一步自然是思考“怎么让它像一个正式系统”该有的样子。这里面有四个方向是我觉得必须补的功课而且越早开始越好。7.1 高可用与控制平面的架构设计测试环境里一台控制平面就够了但生产环境里控制平面挂了整个集群的调度和管理就瘫了。业界标准做法是用三台控制平面做 HA控制平面的关键组件apiserver、etcd也都要多副本冗余。对应地kubeadm 提供了kubeadm init --control-plane-endpoint参数用一组 VIP虚拟 IP负载均衡指向三台控制平面之后的工作节点都通过这个 VIP 加入集群。etcd 至少三节点形成小集群这样即使丢掉一台也不会丢数据。第一次搭 HA 会比较烦尤其在 VIP 的配置和证书签发的互通上一定要保持耐心但搭完之后心里就踏实了。7.2 多环境与命名空间的管理如果把什么都放默认的default命名空间时间一长就是一团乱麻。我的经验是把环境隔开开发环境用dev命名空间、测试用staging、生产用prod。不同团队也可以用各自独立的命名空间。命名空间之间通常默认是不允许互相访问的可以用 NetworkPolicy 来定义具体允许的访问关系作为安全边界的一部分。同时可以借助工具比如 Helm来管理部署模板。Helm 把一组 K8s 资源打包成 chart用values.yaml来渲染不同环境的差异比如镜像 tag、副本数、域名。这样你在 dev 和 prod 之间切换不用维护两套 YAML只改参数就够了。Helm 的模板语法初看有点复杂但确实是现在实际工程里最流行的应用发布方式。7.3 安全RBAC、镜像扫描与密钥管理K8s 的默认配置并不是开箱即安全。生产环境至少要做三件事RBAC给不同成员分配最小权限。比如研发只能看自己命名空间的 Pod只有运维才允许修改 Deployment。用 kubeconfig 区分身份和权限而不是所有人共用一个admin账号。镜像扫描容器镜像来自哪里要可控尽量使用私有镜像仓库Harbor 等在 CI 里接入镜像扫描Trivy、Clair 等排查高危 CVE。供应链攻击是目前非常现实的威胁不可忽视。密钥管理不要把自己的密码写死在 YAML 里K8s 的 Secret 是一个 base64 编码的资源但它只是基本隔离不等于加密。生产建议挂载外部密钥管理服务Vault、AWS Secrets Manager 或云上的凭据管理来同步 Secret再加一层保护。7.4 可观测性没有监控你就是在盲飞最后生产级集群必不可少的是监控和日志体系。至少要做到三件事Metrics在集群内部署 Prometheus把节点指标、Pod 指标、应用自定义指标都采集起来配合 Grafana 打仪表盘。kubectl top只能看到短期数据长期趋势还得靠监控保存和分析。日志Pod 里的应用日志统一输出到 stdout集群再通过 Loki/EFK 等方案采集、检索方便排障时按 trace ID 或请求 ID 查日志。链路追踪如果是微服务架构建议引入 OpenTelemetry 统一埋点把跨服务的调用链可视出来。K8s 会让应用拓扑变得更分散没有链路追踪系统出问题的时候定位范围会非常痛苦。这几块内容单独拎出来每一块都可以写一篇长文我的建议是先跑通 Prometheus Grafana 这一环然后逐步补日志链路追踪等你有多个服务后再说不要一口气全上导致精力分散。8. 常见问题快问快答与避坑锦囊这一节我专门收集了我这些年被问得最多的新手问题它们不是理论问题全都是“我发现不对劲然后查了很久”整理成问答形式你可以直接对号入座。Q1为什么 Pod 一直显示 PendingPending 指调度器还没把这个 Pod 放到某个节点上最常见的原因是资源不够、节点有污点taint不匹配、PVC 没有绑定成功。处理顺序是先看kubectl describe pod的 Events提到0/2 nodes are available就说明集群里没有满足请求的资源提到node(s) had taint就考虑是否要加 toleration提到waiting for a volume to be created就去查 PVC 状态。Q2为什么 Pod 一直 CrashLoopBackOff字面意思是容器启动后崩溃然后 K8s 不断尝试拉起每次失败间隔会变长。最常见的原因是应用启动时依赖的服务还没就绪比如数据库连接超时、环境变量缺失、镜像启动命令错误、硬件资源不足导致进程被杀。重点看kubectl logs里应用的退出日志也可以kubectl describe看退出码。128信号码对应 kill 信号退出码 137 通常是内存超限被系统杀掉。Q3为什么 Service 访问不通这个我踩过最多次。排查按顺序来先确认 Deployment 里 Pod 是 Running 且 ready再看 Service 的 Selector 是否和 Pod 的 labels 匹配接着kubectl get endpoints看有没有后端 IP。如果 endpoints 是空的说明 Selector 没匹配上再检查spec.selector是否多了空格或拼写错误。Selector 写错是这个坑里最隐蔽的原因YAML 里一个缩进差异就会导致完全匹配不上。Q4为什么节点重启后所有 Pod 都不自动恢复了大概率是节点标记了NoExecute污点或者 Pod 走的是静态文件方式、没有 controller 管理。更常见的是以下场景系统重启后 kubelet 因为网络或容器运行时没起来而无法初始化Pod 一直 Pending。用systemctl status kubelet和journalctl -u kubelet看具体报错再按提示解决。Q5kubeadm init 时提示端口被占用怎么办把之前测试环境的残留清理干净或者检查是不是有别的服务占用了 6443、2379-2380、10250 这些端口。通常用的是ss -tlnp | grep -E 6443|2379|10250来找出占用进程杀掉或停掉即可。更干净的方案是直接换一台新机器重新开始避免各种残留问题造成干扰。Q6Pod 内应用访问外网不通怎么排查先确认节点上iptables规则有没有被修改过或者是镜像里 DNS 配置的问题。在 Pod 里执行cat /etc/resolv.conf看 DNS 配置是否为集群内 CoreDNS 的地址试着nslookup kubernetes.default看解析是否正常。如果 DNS 是好的但 TCP 握手超时很可能是集群网络策略比如 Calico 的 ingress/egress 规则拦掉了出站流量。9. 从入门到实战我建议你走这样一条路讲了这么多原理和注意点最后把我自己觉得比较省力、也比较舒服的 K8s 学习路径分享给你。这个过程不一定最快但它的特点是每一步都在“亲手做事”不会停留在只看文档的状态而且每一步都驱动你学习下一块知识比较不容易中途弃坑。第一阶段本地跑起一个单机集群用 kind 或者 k3d 在本地快速起一个小集群。kind 是 Kubernetes in Docker 的意思它用 Docker 容器作为 K8s 的节点一条命令就能把控制平面和 worker 节点拉起来。你可以在本地用一个 yaml 配置文件定义集群然后立刻开始练习部署应用。这一步的目标是让你对“集群是一个可以由多个节点拼起来的系统”这件事形成直观感受。第二阶段部署一个实际的小项目比如一个简单的博客或者一个 API 服务把完整的 Deployment、Service、Ingress 配置写出来。反复做“改镜像版本 - apply - 滚动更新 - 回滚”这套动作直到不假思索就能完成任务。这个阶段不要跳着走熟练了之后再加 ConfigMap、Secret、PVC 这些对象。第三步自己搭一个多节点集群用 kubeadm 在三台虚拟机或云主机上手动搭一个“一控制平面 两工作节点”的集群。这一遍不用太快因为你会遇到真实网络、证书、运行时版本、CNI 兼容这些在本地不起眼的坑。把它们逐个弄清楚比你快速读完十篇博客都有价值。第四步模拟故障和恢复在你搭好的集群上故意制造故障手动删掉多副本 Deployment 里的 Pod、把某台 worker 节点shutdown、给节点加 taint、用kill -9杀掉某个容器进程。观察 K8s 如何自愈哪些情况下它可以自动恢复哪些情况下需要人工干预这些实验能帮你建立对“自愈”这件事的正确预期——它能修复很多问题但绝不是万能。第五步参与真实项目或开源社区从中选择一个相对小的集群项目自己练习为主或参与开源项目的 containde 化部署比如部署一个开源的应用如 WordPress、GitLab前期的可以绕开有状态难题从中练习如何把它拆成 Deployment如何接入已有存储。真实项目会逼你面对资源规划、版本管理、权限隔离这些之前一直想绕开的问题而这些恰恰是生产运维的核心能力。这套路径走下来大概需要一个月时间每天投入 1~2 小时。它的价值不在于“学得快”而在于你遇到的每个问题都是真问题解决后都沉淀成了你说得清的技能。零散地刷文档、跟教程哪怕刷一百遍遇到一次真实故障还是会懵而亲手从零搭过一次集群外加练过排障看别人讨论 K8s 的时候你就会知道自己不再是一个看热闹的旁观者了。个人经验是Kubernetes 真正给人带来信心的那个瞬间不是第一次集群初始化成功也不是第一次把应用跑起来——而是某天半夜你的一个服务实例挂了集群自动把它在其他节点重新拉起你早上看到邮箱里的告警才想起来昨晚发生了什么。那种“系统替我守着”的感觉比任何命令跑通的快感都实在。之后你会慢慢意识到这门技术最难的不是“会用”而是你愿意不愿意信任它把复杂的东西交出去同时理解它所有的边界和脾气。上手、踩坑、总结、进阶循环往复这是每个 K8s 使用者都要走的一段路希望你走得比我们稳一点。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →