Kubernetes 深度实践:架构、API 与避坑指南

第 1 章 背景与演进:为什么需要 Kubernetes

1.1 容器化带来的"幸福的烦恼"

Docker 让"构建一次,到处运行"成为现实,应用被封装成镜像后,开发、测试、生产环境的差异被大幅抹平。但当一个团队需要管理几十、几百甚至上千个容器时,单机 Docker 的局限立刻暴露:

痛点 具体表现
调度问题 容器该放在哪台机器上?如何根据 CPU / 内存合理分配?
故障恢复 容器崩溃、节点宕机后谁来自动拉起?人工重启不可扩展
扩缩容 流量高峰时如何快速扩容?低谷时如何缩容省资源?
服务发现 容器 IP 频繁变化,前端如何找到后端?
滚动发布 如何做到不停机发布、失败自动回滚?
配置管理 不同环境(dev / prod)的配置如何统一管理与注入?

这些问题的本质是:容器的生命周期管理不能靠人肉完成,需要一套自动化系统------这就是容器编排器(Container Orchestrator)的使命。

1.2 编排器的核心职责

一个合格的编排器至少要回答三个问题:

  1. 放哪里跑(调度):把容器放到资源充足、负载合理的节点上;
  2. 跑得好不好(自愈):持续对比"期望状态"与"实际状态",出现偏差就纠正(容器挂了重启、节点挂了迁移);
  3. 怎么被找到(服务发现与负载均衡):给一组容器提供稳定的访问入口。

1.3 为什么是 Kubernetes 胜出

2014-2016 年间出现过 Docker Swarm、Apache Mesos、HashiCorp Nomad、Kubernetes 等多个编排方案。最终 Kubernetes 胜出,核心原因有四:

  1. Google Borg / Omega 的经验背书:K8s 脱胎于 Google 内部运行了十余年的 Borg 系统,设计上继承了大规模集群管理的实战沉淀,而非从零摸索;
  2. 声明式 API 而非命令式:用户只需描述"最终要达到什么状态"(如"我要 3 个副本"),系统自行完成达成路径;相比命令式指令,声明式天然支持自愈、审计与 GitOps;
  3. 开放生态与中立性:K8s 由 CNCF 托管,社区驱动,从容器运行时(CRI)、网络(CNI)、存储(CSI)到设备(Device Plugin)全部插件化,不绑定任何厂商;
  4. 扩展机制:CRD(CustomResourceDefinition)+ Operator 模式让用户能把任意业务系统"变成"一等公民资源,生态爆炸式增长。

如今 Kubernetes 已是云原生(Cloud Native)的技术底座,几乎所有公有云都提供托管 K8s(EKS / AKS / GKE / TKE 等),大量中间件(数据库、消息队列、AI 训练)都以"跑在 K8s 上"为默认交付形态。

1.4 一句话理解 Kubernetes

Kubernetes 是一个"声明式 + 自愈"的分布式系统控制平面:你告诉它世界应该长什么样(Desired State),它负责让世界变成那样,并一直保持那样。

它是操作系统级抽象------如果把数据中心比作一台巨型计算机,K8s 就是它的"操作系统内核",负责进程(Pod)调度、内存(Node 资源)分配、网络(Service)与存储(PV)管理。


第 2 章 架构与核心组件

Kubernetes 集群分为**控制面(Control Plane)与工作节点(Node / Worker)**两部分。控制面负责"决策",节点负责"干活",两者通过 HTTPS 通信。

2.1 控制面(Control Plane)

组件 职责 一句话理解
kube-apiserver 集群唯一入口,提供 REST API,处理所有读写请求并做认证、授权、准入控制(Admission Control) 集群的"前台 + 总闸"
etcd 分布式键值数据库,存储集群全部状态(资源对象、配置、期望状态) 集群的"记忆"与唯一事实来源
kube-scheduler 为新创建的 Pod 挑选最合适的节点(综合资源、亲和性、污点、拓扑约束) 集群的"房产中介"
kube-controller-manager 运行各类控制器(ReplicationController、Deployment、Endpoint 等),执行"期望状态 → 实际状态"的控制回路 集群的"监工"
cloud-controller-manager(可选) 对接云厂商 API,管理负载均衡器、节点、路由等云资源 云上的"接线员"

2.2 工作节点(Node)

组件 职责 说明
kubelet 节点上的"管家",接收 API Server 指令,负责 Pod 的创建、启停、健康检查与状态上报 唯一直接操作容器的控制面代理
kube-proxy 维护节点上的网络规则(iptables / IPVS),实现 Service 的负载均衡与流量转发 只做数据面转发,不负责服务发现决策
容器运行时 实际运行容器的软件,如 containerd、CRI-O、Docker(已废弃) 通过 CRI(Container Runtime Interface)接入

2.3 一次部署请求的完整流转

以 kubectl apply -f deployment.yaml 为例,从提交到运行经过 6 个环节:

复制代码
kubectl ──①──▶ kube-apiserver ──②──▶ etcd
                │ ③
                ▼
            kube-scheduler(为 Pod 选节点)
                │ ④ 写回 Pod 的 nodeName 字段
                ▼
            kube-apiserver
                │ ⑤ Watch 到调度结果
                ▼
            kubelet(调用容器运行时创建容器)
                │ ⑥ 上报 Pod 状态
                ▼
            kube-apiserver ──▶ etcd(状态收敛到期望值)

关键点:所有组件都不直接互相调用,只与 API Server 通信 ;kubelet 等组件通过 Watch(长连接监听) 感知资源变化,而不是轮询。

2.4 自愈能力的根源:控制回路(Reconcile Loop)

Kubernetes 的核心设计思想是期望状态(Desired State)与现实状态(Current State)的循环比对:

复制代码
期望状态(etcd 中的 YAML 描述)
        │ 控制器 Watch
        ▼
控制器比对 ── 有偏差?── 否 ──▶ 保持不动(什么都不做)
        │ 是
        ▼
执行纠正动作(创建 / 删除 / 重启 / 扩缩容)
        │
        ▼
现实状态上报(kubelet 等)──▶ 回到比对

这就是为什么"删掉一个 Pod,它会被自动重建"------不是某个组件盯着 Pod,而是 ReplicaSet 控制器发现"实际副本数 2 < 期望副本数 3",于是主动补建。理解了这个循环,就理解了 K8s 80% 的"魔法"。


第 3 章 核心概念与工作负载资源

3.1 Namespace:集群内的"逻辑分区"

Namespace 用于在同一个集群内做资源隔离与权限划分(如 dev / test / prod),资源名在 Namespace 内唯一。注意:Namespace 是逻辑隔离而非硬性安全隔离,跨 Namespace 的网络默认也互通。

复制代码
# 创建 Namespace
apiVersion: v1
kind: Namespace
metadata:
  name: dev

常用命令:kubectl create ns dev、kubectl get ns、kubectl -n dev get pods。

3.2 Pod:调度与运行的最小单元

Pod 是 K8s 中可以创建和管理的最小计算单元,一个 Pod 可包含一个或多个容器。同 Pod 内容器:

  • 共享同一个网络命名空间(共享 IP、端口空间),通过 localhost 互通;
  • 共享同一个存储卷(Volume);
  • 由一个"暂停容器(pause / sandbox)"先占位拉起网络,业务容器随后加入。

为什么用 Pod 而不是直接调度容器? 因为"调度单位"需要比"进程"更大一些:关系紧密的一组进程(如主进程 + sidecar 日志采集 + 本地代理)必须同生共死、同节点运行,Pod 就是这层抽象。日常场景几乎不直接创建 Pod,而是通过 Deployment 等工作负载管理。

3.3 工作负载(Workload)资源选型

工作负载 有无状态 运行方式 典型场景 关键特性
Deployment 无状态 常驻 Web / API / 微服务 管理 ReplicaSet,支持滚动更新、回滚、水平扩缩容
StatefulSet 有状态 常驻 数据库、消息队列、分布式存储 稳定网络标识(Pod 名 + 序号)、稳定存储(PVC 按序绑定)、顺序部署/删除
DaemonSet 无状态 每节点一个 日志采集(Fluentd)、监控(node-exporter)、网络插件 新节点加入自动部署,节点删除自动清理
Job / CronJob 无状态 一次性 / 定时 数据迁移、批处理、定期备份 运行完成即结束,CronJob 按 cron 表达式定时触发

选型口诀:常驻 + 无状态 → Deployment;常驻 + 有状态 → StatefulSet;每节点必须有一个 → DaemonSet;跑完就走 / 定时 → Job / CronJob。

3.4 配置解耦:ConfigMap 与 Secret

  • ConfigMap:存放非敏感配置(环境变量、配置文件内容、命令行参数)。
  • Secret:存放敏感信息(密码、Token、证书),以 base64 形式存储(注意:base64 只是编码不是加密,详见第 7 章坑位)。

两者都可以通过环境变量 或挂载为文件 的方式注入 Pod。挂载方式支持热更新(Volume 方式更新的文件,K8s 会周期性同步),环境变量方式不支持运行时更新(重建 Pod 才生效)。

复制代码
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  APP_ENV: production
  config.yaml: |
    server:
      port: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  template:
    spec:
      containers:
      - name: app
        image: nginx:1.27
        envFrom:
        - configMapRef:
            name: app-config
        volumeMounts:
        - name: cfg
          mountPath: /etc/app
      volumes:
      - name: cfg
        configMap:
          name: app-config

3.5 Service 与 Ingress:访问入口

  • Service:为一组 Pod 提供稳定的虚拟 IP(ClusterIP)与 DNS 名,内置负载均衡,是 K8s 内部流量的"路由器";
  • Ingress:集群入口层的"反向代理规则",负责把外部 HTTP(S) 流量按域名 / 路径路由到不同 Service(需配合 Ingress Controller 实现,如 Nginx Ingress、Traefik)。

两者职责不同:Service 解决"Pod 之间怎么找到对方",Ingress 解决"外部怎么进到集群"。详见第 6 章。


第 4 章 Kubernetes API 体系详解

Kubernetes 的一切操作最终都是对 API Server 的 REST 请求。kubectl 只是 API 的客户端封装,理解 API 模型才能真正理解 K8s。

4.1 API 三级模型:Group / Version / Resource

每个资源类型都归属于某个 API Group ,并且有自己的 Version:

复制代码
/api/v1/namespaces/{ns}/pods/{name}          → 核心组(core,无 group 名)
/apis/apps/v1/deployments                    → apps 组
/apis/batch/v1/jobs                          → batch 组
/apis/networking.k8s.io/v1/ingresses         → networking.k8s.io 组

为什么分组? 不同领域(工作负载 / 调度 / 网络 / 存储)独立演进,各有自己的版本节奏,互不阻塞。

版本等级 含义 稳定性
alpha(v1alpha1) 试验特性,可能有破坏性变更,默认关闭 不稳定,仅评估用
beta(v1beta1) 已基本可用,默认开启 较稳定,可能有小变更
stable(v1) 正式 GA,长期兼容 稳定,可放心用于生产

生产环境必须优先使用 stable(v1) API。K8s 对废弃 API 的移除有明确的节奏(N-3 规则,即某 API 在版本 N 废弃后,至少要到版本 N+3 才移除),升级集群前务必检查待删除的 API。

4.2 资源对象的元结构:metadata / spec / status

任意 K8s 资源对象都遵守同一三元结构:

字段 谁负责写 作用
metadata 用户 名称、命名空间、标签(labels)、注解(annotations)、UID、资源版本(resourceVersion)
spec 用户 期望状态:用户声明的"世界应该长什么样"
status 控制器 / kubelet 实际状态:系统观测到的"世界现在长什么样",只读

kubectl apply 的核心机制:用户提交完整的 spec,API Server 用 Server-Side Apply / 三方合并 计算差异后更新,而不是简单整体覆盖。这是 GitOps 能够落地的底层保证。

4.3 kubectl 与 API 的对应关系

kubectl 命令 HTTP 方法 对应 API 操作 说明
kubectl create -f x.yaml POST /apis/apps/v1/namespaces/{ns}/deployments 创建新资源
kubectl get deployments GET 同上的 LIST 列出资源
kubectl get deployment myapp -o yaml GET /apis/apps/v1/.../deployments/myapp 读取单个资源
kubectl apply -f x.yaml PATCH(Server-Side Apply) 同上 声明式更新,推荐
kubectl delete deployment myapp DELETE 同上 删除资源
kubectl exec -it pod -- bash 升级为 SPDY/WebSocket 子资源 exec 进入容器执行命令

所有请求都经过认证(Authentication)→ 授权(Authorization,RBAC)→ 准入控制(Admission)三道关卡才写入 etcd。

4.4 认证与授权:RBAC 三要素

RBAC(Role-Based Access Control)由三类对象组成:

  • Role / ClusterRole:定义"能做什么"(对哪些资源有哪些操作权限,如 get/list/watch pods);

  • ServiceAccount:定义"是谁"(Pod 内部的身份,区别于人类用户);

  • RoleBinding / ClusterRoleBinding:把"身份"与"权限"绑定。

    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
    namespace: dev
    name: pod-reader
    rules:

    • apiGroups: [""]
      resources: ["pods", "pods/log"]
      verbs: ["get", "list", "watch"]

    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
    name: pod-reader-bind
    namespace: dev
    subjects:

4.5 资源发现与调试 API

bash 复制代码
# 查看集群支持的 API 组与版本
kubectl api-versions
# 查看某类资源的可用版本(含 alpha/beta/stable 全部)
kubectl api-resources | grep deployment
# 查看某资源对象的详细 YAML 定义(含可写字段)
kubectl explain deployment.spec.template.spec.containers.resources

kubectl explain 是学习 K8s API 的最佳助手:任何字段的合法取值、必填与否、含义都能在线查到,比死记文档高效得多。

4.6 扩展机制:CRD 与 Aggregated API

  • CRD(CustomResourceDefinition):用户自定义资源类型(如 CronTab、MySQLCluster),创建后即可用 kubectl 管理;
  • Operator 模式:CRD + 自定义控制器,把运维专家经验固化为代码,让 K8s 自动运维复杂应用(如 etcd-operator、prometheus-operator)。

这正是 K8s"平台化"能力的关键:API 是可扩展的,而不仅是固定的资源清单。


第 5 章 详细使用说明:从部署到运行的完整链路

5.1 环境搭建:三种方式怎么选

方式 适用场景 说明
minikube / kind 本地学习、快速验证 单节点,分钟级起集群,推荐入门
kubeadm 自建生产集群 官方引导工具,需自行运维 etcd 高可用、证书、网络插件
托管云 K8s(EKS / AKS / GKE / TKE) 生产主力 控制面免运维,按节点付费,推荐企业使用

5.2 最小 YAML:把一个镜像跑起来

以部署 nginx 为例,最小集合是 Deployment + Service 两个对象:

复制代码
# ① Deployment:声明期望状态
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-demo
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.27
        ports:
        - containerPort: 80
---
# ② Service:暴露给其他 Pod / 外部
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  selector:
    app: nginx
  ports:
  - port: 80
    targetPort: 80
  type: ClusterIP
bash 复制代码
kubectl apply -f nginx.yaml
kubectl get deployment,rs,pods,svc -l app=nginx

重要:spec.selector.matchLabels 必须与 Pod 模板的 metadata.labels 一致,这是控制器"认领"Pod 的依据,写错会导致 Deployment 无法管理 Pod。

5.3 暴露服务:外部流量怎么进集群

方式 原理 适用场景 局限
ClusterIP(默认) 集群内虚拟 IP + DNS,仅集群内可访问 内部服务调用 外部无法访问
NodePort 在每个节点上开一个端口(30000-32767),转发到 Service 测试、临时暴露 端口范围有限、需自行管理入口
LoadBalancer 云厂商创建负载均衡器(ELB / SLB)指向 NodePort 生产直接暴露 每个 Service 一个 LB,成本高
Ingress Ingress Controller(Nginx 等)按域名 / 路径路由 生产 HTTP(S) 入口 只支持 HTTP/HTTPS,需安装 Controller
复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-svc
            port:
              number: 80

5.4 配置与密钥注入

推荐用 ConfigMap / Secret 挂载文件(支持热更新)或 envFrom 注入环境变量。注意:

  • Secret 的 value 必须是 base64 编码(echo -n 'xxx' | base64);
  • 敏感信息建议用 ExternalSecret / SOPS 等外部方案管理,避免明文入库;
  • 配置变更后 Pod 不会自动重启,需要 kubectl rollout restart deployment/myapp。

5.5 存储挂载

无状态应用推荐用 emptyDir (临时)或 PVC(持久);有状态应用必须用 PVC + StorageClass 动态供给。最小 PVC 挂载示例:

复制代码
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data-pvc
spec:
  accessModes: ["ReadWriteOnce"]
  resources:
    requests:
      storage: 10Gi
---
# Deployment 中使用
spec:
  template:
    spec:
      containers:
      - name: app
        volumeMounts:
        - name: data
          mountPath: /data
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: data-pvc

5.6 滚动更新、回滚与扩缩容

复制代码
# 更新镜像并滚动发布(默认 maxUnavailable=25%, maxSurge=25%)
kubectl set image deployment/myapp app=nginx:1.28

# 查看发布状态
kubectl rollout status deployment/myapp

# 暂停 / 恢复(金丝雀发布常用)
kubectl rollout pause deployment/myapp
kubectl rollout resume deployment/myapp

# 回滚到上一个版本(或指定版本)
kubectl rollout undo deployment/myapp
kubectl rollout history deployment/myapp

# 手工扩缩容
kubectl scale deployment/myapp --replicas=5

# 自动扩缩容(HPA:按 CPU 利用率 70% 自动伸缩)
kubectl autoscale deployment/myapp --min=2 --max=10 --cpu-percent=70

HPA 生效前提:Pod 必须声明 resources.requests(HPA 依赖其计算利用率),且集群已安装 Metrics Server。

5.7 kubectl 常用命令速查矩阵

场景 命令
查看所有资源 kubectl get all
查看 Pod 详情与事件 kubectl describe pod <name>
查看实时日志 kubectl logs -f <pod> -c 容器名
进入容器 kubectl exec -it <pod> -- /bin/sh
端口转发(本地调试) kubectl port-forward svc/nginx-svc 8080:80
切换上下文 kubectl config use-context <name>
查看当前上下文 kubectl config current-context
查看集群事件 kubectl get events --sort-by='.lastTimestamp'
命令自动补全 source <(kubectl completion bash)(bash)

第 6 章 网络与存储机制

6.1 Pod 网络模型与 CNI

K8s 网络模型有 3 条铁律(无论使用什么插件都必须满足):

  1. 每个 Pod 拥有独立的 IP(同节点 Pod 也要能通过 IP 互通);
  2. 所有节点上的 Pod 之间无 NAT 直连(集群内任何 Pod 到任何 Pod 都可直达);
  3. Pod 看到的网络与节点网络不同,由 CNI(Container Network Interface) 插件负责打通。

主流 CNI 插件对比:

插件 模式 特点 适用
Flannel Overlay(VXLAN) 简单易用、性能一般 小型集群、入门
Calico BGP / 路由 性能好、支持 NetworkPolicy 中大型集群首选之一
Cilium eBPF 性能极佳、可观测性强、支持 NetworkPolicy 高性能 / 安全敏感场景

注意:Service 的 ClusterIP 是虚拟 IP,由 kube-proxy 用 iptables / IPVS 规则转发到真实 Pod,不参与 CNI 路由。

6.2 Service 三种类型的工作原理

以最常见的 ClusterIP 为例,访问链路为:

复制代码
客户端 → ClusterIP:Port → kube-proxy 规则(iptables/IPVS)→ 随机选择一个后端 Pod
                                                        ↑
                                    通过 EndpointSlice(Pod IP 列表)实时更新
  • ClusterIP:虚拟 IP,仅集群内可达,负载均衡到后端 Pod;
  • NodePort:在 ClusterIP 基础上,每个节点额外开放一个端口(默认 30000-32767),外部 → NodeIP:NodePort → ClusterIP → Pod;
  • LoadBalancer:在 NodePort 基础上,云厂商再创建一个外部负载均衡器,流量 外部 → LB → NodePort → Pod。

关键认知:三种类型是"叠加"关系,不是三选一的独立方案;externalTrafficPolicy: Local 可保留客户端源 IP,但会失去跨节点负载均衡。

6.3 Ingress 与 Ingress Controller

Ingress 本身只是一组规则声明 (哪个域名、哪个路径 → 哪个 Service),真正干活的是 Ingress Controller(如 Nginx Ingress Controller、Traefik、ALB Ingress):

复制代码
外部请求 → LoadBalancer(或 NodePort) → Ingress Controller(Pod) → 按规则路由 → Service → Pod

从 K8s 1.19 起 Ingress 的 apiVersion 为 networking.k8s.io/v1(旧版 extensions/v1beta1 已废弃移除);1.21 起建议显式指定 ingressClassName。

6.4 集群 DNS:CoreDNS

K8s 内置 CoreDNS,为 Service 提供域名解析。命名规则:

复制代码
<service-name>.<namespace>.svc.cluster.local

因此同 Namespace 内可直接用 service-name 访问,跨 Namespace 用 service-name.namespace。注意:/etc/hosts 不生效,Pod 内 DNS 由 CoreDNS 统一管理。

6.5 存储:PV / PVC / StorageClass 三层模型

对象 角色 谁创建
PV(PersistentVolume) 集群级存储资源(一块"硬盘") 管理员静态创建,或 StorageClass 动态创建
PVC(PersistentVolumeClaim) 用户对存储的"申请单"(我要 10Gi 读写一块) 用户 / 工作负载
StorageClass 存储"模板"(对接云盘 / NFS / 本地盘) 管理员,用于动态供给

动态供给流程:

复制代码
用户创建 PVC → 控制器看到 StorageClass → 调用云厂商 CSI 驱动创建云盘 → 生成 PV 并绑定 PVC → Pod 挂载

**回收策略(reclaimPolicy)**三选一:

策略 含义 适用
Delete(默认,动态供给) 删除 PVC 时连带删除底层存储(数据丢失!) 无状态数据、可重建
Retain 删除 PVC 后 PV 保留,需管理员手动处理 生产数据、数据库备份
Recycle(已废弃) 旧版清理后复用 不推荐

高频事故:误删 PVC 后"云盘没了、数据没了"------因为默认是 Delete 策略。生产库务必确认回收策略为 Retain,并做好备份。

6.6 有状态应用与 StatefulSet 的存储约定

StatefulSet 的每个副本(Pod-0、Pod-1...)按序号绑定独立 PVC (volumeClaimTemplates),删除 Pod 后重新创建仍绑定原 PVC,数据不丢。这也是它适合跑数据库的原因:每个实例有专属、稳定的存储身份。


第 7 章 常错点与坑:高频踩坑指南

排障方法论:先 kubectl describe 看事件 → 再 kubectl logs 看日志 → 最后看 kubectl get events 全局事件。多数问题 5 分钟内可定位。

7.1 启动失败类:ImagePullBackOff / ErrImagePull

现象 根因 排查 / 解法
ImagePullBackOff、ErrImagePull 镜像名写错、Tag 不存在、私有仓库认证失败、镜像拉取被限流 kubectl describe pod 看 Events 的拉取错误原文;docker pull 本地验证;私有仓库配置 imagePullSecrets;确认镜像名含正确 Tag 而非 latest 裸用
InvalidImageName 镜像名格式非法(如多写分隔符) 检查 YAML 镜像字段
一直 ContainerCreating 拉取超大镜像 / 存储驱动问题 事件定位,必要时优化镜像大小或预热

7.2 CrashLoopBackOff:容器反复崩溃

根因 特征 解法
应用启动即报错(依赖的 DB / 配置缺失) 日志有明显报错 看 kubectl logs 修复应用配置
启动命令写错(command / args 覆盖了镜像默认入口) 日志提示 command not found 检查容器的 command / args
探针误配:livenessProbe 太严格导致健康检查失败被杀 日志正常但 Pod 反复重启 调大 initialDelaySeconds / periodSeconds / failureThreshold;区分 liveness(活不活,杀)与 readiness(能不能接流量,摘流量不杀)
资源限制太小(OOMKilled) Events 显示 OOMKilled 调大 resources.limits.memory,见 7.4
启动后立即退出(一次性任务误用常驻工作负载) 日志显示正常结束 Job 场景改用 Job / CronJob

7.3 探针三连问(最高频的"玄学"坑)

  1. livenessProbe 挂了 → K8s 杀容器重启:适合"进程活着但死锁"的场景;不适合启动慢的应用(会反复被杀);

  2. readinessProbe 失败 → 只是从 Service 摘流量,不杀容器:用于"还没准备好"的优雅处理;

  3. startupProbe 存在时,liveness 在其成功前不生效:慢启动应用用 startupProbe 兜底。

    readinessProbe:
    httpGet:
    path: /healthz
    port: 8080
    initialDelaySeconds: 10
    periodSeconds: 10
    failureThreshold: 3

常见翻车:探针路径写错(404)、依赖外部组件导致探针误报、探针超时(timeoutSeconds 默认 1s 太短)。

7.4 资源请求 / 限制的坑

  • 只配 limit 不配 request:调度时按 request 分配资源,limit 只做运行期上限;Pod 可能因 limit 过高被调度到资源不足的节点然后 OOM;反之只配 request 不配 limit,突发流量可能把节点打爆;
  • CPU 是压缩资源:超过 limit 会被限流(throttling),表现为响应变慢而不是崩溃,性能排查时 container_cpu_cfs_throttled 指标暴涨即为此因;
  • memory 是非压缩资源:超过 limit 直接 OOMKilled;
  • request == limit 才是"Guaranteed" QoS:生产建议所有关键服务都配齐,避免被系统驱逐(Eviction)。

7.5 配置与 Secret 的坑

  • ConfigMap / Secret 改了不生效 :Volume 挂载方式约 1 分钟同步,但环境变量注入不热更新 ,需要 kubectl rollout restart;且更新 ConfigMap 时引用它的 Deployment 不会自动重建 Pod------不要以为改了配置就会自动生效;
  • Secret 是 base64 而非加密:kubectl get secret -o yaml 可直接解码明文,绝不要把 Secret 提交到公开仓库;
  • Secret 无法直接更新被大量 Deployment 引用的场景:考虑 ExternalSecret / SOPS 等外部密钥方案;
  • 镜像 Tag 用 latest :更新镜像后 kubectl rollout restart 可能拉不到新版本(节点缓存),生产必须用不可变 Tag(如 v1.2.3 或 commit SHA)。

7.6 存储的坑

  • PVC 删除即数据丢失:动态供给默认 reclaimPolicy: Delete,删 PVC 云盘随之删除(见 6.5);
  • PVC 扩容限制:accessModes 与存储类决定了能否在线扩容(ReadWriteOnce 可扩容,但部分存储类不支持缩小);
  • StatefulSet 删 Pod 不删 PVC:需要手动清理 PVC,否则重建同名 Pod 会用旧数据(可能正是你想要的,也可能导致"数据残留"事故);
  • emptyDir 在 Pod 删除后消失:跨 Pod 生命周期持久化数据必须用 PVC。

7.7 网络与入口的坑

  • NodePort 端口冲突:默认范围 30000-32767,多个 Service 抢同一端口报错;
  • Service selector 写错:后端 Pod 列表为空 → 访问 Connection Refused,用 kubectl get endpoints 检查是否有 Endpoint;
  • 跨 Namespace 访问忘加域名后缀:svc.namespace 才是全名;
  • Ingress 不生效:忘记安装 Ingress Controller、ingressClassName 未指定、TLS 证书格式错误(必须 PEM 格式含证书链);
  • externalTrafficPolicy: Cluster(默认)丢失客户端源 IP:日志里全是节点 IP,需要改 Local。

7.8 版本与升级的坑

  • API 版本被移除:升级集群前用 kubectl convert 或查阅 Release Notes 迁移废弃 API(如 extensions/v1beta1 Ingress、apps/v1beta1 Deployment);
  • kubectl 与集群版本不匹配:建议 kubectl version 校验,差异过大报 client/server version mismatch;
  • kubeadm 集群证书过期:默认一年有效期,kubeadm certs renew 续期,配合 kubeadm alpha certs renew(旧版命令)注意版本差异;
  • 集群升级跳过多个版本:kubeadm 不支持跨多个 minor 版本直跳,必须逐版本升级。

7.9 HPA / 自动伸缩不生效

现象 原因
HPA 一直显示 <unknown> 利用率 未安装 Metrics Server
HPA 不伸缩 Pod 未声明 resources.requests.cpu(HPA 计算利用率的依据)
HPA 频繁抖动 --horizontal-pod-autoscaler-sync-period 与冷却窗口、单 Pod 指标波动大;建议用 behavior 字段配置扩缩容策略
扩容到上限后仍有热点 需要结合 scaleUp 策略 / 自定义指标(KEDA)

7.10 集群管理与排障速查

复制代码
# 看 Pod 事件(90% 问题的第一现场)
kubectl describe pod <pod>
# 看容器日志(前 200 行 / 全部)
kubectl logs <pod> --tail=200
kubectl logs <pod> --previous   # 崩溃前容器日志
# 全局事件(按时间排序)
kubectl get events --sort-by='.lastTimestamp' | tail -30
# 节点资源与污点
kubectl describe node <node>
kubectl get nodes -o wide
# 检查 kubelet(节点上执行)
journalctl -u kubelet -f   # systemd 环境

终极兜底:事件与日志都正常但行为诡异时,检查 kubectl get all -A 全局资源、kubectl top nodes / pods 资源水位、以及 ConfigMap / Secret 引用是否被错误覆盖。


第 8 章 生产级最佳实践

8.1 资源治理:配额、限制与优先级

机制 作用 落地示例
ResourceQuota 限制 Namespace 级总资源(CPU / 内存 / 对象数量) 每个环境 Namespace 设置配额,防止"一个团队吃光集群"
LimitRange 限定 Pod / 容器级别的资源上下限,强制 request 与 limit 必填 default-request-cpu: 100m、default-limit-memory: 1Gi
PriorityClass 区分优先级,资源紧张时先驱逐低优先级 在线服务 > 批处理任务
PodDisruptionBudget(PDB) 保证主动驱逐(节点维护)时最少存活副本数 关键服务 minAvailable: 2

生产硬要求:所有 Deployment 显式声明 resources.requests 与 resources.limits;关键服务 QoS 为 Guaranteed(request == limit)。

8.2 多环境隔离与命名规范

  • 每个环境独立 Namespace(dev / staging / prod),配合 RBAC 做到"谁只能看自己的环境";
  • 统一标签规范(app / env / version / team),labels 是 K8s 的"索引系统",后续监控、网络策略、成本分摊都依赖它;
  • 环境差异用 ConfigMap / Secret 区分,不要在镜像里烧环境配置。

8.3 安全基线(必做清单)

  1. RBAC 最小权限:ServiceAccount 只授予所需资源的最小 verbs;禁止把 cluster-admin 绑定给应用 Pod;
  2. 镜像安全:使用可复现构建、镜像扫描(Trivy / Grype)、私有仓库 + 签名验证、禁止 latest 进生产;
  3. 准入控制 :启用 Pod Security Admission(取代已废弃的 PSP),强制 restricted / baseline 策略(禁止特权容器、禁止 hostPath 等);
  4. NetworkPolicy:默认拒绝 + 白名单放行(Calico / Cilium 支持),防止横向渗透;
  5. Secret 管理:使用 External Secrets Operator / SOPS 管理密钥,杜绝明文入库;
  6. 节点加固:关闭不必要端口、kubelet 只监听内网、etcd 加密与 TLS。

8.4 可观测性:Metrics / Logs / Tracing 三支柱

支柱 方案 关键点
指标 Prometheus + Grafana 必配:Pod 资源、HPA 指标、kube-state-metrics;告警规则覆盖 CPU / 内存 / 重启 / PDB
日志 Loki / ELK(EFK) 结构化日志(JSON)、kubectl logs 只查单 Pod,集群级检索必须集中式
链路 OpenTelemetry + Jaeger / Tempo 微服务排障必备,与 K8s 标签关联

最小闭环:先有 kubectl top 能看到资源,再有 Prometheus 历史曲线(容量规划),最后有告警(故障感知)------三者缺一不可。

8.5 声明式与 GitOps

  • 所有资源用 Git 管理,kubectl apply -f 只用于 CI/CD,禁止手工 kubectl create 或 kubectl edit 直接改线上;
  • Argo CD / Flux 作为 GitOps 引擎:Git 是唯一事实来源,集群自动同步,天然支持审计、回滚、多集群管理;
  • 配置漂移检测:GitOps 工具会自动发现并修复"有人手动改过集群"的漂移。

8.6 高可用集群设计

维度 建议
控制面 3 个 master 节点 + 奇数 etcd,etcd 与 API Server 分离部署
工作节点 跨可用区(AZ)分布,配 PDB 容忍节点维护
网络 双栈 / 多 CNI 高可用方案,Ingress Controller 多副本 + PDB
备份 etcd 定期快照(etcdctl snapshot save),配置与资源清单 Git 备份
升级 小版本持续升级(不要跳大版本),先 staging 验证再 prod,配合 kubectl drain 优雅排空节点

8.7 上线前自检清单

  • 所有工作负载有 request / limit,关键服务 Guaranteed QoS
  • liveness / readiness 探针路径经过测试(不是 404)
  • 存储回收策略确认(生产数据 Retain),有备份与恢复演练
  • Service selector 与 labels 一致,kubectl get endpoints 非空
  • 镜像使用不可变 Tag,来源受控(私有仓库)
  • RBAC 最小权限,Pod Security 策略 applied
  • 有监控与告警(CPU / 内存 / OOM / CrashLoop / 证书过期)
  • 配置通过 ConfigMap / Secret 管理,Git 化,非手工维护

第 9 章 总结与进阶路线

9.1 全文核心结论

主题 一句话结论
为什么需要 K8s 大规模容器生命周期管理无法人肉完成,需要声明式、自愈的编排系统
架构 控制面"决策"(API Server / etcd / scheduler / controller-manager),节点"执行"(kubelet / kube-proxy / 运行时),全部通过 API Server 通信
核心机制 期望状态 vs 实际状态的控制回路(Reconcile Loop)是自愈与自动化的根源
工作负载 按"有无状态 / 是否常驻 / 是否批量"三问选型:Deployment / StatefulSet / DaemonSet / Job
API Group / Version / Resource 三级模型 + spec/status 分离 + RBAC 三道关卡;kubectl 只是 API 客户端
使用链路 部署 → 暴露 → 配置 → 存储 → 更新 → 扩容,六步覆盖日常 80% 操作
网络存储 网络走 CNI + Service 虚拟 IP + Ingress 入口;存储走 PV / PVC / StorageClass 动态供给
高频坑 集中在镜像 / 资源 / 配置 / 版本四类根因,用 describe / logs / events 三板斧系统性排障
生产化 资源治理 + 安全基线 + 可观测性 + GitOps 是四件必做的系统工程

9.2 进阶学习路线(建议按阶段推进)

阶段一:会操作(1-2 周)

  • minikube 本地起集群,把第 5 章链路完整跑一遍;
  • 熟练 kubectl describe / logs / get events 排障三板斧;
  • 手写 Deployment / Service / ConfigMap / Secret / PVC 的 YAML,不依赖模板。

阶段二:懂原理(3-4 周)

  • 阅读第 4 章 API 模型,用 kubectl explain 查字段;
  • 弄懂控制回路:删掉 Pod 看它如何被重建,改 replicas 看控制器动作;
  • 动手搭一次 kubeadm 集群(哪怕 1 master + 1 node),理解证书、etcd、网络插件。

阶段三:深入生态(1-2 个月)

方向 学习内容 适合人群
Operator 开发 CRD + controller-runtime / Operator SDK 想平台化、做中间件运维的开发
交付与发布 Helm(打包)、Argo CD / Flux(GitOps)、Kustomize 平台 / 运维工程师
可观测性 Prometheus、OpenTelemetry、Loki、Grafana 运维 / SRE
服务网格 Istio / Linkerd(流量治理、安全、可观测) 微服务团队
云原生存储 / 网络 CSI / CNI 插件机制、Cilium eBPF 资深基础设施工程师

建议 :不要一开始就扎进 Istio 或复杂 Operator。先把"资源模型 + 控制回路"这两个思维底座打牢,后续所有生态组件(Helm 只是模板引擎、Operator 只是控制器、Argo CD 只是持续 reconcile)都能在同一个心智模型里找到位置。

9.3 最后的话

Kubernetes 学习的真正难点不是命令,而是思维模式的转换:从"我手动执行每一步"转变为"我声明目标状态,系统负责达成并维持"。一旦完成这个转换,你会发现 K8s 的每一块拼图(调度、网络、存储、Operator、GitOps)都遵循同一个模式。祝你在云原生的路上少踩坑、多沉淀。

相关推荐
MayBaymax2 小时前
MQ 基础概念与架构
java·中间件·架构·java-rocketmq
嘎嘎风2 小时前
MiniMind 学习笔记之 04 注意力之外:位置、记忆、省显存、省时间、深加工
架构·源码阅读
国科安芯3 小时前
商业立方星平台中高集成度抗辐射MCU的功耗优化与批量化应用可行性探讨
单片机·嵌入式硬件·架构·risc-v·抗辐射·as32x601
ESDWAN5 小时前
企业跨境网络合规建设指南:从线路选择到数据出境的全流程方案
网络·架构
MrSYJ5 小时前
别人再问你路由表是啥,这篇文章摔它脸上
docker·云原生·kubernetes
用户5372312882466 小时前
从一句话到水密 STL:给科研工具装 LLM Agent 的安全架构实录
架构
沫璃染墨6 小时前
《从零入门Linux系统篇(五十八):线程篇·十一——线程安全与死锁详解:从可重入到多锁管理》
linux·服务器·开发语言·c++·驱动开发·安全·架构
用户5708462574406 小时前
AI 会话该什么时候重开?一份「上下文卫生」的判断清单
架构
羑悻6 小时前
穿越Docker内核迷雾:揭秘镜像分层存储的叠加态与卷挂载的多维空间穿梭技术
后端·docker·容器