SRE & AI 实践录

Kubernetes 集群高可用与故障自动愈合实践

· 更新于 2026-07-26 ⏱️ 阅读约 2 分钟 (683 字) Kubernetes SRE 高可用

深入探讨控制面多活部署、etcd 集群调优、Pod 反亲和策略与自定义 Controller 实现故障自愈的最佳实践。

一、控制面多活部署

Kubernetes 控制面的高可用是所有上层服务稳定的基石。我们采用三节点多活部署模式,通过负载均衡器分发 API Server 请求,etcd 集群以 Raft 协议保证数据一致性。

二、etcd 集群调优

etcd 是集群状态存储的核心,其性能直接关系到集群恢复速度。实践中我们将 etcd 的数据目录部署在 NVMe SSD 上,调整 --quota-backend-bytes 至 8GB,并开启客户端侧压缩。

三、Pod 反亲和与拓扑分布

为了规避单点故障,跨可用区部署时通过 Pod 反亲和策略保证同一服务的多个副本分布在不同的节点和可用区。

Deployment 反亲和配置

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-gateway
spec:
  replicas: 3
  selector:
    matchLabels:
      app: api-gateway
  template:
    metadata:
      labels:
        app: api-gateway
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - api-gateway
              topologyKey: "kubernetes.io/hostname"
      topologySpreadConstraints:
      - maxSkew: 1
        topologyKey: "topology.kubernetes.io/zone"
        whenUnsatisfiable: DoNotSchedule
        labelSelector:
          matchLabels:
            app: api-gateway
      containers:
      - name: api-gateway
        image: api-gateway:latest
        resources:
          requests:
            cpu: "500m"
            memory: "512Mi"
          limits:
            cpu: "2"
            memory: "2Gi"
        readinessProbe:
          httpGet:
            path: /health
            port: 8080

自定义自愈 Controller

go
package controller

import (
    "context"
    "log"

    corev1 "k8s.io/api/core/v1"
    "sigs.k8s.io/controller-runtime/pkg/client"
    "sigs.k8s.io/controller-runtime/pkg/reconcile"
)

type PodReconciler struct {
    client.Client
}

func (r *PodReconciler) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) {
    var pod corev1.Pod
    if err := r.Get(ctx, req.NamespacedName, &pod); err != nil {
        return reconcile.Result{}, client.IgnoreNotFound(err)
    }

    if pod.Status.Phase == corev1.PodPending {
        for _, cond := range pod.Status.Conditions {
            if cond.Reason == "Unschedulable" {
                log.Printf("检测到不可调度 Pod: %s/%s, 尝试驱逐", pod.Namespace, pod.Name)
                // 执行驱逐或通知调度器
            }
        }
    }
    return reconcile.Result{}, nil
}

四、总结

高可用不是一次性配置,而是持续演进的过程。通过控制面多活、etcd 调优、反亲和策略与自愈 Controller 的组合,我们将集群的年化故障时间从 12 小时降低到 30 分钟以内。

本文作者:技术领航员 | 许可协议:CC BY-NC-SA 4.0

本文链接:https://sre-ai-blog.pages.dev/zh/posts/kubernetes-ha/(转载请注明出处)