跳转到内容
123xiao | 无名键客

《Kubernetes 集群架构实战:从控制平面高可用到工作负载故障隔离的设计与落地》

字数: 0 阅读时长: 1 分钟

背景与问题

很多团队上 Kubernetes,第一阶段往往只关注“能跑起来”,第二阶段才会真正遇到架构问题:

  • 控制平面单点,kube-apiserver 一挂,全员失联
  • etcd 抖动,集群看起来“活着”,但所有变更都卡住
  • 某个 noisy neighbor 工作负载把节点 CPU、内存、IO 打满,别的业务一起陪葬
  • 一个命名空间里的错误配置,把整个集群调度和网络都拖慢
  • Pod 频繁重建,但业务方只看到一句“服务偶发超时”

我自己第一次接手生产集群时,最痛的不是某一个组件坏了,而是系统没有隔离层次:控制平面和业务平面互相影响、业务之间互相争抢、排障路径也没有固定套路。结果就是一旦出问题,大家都在猜。

这篇文章不从“组件百科”讲起,而是站在 troubleshooting(故障排查) 的角度,带你把两个关键问题串起来:

  1. 控制平面怎么做高可用,才能在故障时不失控?
  2. 工作负载怎么做故障隔离,才能把事故影响面收小?

如果你已经有基础的 Kubernetes 使用经验,这篇文章会更适合你。


典型故障现象

在进入设计前,先看几类常见现象。很多线上事故,其实都能映射到下面几种模式。

现象 1:kubectl 偶发超时或完全不可用

表现:

  • kubectl get pods -A 卡住
  • CI/CD 发版失败
  • 控制器无法更新资源状态
  • 新 Pod 一直 Pending,但节点其实有资源

这类问题往往指向:

  • kube-apiserver 单点或负载均衡异常
  • etcd 延迟高
  • 控制平面节点资源被抢占
  • 网络策略或证书问题

现象 2:节点没挂,但业务开始大面积超时

表现:

  • 某些服务 RT 飙升
  • Pod 重启变多
  • 节点 MemoryPressure / DiskPressure
  • kubelet 日志里出现 eviction

这通常不是“集群挂了”,而是隔离失效

  • 没有 requests/limits
  • 没有 QoS 区分
  • 没有 PodDisruptionBudget
  • 没有节点污点和业务分层
  • 核心系统组件和普通业务混跑

现象 3:某个业务故障扩散成全集群事故

表现:

  • 一个批处理任务把整个节点池打爆
  • 某租户命名空间里的 Pod 数暴涨
  • 大量短生命周期 Job 导致 apiserver、controller-manager 压力飙升

这时候你会发现:故障不怕局部爆发,怕没有边界


核心原理

这一部分我们只讲排障和落地最相关的原理,不追求面面俱到。

1. 控制平面高可用的本质

Kubernetes 控制平面高可用,核心有三层:

  1. kube-apiserver 多副本
  2. etcd 高可用
  3. 稳定的访问入口(LB/VIP)

可以把它理解成:

  • apiserver 是集群入口
  • etcd 是状态真相
  • 负载均衡器是入口门面

只要这三层里有任意一层设计不稳,集群就会进入“看起来有些组件活着,但实际上无法治理”的状态。

flowchart TD
    U[运维/控制器/kubectl] --> LB[负载均衡器 VIP/LB]
    LB --> A1[kube-apiserver-1]
    LB --> A2[kube-apiserver-2]
    LB --> A3[kube-apiserver-3]

    A1 --> E1[etcd-1]
    A2 --> E2[etcd-2]
    A3 --> E3[etcd-3]

    CM1[kube-controller-manager] --> LB
    SCH1[kube-scheduler] --> LB

    subgraph Worker Nodes
      P1[业务 Pod]
      P2[系统 Pod]
    end

    P1 --> LB
    P2 --> LB

为什么 apiserver 要多副本?

因为所有控制动作几乎都经过它:

  • 创建/删除 Pod
  • 调度结果写入
  • 控制器更新状态
  • kubelet 上报 Node/Pod 状态

单实例时,一旦宕机,已有 Pod 可能还能跑,但整个集群会进入不可变更状态。

为什么 etcd 是关键中的关键?

因为 etcd 保存集群状态。如果 etcd 不可写或延迟很高:

  • apiserver 响应会变慢
  • 控制器同步会卡住
  • 调度器失去最新视图
  • 资源对象可能出现“读得到旧状态,写不进去新状态”

etcd 不是普通数据库替代品,它更像是控制平面的“共识底座”。

2. 工作负载故障隔离的本质

隔离不是一个功能点,而是多层机制叠加出来的结果:

  • 资源隔离:requests/limits、LimitRange、ResourceQuota
  • 调度隔离:taint/toleration、nodeSelector、affinity
  • 生命周期隔离:PDB、优雅终止、探针
  • 网络隔离:NetworkPolicy
  • 权限隔离:RBAC、命名空间、ServiceAccount
  • 故障域隔离:拓扑分布、跨可用区、副本反亲和
flowchart LR
    A[故障隔离] --> B[资源隔离]
    A --> C[调度隔离]
    A --> D[网络隔离]
    A --> E[权限隔离]
    A --> F[故障域隔离]

    B --> B1[requests/limits]
    B --> B2[Quota/LimitRange]

    C --> C1[taint/toleration]
    C --> C2[affinity/anti-affinity]

    D --> D1[NetworkPolicy]
    E --> E1[RBAC]
    F --> F1[topologySpreadConstraints]

3. 为什么“高可用”和“隔离”必须一起设计?

一个很现实的问题:
如果控制平面高可用做了,但业务工作负载没隔离,那么在资源争抢时,控制平面仍然可能被业务拖死

反过来也一样:
如果工作负载隔离做得不错,但控制平面单点,平台治理能力一断,修复动作就很慢

所以我的经验是:先保控制平面可治理,再保业务故障有边界。


方案设计:从止血到长期架构

这里给一个适合中小到中大型集群的实战思路。

控制平面建议架构

  • 3 个控制平面节点
  • 每个节点运行:
    • kube-apiserver
    • kube-controller-manager
    • kube-scheduler
    • etcd(stacked etcd 方案)
  • 前置一个 LB 或 VIP
  • 控制平面节点打污点,不跑普通业务

什么时候选 stacked etcd?

适合:

  • 集群规模中等
  • 运维团队不想单独维护 etcd 集群
  • 想降低部署复杂度

什么时候考虑 external etcd?

适合:

  • 大规模集群
  • etcd 需要独立扩容、独立运维
  • 对控制平面和存储平面隔离要求更高

工作负载分层建议

建议至少分三层:

  1. 系统层
    • CoreDNS、CNI、metrics-server、ingress controller
  2. 关键业务层
    • 订单、支付、用户核心链路
  3. 普通业务/批处理层
    • 报表、离线任务、临时任务

落地方式:

  • 系统层节点池
  • 关键业务节点池
  • 批处理节点池

再通过:

  • taint/toleration
  • node affinity
  • resource quota
  • priority class

把边界真正“钉住”。


实战代码(可运行)

下面这部分我尽量给出可以直接应用或最少改动即可运行的示例。

1. 使用 kubeadm 初始化高可用控制平面

kubeadm-config.yaml

说明:这是一个简化可运行示例,适合实验或标准化部署模板起点。请将 IP、域名、版本替换成你的环境值。

apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
kubernetesVersion: v1.28.0
controlPlaneEndpoint: "k8s-api.example.com:6443"
networking:
  podSubnet: "10.244.0.0/16"
apiServer:
  certSANs:
    - "k8s-api.example.com"
    - "10.0.0.10"
controllerManager: {}
scheduler: {}
etcd:
  local:
    dataDir: /var/lib/etcd
---
apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: "10.0.0.11"
  bindPort: 6443
nodeRegistration:
  name: "cp-1"
  criSocket: "unix:///run/containerd/containerd.sock"
  taints:
    - key: "node-role.kubernetes.io/control-plane"
      effect: "NoSchedule"

初始化:

kubeadm init --config kubeadm-config.yaml --upload-certs

把输出中的 join 命令保存好,用于其他控制平面节点加入。

其他控制平面节点加入

kubeadm join k8s-api.example.com:6443 \
  --token <your-token> \
  --discovery-token-ca-cert-hash sha256:<hash> \
  --control-plane \
  --certificate-key <certificate-key>

工作节点加入

kubeadm join k8s-api.example.com:6443 \
  --token <your-token> \
  --discovery-token-ca-cert-hash sha256:<hash>

2. HAProxy 作为 apiserver 前置负载均衡

如果你没有云 LB,可以先用 HAProxy。

haproxy.cfg

global
    log /dev/log local0
    maxconn 2000

defaults
    log global
    mode tcp
    timeout connect 10s
    timeout client  1m
    timeout server  1m

frontend k8s_api
    bind *:6443
    default_backend k8s_api_backend

backend k8s_api_backend
    option tcp-check
    balance roundrobin
    server cp1 10.0.0.11:6443 check
    server cp2 10.0.0.12:6443 check
    server cp3 10.0.0.13:6443 check

如果用 Docker 快速启动:

docker run -d --name haproxy \
  -p 6443:6443 \
  -v $(pwd)/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro \
  haproxy:2.8

3. 给控制平面节点加隔离,避免普通业务调度上来

先看节点污点:

kubectl describe node cp-1 | grep Taints -A2

如果没有,可手动添加:

kubectl taint nodes cp-1 node-role.kubernetes.io/control-plane=:NoSchedule
kubectl taint nodes cp-2 node-role.kubernetes.io/control-plane=:NoSchedule
kubectl taint nodes cp-3 node-role.kubernetes.io/control-plane=:NoSchedule

4. 对普通业务启用 requests/limits 和配额

namespace-quota.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: team-a
---
apiVersion: v1
kind: LimitRange
metadata:
  name: default-limits
  namespace: team-a
spec:
  limits:
    - type: Container
      default:
        cpu: "500m"
        memory: "512Mi"
      defaultRequest:
        cpu: "200m"
        memory: "256Mi"
---
apiVersion: v1
kind: ResourceQuota
metadata:
  name: team-a-quota
  namespace: team-a
spec:
  hard:
    requests.cpu: "4"
    requests.memory: 8Gi
    limits.cpu: "8"
    limits.memory: 16Gi
    pods: "30"

应用:

kubectl apply -f namespace-quota.yaml

5. 用节点池和污点做业务分层

假设我们有一组批处理节点,标签为 workload=batch,并打上污点。

kubectl label nodes worker-3 workload=batch
kubectl label nodes worker-4 workload=batch
kubectl taint nodes worker-3 workload=batch:NoSchedule
kubectl taint nodes worker-4 workload=batch:NoSchedule

批处理任务 Deployment:

batch-app.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: batch-app
  namespace: team-a
spec:
  replicas: 2
  selector:
    matchLabels:
      app: batch-app
  template:
    metadata:
      labels:
        app: batch-app
    spec:
      tolerations:
        - key: "workload"
          operator: "Equal"
          value: "batch"
          effect: "NoSchedule"
      nodeSelector:
        workload: batch
      containers:
        - name: app
          image: nginx:1.25
          resources:
            requests:
              cpu: "300m"
              memory: "256Mi"
            limits:
              cpu: "1"
              memory: "512Mi"
          ports:
            - containerPort: 80

应用:

kubectl apply -f batch-app.yaml

6. 用反亲和和拓扑分布避免副本扎堆

critical-app.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: critical-app
  namespace: team-a
spec:
  replicas: 3
  selector:
    matchLabels:
      app: critical-app
  template:
    metadata:
      labels:
        app: critical-app
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              podAffinityTerm:
                labelSelector:
                  matchExpressions:
                    - key: app
                      operator: In
                      values:
                        - critical-app
                topologyKey: kubernetes.io/hostname
      topologySpreadConstraints:
        - maxSkew: 1
          topologyKey: topology.kubernetes.io/zone
          whenUnsatisfiable: ScheduleAnyway
          labelSelector:
            matchLabels:
              app: critical-app
      containers:
        - name: app
          image: registry.k8s.io/pause:3.9
          resources:
            requests:
              cpu: "100m"
              memory: "64Mi"
            limits:
              cpu: "200m"
              memory: "128Mi"

7. 用 PDB 防止运维动作把服务一起赶下线

pdb.yaml

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: critical-app-pdb
  namespace: team-a
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: critical-app

应用:

kubectl apply -f critical-app.yaml
kubectl apply -f pdb.yaml

8. 最小化 NetworkPolicy,先实现命名空间间隔离

前提:你的 CNI 支持 NetworkPolicy,例如 Calico、Cilium。

default-deny.yaml

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: team-a
spec:
  podSelector: {}
  policyTypes:
    - Ingress

allow-same-namespace.yaml

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-same-namespace
  namespace: team-a
spec:
  podSelector: {}
  ingress:
    - from:
        - podSelector: {}

应用:

kubectl apply -f default-deny.yaml
kubectl apply -f allow-same-namespace.yaml

现象复现:模拟一个“资源争抢导致故障扩散”的场景

为了让排障更具体,我们模拟一个 CPU 打满的工作负载。

cpu-burn.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: cpu-burn
  namespace: team-a
spec:
  replicas: 4
  selector:
    matchLabels:
      app: cpu-burn
  template:
    metadata:
      labels:
        app: cpu-burn
    spec:
      containers:
        - name: stress
          image: polinux/stress
          args: ["--cpu", "2"]
          resources:
            requests:
              cpu: "100m"
              memory: "64Mi"
            limits:
              cpu: "2"
              memory: "128Mi"

部署:

kubectl apply -f cpu-burn.yaml

观察节点资源:

kubectl top nodes
kubectl top pods -n team-a

如果你的集群没有做分层和配额,很容易看到某些节点被迅速打满,进而影响同节点其他业务。


定位路径:出了问题先看哪里

这一节是 troubleshooting 的重点。我建议排障时不要一上来就“到处翻日志”,而是按层次走。

sequenceDiagram
    participant User as 用户/业务
    participant SVC as Service/Ingress
    participant Pod as Pod
    participant Node as Node/Kubelet
    participant API as kube-apiserver
    participant ETCD as etcd

    User->>SVC: 请求超时/失败
    SVC->>Pod: 转发失败或无可用后端
    Pod-->>Node: Pod 重启/探针失败/被驱逐
    Node-->>API: 状态上报异常或延迟
    API-->>ETCD: 读写慢/失败
    ETCD-->>API: 高延迟

第一步:先分清是控制平面问题还是数据平面问题

快速判断命令

kubectl get --raw='/readyz?verbose'
kubectl get componentstatuses
kubectl get nodes
kubectl get pods -A

注意:

  • componentstatuses 已不推荐长期依赖,但在某些环境里还可以做粗略观察
  • 更可靠的是直接看 readyz、Pod 状态和组件日志

如果 kubectl 都连不上,优先检查:

  • LB/VIP 是否通
  • 6443 端口是否可达
  • apiserver 进程是否存活
  • 证书是否过期

第二步:控制平面排查路径

检查 apiserver

kubectl -n kube-system get pods -l component=kube-apiserver -o wide
kubectl -n kube-system logs kube-apiserver-cp-1 --tail=100

看这些关键词:

  • etcdserver: request timed out
  • context deadline exceeded
  • x509: certificate has expired
  • too many open files

检查 etcd

如果是 kubeadm stacked etcd:

kubectl -n kube-system get pods -l component=etcd -o wide
kubectl -n kube-system logs etcd-cp-1 --tail=100

常见异常:

  • leader 频繁切换
  • 磁盘延迟高
  • WAL/fsync 慢
  • 空间不足触发告警

如果节点上有 etcdctl,可以直接健康检查:

ETCDCTL_API=3 etcdctl \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key \
  endpoint health

检查 LB

nc -vz k8s-api.example.com 6443
curl -k https://k8s-api.example.com:6443/readyz

如果 LB 不健康,往往表现为:

  • 某个 apiserver 已挂,但 LB 还在转发
  • TCP 通,但后端 TLS 或 HTTP readyz 不正常
  • 健康检查策略过于简单

我踩过一个坑:LB 只做 TCP 端口探测,结果后端 apiserver 进程还在,但实际上已经无法正常处理请求,最终表现就是“偶发卡死”。

第三步:工作负载排查路径

看 Pod 为什么不可用

kubectl describe pod <pod-name> -n team-a
kubectl logs <pod-name> -n team-a --previous

重点看:

  • OOMKilled
  • CrashLoopBackOff
  • Readiness probe failed
  • Evicted
  • Insufficient cpu
  • Insufficient memory

看节点压力

kubectl describe node <node-name>
kubectl top node <node-name>
journalctl -u kubelet -n 100 --no-pager

观察是否有:

  • MemoryPressure
  • DiskPressure
  • eviction 相关日志
  • 镜像拉取卡顿
  • 容器运行时异常

看调度是否出问题

kubectl get events -A --sort-by=.lastTimestamp | tail -n 50

常见调度事件:

  • 0/6 nodes are available
  • node(s) had taint that the pod didn’t tolerate
  • node(s) didn’t match Pod’s node affinity
  • insufficient cpu/memory

这些信息非常关键,因为它告诉你:是资源不够,还是规则把自己卡住了。


常见坑与排查

这一节我列一些线上最常见、也最容易被忽略的问题。

坑 1:控制平面高可用了,但 etcd 仍然是隐形单点

现象

  • apiserver 有多个副本
  • 但一旦某个控制平面节点磁盘异常,整个集群变慢

原因

  • stacked etcd 虽然是多节点,但磁盘性能差、网络延迟高,仍然会导致整体不可用
  • etcd 对磁盘 fsync 很敏感,不能拿普通低性能盘硬扛

排查

kubectl -n kube-system logs etcd-cp-1 --tail=200 | grep -Ei "took too long|leader|timeout|slow"

止血方案

  • 先限制大规模对象变更操作
  • 暂停批量发布、批量 Job 创建
  • 检查磁盘 IO 和容量
  • 必要时迁移 etcd 到更稳定的存储节点

坑 2:节点资源没设 requests,调度看起来“很空”,运行时却被打爆

现象

  • Pod 都能调度成功
  • 运行一会儿后节点高负载、频繁 OOM

原因

调度器依据 requests 做资源预估,不是依据 limits,更不是依据“程序真实可能吃掉多少”。

排查

kubectl get pod -A -o jsonpath='{range .items[*]}{.metadata.namespace}/{.metadata.name}{"\t"}{range .spec.containers[*]}{.name}{": reqCPU="}{.resources.requests.cpu}{", reqMem="}{.resources.requests.memory}{"; "}{end}{"\n"}{end}'

止血方案

  • 立即通过 LimitRange 给默认 requests/limits
  • 对高风险命名空间加 ResourceQuota
  • 关键业务单独节点池

坑 3:只配了 liveness probe,没配 readiness probe

现象

  • Pod 已 Running,但服务大量 502/超时
  • 重启反而加剧问题

原因

  • liveness 只负责“活没活”
  • readiness 才负责“能不能接流量”

止血方案

  • 关键服务至少配置 readiness
  • 启动慢的应用加 startupProbe
  • 探针阈值不要照抄模板

坑 4:PDB 配太死,节点维护时 drain 不动

现象

kubectl drain <node-name> --ignore-daemonsets

卡住很久。

原因

  • minAvailable 过高
  • 副本数本来就不够
  • 单副本服务还配置了严格 PDB

排查

kubectl get pdb -A
kubectl describe pdb critical-app-pdb -n team-a

边界条件

PDB 是防止“主动驱逐”过度,不防节点突然宕机。不要把它理解成“高可用保险”。

坑 5:NetworkPolicy 一上来就全拒绝,结果 DNS 先挂了

现象

  • Pod 之间互通失败
  • 外部依赖访问异常
  • 应用报“无法解析域名”

原因

  • 默认拒绝后,没有放行到 CoreDNS 的流量

止血方案

补允许 DNS 的策略,例如:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-dns
  namespace: team-a
spec:
  podSelector: {}
  policyTypes:
    - Egress
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kube-system
      ports:
        - protocol: UDP
          port: 53
        - protocol: TCP
          port: 53

安全/性能最佳实践

这一节不追求大全,但都是能实打实减少事故概率的点。

安全最佳实践

1. 控制平面节点禁止跑普通业务

这是最基本、也最容易被忽视的一条。

建议:

  • 保留控制平面污点
  • 仅允许必要系统组件容忍该污点
  • 不要为了“资源利用率”把普通业务塞进去

2. 最小权限原则

  • 不要给默认 ServiceAccount 过高权限
  • 每个系统组件独立 RBAC
  • 租户隔离场景下,按命名空间细分 Role/RoleBinding

快速查看高风险绑定:

kubectl get clusterrolebinding
kubectl get rolebinding -A

3. 证书和密钥轮换要有台账

生产里经常不是组件挂了,而是证书过期了。

检查 kubeadm 证书:

kubeadm certs check-expiration

4. 审计日志要开,但不要无限制落盘

审计日志很有用,尤其是排查“谁改了配置”。
但如果不控制策略和存储,很容易变成 IO 压力源。


性能最佳实践

1. etcd 优先保证稳定磁盘和低延迟网络

如果预算有限,先别急着上更多插件,先把 etcd 所在节点硬件打稳。

重点关注:

  • 磁盘延迟
  • 空间碎片
  • leader 稳定性
  • 备份恢复演练

2. 限制对象风暴

会给控制平面施压的常见行为:

  • 短时间创建大量 Job/Pod
  • 频繁更新 ConfigMap/Secret
  • 控制器重试风暴
  • 大量 watch client

建议:

  • 对批处理任务做速率限制
  • 控制部署波次
  • 避免把 Kubernetes 当高频配置数据库

3. 系统组件资源要保底

例如 CoreDNS、CNI、ingress controller,建议明确 requests/limits。
否则业务波峰一来,最先被挤压的往往是这些“底座服务”。

4. 关键业务使用 PriorityClass,但不要滥用

如果所有业务都说自己“关键”,那实际上谁都不关键。

一个简化示例:

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: critical-workload
value: 100000
globalDefault: false
description: "用于核心业务工作负载"

应用后在 Pod 中引用:

priorityClassName: critical-workload

一套实用的止血方案

当线上已经出问题时,不要一上来就大改架构。我的建议是按下面顺序止血。

场景 1:apiserver 变慢或不稳定

优先级:

  1. 检查 LB 是否把流量发往不健康节点
  2. 检查 etcd 健康和延迟
  3. 停止大批量发布/批量 Job
  4. 检查控制平面节点是否被资源打满
  5. 查看证书、磁盘、文件句柄等基础问题

场景 2:节点资源争抢严重

优先级:

  1. 暂停高消耗批处理任务
  2. 驱逐或缩容异常工作负载
  3. 对命名空间补 ResourceQuota / LimitRange
  4. 给关键业务迁移到专用节点池
  5. 为系统组件补资源保底

场景 3:某租户影响全局

优先级:

  1. 用 Quota 限流该租户对象数和资源量
  2. 加默认 deny 网络策略,阻止横向扩散
  3. 拆分节点池,避免与关键业务同池
  4. 复盘该租户的发布和权限边界

总结

Kubernetes 集群架构做得好不好,不是看图画得多漂亮,而是看故障来了以后:

  • 控制平面是不是还能治理
  • 故障是不是能被限制在局部
  • 排障是不是有稳定路径
  • 止血动作是不是能快速执行

如果你希望把这篇文章里的内容真正落地,我建议按这个顺序推进:

  1. 先做控制平面高可用
    • 3 控制平面节点
    • 稳定 LB/VIP
    • etcd 健康检查和备份
  2. 再做最基本的工作负载隔离
    • requests/limits
    • LimitRange / ResourceQuota
    • 控制平面和普通业务分离
  3. 然后做关键业务保护
    • 独立节点池
    • PDB
    • 反亲和和拓扑分布
  4. 最后补网络和权限边界
    • NetworkPolicy
    • 最小 RBAC
    • 审计和证书轮换

边界条件也要说清楚:

  • 如果你的集群规模很小,别一上来把架构搞得过重,先守住最关键的高可用和隔离底线
  • 如果你的集群已经进入多租户、多环境共用阶段,那“靠约定隔离”基本不够,必须制度化、模板化、平台化
  • 如果 etcd 和控制平面节点底层硬件不稳,再多 YAML 也救不了根问题

一句话收尾:
高可用保证你“还能管”,故障隔离保证你“不会一起炸”。这两件事,是 Kubernetes 生产架构最该优先做的基本功。


分享到:

上一篇
《从单体到集群:面向中级工程师的高可用服务拆分与流量治理实战》
下一篇
《分布式架构中基于一致性哈希与服务发现的灰度发布实践与故障切换设计》