跳过正文

Kubernetes 核心架构全景

·2451 字·12 分钟·
目录

1. Kubernetes 是什么
#

一句话定义:Kubernetes(简称 K8s)是一个开源的容器编排平台,用于自动化部署、扩缩容和管理容器化应用。

解决什么问题:在容器技术(Docker)普及之后,单机跑容器很简单,但当应用需要跨多台机器部署、自动故障恢复、滚动升级、流量负载均衡时,手工管理几乎不可能。Kubernetes 的核心价值在于:

  • 声明式管理:描述"期望状态",系统自动驱动实际状态向期望收敛
  • 自愈能力:Pod 挂了自动重启,节点挂了自动迁移
  • 弹性扩缩容:基于 CPU/内存指标自动水平扩缩 Pod 数量
  • 服务发现与负载均衡:内置 DNS + Service 抽象,屏蔽 Pod IP 变化
  • 配置与密钥管理:ConfigMap/Secret 解耦配置与镜像

2. 整体架构
#

Kubernetes 集群由**控制面(Control Plane)工作节点(Worker Node)**两部分组成,etcd 作为整个集群的状态存储独立存在(生产建议与控制面分离部署)。

┌─────────────────────────────────────────────────────────────────┐
│                        Control Plane                            │
│                                                                 │
│  ┌─────────────────┐   ┌──────────────┐   ┌─────────────────┐  │
│  │  kube-apiserver  │   │kube-scheduler│   │  kube-controller│  │
│  │  (唯一入口)       │   │  (调度决策)   │   │    -manager     │  │
│  │  :6443           │   │              │   │  (控制循环)      │  │
│  └────────┬─────────┘   └──────┬───────┘   └────────┬────────┘  │
│           │                   │                     │           │
│           └───────────────────┼─────────────────────┘           │
│                               │  (全部经由 apiserver 通信)       │
│           ┌───────────────────┘                                 │
│           ▼                                                     │
│  ┌─────────────────┐   ┌──────────────────────────────────┐    │
│  │      etcd        │   │     cloud-controller-manager     │    │
│  │  (集群状态存储)   │   │   (云厂商集成: LB/节点/路由)      │    │
│  │  :2379           │   │                                  │    │
│  └─────────────────┘   └──────────────────────────────────┘    │
└────────────────────────────┬────────────────────────────────────┘
                             │  HTTPS (apiserver → kubelet)
              ┌──────────────┼──────────────────┐
              ▼              ▼                  ▼
┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐
│   Worker Node 1  │  │   Worker Node 2  │  │   Worker Node N  │
│                 │  │                 │  │                 │
│ ┌─────────────┐ │  │ ┌─────────────┐ │  │ ┌─────────────┐ │
│ │   kubelet   │ │  │ │   kubelet   │ │  │ │   kubelet   │ │
│ └─────────────┘ │  │ └─────────────┘ │  │ └─────────────┘ │
│ ┌─────────────┐ │  │ ┌─────────────┐ │  │ ┌─────────────┐ │
│ │ kube-proxy  │ │  │ │ kube-proxy  │ │  │ │ kube-proxy  │ │
│ └─────────────┘ │  │ └─────────────┘ │  │ └─────────────┘ │
│ ┌─────────────┐ │  │ ┌─────────────┐ │  │ ┌─────────────┐ │
│ │  containerd │ │  │ │  containerd │ │  │ │  containerd │ │
│ └─────────────┘ │  │ └─────────────┘ │  │ └─────────────┘ │
│ ┌────┐ ┌────┐  │  │ ┌────┐ ┌────┐  │  │ ┌────┐ ┌────┐  │
│ │Pod │ │Pod │  │  │ │Pod │ │Pod │  │  │ │Pod │ │Pod │  │
│ └────┘ └────┘  │  │ └────┘ └────┘  │  │ └────┘ └────┘  │
└─────────────────┘  └─────────────────┘  └─────────────────┘

核心设计原则:所有组件都只与 apiserver 通信,不互相直连。etcd 只有 apiserver 可以访问,其他组件通过 apiserver 读写集群状态。


3. 控制面组件详解
#

3.1 kube-apiserver
#

职责:集群的唯一入口,所有对 Kubernetes 资源的读写操作都必须经过 apiserver。

请求处理流程

客户端请求
    │
    ▼
┌──────────────┐
│  认证 (AuthN) │  ← 证书 / ServiceAccount Token / OIDC / Webhook
└──────┬───────┘
       │
       ▼
┌──────────────┐
│  授权 (AuthZ) │  ← RBAC / ABAC / Node / Webhook
└──────┬───────┘
       │
       ▼
┌──────────────────┐
│  准入控制 (Admission)│  ← MutatingWebhook → ValidatingWebhook
└──────┬───────────┘
       │
       ▼
┌──────────────┐
│  写入 etcd    │
└──────────────┘

生产注意事项

  • apiserver 是无状态服务,可以水平扩展多副本,前面挂 LB(内网 NLB 或 HAProxy)
  • 通过 --audit-log-path 开启审计日志,生产合规必须
  • --etcd-servers 指定 etcd 集群地址,多个 etcd 节点逗号分隔
  • 请求量大时关注 apiserver_request_total 指标,按动词/资源分类监控
# 查看 apiserver 状态
kubectl get componentstatuses

# 查看 apiserver 暴露的 API 版本
kubectl api-versions

# 查看某个资源的 API 详情
kubectl explain pod.spec.containers

3.2 etcd
#

职责:分布式键值存储,存储 Kubernetes 集群的所有状态数据(Pod、Service、Deployment 等所有对象)。

关键特性

  • 使用 Raft 共识算法保证强一致性
  • 只有 kube-apiserver 直接访问 etcd(其他组件不直连)
  • etcd 集群节点数建议为奇数:3 节点容忍 1 节点故障,5 节点容忍 2 节点故障

生产部署建议

场景建议
开发/测试etcd 与控制面同机部署,单节点即可
生产小规模独立 3 节点 etcd 集群,SSD 存储
生产大规模独立 5 节点 etcd 集群,专用 SSD,与控制面网络隔离

备份与恢复(极其重要,etcd 数据丢失 = 集群数据全丢):

# 备份 etcd 快照
ETCDCTL_API=3 etcdctl snapshot save /backup/etcd-$(date +%Y%m%d%H%M%S).db \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key

# 验证备份完整性
ETCDCTL_API=3 etcdctl snapshot status /backup/etcd-20251208.db --write-out=table

# 从快照恢复(需停止 apiserver)
ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-20251208.db \
  --data-dir=/var/lib/etcd-restore \
  --name=etcd-node1 \
  --initial-cluster=etcd-node1=https://10.0.0.1:2380 \
  --initial-advertise-peer-urls=https://10.0.0.1:2380

监控关键指标

  • etcd_server_leader_changes_seen_total:Leader 切换次数,频繁切换说明网络或磁盘问题
  • etcd_disk_wal_fsync_duration_seconds:WAL 刷盘延迟,SSD 建议 < 10ms
  • etcd_mvcc_db_total_size_in_bytes:数据库大小,建议不超过 8GB

3.3 kube-scheduler
#

职责:为新创建的(未绑定节点的)Pod 选择合适的 Worker Node。

调度决策流程

待调度 Pod 进入队列
        │
        ▼
┌───────────────────┐
│  Filter(过滤)    │  筛选出所有"可行"节点
│  - NodeSelector   │
│  - Taints/Tolerations│
│  - 资源是否充足    │
│  - PodAffinity    │
│  - NodeAffinity   │
│  - HostPort 冲突  │
└────────┬──────────┘
         │  可行节点列表
         ▼
┌───────────────────┐
│  Score(打分)     │  对可行节点评分 0-100
│  - LeastRequested │  资源剩余越多分越高
│  - NodeAffinity   │  软亲和加分
│  - ImageLocality  │  节点已有镜像加分
│  - InterPod*      │  Pod 间亲和/反亲和
└────────┬──────────┘
         │  最高分节点
         ▼
┌───────────────────┐
│  Bind(绑定)      │  写入 Pod.spec.nodeName
└───────────────────┘

影响调度的主要因素

# 示例:带完整调度约束的 Pod spec
apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  # 节点选择器(硬性要求)
  nodeSelector:
    kubernetes.io/arch: amd64

  # 节点亲和性(支持软/硬两种)
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
          - matchExpressions:
              - key: node-role
                operator: In
                values: ["worker"]
      preferredDuringSchedulingIgnoredDuringExecution:
        - weight: 100
          preference:
            matchExpressions:
              - key: topology.kubernetes.io/zone
                operator: In
                values: ["us-west-2a"]

    # Pod 反亲和:同一 Deployment 的 Pod 不调度到同一节点
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchLabels:
              app: my-service
          topologyKey: kubernetes.io/hostname

  # 容忍污点
  tolerations:
    - key: "dedicated"
      operator: "Equal"
      value: "gpu"
      effect: "NoSchedule"

  containers:
    - name: app
      image: my-app:latest
      resources:
        requests:
          cpu: "500m"
          memory: "512Mi"
        limits:
          cpu: "1"
          memory: "1Gi"

3.4 kube-controller-manager
#

职责:运行所有内置控制器的进程,每个控制器负责将某类资源的实际状态驱动到期望状态。

控制循环原理(Reconcile Loop)

         ┌─────────────────────────────────┐
         │         Controller              │
         │                                 │
         │  Watch(apiserver) → 事件触发     │
         │          │                      │
         │          ▼                      │
         │  读取期望状态 (Spec)              │
         │          │                      │
         │          ▼                      │
         │  读取实际状态 (Status)            │
         │          │                      │
         │          ▼                      │
         │  Diff → 执行操作 → 更新 Status   │
         │          │                      │
         │          └──→ 循环              │
         └─────────────────────────────────┘

内置控制器列表(常用):

控制器职责
Deployment Controller管理 ReplicaSet,实现滚动更新/回滚
ReplicaSet Controller保证指定数量的 Pod 副本运行
StatefulSet Controller有序部署/扩缩/删除有状态应用
DaemonSet Controller确保每个节点运行一个 Pod 副本
Job Controller管理一次性任务,保证完成数
CronJob Controller按计划触发 Job
Node Controller监控节点状态,处理节点不可达
Namespace Controller处理 Namespace 删除时的级联清理
Endpoints Controller维护 Service 对应的 Endpoints 列表
ServiceAccount Controller为新 Namespace 创建默认 ServiceAccount
PV Controller绑定 PV 与 PVC,处理存储回收

查看控制器日志

# 控制面用 kubeadm 部署时,controller-manager 作为 static pod 运行
kubectl logs -n kube-system kube-controller-manager-<node-name>

# 查看 Deployment 控制器的事件
kubectl describe deployment my-deployment
kubectl get events --field-selector involvedObject.name=my-deployment

3.5 cloud-controller-manager
#

职责:将 Kubernetes 与具体云厂商的 API 集成,实现云资源的自动管理。

主要集成能力

控制器功能示例
Node Controller节点注册/删除时同步云资源AWS EC2 实例标签同步
Route Controller配置云网络路由VPC 路由表,Pod CIDR 路由
Service ControllerLoadBalancer 类型 Service 自动创建云 LBAWS NLB/ALB,阿里云 SLB

实际效果:创建一个 type: LoadBalancer 的 Service,cloud-controller-manager 自动在云上创建对应的负载均衡器并配置好转发规则,无需手动操作:

apiVersion: v1
kind: Service
metadata:
  name: my-service
  annotations:
    # AWS 特定注解
    service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
    service.beta.kubernetes.io/aws-load-balancer-internal: "true"
spec:
  type: LoadBalancer
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 8080

4. 工作节点组件详解
#

4.1 kubelet
#

职责:运行在每个 Worker Node 上,是节点的"代理",负责管理该节点上所有 Pod 的生命周期。

核心职责

  1. 向 apiserver 注册节点,定期汇报节点状态(心跳)
  2. Watch apiserver,获取调度到本节点的 Pod 定义
  3. 调用 CRI(容器运行时接口)创建/删除容器
  4. 调用 CNI(容器网络接口)配置 Pod 网络
  5. 调用 CSI(容器存储接口)挂载持久卷
  6. 执行 liveness/readiness/startup probe,处理探针失败

Pod 生命周期管理

apiserver 下发 Pod 定义
        │
        ▼
kubelet 接收到 Pod (PodAdmission)
        │
        ▼
拉取镜像 (ImagePull via CRI)
        │
        ▼
创建 Pause 容器 (infra container, 持有 network namespace)
        │
        ▼
CNI 为 Pause 容器配置网络 (分配 Pod IP)
        │
        ▼
创建 Init 容器 (按顺序,逐个完成)
        │
        ▼
创建业务容器 (并发启动)
        │
        ▼
执行 PostStart Hook (若配置)
        │
        ▼
Startup Probe → Readiness Probe → Liveness Probe (持续运行)
        │
  Pod 正常运行中
        │
  收到删除信号
        │
        ▼
执行 PreStop Hook (若配置,等待完成)
        │
        ▼
发送 SIGTERM 信号给容器进程
        │
        ▼
等待 terminationGracePeriodSeconds (默认 30s)
        │
        ▼
发送 SIGKILL(若进程仍存在)
        │
        ▼
CNI 清理网络,CSI 卸载存储

生产关键配置

# Pod 中关于优雅终止的配置
spec:
  terminationGracePeriodSeconds: 60  # 根据应用实际停止时间调整
  containers:
    - name: app
      lifecycle:
        preStop:
          exec:
            command: ["/bin/sh", "-c", "sleep 5"]  # 给 LB 摘流时间
      livenessProbe:
        httpGet:
          path: /health
          port: 8080
        initialDelaySeconds: 30
        periodSeconds: 10
        failureThreshold: 3
      readinessProbe:
        httpGet:
          path: /ready
          port: 8080
        initialDelaySeconds: 5
        periodSeconds: 5
        failureThreshold: 2

4.2 kube-proxy
#

职责:运行在每个节点上,维护节点的网络规则,实现 Service 的流量转发(ClusterIP/NodePort/LoadBalancer)。

工作模式对比

特性iptables 模式ipvs 模式
实现方式iptables 规则链Linux IPVS(内核级 LVS)
规则复杂度O(n) 线性,规则量随 Service 增长O(1) hash 表,性能稳定
负载均衡算法随机(概率分配)rr/lc/dh/sh/sed/nq 多种
适用场景Service 数量 < 1000Service 数量大,高性能要求
依赖无额外依赖需要内核模块 ip_vs
连接跟踪依赖 conntrack依赖 conntrack
默认模式是(老版本)推荐切换

切换到 ipvs 模式

# 确认内核模块
lsmod | grep ip_vs
# 若没有,加载模块
modprobe ip_vs
modprobe ip_vs_rr
modprobe ip_vs_wrr
modprobe ip_vs_sh

# 修改 kube-proxy ConfigMap
kubectl edit configmap kube-proxy -n kube-system
# 将 mode: "" 改为 mode: "ipvs"

# 重启 kube-proxy DaemonSet
kubectl rollout restart daemonset kube-proxy -n kube-system

# 验证 ipvs 规则
ipvsadm -ln

Service 流量转发原理(iptables 模式简示)

Pod 发出请求 → ClusterIP:Port
        │
        ▼ iptables PREROUTING
KUBE-SERVICES chain
        │
        ▼ 匹配 ClusterIP
KUBE-SVC-XXXX chain (按概率 DNAT 到某个 Pod)
        │
        ▼
KUBE-SEP-YYYY chain (DNAT: ClusterIP → PodIP:Port)
        │
        ▼
实际 Pod 收到请求

4.3 Container Runtime(容器运行时)
#

职责:实际负责容器的创建、启动、停止、删除,kubelet 通过 CRI 接口与其通信。

CRI(Container Runtime Interface):kubelet 与容器运行时之间的标准接口(gRPC),使 kubelet 不依赖具体实现。

主流运行时对比

特性containerdCRI-ODocker (via cri-dockerd)
CNCF 项目
轻量程度轻量最轻量较重
镜像兼容性OCI 标准OCI 标准OCI 标准
生产使用最广泛OpenShift 默认逐渐淘汰
K8s 1.24+直接支持直接支持需额外 shim
调试工具crictl, nerdctlcrictldocker CLI

K8s 1.24 起正式移除了内置的 dockershim,Docker 作为运行时需要通过 cri-dockerd 桥接。新集群推荐直接使用 containerd。

常用 containerd 调试命令

# 安装 crictl(CRI 调试工具)
# 配置指向 containerd socket
cat > /etc/crictl.yaml <<EOF
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 30
EOF

# 列出运行中的容器
crictl ps

# 列出所有镜像
crictl images

# 查看容器日志
crictl logs <container-id>

# 查看 Pod 详情
crictl inspect <container-id>

# 拉取镜像
crictl pull nginx:1.25

5. 核心资源对象速览
#

5.1 工作负载资源
#

资源对象作用常用场景
Pod最小部署单元,一组共享网络/存储的容器直接使用较少,通常由上层控制器管理
ReplicaSet保证指定数量的 Pod 副本运行通常不直接创建,由 Deployment 管理
Deployment管理无状态应用,支持滚动更新/回滚Web 服务、API 服务等无状态应用
StatefulSet有序部署,稳定网络标识,稳定存储数据库、Kafka、ZooKeeper 等有状态应用
DaemonSet每个节点运行一个 Pod日志采集(Fluentd)、监控(node-exporter)、CNI 插件
Job一次性任务,保证成功完成 N 次数据迁移、批量处理、初始化脚本
CronJob按 cron 表达式定期创建 Job定时报表、定时清理、定时备份

5.2 服务与网络资源
#

资源对象作用常用场景
Service为一组 Pod 提供稳定的访问入口内部服务发现、LoadBalancer 暴露外部
IngressHTTP/HTTPS 七层路由规则多个服务共享一个 LB,基于域名/路径路由
EndpointsService 对应的后端 Pod IP 列表手动管理时用于接入集群外部服务
EndpointSliceEndpoints 的分片实现,大规模下性能更好K8s 1.17+ 自动使用
NetworkPolicy定义 Pod 间的网络访问规则微服务安全隔离,限制东西向流量

5.3 配置与存储资源
#

资源对象作用常用场景
ConfigMap存储非敏感配置数据(键值/文件)应用配置文件、环境变量
Secret存储敏感数据(base64 编码,可对接 KMS)密码、证书、镜像拉取凭证
PersistentVolume (PV)集群层面的存储资源管理员预先配置或动态供应的存储
PersistentVolumeClaim (PVC)Pod 对存储的请求声明应用申请存储,与具体存储解耦
StorageClass定义存储的"类型"和供应方式动态 PV 供应,区分 SSD/HDD/NFS

5.4 访问控制资源
#

资源对象作用常用场景
Namespace集群内的逻辑隔离单元多团队/多环境隔离
ServiceAccountPod 的身份标识,用于访问 apiserver为应用赋予最小权限
RoleNamespace 级别的权限定义限定某命名空间内的操作权限
ClusterRole集群级别的权限定义跨命名空间或集群级别资源权限
RoleBinding将 Role 绑定到用户/组/ServiceAccountNamespace 内授权
ClusterRoleBinding将 ClusterRole 绑定到主体集群管理员权限授予

5.5 自动伸缩与稳定性资源
#

资源对象作用常用场景
HPA (HorizontalPodAutoscaler)基于指标自动水平扩缩 Pod 数CPU/内存/自定义指标驱动弹性扩缩
VPA (VerticalPodAutoscaler)自动调整 Pod 的 resource requests优化资源利用率(谨慎用于生产)
PodDisruptionBudget (PDB)限制同时中断的 Pod 数量滚动更新/节点维护时保证可用性
PriorityClass定义 Pod 调度优先级关键服务高优先级,确保资源抢占

PDB 示例(生产中关键服务必须配置):

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: my-service-pdb
  namespace: production
spec:
  # 至少保证 2 个 Pod 可用
  minAvailable: 2
  # 或者用百分比:maxUnavailable: 25%
  selector:
    matchLabels:
      app: my-service

HPA 示例

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: my-service-hpa
  namespace: production
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-service
  minReplicas: 3
  maxReplicas: 20
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300  # 缩容冷却 5 分钟,避免抖动
      policies:
        - type: Percent
          value: 20
          periodSeconds: 60
    scaleUp:
      stabilizationWindowSeconds: 30
      policies:
        - type: Percent
          value: 100
          periodSeconds: 30

6. 请求链路追踪:kubectl apply 背后发生了什么
#

kubectl apply -f deployment.yaml 为例,追踪完整链路:

Step 1: kubectl 读取本地 kubeconfig(~/.kube/config)
        确定 apiserver 地址、证书、当前 context

Step 2: kubectl 发送 HTTP PATCH 请求到 apiserver
        POST /apis/apps/v1/namespaces/default/deployments
        Body: Deployment 的 JSON 定义
        Header: 证书或 Token 认证

Step 3: apiserver 认证(AuthN)
        验证客户端证书或 Bearer Token
        确认请求者身份(如 admin 用户)

Step 4: apiserver 授权(AuthZ)
        RBAC 检查:admin 是否有 create deployments 权限
        通过则继续,否则返回 403

Step 5: apiserver 准入控制(Admission)
        MutatingWebhook:注入 sidecar、设置默认值(如默认 requests/limits)
        ValidatingWebhook:校验资源定义合法性
        内置准入:ResourceQuota 检查命名空间配额

Step 6: apiserver 将 Deployment 对象写入 etcd
        对象获得 resourceVersion、uid 等元数据

Step 7: Deployment Controller 感知到新 Deployment(Watch 事件)
        计算需要创建的 ReplicaSet
        创建 ReplicaSet 对象(写入 etcd via apiserver)

Step 8: ReplicaSet Controller 感知到新 ReplicaSet
        计算需要创建 N 个 Pod
        创建 Pod 对象(nodeName 为空,写入 etcd via apiserver)

Step 9: kube-scheduler 感知到未调度的 Pod(Watch 事件)
        执行 Filter → Score → Bind
        选定节点,更新 Pod.spec.nodeName(写入 etcd via apiserver)

Step 10: 目标节点的 kubelet 感知到分配给自己的 Pod(Watch 事件)
         调用 CRI(containerd)拉取镜像
         创建 Pause 容器,调用 CNI 分配 Pod IP
         创建 Init 容器(按顺序)
         创建业务容器

Step 11: kubelet 更新 Pod Status(写入 etcd via apiserver)
         phase: Running, conditions: Ready: True

Step 12: Endpoints Controller 感知到 Pod Ready
         将 Pod IP 加入对应 Service 的 Endpoints

Step 13: kube-proxy 感知到 Endpoints 变更
         更新节点上的 iptables/ipvs 规则
         新 Pod 开始接收流量

整个过程从 kubectl apply 到 Pod 开始接收流量,正常情况下 10-60 秒(取决于镜像大小和资源充裕程度)。


7. 生产实践要点
#

7.1 etcd 备份策略
#

etcd 是整个集群的"大脑",数据丢失无法恢复(集群中所有 Deployment、Service、Secret 等全部消失),必须认真对待备份。

#!/bin/bash
# etcd 定时备份脚本,建议每小时执行一次
# 配合 cron: 0 * * * * /usr/local/bin/etcd-backup.sh

BACKUP_DIR="/data/etcd-backups"
RETAIN_DAYS=7
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="${BACKUP_DIR}/etcd-snapshot-${TIMESTAMP}.db"

mkdir -p "${BACKUP_DIR}"

ETCDCTL_API=3 etcdctl snapshot save "${BACKUP_FILE}" \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key

# 验证备份
if ETCDCTL_API=3 etcdctl snapshot status "${BACKUP_FILE}" > /dev/null 2>&1; then
  echo "[OK] etcd backup succeeded: ${BACKUP_FILE}"
  # 同步到远端存储(S3/OSS)
  aws s3 cp "${BACKUP_FILE}" "s3://my-k8s-backup/etcd/${TIMESTAMP}.db"
else
  echo "[ERROR] etcd backup failed!"
  exit 1
fi

# 清理超过 7 天的本地备份
find "${BACKUP_DIR}" -name "etcd-snapshot-*.db" -mtime "+${RETAIN_DAYS}" -delete

7.2 apiserver 高可用
#

生产环境 apiserver 至少 2 副本,kubeadm 部署的控制面节点建议 3 个:

                    ┌─────────────────┐
                    │   Internal LB   │
                    │  (NLB / HAProxy)│
                    │  :6443          │
                    └────────┬────────┘
                             │
           ┌─────────────────┼─────────────────┐
           ▼                 ▼                 ▼
  ┌─────────────┐   ┌─────────────┐   ┌─────────────┐
  │ apiserver-1 │   │ apiserver-2 │   │ apiserver-3 │
  │ :6443       │   │ :6443       │   │ :6443       │
  └─────────────┘   └─────────────┘   └─────────────┘
           │                 │                 │
           └─────────────────┼─────────────────┘
                             │
                    ┌────────▼────────┐
                    │   etcd 集群      │
                    │  (3 or 5 节点)   │
                    └─────────────────┘

kubeconfig 中的 server 指向 LB 地址,任一 apiserver 实例故障,LB 自动摘除,不影响集群操作。

7.3 资源限制必须设置
#

不设置 resources.requestsresources.limits 是生产事故的重要来源之一:

# 错误示例:不设置资源限制
containers:
  - name: app
    image: my-app:latest
    # 没有 resources 字段 → QoS 为 BestEffort → 节点资源紧张时第一个被驱逐

# 正确示例:明确设置资源
containers:
  - name: app
    image: my-app:latest
    resources:
      requests:        # 调度依据,保证这么多资源
        cpu: "500m"
        memory: "512Mi"
      limits:          # 硬性上限,超过 CPU 被限速,超过内存被 OOM Kill
        cpu: "1"
        memory: "1Gi"

QoS 等级与驱逐优先级

QoS 等级条件驱逐优先级
Guaranteedrequests == limits(所有容器)最后被驱逐
Burstablerequests < limits,或部分设置中等
BestEffort未设置任何 requests/limits最先被驱逐

使用 LimitRange 设置命名空间默认值

apiVersion: v1
kind: LimitRange
metadata:
  name: default-limits
  namespace: production
spec:
  limits:
    - type: Container
      default:           # 默认 limits
        cpu: "500m"
        memory: "512Mi"
      defaultRequest:    # 默认 requests
        cpu: "100m"
        memory: "128Mi"
      max:               # 最大值
        cpu: "4"
        memory: "8Gi"

使用 ResourceQuota 限制命名空间总用量

apiVersion: v1
kind: ResourceQuota
metadata:
  name: production-quota
  namespace: production
spec:
  hard:
    requests.cpu: "20"
    requests.memory: "40Gi"
    limits.cpu: "40"
    limits.memory: "80Gi"
    count/pods: "100"
    count/services: "20"
    count/persistentvolumeclaims: "30"

7.4 命名空间隔离策略
#

多团队共享集群时,命名空间隔离是关键:

# NetworkPolicy:禁止跨命名空间访问(默认拒绝所有入站)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-cross-namespace
  namespace: team-a
spec:
  podSelector: {}  # 匹配所有 Pod
  policyTypes:
    - Ingress
    - Egress
  ingress:
    # 只允许来自同命名空间的流量
    - from:
        - podSelector: {}
    # 允许来自 monitoring 命名空间的 Prometheus 抓取
    - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: monitoring
      ports:
        - port: 9090
          protocol: TCP
  egress:
    # 允许访问 kube-dns
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kube-system
      ports:
        - port: 53
          protocol: UDP
        - port: 53
          protocol: TCP
    # 允许访问同命名空间
    - to:
        - podSelector: {}
    # 允许访问外网(视需要开放)
    - to:
        - ipBlock:
            cidr: 0.0.0.0/0
            except:
              - 10.0.0.0/8
              - 172.16.0.0/12
              - 192.168.0.0/16

RBAC 最小权限原则

# 为应用 ServiceAccount 授予最小权限
apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-service-account
  namespace: production

---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: my-service-role
  namespace: production
spec:
  rules:
    # 只允许读取自己命名空间的 ConfigMap 和 Secret
    - apiGroups: [""]
      resources: ["configmaps", "secrets"]
      verbs: ["get", "list", "watch"]
    # 允许读取 Pod 信息(用于服务发现)
    - apiGroups: [""]
      resources: ["pods"]
      verbs: ["get", "list"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: my-service-rolebinding
  namespace: production
subjects:
  - kind: ServiceAccount
    name: my-service-account
    namespace: production
roleRef:
  kind: Role
  name: my-service-role
  apiGroup: rbac.authorization.k8s.io

7.5 常用生产排障命令
#

# 查看集群整体状态
kubectl get nodes -o wide
kubectl get pods -A | grep -v Running

# 查看 Pod 异常原因
kubectl describe pod <pod-name> -n <namespace>
kubectl logs <pod-name> -n <namespace> --previous  # 查看上一次崩溃的日志
kubectl logs <pod-name> -n <namespace> -c <container>  # 多容器 Pod 指定容器

# 进入 Pod 内部调试
kubectl exec -it <pod-name> -n <namespace> -- /bin/sh

# 查看节点资源使用情况
kubectl top nodes
kubectl top pods -A --sort-by=memory

# 查看事件(按时间排序)
kubectl get events -n <namespace> --sort-by='.lastTimestamp'

# 强制删除卡住的 Pod(谨慎!有状态应用慎用)
kubectl delete pod <pod-name> -n <namespace> --grace-period=0 --force

# 查看 Pod 调度失败原因
kubectl get events -n <namespace> | grep Warning | grep FailedScheduling

# 临时扩缩 Deployment 副本数
kubectl scale deployment <name> -n <namespace> --replicas=5

# 查看 Deployment 滚动更新状态
kubectl rollout status deployment/<name> -n <namespace>

# 回滚 Deployment 到上一版本
kubectl rollout undo deployment/<name> -n <namespace>

# 查看 Deployment 历史版本
kubectl rollout history deployment/<name> -n <namespace>

8. 参考链接
#

Wenzhuo Huang
作者
Wenzhuo Huang
搞运维的工程师,写代码的运维人。专注 Kubernetes、AWS、GitOps 与基础设施可靠性。这个博客既是我的技术笔记本,也是我踩过的坑的受害者档案。

相关文章