从零搞懂 Kubernetes:架构剖析 + YAML 实战 + 常用命令速查
写在前面:本文基于 Kubernetes v1.36(代号 Haru)编写,适用于 v1.30+ 版本集群。文中所有示例均经过实测验证,可直接复制使用。
一、为什么需要 Kubernetes?
在容器化时代,Docker 解决了"应用打包"的问题,但当规模从几个容器膨胀到成百上千个时,运维噩梦才刚刚开始:
| 痛点 | 具体场景 |
|---|---|
| 规模管理 | 手动docker run启动 200 个容器?不现实 |
| 故障自愈 | 容器崩溃后谁来自动拉起? |
| 滚动更新 | 如何做到零停机发布新版本、出问题秒级回滚? |
| 负载均衡 | 请求怎么均匀分发到后端多个实例? |
| 资源调度 | 哪个节点剩余资源最多?哪个节点最适合跑这个服务? |
Kubernetes(简称 K8s)正是为解决上述问题而生的容器编排平台。它的核心价值可以浓缩为四句话:
- 声明式管理—— 你只管写"我想要什么",K8s 负责把现实掰到你想要的样子
- 自动化运维—— 调度、部署、伸缩、自愈,全程无需人工干预
- 解耦架构—— 应用逻辑与底层基础设施彻底分离,上云下云随意迁移
- 生态可扩展—— 通过 CRD、Operator、Webhook 等机制无限延伸能力边界
二、K8s 集群架构全景图
K8s 采用经典的控制平面(Control Plane)+ 工作节点(Worker Node)分层架构。控制平面是"大脑",工作节点是"手脚",两者通过 API Server 紧密协作。
下面逐一拆解每个组件的职责,这是面试高频考点,建议熟记。
2.1 控制平面四大核心
🧠 kube-apiserver —— 集群唯一入口
- 暴露 REST API,是所有内部和外部通信的唯一通道
- 所有组件(kubectl、kubelet、控制器等)都必须通过它来读写集群状态
- 无状态设计,可以水平扩展多实例
- 负责认证(Authentication)、授权(Authorization)、准入控制(Admission Control)
- 唯一与 etcd 直接对话的组件,安全边界非常清晰
💡记忆技巧:把 API Server 想象成公司前台——所有访客(请求)都必须先登记,由前台统一转达。
💾 etcd —— 集群唯一真相源
- 高可用的分布式键值存储,基于 Raft 共识算法保证强一致性
- 持久化存储所有集群数据:Pod、Service、ConfigMap、Secret 等一切对象的配置和状态
- 生产环境建议部署3 / 5 / 7节点的 etcd 集群以保证高可用
- 只有 API Server 能直接访问 etcd,简化了安全模型和一致性保证
⚠️血的教训:etcd 数据务必定期备份!它是整个集群的"命根子",丢了就全完了。
📋 kube-scheduler —— 智能调度器
- 监听 API Server,发现未被调度的新 Pod
- 采用“过滤 → 评分”两阶段算法,为 Pod 挑选最优 Node
- 考虑因素包括:
- 资源需求:CPU、内存的 Request 和 Limit
- 亲和性规则:NodeSelector、NodeAffinity、PodAffinity/AntiAffinity
- 数据局部性:优先调度到已有相关数据的节点
- 干扰度(Disruption):避免把高负载 Pod 堆到同一节点
- 只做决策,不负责执行——实际拉起容器是 kubelet 的活
🤖 kube-controller-manager —— 自动驾驶系统
- 运行一系列控制循环(Control Loop),不断将"实际状态"向"期望状态"靠拢
- 每个控制器逻辑上独立,但编译为单个二进制文件、运行在一个进程中
- 核心控制器一览:
| 控制器 | 职责 |
|---|---|
| Node Controller | 监控节点健康,宕机时标记并驱逐 Pod |
| ReplicaSet Controller | 确保指定数量的 Pod 副本始终运行 |
| Endpoints Controller | 维护 Service 与 Pod 的映射关系 |
| ServiceAccount Controller | 为新命名空间创建默认账户和 Token |
| Deployment Controller | 管理滚动更新和回滚 |
2.2 工作节点三大组件
👷 kubelet —— 节点上的"工头"
- 与控制平面通信的节点代理
- 监听 API Server 下发的指令,管理本节点 Pod 的完整生命周期
- 通过CRI(容器运行时接口)调用底层运行时拉镜像、启容器
- 定期向 API Server上报节点和 Pod 的状态
- 执行存活探针(LivenessProbe)和就绪探针(ReadinessProbe)
- ⚠️ 只管理 K8s 创建的容器,不管"野生"容器
🔀 kube-proxy —— 网络代理与负载均衡
- 维护节点上的网络规则,实现 Service 的流量转发
- 支持三种模式:
- iptables(默认):利用内核 netfilter 规则,性能不错
- ipvs(推荐):基于内核 L4 负载均衡,性能更优,支持更多算法
- userspace(已废弃):早期方案,性能差
- 类比:就像公司电话总机,把打进来的外部电话(请求)转接到正确的分机(Pod)
📦 Container Runtime —— 容器的真正执行者
- 负责下载镜像、解压、运行容器
- K8s 通过CRI 标准接口对接多种运行时,不绑定某一种
- 常见选择:
- containerd(当前主流,轻量高效)
- CRI-O(专为 K8s 设计,极简主义)
- Docker Engine(已废弃内置支持,内部仍用 containerd)
三、Pod:K8s 的最小调度单元
3.1 什么是 Pod?
Pod 是 K8s 中最小的可部署计算单元。可以把 Pod 理解为一个"逻辑主机"——它封装了:
- 一个或多个应用容器
- 共享的存储卷(Volume)
- 独立的网络 IP
- 管理容器运行方式的策略
关键特性:
- K8s 调度的最小单位是 Pod,不是容器
- Pod 内的容器共享网络命名空间(同一 IP、可 localhost 通信)
- Pod 内的容器共享存储卷
- Pod 内的容器同生共死(生命周期一致)
3.2 单容器 vs 多容器 Pod
单容器 Pod(最常见):一个 Pod 只跑一个应用容器,Pod 就是这个容器的"壳"。
多容器 Pod(Sidecar 模式):当多个容器需要紧密协作时使用。典型场景:
- 日志收集:主容器跑业务,Sidecar 容器负责采集日志并推送到 ELK
- 服务网格:主容器跑应用,Sidecar(如 Envoy)处理流量劫持和治理
- 适配器模式:主容器输出非标准格式,Sidecar 做格式转换
📌经验法则:如果容器之间不需要共享网络/存储,就拆成独立 Pod;如果必须 localhost 通信或共享文件,才放同一个 Pod。
四、YAML 资源清单文件详解
K8s 的声明式管理依赖 YAML 文件来描述"期望状态"。一个标准的资源清单包含四个根字段:
apiVersion:apps/v1# API 版本,不同资源对应不同版本kind:Deployment# 资源类型metadata:# 元数据(名称、标签、命名空间等)name:my-appnamespace:productionspec:# 期望状态(核心配置区)replicas:3# ... 具体配置因资源类型而异# status: # 当前状态(由 K8s 自动维护,用户不写)4.1 各字段说明
| 字段 | 说明 |
|---|---|
apiVersion | API 版本号,可用kubectl api-resources查看所有资源对应的版本 |
kind | 资源种类,如 Pod、Deployment、Service、ConfigMap、Ingress 等 |
metadata | 资源的身份标识:name(必填)、namespace(默认 default)、labels 等 |
spec | 资源的期望状态描述,不同 kind 结构完全不同 |
4.2 一个完整的 Deployment 示例
apiVersion:apps/v1kind:Deploymentmetadata:name:nginx-deploymentlabels:app:nginxspec:replicas:3selector:matchLabels:app:nginxtemplate:metadata:labels:app:nginxspec:containers:-name:nginx-containerimage:nginx:1.25ports:-containerPort:80env:-name:ENV_VAR_NAMEvalue:"production"resources:requests:memory:"64Mi"cpu:"250m"limits:memory:"128Mi"cpu:"500m"livenessProbe:httpGet:path:/port:80initialDelaySeconds:5periodSeconds:10readinessProbe:httpGet:path:/port:80initialDelaySeconds:5periodSeconds:10volumes:-name:config-volumeconfigMap:name:nginx-config4.3 探针机制(重点)
| 探针类型 | 作用 | 失败后果 |
|---|---|---|
| LivenessProbe | 检测容器是否存活 | 杀死容器并重启 |
| ReadinessProbe | 检测容器是否就绪 | 从 Service 后端摘除,不接收流量 |
| StartupProbe | 检测慢启动应用是否就绪 | 在成功前不会执行 liveness 检查 |
三种探针都支持httpGet、tcpSocket、exec三种检测方式。
五、kubectl 常用命令速查表
kubectl 命令的通用语法:
kubectl[command][TYPE][NAME][flags]5.1 资源查看类
# 查看所有 Pod(默认命名空间)kubectl get pods# 查看所有命名空间的 Podkubectl get pods-Akubectl get pods --all-namespaces# 查看指定命名空间的服务kubectl get svc-n<namespace># 查看所有 Deploymentkubectl get deployments# 宽格式输出(含节点信息)kubectl get pods-owide# 查看节点状态kubectl get nodes# 以 YAML 格式导出资源定义(常用于备份)kubectl get pod<pod-name>-oyaml# 动态监听资源变化(类似 tail -f)kubectl get pods-w5.2 资源详情与诊断
# 查看 Pod 详细信息(含事件、IP、状态)kubectl describe pod<pod-name># 查看 Node 详细信息kubectl describenode<node-name># 查看 Deployment 详情kubectl describe deployment<deployment-name>5.3 创建 / 更新 / 删除
# 从 YAML 文件创建资源(首次创建用)kubectl create-fmanifest.yaml# 创建或更新资源(声明式,推荐日常使用)kubectl apply-fmanifest.yaml# 从 URL 直接创建kubectl apply-fhttps://example.com/manifest.yaml# 删除 YAML 定义的资源kubectl delete-fmanifest.yaml# 删除指定 Podkubectl delete pod<pod-name># 强制删除卡在 Terminating 的 Podkubectl delete pod<pod-name>--force--grace-period=0# 删除命名空间下所有 Podkubectl delete pods--all-n<namespace>5.4 日志与调试(排障利器)
# 查看 Pod 日志kubectl logs<pod-name># 多容器 Pod 中查看指定容器日志kubectl logs<pod-name>-c<container-name># 实时跟踪日志(类似 tail -f)kubectl logs-f<pod-name># 查看上一次崩溃的日志(排障超有用)kubectl logs-p<pod-name># 进入 Pod 交互式终端kubectlexec-it<pod-name>-- /bin/bash# 多容器 Pod 中进入指定容器kubectlexec-it<pod-name>-c<container-name>-- /bin/sh# 不进入交互模式,直接执行命令kubectlexec<pod-name>--ls/app5.5 端口转发
# 本地 8080 → Pod 80kubectl port-forward<pod-name>8080:80# 本地 8080 → Service 80kubectl port-forward service/<service-name>8080:80# 后台运行kubectl port-forward<pod-name>8080:80&5.6 辅助命令
# 查看所有资源类型及其 API 版本kubectl api-resources# 查看 YAML 字段含义(官方文档内嵌,超好用)kubectl explain pod.spec.containers# 查看集群信息kubectl cluster-info# 切换命名空间(避免每次 -n)kubectl config set-context--current--namespace=test-dev六、实战:从零部署一个 Nginx 服务
理论讲完,动手才是王道。下面演示如何在本地 K8s 环境(Minikube / Kind / Docker Desktop 均可)部署一套完整的 Nginx 服务。
6.1 创建命名空间
# 01-namespace.yamlapiVersion:v1kind:Namespacemetadata:name:web-demo6.2 创建 Deployment
# 02-deployment.yamlapiVersion:apps/v1kind:Deploymentmetadata:name:nginx-deploynamespace:web-demolabels:app:nginxspec:replicas:3selector:matchLabels:app:nginxtemplate:metadata:labels:app:nginxspec:containers:-name:nginximage:nginx:1.25ports:-containerPort:80resources:requests:memory:"64Mi"cpu:"50m"limits:memory:"128Mi"cpu:"100m"livenessProbe:httpGet:path:/port:80initialDelaySeconds:30periodSeconds:10readinessProbe:httpGet:path:/port:80initialDelaySeconds:5periodSeconds:56.3 创建 Service 暴露服务
# 03-service.yamlapiVersion:v1kind:Servicemetadata:name:nginx-svcnamespace:web-demospec:selector:app:nginxports:-protocol:TCPport:80targetPort:80type:ClusterIP6.4 一键部署 & 验证
# 依次创建资源kubectl apply-f01-namespace.yaml kubectl apply-f02-deployment.yaml kubectl apply-f03-service.yaml# 也可以用 --- 分隔符合并到一个文件,一条命令搞定kubectl apply-fall-in-one.yaml# 查看部署进度kubectl get pods-nweb-demo-w# 查看 Service 详情和端口映射kubectl get svc-nweb-demo# 进入 Pod 内部验证kubectlexec-it-nweb-demo<pod-name>-- /bin/bash# 查看 Pod 日志kubectl logs-nweb-demo<pod-name># 端口转发到本地,浏览器访问验证kubectl port-forward-nweb-demo svc/nginx-svc8080:80# 浏览器打开 http://127.0.0.1:8080 即可看到 Nginx 欢迎页6.5 合并版 YAML(一个文件搞定)
# all-in-one.yamlapiVersion:v1kind:Namespacemetadata:name:web-demo---apiVersion:apps/v1kind:Deploymentmetadata:name:nginx-deploynamespace:web-demolabels:app:nginxspec:replicas:3selector:matchLabels:app:nginxtemplate:metadata:labels:app:nginxspec:containers:-name:nginximage:nginx:1.25ports:-containerPort:80resources:requests:memory:"64Mi"cpu:"50m"limits:memory:"128Mi"cpu:"100m"livenessProbe:httpGet:path:/port:80initialDelaySeconds:30periodSeconds:10readinessProbe:httpGet:path:/port:80initialDelaySeconds:5periodSeconds:5---apiVersion:v1kind:Servicemetadata:name:nginx-svcnamespace:web-demospec:selector:app:nginxports:-protocol:TCPport:80targetPort:80type:ClusterIP💡 使用
---分隔符可以在一个 YAML 文件中定义多个资源,K8s 会按顺序依次创建。
七、排障思路总结
当 Pod 出现异常时,推荐按以下顺序排查:
kubectl get pods → 看状态(Pending? CrashLoopBackOff?) kubectl describe pod <pod-name> → 看事件(镜像拉取失败?调度失败?) kubectl logs <pod-name> → 看应用日志 kubectl logs -p <pod-name> → 看上一次崩溃日志 kubectl exec -it <pod-name> -- sh → 进容器排查 kubectl get events -n <ns> → 看命名空间级别事件八、学习建议
- 先跑通再理解:用 Minikube 或 Kind 在本地搭一套单节点集群,把本文所有命令敲一遍
- 善用
kubectl explain:这是内置的官方文档,比翻网页快得多 - 从 Pod → Deployment → Service的顺序逐步学习,不要一上来就搞 Ingress + Istio
- 多看官方文档:kubernetes.io 的中文文档质量已经很高了
参考资源:
- Kubernetes 官方文档:https://kubernetes.io/zh-cn/docs/
- Kubernetes v1.36 Release Notes
kubectl api-resources/kubectl explain命令输出