首页 / 资讯中心 / 文章详情

K8s入门指南:核心概念、集群搭建与排错实战

K8s入门指南:核心概念、集群搭建与排错实战 ★ FEATURED ARTICLE
1. 项目概述Kubernetes 到底是什么先说结论Kubernetes以下简称 K8s是一个开源的容器编排平台解决的问题是“怎么把一大堆容器稳定、高效、自动化地跑起来”。如果你只是单机跑几个 Docker 容器K8s 确实用不上但一旦你的服务数量超过几十个、需要滚动升级、自动扩缩容、跨机器调度、故障自愈手写脚本管理就会迅速失控这时候 K8s 几乎是事实标准。从 v1.26.0 这个版本号也能看出一些趋势K8s 的迭代节奏非常快大约每三个月发布一个大版本v1.26 属于 2022 年底到 2023 年初的版本引入了不少关键特性。现在社区已经推进到更新的版本了但核心架构和基础概念依然是相通的学会 v1.26 的概念换到新版本依然是同一套心智模型只是功能更多、默认行为更稳。这篇博文适合谁看两种人一是刚接触容器编排、想搞懂 K8s 到底在解决什么问题的后端或运维工程师二是已经用过 Docker、但面对 K8s 一堆概念Pod、Service、Deployment、Namespace感到混乱的初学者。我会从“为什么要做容器编排”讲起逐步拆解架构、核心对象、资源调度、排错思路最后给出一套能直接上手的入门路径——包括初始化集群时kubeadm init输出里那一大串[preflight]检查到底在查什么。2. 为什么需要 Kubernetes从“手动管理容器”到“声明式编排”2.1 容器时代的第一道坎单机搞定不了的事Docker 把应用和依赖一起打包成镜像解决了“在我机器上能跑”的问题但紧接着就撞上新的墙一台物理机资源有限CPU、内存、磁盘总有耗尽的一天。你当然可以多买几台机器每台都手动docker run可一旦容器数量多起来麻烦就来了——容器分布在哪些机器上靠记忆机器挂了上面的容器谁负责重启流量进来哪个容器处理要不要做负载均衡发布新版本怎么做到不停机直接docker stop再docker run用户会骂的。高峰期想多开几个副本低峰期想缩回来手动操作显然跟不上节奏。这些问题的本质是容器的生命周期需要被“管理”而不仅仅是被“创建”。K8s 就是为管理而生的一套控制体系。用生活化的类比来说如果 Docker 是“预制菜”——把菜洗好切好装在统一的盒子里方便运输和烹饪那 Kubernetes 就是“中央厨房的自动化烹饪流水线”——它知道你有多少份食材容器副本数、哪个灶台空着节点调度、火候大了怎么办自动扩缩容、某个灶台坏了由哪个备用灶顶上故障自愈。你只需要告诉流水线“我要 3 份番茄炒蛋”它自己安排一切。2.2 声明式 API你只需要描述“想要什么”K8s 最核心的设计哲学我愿称之为“声明式管理”。传统运维是命令式思维先做什么、再做什么、遇到什么情况执行什么命令全流程由你来设计。K8s 反过来——你只需要提交一份 YAML声明“我要跑 3 个副本的 Nginx”剩下的“怎么跑、跑在哪、挂了怎么拉起、流量怎么进去”全部由控制平面自行决定。这一点极其重要它把运维人员从“写一堆 if-else 脚本”里解放出来变成“描述终态”的人。你的 YAML 是“愿望清单”K8s 的控制循环Control Loop则是那个不断检查“现实是否符合愿望不符合就纠正”的强迫症机器人。这种模式在规模上去之后优势巨大因为系统自动处理的东西越多人能犯的错就越少。我见过很多从传统运维转过来的同事初期最大的别扭就在这总想手动kubectl scale去扩容而不是改 YAML 让 Deployment 去协调。实际上手动命令确实能应急但正式的业务变更应当全部走声明式配置这样才能被审计、被版本管理、被 GitOps 流程控制。3. 核心概念拆解先把这些词搞明白再谈别的3.1 PodK8s 最小调度单元一组亲密容器很多人初学 K8s 会有一个惯性思维K8s 管理的是容器吧严格说K8s 的最小调度单位是Pod不是一个容器。Pod 里可以装一个容器也可以装多个容器这些容器共享同一个网络命名空间、共享存储卷、通过 localhost 互相通信。为什么要有 Pod 这一层抽象因为有的时候几个容器必须部署在同一台机器上才算合理——比如一个容器负责读取日志文件另一个容器负责把日志转发到远端存储。这两个容器生命周期应该绑定、网络必须互通、磁盘要共享如果把它们拆成两个独立调度的容器调度器可能把它们分到不同节点整个设计就崩了。Pod 还有一个重要特性Pod 是“可牺牲”的。K8s 把 Pod 当作“一次性物体”它随时可能因为节点故障、资源驱逐、手动删除而消失而且消失后 IP 会变。所以 Pod 本身不适合被直接访问这也是为什么我们通常不直接创建 Pod而是通过 Deployment 等控制器来管理它们。实操里一个经验能用kubectl run直接创建一个裸 Pod 做调试没问题但生产环境别这么干。裸 Pod 没有控制器管理删了就是真的没了不会被重建。3.2 Deployment声明副本数剩下的交给控制器Deployment 是 K8s 里最常用的工作负载控制器用来管理无状态应用。你告诉它“我要 5 个副本”它会创建 ReplicaSetReplicaSet 再负责创建 Pod 并保证副本数始终为 5。某个 Pod 被删了控制循环会立刻创建一个新的顶上。Deployment 的另一个核心能力是滚动更新Rolling Update。升级镜像版本时它会分批替换旧 Pod而不是一次性全部干掉。默认策略下它会先起几个新 Pod等它们 Ready 了再下线等量的旧 Pod整个过程服务不中断。线上发布如果只允许停机窗口你需要的是 Deployment 滚动更新这正是它存在的意义。使用 Deployment 时的配置重点有三个replicas期望副本数平时按负载评估高峰期可以临时调整。strategy.rollingUpdate滚动更新的参数比如maxUnavailable和maxSurge控制更新过程中最多允许多少旧 Pod 不可用、最多允许多出多少新 Pod。templatePod 模板里面定义了镜像、端口、资源请求等。我实测下来maxUnavailable: 0, maxSurge: 1是保守且常用的组合——先起一个新 Pod确认健康后再杀一个旧 Pod牺牲一点更新速度换取稳定性。3.3 Service给“易变的 Pod”一个稳定的入口上面说了 Pod 是易变的IP 随时可能更换那么问题来了客户端怎么访问服务答案是Service。Service 是一组 Pod 的稳定访问入口它本身拥有一个固定的虚拟 IPClusterIP并且通过 Selector标签选择器动态匹配到一组 Pod 上。只要 Pod 上的标签和 Service 的 selector 匹配这个 Pod 就会自动加入服务后端不需要你手动改任何配置。Service 的类型主要有四种ClusterIP集群内部虚拟 IP仅供集群内访问默认类型。NodePort在每个节点上开放一个端口30000-32767外部流量可以通过节点IP:端口访问。LoadBalancer云平台会分配一个负载均衡 IP流量先到 LB再转发到节点上的 NodePort。Headless Service不分配 ClusterIP配合 StatefulSet 获取 Pod 的独立 DNS 记录常用于有状态应用。初学阶段很多人会在 Service 和 Ingress 之间犯迷糊。简单区分Service 是四层负载均衡负责“把流量转到 Pod”Ingress 是七层路由负责“根据域名或 URL 路径决定流量转给哪个 Service”。打个比方Service 是总机接线员你拨内部号码它会接通对应分机Ingress 是前台会根据你说“我要找技术部”把你带到对应区域。3.4 Namespace逻辑上的“虚拟集群”Namespace 解决的是“多个团队/多个环境共用一套 K8s 集群”的隔离问题。它的隔离是逻辑层面的——不同 Namespace 里的资源互不可见默认情况下但底层还是同一批节点。K8s 默认有三个 Namespacedefault无特殊声明时资源都在这里、kube-system运行系统组件、kube-public公共资源。实践中我建议按业务环境或团队划分dev、test、prod各一个 Namespace权限控制RBAC、资源配额ResourceQuota、网络策略都可以挂在 Namespace 级别上。有个常见的坑很多人刚用 K8s 时看到kubectl get pod只显示几个 Pod 就开始怀疑人生其实是忘了加-n 某个namespace参数。默认只会看default这一个命名空间系统组件都在kube-system里。4. 架构详解控制平面和数据平面各司其职4.1 控制平面组件集群的大脑一个标准的 K8s 集群由两部分组成控制平面Control Plane和工作节点Worker Node。控制平面负责决策和状态维护工作节点负责实际运行 Pod。下面挨个过一遍控制平面的核心组件kube-apiserver整个集群的“唯一入口”。所有请求kubectl 命令、组件间通信都必须经过它它负责认证、授权、准入控制然后才把数据写入 etcd。它是我眼里最重要的组件——所有组件都不直接访问 etcd而是通过 API Server 间接读写。etcd集群数据的“最终存储”。一个 key-value 数据库存着所有对象的状态期望状态和实际状态。它是 K8s 的“真相来源”如果 etcd 挂了整个集群就瘫痪了。生产环境一定要给 etcd 做定期备份。kube-controller-manager一个“控制器集合体”。节点控制器、副本控制器、端点控制器、服务账户控制器全在这里面各自负责维持期望状态。cloud-controller-manager云厂商相关的逻辑控制器比如云负载均衡、云存储卷的创建和删除。自建集群通常不需要云上托管的 K8s 才会用到。kube-scheduler调度器。它决定“新创建出来的 Pod 应该落在哪个节点上”依据是节点的资源余量、亲和性规则、污点容忍等条件。如果用公司结构来类比API Server 是前台秘书所有申请都交到它手里etcd 是档案室记录整个公司所有员工的资料controller-manager 是各部门经理定期对照公司规章制度检查工作进度scheduler 是人力资源调配主管决定新人分到哪个部门。4.2 工作节点组件干活的工人每个工作节点上有两类核心组件kubelet节点上的“监工”。它的职责是和 API Server 通信确保本节点上的 Pod 都在运行状态。它会定期向 API Server 上报节点状态和资源使用情况如果某个 Pod 的健康检查失败它会负责杀掉容器并上报状态。kube-proxy节点上的“网络转发员”。它负责维护 Service 对应的网络规则让发往 Service 的流量能到达某个真正的 Pod。在 iptables 模式下它通过创建 iptables 规则实现转发在 IPVS 模式下则利用 IPVS 模块性能更好、负载均衡算法更多。还需要说的一个组件是容器运行时Container Runtime。K8s 通过 CRIContainer Runtime Interface和运行时通信最常用的是 containerd 和 CRI-ODocker 本身已经不适合直接作为 K8s 的运行时了v1.24 起移除了 dockershim。我看到不少老教程还在提 Docker 可以直接跑 K8s其实新版本基本都是用 containerd这点对新入门的人是个容易踩的坑。4.3 Addons锦上添花的生态组件除了核心组件一个功能完备的集群还需要一些插件AddonCNI 网络插件负责集群网络的打通常见有 Calico、Flannel、Cilium。没有 CNIPod 之间是无法通信的。CoreDNS集群内 DNS 解析服务让 Pod 可以通过服务名访问别的服务。Ingress Controller配合 Ingress 资源工作的落地组件常见是 Nginx Ingress Controller 或 Traefik。Metrics Server提供节点和 Pod 的 CPU/内存监控数据kubectl top命令依赖它还能为 HPA水平自动扩缩容提供数据来源。从我个人的搭建经验来看Calico CoreDNS Metrics Server是三件套标配几乎每次初始化集群都要装一个都不能少。5. 集群搭建实战kubeadm init 输出逐行解读5.1 初始化前的准备kubeadm 的前置检查聊完概念来点接地气的实操。假设你要用 kubeadm 搭建一套 K8s 集群v1.26.0执行kubeadm init后控制台会先打印一大段[init]和[preflight]日志。很多人看到这堆输出会有点慌其实它的信息量很大值得逐段理解。拿开头那两行热词来说[init] using kubernetes version: v1.26.0这行表示 kubeadm 将安装的 Kubernetes 版本是 v1.26.0也意味着 kubeadm 和 kubelet 的版本必须与之兼容。紧接着是[preflight] running pre-flight checks这是 kubeadm 在正式安装前做的一堆环境和配置检查常见检查项包括内核参数要求net.bridge.bridge-nf-call-iptables为 1否则网络转发可能有问题。swap 状态默认要求关闭 swap。K8s 在设计上不支持在启用 swap 的节点上调度关闭后 Kubelet 才会正常工作。端口占用检查 6443API Server、2379/2380etcd等端口是否被占用有服务占用会直接失败。容器运行时连接kubeadm 会尝试通过 CRI 连接到 containerd连接不上会报错。资源充足性检查 CPU、内存是否满足最低要求至少 2 核 2G生产建议更高。modprobe 模块加载需要加载br_netfilter、overlay等内核模块不然网络和存储层会出问题。这些[preflight]检查是防患于未然的重要手段。我处理过好几个失败的初始化案例十有八九都能在这阶段找到线索——比如 swap 没关、containerd socket 路径不对、内核参数没持久化。与其失败之后反复折腾不如先把 preflight 阶段通过。5.2 初始化成功后的三类关键信息如果一切正常kubeadm init会在最后输出几段关键信息我看到很多新手会直接跳过。这里提个醒这些信息一定要保存下来尤其是前两条kubeadm join 命令包含 token 和 CA 证书哈希后续所有工作节点加入集群都要用到。token 默认有效期 24 小时过期了可以用kubeadm token create重新生成。KUBECONFIG 配置路径通常是/etc/kubernetes/admin.conf是集群管理员访问集群用的配置文件。你需要把它复制到~/.kube/config否则kubectl命令连不上集群。必须安装的 CNI 插件提示初始化完成后集群处于NotReady状态是正常的直到装好 CNI 插件节点才会转为Ready。安装完 CNI 插件后你可以用kubectl get nodes确认节点状态。如果状态还是NotReady别急着怪 CNI先看kubectl describe node很多情况下是因为 kubelet 没启动、证书过期、或容器运行时配置有误。5.3 单机测试环境的替代方案如果你的本子只有 2 核 4G 资源不想玩整套集群我强烈建议先试试kindKubernetes in Docker或minikube。kind 会把控制平面和工作节点都跑成 Docker 容器适合快速测试 YAML、练手 kubectl 命令minikube 则更适合体验“有单节点集群真实感”的开发场景。我个人对初学者的建议是先 minikube 或 kind 玩一周把 Pod、Deployment、Service 的 YAML 写熟了再上 kubeadm 搭真实集群。一步到位搭集群难度不大但排错环境复杂容易把信心磨没了。先小后大学习曲线会平滑很多。6. 常见问题与排查技巧实录6.1 Pod 一直 Pending 或 CrashLoopBackOff这两个状态是新手遇到最多的。Pending一般意味着调度失败排查方向是节点资源是否不足kubectl describe node查看 Allocatable 和 Requests。是否存在污点不匹配kubectl describe node查看 TaintsPod 需要对应容忍。是否有 PVC 绑定超时kubectl describe pod看事件。CrashLoopBackOff表示容器启动后反复崩溃。先看日志kubectl logs pod-name如果是上一个容器已崩溃加上--previous。常见的崩溃原因有镜像启动命令报错、配置文件挂载路径不对、探针LivenessProbe配置太激进导致容器反复被杀。我见过一个相当隐蔽的问题健康检查路径写错/healthz写成了/health探针一直失败Pod 反复重启日志里又找不到错误因为应用本身是正常启动的。遇到这种“看起来没问题但就是重启”的情况先把探针停了试试基本能定位。6.2 kubectl 报 connection refused 怎么办kubectl无法连接集群先检查自己的 kubeconfig 是否正确。kubectl config view看当前上下文确认 server 地址和证书有效。本地 kind 集群经常发生集群重建后 kubeconfig 未更新的问题重新执行kind export kubeconfig即可。如果是远程 API Server 连不上可能是防火墙没放行 6443 端口。我在一台云服务器上搭 K8s 时折腾了半天发现安全组规则只开放了 22 端口加一条 TCP 6443 入站规则就好了。这类“环境级”问题检查顺序应该是网络连通性 - 防火墙/安全组 - 证书有效性 - kube-apiserver 服务状态。6.3 节点重新加入集群时报错kubeadm join失败大概率是 token 过期或 CA 哈希不匹配。重新生成即可kubeadm token create --print-join-command这条命令会直接打印完整的 join 命令复制执行就行。还有种情况是节点之前已加入过集群/etc/kubernetes下有残留配置需要先执行kubeadm reset清理干净再 join。6.4 常用排查命令速查表场景命令说明查看所有命名空间的 Podkubectl get pods -A只敲kubectl get pods会默认只显示 default 命名空间看 Pod 的详细事件kubectl describe pod name事件尾部往往藏着失败原因看容器日志kubectl logs name单容器 Pod 可以直接用多容器要加-c container监听资源变化kubectl get pods -wwatch 模式实时刷新状态变更把 YAML 渲染成可提交的配置kubectl create deployment demo --imagenginx --dry-runclient -o yaml不实际创建只输出 YAML 样板故障节点清出集群kubectl drain node --ignore-daemonsets会把节点上的 Pod 驱逐到其他节点节点恢复后重新可调度kubectl uncordon node先把节点置为可调度Pod 才会重新被调度上来我通常的做法是“先 describe 后 logs”遇到异常 Pod先describe看事件和状态再logs看应用日志。很多人一上来直接看日志容易忽略调度失败、镜像拉取失败这类基础设施层面的原因。注意kubectl drain是运维高危操作执行前确认节点上的业务 Pod 已由 Deployment/StatefulSet 管理否则被驱逐的裸 Pod 不会自动重建。7. 实际业务中怎么选型什么样的场景该上 K8s7.1 适合上 K8s 的三个信号我经常被问到“我们该不该上 K8s”。这个问题没有标准答案但有三个很明确的信号可以参考服务数量多且有相互调用关系比如微服务架构里 20 个以上服务服务间通过 DNS 互相发现用 K8s 的 Service 和 CoreDNS 天然合适。流量波动剧烈需要自动扩缩容K8s 的 HPA 可以根据 CPU/内存或自定义指标自动调整副本数高峰期扩、低峰期缩比人工盯监控靠谱得多。已有容器化基础但部署靠手动脚本说明你已经走到“容器化之后但还没自动化”的阶段。把一堆docker run脚本改成 Deployment YAML是收益最高的一步。反之如果你的业务只有两三个服务、流量平稳、可以接受深夜停机发布那 K8s 的复杂度就是纯成本。技术选型最怕跟风K8s 再流行它在 5 个服务的小团队里也是杀鸡用牛刀。7.2 按环境取舍功能模块就算决定上 K8s也不用一把梭全上。按我的经验不同阶段的功能取舍是这样的阶段核心功能暂时放一放第一阶段容器编排入门Deployment、Service、Namespace、kubectl 基础Ingress、HPA、StatefulSet第二阶段稳定性和自动化HPA、滚动更新策略、资源 requests/limits、Pod 探针Operator、自定义控制器第三阶段复杂业务治理Ingress 证书管理、NetworkPolicy、RBAC、服务网格多集群、联邦管理这样逐级深入的好处是每一层都能真正吃透再往下一层走而不是被 K8s 庞大的生态吓退。8. 新手入门路线图一份可以直接照着走的计划8.1 阶段一概念建立期第 1 周目标不是搭建集群而是把概念框架建立起来。我建议的顺序是先读 Docker 基础保证对“镜像、容器、卷”有直观理解。再学 Pod、Deployment、Service 三个核心对象用 minikube 或 kind 反复创建、修改、删除。用kubectl explain查看每个资源的字段说明比翻文档快得多。比如kubectl explain deployment.spec.replicas会直接告诉你这个字段的含义和类型这个命令在日常工作中也特别常用遇到不熟悉的资源字段先explain一下再填值能少踩很多 YAML 校验的坑。8.2 阶段二集群实操期第 2-3 周这一阶段建议用 kubeadm 搭一套三节点集群1 控制平面 2 工作节点真实体验一次集群初始化和节点加入的过程。搭完后做三件事部署一个有状态 MySQL体会 StatefulSet、PersistentVolumeClaim、Headless Service 是怎么配合工作的。配置 Ingress Controller把服务暴露到集群外理解域名解析到 Service 的完整链路。部署 Metrics Server配置 HPA压测一个应用观察自动扩缩容行为。这三件事做完你对 K8s 的认知会从“纸面概念”变成“肌肉记忆”。8.3 阶段三原理深挖期第 4 周起当你已经能熟练部署应用后建议深入三个方向网络模型CNI 插件到底怎么实现 Pod 间通信的service 的 iptables/IPVS 规则长什么样这对排查复杂网络问题极其重要。调度机制nodeSelector、亲和性、污点与容忍怎么组合使用为什么有些 Pod 会调度到你不期望的节点控制器模式自己写一个简单 Operator理解“观察、对比、纠正”的控制器循环这是理解 K8s 生态一切复杂功能的钥匙。这三个方向是 K8s 进阶的分水岭能啃下来你在团队里基本就是 K8s 方向的“专家”了。我个人在实际操作中最深的体会是K8s 入门不难难的是在复杂场景下建立正确的直觉。很多问题表面上千奇百怪但底层都是“期望状态和实际状态不一致”导致的。遇到任何诡异现象先问一句控制循环卡在哪一步搞清楚这个问题九十以上的问题都能迎刃而解。最后分享一个小技巧没事多敲kubectl get events --sort-by.lastTimestamp -A看看集群里最近发生的所有事件。很多潜在问题在爆发之前都会先在事件里不经意的露个脸。养成了看事件的习惯你就能比监控报警更早发现异常这大概是运维 K8s 最实用的一项软技能。
阅读完成 · 觉得有帮助?
咨询建站