Appearance
K8s 基础概念
Docker 解决单个容器怎么运行。Compose 解决单机多容器怎么组织。当服务要跑在多台机器上、副本数要动态调整、某台机器挂了服务要自动迁走时,这两样就不够了。
Kubernetes 处理的是多节点、多副本、多服务长期运行时的调度、网络、存储、配置、发布和故障恢复。
编排的本质——声明期望状态
Kubernetes 的工作方式是:提交期望状态("我要 3 个 web 副本"),控制器持续把集群实际状态调整到期望状态。副本少了就补,多了就缩,节点坏了就在别处重建。
不用 K8s 时,这些动作通常是运维脚本在做——检查进程、手动重启、改 Nginx upstream、更新 DNS。用 K8s 之后,这些"检查→纠正"的循环由控制器接管。
K8s 覆盖的主要场景和对应核心对象如下。Pod、Service、ConfigMap 这些对象先按职责区分,具体字段和排查方式会落到对应资源里。
| 场景 | Kubernetes 负责的部分 |
|---|---|
| 多副本 Web/API | 调度 Pod(最小调度单元,一组容器)、维护副本数、滚动发布 |
| 服务发现 | Service 提供稳定访问入口,Pod IP 变化不影响调用方 |
| 节点故障 | 节点异常后,控制器在其他节点重建副本 |
| 配置分发 | ConfigMap(明文配置)、Secret(敏感配置)挂载或注入到容器 |
| 资源约束 | requests(申请量)、limits(上限)、QoS、驱逐策略 |
| 发布治理 | 滚动更新、回滚、蓝绿、金丝雀 |
| 可观测性 | 事件、日志、指标、审计 |
K8s 把调度、服务发现、配置挂载、滚动更新这些动作标准化了。但应用自身的启动逻辑、健康检查、数据一致性、数据库迁移、连接池配置仍然是应用和运维一起处理的——平台提供能力,不替代应用设计。
集群结构——控制平面和工作节点
一个集群分成两部分:控制平面负责决策和记录状态,工作节点负责运行容器。
所有组件都通过 kube-apiserver 读写资源对象——kubectl、scheduler、controller-manager、kubelet 没有例外。etcd 只在 API Server 后面做持久化存储,没有组件直接操作 etcd。这意味着:想查集群里有什么对象、想改对象的状态、想监听变化——全部走 API Server。这个设计让认证、授权、审计和准入控制在同一个入口完成,不需要在每个组件上分别做一遍。
核心组件
每个组件解决一类问题:
| 组件 | 所在位置 | 解决的问题 | 常见故障 |
|---|---|---|---|
kube-apiserver | 控制平面 | 提供统一的 API 入口 | 证书过期、认证失败、请求延迟高 |
etcd | 控制平面 | 持久化保存所有集群对象状态 | 磁盘慢、快照丢失、quorum 丢失 |
kube-scheduler | 控制平面 | 新 Pod 应该放在哪个节点 | 资源不足、污点、亲和性、PVC 未绑定 |
kube-controller-manager | 控制平面 | 持续调和期望状态和实际状态 | 副本不补、节点状态更新异常 |
kubelet | 每个节点 | 管理本节点的 Pod 和容器生命周期 | 镜像拉取失败、挂载失败、探针失败 |
containerd / CRI-O | 每个节点 | 容器运行时——真正创建和运行容器 | 镜像损坏、容器创建失败 |
kube-proxy | 每个节点 | 把 Service 规则变成节点上的转发规则 | iptables/IPVS 规则异常、Service 不通 |
| CNI 插件 | 每个节点 | 给 Pod 分配 IP、实现 Pod 间通信 | Pod 无 IP、跨节点不通、策略异常 |
etcd 是整个集群状态的唯一持久化存储。控制平面节点故障后可以重建,Pod 可以重建——etcd 数据丢了等于集群所有对象(Deployment、Service、ConfigMap、Secret、RBAC)全部丢失。生产集群里 etcd 快照、证书有效期、磁盘延迟是固定巡检项。
声明式 API 和控制循环
K8s 的基本动作不是"执行一次命令",而是"提交期望状态,控制器持续调和":
把 Deployment 副本数从 2 改到 5 时,实际发生的不是"启动三个新容器"一条指令,而是每个组件接力完成自己那一段。变更后的状态传递过程:
| 步骤 | 哪个组件 | 具体动作 |
|---|---|---|
修改 spec.replicas 为 5 | API Server | 接收新期望状态,写入 etcd |
| Deployment 控制器发现差异 | controller-manager | 当前 2 个副本 < 期望 5 个副本 |
| 创建 3 个新 Pod | controller-manager | 新 Pod 字段写入 etcd |
| 给 Pod 选节点 | scheduler | 写入 Pod 的 spec.nodeName |
| 拉起容器 | kubelet | 节点上拉镜像、挂载卷、启动进程 |
这个接力模型直接决定了排错方式。API 是否接收对象、控制器是否创建对象、调度是否成功、kubelet 是否创建容器、应用是否健康——五个不同阶段,排查入口和日志来源完全不同。
spec 和 status
Kubernetes 不直接操作进程,而是操作资源对象。所有资源对象共享一个结构:
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: demo
labels:
app: web
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:1.26
status: # 由控制器维护,用户不写spec 是期望状态——用户写的内容。status 是当前状态——控制器写的内容。Pod IP、Ready 状态、重启次数、Deployment 可用副本数都在 status 里。
注意 YAML 里 selector.matchLabels 和 template.metadata.labels 写了同样的 app: web——这不是重复。selector 告诉 Deployment"哪些 Pod 归我管",template labels 是 Pod 出生时被打上的标记。两边的值必须匹配,否则 Deployment 创建出来的 Pod 不会被它自己识别,会导致副本数失控。
常见资源对象:
| 对象 | 解决的问题 |
|---|---|
| Namespace | 资源按项目/环境分组,权限作用范围 |
| Pod | 最小调度单元——一组共享网络和存储的容器 |
| Deployment | 管理无状态副本,滚动更新和回滚 |
| StatefulSet | 管理有状态副本,提供稳定网络身份和持久存储 |
| DaemonSet | 每个节点跑一个 Pod(日志采集、监控 Agent、CNI) |
| Service | 提供不随 Pod IP 变化的稳定访问入口 |
| ConfigMap | 注入非敏感的明文配置 |
| Secret | 注入敏感配置(密码、Token、证书) |
| Ingress / Gateway | 七层入口规则(域名路由、TLS、灰度) |
| PV / PVC / StorageClass | 把存储从 Pod 生命周期里独立出来 |
label 和 selector——资源关联的核心
K8s 里资源之间不靠固定 IP,靠 label 和 selector 建立关联:
| 关系 | 关联方式 |
|---|---|
| Deployment → Pod | spec.selector.matchLabels 匹配 Pod labels |
| Service → Pod | spec.selector 匹配 Pod labels |
| NetworkPolicy → Pod | podSelector 匹配 Pod labels |
| ServiceMonitor → Service | selector 匹配 Service labels |
| Pod → PVC | claimName 引用 PVC 名称 |
| Ingress/Gateway → Service | backend 引用 Service 名称和端口 |
标签写错或没对上时不会报错——Service 安安静静地没有后端 Pod,Deployment 接管不到新 Pod,监控采集不到目标。排查 Service "怎么不通"时,先确认 selector 和 Pod labels 是否一致。
K8s 的边界——什么能处理,什么处理不了
| K8s 能处理 | 说明 |
|---|---|
| 副本数维护 | Pod 少了补,多了缩 |
| 调度 | 按资源、污点、亲和性选择节点 |
| 服务发现 | Service 和 DNS 提供稳定访问入口 |
| 配置挂载 | ConfigMap、Secret 注入容器 |
| 滚动发布 | 分批替换 Pod |
| 基础自愈 | 容器退出后重启,节点故障后重调度 |
| K8s 处理不了 | 现场表现 |
|---|---|
| 应用启动逻辑错误 | CrashLoopBackOff——容器反复退出重启 |
| 数据库一致性 | Pod 重启不等于数据恢复——StatefulSet 提供稳定身份,不提供高可用方案 |
| 镜像 tag 混乱 | 同名 tag 在不同节点可能指向不同镜像内容 |
| 连接池过大 | 扩副本后数据库连接数打满——HPA 不会帮你调连接池 |
| 外部依赖故障 | Pod Running,但接口超时——探针定义在 K8s 里,根因在外部 |
| 存储后端故障 | PVC Bound,但挂载或 IO 异常——K8s 只看绑定状态,不看磁盘 IO |
Kubernetes 适合无状态服务、批处理任务、节点级采集组件和可水平扩展的应用。有状态服务也能跑,但存储、备份、升级顺序和故障切换需要单独设计。