Kubernetes 核心概念与集群实战避坑指南

发布时间:2026/10/12 14:56:12
Kubernetes 核心概念与集群实战避坑指南
简介《Kubernetes in Action》英文原版电子书是一本面向容器编排技术学习者的系统化参考手册适合正在使用或计划采用Kubernetes的开发者、DevOps工程师与架构师。这本书聚焦Kubernetes在生产环境中的部署、扩展与管理系统讲解了命名空间、Pod、工作负载、服务发现、配置管理、持久化存储与安全防护等核心知识帮助读者从零构建对分布式应用编排的完整理解。资源包内仅有1个PDF文件压缩后约11.1MB轻量便于在电脑、平板等设备上阅读和检索。目前已有436人学习下载。书中内容按照集群级资源、部署、服务、配置、存储等模块展开并提供一份Kubernetes资源速查表列出各资源的API版本与用途同时通过大量示例演示了如何声明式发布应用、暴露服务、配置密钥以及使用持久卷保存数据。这些内容既适合作为入门阶段的系统教程也可作为日常集群运维和认证备考的案头参考资料。1. Kubernetes In Action这份英文原版 PDF 值不值得啃几年前我还在用 docker-compose 一把梭直到接手一个需要横向扩容的线上项目才真正意识到 kubernetes 不是一个会写 YAML 就行的工具。当时手边就放着这份 Kubernetes in Action 英文原版 PDF原以为是本劝退大部头翻完才发现里面把 Pod、控制器、调度器这些概念讲得比网上绝大多数文章透。它解决的不只是怎么装集群而是为什么 K8s 要这么设计——这对排查问题特别关键。适合两类人一类是被 K8s 面试题追着跑的新手一类是想把集群调稳的运维或后端开发。2. 先弄懂三个抽象Pod、Service、控制器工作负载是如何被编排的2.1 Pod为什么它是调度和资源分配的最小单位很多人上手 K8s 时第一个疑惑是既然有容器为什么非要再包一层 Pod其实把一个 Pod 理解成进程组就顺了。单容器场景下 Pod 只是壳但多容器场景里同一个 Pod 内的容器共享网络命名空间和存储卷意味着它们可以通过 localhost 互相访问也可以挂载同一块数据盘。最常见的搭档是业务容器加 sidecar 容器——比如日志采集器跟着业务容器一起跑业务在哪个节点它就在哪个节点不用单独维护一套映射。实际排查时你几乎所有的操作都围绕 Pod 展开。我一般先执行kubectl get pods -o wide看状态再kubectl describe pod看事件。后者是排查的第一现场PullImage 失败、探针失败、调度不满足条件都会以事件的形式出现在末尾的 Events 里。# 查看所有命名空间下的 Pod 及所在节点 kubectl get pods -A -o wide # 查看某个 Pod 的详细事件与状态 kubectl describe pod pod-name -n namespace第一行命令的-o wide会多输出节点 IP 和 Pod IP方便你确认 Pod 到底被调度到了哪台机器第二行是定位问题的关键步骤描述信息里的 Events 区块记录了最近发生的所有调度与运行事件比如镜像拉取失败、端口冲突、内存不足。大多数异常在这里都能直接看到原因而不是靠猜。2.2 Service稳定接入入口kube-proxy 到底做了什么Pod 是会被创建和销毁的IP 也随之变化所以需要 Service 提供一个稳定的访问入口。Service 的底层机制不复杂它是一组 iptables 规则由 kube-proxy 维护把发往 Service IP 的流量转发到后端某个 Pod 的 IP 上。种类主要有三种选型看场景Service 类型访问范围适用场景备注ClusterIP集群内部服务间调用默认类型外部无法直接访问NodePort集群外部通过节点 IP 访问快速对外暴露端口端口范围默认 30000-32767LoadBalancer公网/云环境面向外部流量的生产服务通常由云平台负载均衡器实现一个常见的坑是把 Service 的 selector 写错导致没有后端 Pod 被选中。kubectl get endpoints能立刻看出来——如果 Endpoints 列表为空说明 Service 和 Pod 的标签没对上。这时候回头查 Deployment 里的metadata.labels和 Service 的spec.selector是否一致多半是少写了或者值写错了。2.3 控制器Deployment、StatefulSet 与 ReplicaSet 的分工ReplicaSet 负责维持指定数量的 Pod 副本但日常你很少直接操作它而是通过 Deployment 来管理。Deployment 在 ReplicaSet 之上加了滚动更新和回滚能力适合无状态服务。StatefulSet 则给有状态服务提供稳定的网络标识和持久化存储绑定比如数据库、消息队列但复杂度也更高节点故障时恢复步骤更繁琐。apiVersion: apps/v1 kind: Deployment metadata: name: web-demo labels: app: web-demo spec: replicas: 3 selector: matchLabels: app: web-demo template: metadata: labels: app: web-demo spec: containers: - name: web image: registry.example.com/web-demo:v1.2 ports: - containerPort: 8080 resources: requests: cpu: 100m memory: 128Mi limits: cpu: 500m memory: 512Mi这份 YAML 的关键点有三个。selector.matchLabels必须和template.metadata.labels一致Deployment 靠这个标签管理它创建的 Podreplicas声明期望副本数控制器会保证集群里始终有这么多副本在运行资源里的requests用于调度时的资源预留limits则是运行时的硬上限超过会被 OOM-Killed。注意requests不要设置过小否则调度器可能把多个对 CPU 敏感的 Pod 堆到同一台机器上运行时互相争抢。3. 从零拉起一个集群版本规划、初始化参数与应用落地3.1 环境准备先把容器运行时和内核参数搞对不管你是用 minikube 在本机尝鲜还是用 kubeadm 搭多节点集群底层的容器运行时都是绕不开的。当前主流是 containerd你的这份 PDF 覆盖面足够让你看懂这套架构。两个阶段要注意一是节点上必须先装好 containerd再装 kubelet、kubeadm、kubectl二是节点必须关闭 swap否则 kubelet 会拒绝启动。# 加载内核模块并设置 IP 转发Debian/Ubuntu 系 cat EOF | sudo tee /etc/modules-load.d/k8s.conf overlay br_netfilter EOF sudo modprobe overlay sudo modprobe br_netfilter cat EOF | sudo tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-iptables 1 net.ipv4.ip_forward 1 EOF sudo sysctl --systemoverlay是容器镜像分层存储依赖的内核模块br_netfilter让桥接流量也能通过 iptables 过滤这两项不加载后续 Pod 网络和数据包转发都会出现诡异问题。net.ipv4.ip_forward必须为 1否则节点无法转发 Pod 之间的跨主机流量Service 转发也会中断。做完这些sysctl --system是让配置立即生效别漏。3.2 kubeadm 初始化参数怎么给才不出幺蛾子初始化时最值得注意的参数是--pod-network-cidr它决定了 Pod 网络的地址段。这个段不能和节点网段、Service 网段重叠否则路由会错乱。常见的做法是给 Pod 网段分配一个专用的私有段比如 10.244.0.0/16给 Service 网段用--service-cidr单独指定。如果你用的是 flannel它对网段有默认预期配合 10.244.0.0/16 可以减少配置量。# 仅在控制平面节点执行 sudo kubeadm init \ --pod-network-cidr10.244.0.0/16 \ --service-cidr10.96.0.0/12 \ --cri-socket/run/containerd/containerd.sock初始化成功后终端会输出两段关键信息一段是让你在普通用户下执行的kubectl配置命令也就是把管理员证书拷贝到当前用户目录下的操作另一段是加入集群的kubeadm join命令包含 token 和 ca 证书哈希工作节点靠它加入集群。这两段建议先存到文本文件里因为 token 有效期默认 24 小时过期就得重新生成到时候再去翻会很被动。3.3 安装网络插件把 Pod 网络打通初始化完集群如果不装 CNI 插件节点状态会一直停留在 NotReady因为 kubelet 检查到网络未就绪。这个环节选 flannel 还是 Calico主要看规模。小规模集群 flannel 够用VXLAN 模式配置简单需要 NetworkPolicy 做租户隔离时选 Calico但它的资源占用和能力复杂度都更高。对比项FlannelCalico网络模型VXLAN 覆盖网络纯三层 BGP 路由NetworkPolicy 支持不支持支持性能开销较高较低推荐场景小型集群、快速验证生产环境、政策隔离需求# 以 flannel 为例安装网络插件 kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml这里有个常见做法是先把 YAML 下载到本地检查里面的镜像地址是否在你能访问的仓库里再执行 apply。不同网络插件对--pod-network-cidr有约定flannel 默认就是用 10.244.0.0/16改来改去容易翻车。安装完成后用kubectl get nodes观察节点从 NotReady 变成 Ready 通常需要一两分钟如果长时间卡住去看 kube-system 命名空间下 flannel Pod 的日志。3.4 部署第一个无状态应用从镜像到对外访问集群就绪后从部署到访问的完整链路走一遍能验证前面所有配置是否真的通了。准备一个简单的 Nginx 镜像建 Deployment 暴露 80 端口再用 NodePort 类型的 Service 把端口映射出来。# 创建一个测试 Deployment kubectl create deployment nginx-test --imagenginx:1.27 # 暴露为 NodePort 服务 kubectl expose deployment nginx-test \ --typeNodePort \ --port80 \ --target-port80 # 查看映射出的访问端口 kubectl get svc nginx-test--port是 Service 对外暴露的端口--target-port是后端 Pod 实际监听的端口两者可以不一样。kubectl get svc输出里PORT(S)一列如果显示80:31234/TCP说明 Service 的 80 端口被映射到了节点的 31234 端口通过任意节点的 IP 加 31234 就能访问到 Nginx。这个链路通了说明 Pod 网络、kube-proxy 转发、节点端口都正常。4. 避坑与排查集群运行中最常翻车的五个现场4.1 镜像拉取失败ImagePullBackOff 和 ErrImagePull现象Pod 一直停留在 ImagePullBackOff 状态describe看到事件里有Failed to pull image。原因有三类镜像地址写错或者 tag 不存在镜像在私有仓库需要认证但 YAML 里没有配置imagePullSecrets节点无法访问镜像仓库的域名。最后这种情况在国内环境尤其常见仓库域名解析被卡住后kubelet 反复重试事件里全是 429 或超时。解决先用crictl pull 镜像地址在节点上手动拉一次能区分是仓库认证问题还是网络问题。地址写错就改 Deployment 的 image 字段私有仓库就创建 docker-registry 类型的 Secret然后在 Deployment 的spec.template.spec下加imagePullSecrets。如果确认是仓库访问问题把镜像地址换到能访问的镜像仓库前缀比如某云厂商提供的镜像加速地址再重新部署。4.2 节点一直 NotReadyCNI 网络插件没有就绪现象kubectl get nodes看到某个节点状态是 NotReadykubectl get pods -n kube-system里 coredns 一直 CrashLoopBackOff。原因最常见的是节点加入集群时没有安装 CNI 插件或者插件的 DaemonSet 没有调度到该节点。另一个隐蔽原因是容器运行时和 CNI 插件的版本不兼容比如 containerd 和 flannel 的 cni-plugin 版本相差过大导致网络命名空间配置失败。解决在 NotReady 节点上执行ls /etc/cni/net.d/看是否有配置目录。没有就是 CNI 没装到位。删除插件 DaemonSet 再重新 apply前提是确认该节点没有被污点拦截。遇到 containerd 与 CNI 插件版本不匹配时把 flannel 的镜像版本升级一档或者换用 Calico一般能解决。4.3 证书过期集群突然无法认证现象某天kubectl执行任何命令都报证书无效或过期kubelet 连接 apiserver 也报 TLS 握手失败。原因kubeadm 生成的证书有效期只有一年官方推荐一年内做一次续期或者直接升级集群。很多集群建完就没人管证书到期自然就翻车。解决在控制平面节点执行kubeadm certs renew all续期所有证书然后重启 kubelet 和静态 Pod 组件。这个操作会覆盖掉旧的证书文件建议续期前先把/etc/kubernetes/pki整个目录备份一次——这是你的后悔药。续期后kubectl如果还报证书错误重新拷贝一次 admin 配置即可。4.4 PVC 一直 Pending没有可用的 StorageClass现象创建 PVC 后一直处于 Pendingdescribe pvc事件里提示waiting for a volume to be created, either by external provisioner or by storage class。原因集群里没有部署任何存储插件比如 NFS Client Provisioner 或云平台自带的存储驱动。有些裸金属集群装完 K8s 就认为存储是自带的其实 PVC 和 PV 不会自动绑定。解决先kubectl get storageclass确认有没有默认存储类。如果完全没有最简单的方案是先部署一个 NFS 子目录供给器把 NFS 服务端路径挂上去本地测试场景不想搭 NFS也可以直接在 PVC 里手动绑定一个 hostPath 类型的 PV。但要注意 hostPath 只适合单节点测试多节点集群里 Pod 被调度到其他节点后数据就不在本地了。4.5 Pod 频繁被驱逐或重启内存 limit 设置不合理现象某个服务运行一段时间后容器被 OOM-Killedkubectl get pods看到重启次数不断上涨节点上/var/log/kern.log里也有 OOM 记录。原因YAML 里limits.memory设置得太小或者存在内存泄漏。另一个常被忽略的因素是节点本身内存已经吃紧kubelet 根据可分配资源量驱逐低优先级 Pod。解决先把内存 limit 调大一档观察比如从 512Mi 调到 1Gi看是否继续被 OOM如果还会就需要排查应用内存占用曲线而非盲目加资源。如果节点确实内存不足检查节点上是否有其他占用大户或者干脆增加节点规格。总之limits不是摆设设置前至少要有压测数据支撑。5. 进阶技巧用滚动更新、标签选择器与亲和性把集群调稳滚动更新是把新版本 Pod 逐步替换旧版本的过程但很多人只改了镜像 tag 就完事忽略了另外两个核心参数。spec: replicas: 3 strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 0 template: spec: containers: - name: web image: registry.example.com/web-demo:v1.3 readinessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 5 periodSeconds: 10maxSurge: 1表示更新时允许额外多创建一个 PodmaxUnavailable: 0表示更新期间不能有旧 Pod 下线。两者的配合决定了发布速度和可用性追求快速发布就把 maxUnavailable 设成 1允许旧副本先下线追求零中断就把 maxUnavailable 设成 0靠 maxSurge 先拉起新副本再淘汰旧副本。但注意maxUnavailable: 0依赖 readinessProbe 正常工作——如果探针一直不通过新 Pod 永远不会进入 Ready发布就直接卡死这也是很多人改完参数后发布莫名其妙不动的常见原因。readinessProbe 是做滚动更新的前置条件。它告诉 kubelet 什么时候可以认为容器已经就绪、可以接收流量。initialDelaySeconds是容器启动后等多久才开始探测给应用留出加载配置、建立连接的时间periodSeconds是探测间隔。生产里我一般会额外加timeoutSeconds和failureThreshold避免网络抖动导致探针误判。标签选择器和节点亲和性解决的是把 Pod 放在哪的问题。节点亲和性比 nodeSelector 更灵活可以用 In 或 NotIn 表达复杂条件。affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: disktype operator: In values: - ssd这段配置的意思是Pod 只能调度到带有disktypessd标签的节点上。requiredDuringSchedulingIgnoredDuringExecution这种硬亲和力适合数据库这类对存储介质有要求的服务。还有一类软亲和力preferredDuringSchedulingIgnoredDuringExecution只是调度时优先找不到也能跑在别处适合把有网络依赖的服务尽量聚拢。官方文档里把这两者的区别写得清楚但你手头这份 PDF 的价值在于它能帮你把亲和性和污点容忍放在同一个调度链路里理解——先过滤掉不满足硬性条件的节点再按软性偏好打分排序。理解这个顺序你才能灵活组合出合理的拓扑分布。现在每当我搭一个新的生产集群都会强制走一遍这套流程从确认容器运行时版本到 CNI 插件事前选型再到给关键服务补全 readinessProbe最后检查证书余量。特别是证书我在日历上标了到期日每年提前一个月续期已经成了条件反射。这份 PDF 里的英文原版内容虽然对新手有阅读门槛但它跳过了一堆翻译失真和不准确的二手内容值得花时间啃下来。希望帮到你。本文还有配套的精品资源点击获取