APISIX 原生支持集群部署,且集群架构是其核心设计之一


集群架构总览

┌─────────────────────────────────────────────────────────────┐
│                        客户端流量                            │
└─────────────────────────┬───────────────────────────────────┘
                          ↓
              ┌───────────────────────┐
              │    负载均衡器 / SLB    │
              │  (Nginx / 阿里SLB等)  │
              └───────────┬───────────┘
              ┌───────────┼───────────┐
              ↓           ↓           ↓
     ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
     │   APISIX-1   │ │   APISIX-2   │ │   APISIX-3   │
     │  (数据面)     │ │  (数据面)     │ │  (数据面)     │
     │  Node1       │ │  Node2       │ │  Node3       │
     └──────┬───────┘ └──────┬───────┘ └──────┬───────┘
            └────────────────┼────────────────┘
                             ↓  Watch 监听配置变更
              ┌──────────────────────────────┐
              │         etcd 集群             │
              │  etcd-1  etcd-2  etcd-3      │
              │       (3节点高可用)            │
              └──────────────────────────────┘
                             ↑
              ┌──────────────────────────────┐
              │         控制面               │
              │  Admin API  +  Dashboard     │
              └──────────────────────────────┘

核心:数据面与控制面分离

APISIX 集群 = 无状态数据面节点 + 有状态 etcd 集群

数据面节点(APISIX 实例):
  ✅ 完全无状态
  ✅ 可随意水平扩展
  ✅ 任意节点宕机不影响其他节点
  ✅ 配置全量缓存在本地内存

控制面(etcd):
  ✅ 存储所有路由/插件/上游配置
  ✅ 变更通过 Watch 机制推送给所有数据面
  ✅ etcd 本身也支持集群(奇数节点 3/5/7)

集群核心特性

1. 无中心化设计(去中心化)

传统中心化网关集群:

          ┌─────────────┐
          │  主节点      │  ← 单点,宕机影响全局
          │ (Master)    │
          └──────┬──────┘
        ┌────────┼────────┐
        ↓        ↓        ↓
     Worker1  Worker2  Worker3

─────────────────────────────────────────

APISIX 集群(无中心):

  APISIX-1 ──┐
  APISIX-2 ──┼── 都从 etcd 获取配置,地位完全对等
  APISIX-3 ──┘

  任何一个节点宕机:
    ✅ 其他节点完全不受影响
    ✅ 流量自动由 SLB 切走
    ✅ 无需主从切换

2. 配置一致性保证

配置变更同步流程:

① 管理员通过 Admin API 修改路由
         ↓
② 写入 etcd 集群(强一致性)
         ↓
③ 所有 APISIX 节点同时收到 Watch 事件
         ↓
④ 各节点更新本地内存缓存
         ↓
⑤ 毫秒内全集群配置统一生效

关键保证:
  ✅ 任意节点看到的配置完全一致
  ✅ etcd 宕机期间:数据面继续用本地缓存服务
  ✅ etcd 恢复后:自动同步最新配置

3. etcd 宕机期间的容灾能力

场景:etcd 集群全部宕机

APISIX 的行为:
  ┌─────────────────────────────────────┐
  │  数据面继续正常工作!                 │
  │                                     │
  │  原因:APISIX 启动时将配置全量加载    │
  │        到共享内存(shared dict)      │
  │                                     │
  │  影响:无法修改路由/插件配置          │
  │  不影响:现有流量处理(读内存)        │
  └─────────────────────────────────────┘

  etcd 宕机 → 只影响控制面(改配置)
              不影响数据面(处理请求)

这是 APISIX 高可用设计的核心之一

集群部署实践

Docker Compose 本地集群(开发验证)

# docker-compose-cluster.yml
version: "3"

services:
  # etcd 集群(3节点)
  etcd1:
    image: bitnami/etcd:3.5.7
    environment:
      - ETCD_NAME=etcd1
      - ETCD_INITIAL_ADVERTISE_PEER_URLS=http://etcd1:2380
      - ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380
      - ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379
      - ETCD_ADVERTISE_CLIENT_URLS=http://etcd1:2379
      - ETCD_INITIAL_CLUSTER=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380
      - ETCD_INITIAL_CLUSTER_STATE=new
      - ALLOW_NONE_AUTHENTICATION=yes

  etcd2:
    image: bitnami/etcd:3.5.7
    environment:
      - ETCD_NAME=etcd2
      - ETCD_INITIAL_ADVERTISE_PEER_URLS=http://etcd2:2380
      - ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380
      - ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379
      - ETCD_ADVERTISE_CLIENT_URLS=http://etcd2:2379
      - ETCD_INITIAL_CLUSTER=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380
      - ETCD_INITIAL_CLUSTER_STATE=new
      - ALLOW_NONE_AUTHENTICATION=yes

  etcd3:
    image: bitnami/etcd:3.5.7
    environment:
      - ETCD_NAME=etcd3
      - ETCD_INITIAL_ADVERTISE_PEER_URLS=http://etcd3:2380
      - ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380
      - ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379
      - ETCD_ADVERTISE_CLIENT_URLS=http://etcd3:2379
      - ETCD_INITIAL_CLUSTER=etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380
      - ETCD_INITIAL_CLUSTER_STATE=new
      - ALLOW_NONE_AUTHENTICATION=yes

  # APISIX 数据面节点1
  apisix1:
    image: apache/apisix:3.6.0-debian
    volumes:
      - ./apisix_conf/config.yaml:/usr/local/apisix/conf/config.yaml
    ports:
      - "9080:9080"   # HTTP 流量
      - "9443:9443"   # HTTPS 流量
    depends_on:
      - etcd1
      - etcd2
      - etcd3

  # APISIX 数据面节点2
  apisix2:
    image: apache/apisix:3.6.0-debian
    volumes:
      - ./apisix_conf/config.yaml:/usr/local/apisix/conf/config.yaml
    ports:
      - "9081:9080"
      - "9444:9443"
    depends_on:
      - etcd1
      - etcd2
      - etcd3

  # APISIX 数据面节点3
  apisix3:
    image: apache/apisix:3.6.0-debian
    volumes:
      - ./apisix_conf/config.yaml:/usr/local/apisix/conf/config.yaml
    ports:
      - "9082:9080"
      - "9445:9443"
    depends_on:
      - etcd1
      - etcd2
      - etcd3

  # Admin API / 控制面(只需一个)
  apisix-dashboard:
    image: apache/apisix-dashboard:3.0.0
    ports:
      - "9000:9000"
    depends_on:
      - etcd1

  # 前端负载均衡
  nginx-lb:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx-lb.conf:/etc/nginx/nginx.conf
    depends_on:
      - apisix1
      - apisix2
      - apisix3

APISIX 配置文件(连接 etcd 集群)

# config.yaml
apisix:
  node_listen: 9080
  enable_ipv6: false

deployment:
  role: data_plane          # 数据面角色
  role_data_plane:
    config_provider: etcd

etcd:
  host:                     # 连接所有 etcd 节点
    - "http://etcd1:2379"
    - "http://etcd2:2379"
    - "http://etcd3:2379"
  prefix: "/apisix"
  timeout: 30

  # 开启 TLS(生产必须)
  tls:
    cert: /path/to/etcd-client.crt
    key:  /path/to/etcd-client.key
    verify: true
    sni: etcd.cluster.local

Nginx 前端负载均衡配置

# nginx-lb.conf
events { worker_processes auto; }

stream {
  upstream apisix_cluster {
    least_conn;                    # 最少连接负载均衡
    server apisix1:9080 weight=1;
    server apisix2:9080 weight=1;
    server apisix3:9080 weight=1;
  }

  server {
    listen 80;
    proxy_pass apisix_cluster;
    proxy_timeout 30s;
    proxy_connect_timeout 5s;
  }
}

Kubernetes 集群部署(生产推荐)

Helm 一键部署

# 添加 APISIX Helm 仓库
helm repo add apisix https://charts.apiseven.com
helm repo update

# 创建命名空间
kubectl create namespace apisix

# 部署 APISIX 集群(含 etcd、Dashboard)
helm install apisix apisix/apisix \
  --namespace apisix \
  --set replicaCount=3 \
  --set etcd.replicaCount=3 \
  --set dashboard.enabled=true \
  --set ingress-controller.enabled=true \
  --set apisix.ssl.enabled=true

K8s 部署结构

# apisix-values.yaml
replicaCount: 3              # APISIX 数据面副本数

resources:
  requests:
    cpu: "2"
    memory: "2Gi"
  limits:
    cpu: "4"
    memory: "4Gi"

# 反亲和性:确保节点分散在不同物理机
affinity:
  podAntiAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchLabels:
            app: apisix
        topologyKey: kubernetes.io/hostname

# HPA 自动扩缩容
autoscaling:
  enabled: true
  minReplicas: 3
  maxReplicas: 20
  targetCPUUtilizationPercentage: 70
  targetMemoryUtilizationPercentage: 80

# etcd 集群配置
etcd:
  replicaCount: 3
  persistence:
    storageClass: "ssd-storage"
    size: 20Gi

# Ingress Controller(让 APISIX 管理 K8s Ingress)
ingress-controller:
  enabled: true
  config:
    apisix:
      serviceName: apisix-admin
      serviceNamespace: apisix

K8s 内部架构

┌──────────────────────────────────────────────────────────┐
│                   Kubernetes Cluster                      │
│                                                          │
│  ┌─────────────┐   ┌─────────────┐   ┌─────────────┐   │
│  │   Node 1    │   │   Node 2    │   │   Node 3    │   │
│  │ ┌─────────┐ │   │ ┌─────────┐ │   │ ┌─────────┐ │   │
│  │ │ apisix  │ │   │ │ apisix  │ │   │ │ apisix  │ │   │
│  │ │  Pod-1  │ │   │ │  Pod-2  │ │   │ │  Pod-3  │ │   │
│  │ └─────────┘ │   │ └─────────┘ │   │ └─────────┘ │   │
│  │ ┌─────────┐ │   │ ┌─────────┐ │   │ ┌─────────┐ │   │
│  │ │  etcd   │ │   │ │  etcd   │ │   │ │  etcd   │ │   │
│  │ │  Pod-1  │ │   │ │  Pod-2  │ │   │ │  Pod-3  │ │   │
│  │ └─────────┘ │   │ └─────────┘ │   │ └─────────┘ │   │
│  └─────────────┘   └─────────────┘   └─────────────┘   │
│                                                          │
│  ┌────────────────────────────────────────────────────┐  │
│  │   apisix Service (LoadBalancer / NodePort)          │  │
│  │   自动将流量分发到3个 apisix Pod                    │  │
│  └────────────────────────────────────────────────────┘  │
│                                                          │
│  ┌────────────────────────────────────────────────────┐  │
│  │   HPA (Horizontal Pod Autoscaler)                  │  │
│  │   CPU > 70% 自动扩容,最多 20 个副本               │  │
│  └────────────────────────────────────────────────────┘  │
└──────────────────────────────────────────────────────────┘

集群限流:跨节点共享计数

集群中最常见的问题:每个节点各自计数,限流不准确

问题场景:

限流设置:100次/分钟/用户

3个 APISIX 节点各自计数:
  Node1: 用户A请求 100次 → 不触发限流
  Node2: 用户A请求 100次 → 不触发限流
  Node3: 用户A请求 100次 → 不触发限流

实际:用户A请求了 300次,但没有任何限流!

解决方案:Redis 集群共享计数

# 配置 limit-count 使用 Redis 集群共享计数
curl -X PUT http://localhost:9180/apisix/admin/routes/1 \
  -d '{
    "uri": "/api/*",
    "plugins": {
      "limit-count": {
        "count": 100,
        "time_window": 60,
        "key": "consumer_name",
        "policy": "redis-cluster",    
        "redis_cluster_nodes": [
          "redis-node1:6379",
          "redis-node2:6379",
          "redis-node3:6379"
        ],
        "redis_cluster_name": "apisix-redis-cluster",
        "redis_password": "your-password",
        "rejected_code": 429
      }
    },
    "upstream": {
      "type": "roundrobin",
      "nodes": {"backend:8080": 1}
    }
  }'
加入 Redis 集群后:

Node1 收到用户A请求 → Redis 计数器 +1(当前: 33)
Node2 收到用户A请求 → Redis 计数器 +1(当前: 67)
Node3 收到用户A请求 → Redis 计数器 +1(当前: 100)→ 触发限流!

三个节点共享同一个 Redis 计数器
全局精准限流 ✅

完整集群限流架构

┌─────────────────────────────────────────────────────┐
│               APISIX 集群(3节点)                   │
│                                                     │
│  Node1: limit-count ──┐                            │
│  Node2: limit-count ──┼──→ Redis Cluster(共享计数)│
│  Node3: limit-count ──┘                            │
│                                                     │
│  所有节点读写同一个计数器 → 全局精准限流              │
└─────────────────────────────────────────────────────┘

集群健康检查与故障转移

# 上游健康检查配置
upstream:
  type: roundrobin
  nodes:
    "backend1:8080": 1
    "backend2:8080": 1
    "backend3:8080": 1

  # 主动健康检查(APISIX 主动探测)
  checks:
    active:
      type: http
      http_path: "/health"
      timeout: 3
      interval: 5            # 每5秒检查一次

      healthy:
        interval: 2
        successes: 2          # 连续2次成功 → 标记健康

      unhealthy:
        interval: 1
        http_failures: 3      # 连续3次失败 → 标记不健康
        tcp_failures: 2
        http_statuses: [500, 502, 503, 504]

    # 被动健康检查(基于真实流量判断)
    passive:
      healthy:
        http_statuses: [200, 201, 204]
        successes: 3

      unhealthy:
        http_statuses: [500, 502, 503, 504]
        http_failures: 5
        tcp_failures: 2
健康检查工作机制:

APISIX 集群每个节点都独立做健康检查

backend2 宕机
   ↓
Node1 检测到 → 标记 backend2 不健康 → 停止转发
Node2 检测到 → 标记 backend2 不健康 → 停止转发
Node3 检测到 → 标记 backend2 不健康 → 停止转发

backend2 恢复
   ↓
各节点主动探测成功 → 自动重新加入负载均衡

多机房 / 异地多活部署

┌─────────────────┐         ┌─────────────────┐
│    机房 A        │         │    机房 B        │
│                 │         │                 │
│ ┌─────────────┐ │         │ ┌─────────────┐ │
│ │ APISIX 集群  │ │         │ │ APISIX 集群  │ │
│ │ Node1       │ │         │ │ Node4       │ │
│ │ Node2       │ │         │ │ Node5       │ │
│ │ Node3       │ │         │ │ Node6       │ │
│ └──────┬──────┘ │         │ └──────┬──────┘ │
│        │        │         │        │        │
│ ┌──────┴──────┐ │         │ ┌──────┴──────┐ │
│ │ etcd 集群   │◄├─────────►│ etcd 集群   │ │
│ │ A1 A2 A3   │ │  数据同步  │ │ B1 B2 B3   │ │
│ └─────────────┘ │         │ └─────────────┘ │
└─────────────────┘         └─────────────────┘
         ↑                           ↑
         └───────────┬───────────────┘
                     │
              全局流量调度
              (DNS/GTM/GSLB)
异地多活策略:
  ✅ 就近接入:用户连接最近的机房
  ✅ 配置同步:etcd 跨机房数据同步
  ✅ 机房故障:DNS 切换到另一机房
  ✅ 数据隔离:各机房 APISIX 前缀区分
              机房A: /apisix-dc-a
              机房B: /apisix-dc-b

集群运维要点

滚动升级(零停机)

# K8s 环境下滚动升级 APISIX 版本
kubectl set image deployment/apisix \
  apisix=apache/apisix:3.7.0-debian \
  -n apisix \
  --record

# 观察滚动过程(逐个替换 Pod,不中断流量)
kubectl rollout status deployment/apisix -n apisix

# 升级过程:
# Pod-1 → 新版本(等待就绪)
#   ↓
# Pod-2 → 新版本(等待就绪)
#   ↓
# Pod-3 → 新版本(等待就绪)
# 全程流量不中断 ✅

节点扩缩容

# 手动扩容到5个节点
kubectl scale deployment apisix --replicas=5 -n apisix

# 自动扩缩容已由 HPA 管理
# 新节点启动后自动从 etcd 拉取全量配置
# 无需人工干预,立即加入集群处理流量

集群监控关键指标

必须监控的指标:

APISIX 节点:
  ├── apisix_http_requests_total       请求总数
  ├── apisix_http_latency              响应延迟
  ├── apisix_node_info                 节点信息
  └── apisix_nginx_http_current_connections 当前连接数

etcd 集群:
  ├── etcd_server_is_leader            谁是 Leader
  ├── etcd_server_proposals_failed     提案失败次数
  ├── etcd_disk_wal_fsync_duration     磁盘写入延迟
  └── etcd_network_peer_round_trip_time 节点间延迟

Redis(限流共享计数):
  ├── redis_connected_clients          连接数
  ├── redis_commands_processed         命令处理速率
  └── redis_cluster_state              集群状态

集群高可用保障总结

┌───────────────────────────────────────────────────────┐
│              APISIX 集群高可用矩阵                      │
├─────────────────┬─────────────────────────────────────┤
│ 故障场景         │ 影响 & 应对                          │
├─────────────────┼─────────────────────────────────────┤
│ 1个APISIX节点宕机│ ✅ 其他节点继续服务,SLB自动切流      │
├─────────────────┼─────────────────────────────────────┤
│ etcd 1个节点宕机 │ ✅ etcd集群仍有多数派,正常工作       │
├─────────────────┼─────────────────────────────────────┤
│ etcd 全部宕机   │ ✅ 数据面读本地缓存继续服务            │
│                 │ ❌ 无法修改路由配置                   │
├─────────────────┼─────────────────────────────────────┤
│ Redis 宕机      │ ⚠️ 集群限流降级为本地限流             │
│                 │ ✅ 流量处理不中断                     │
├─────────────────┼─────────────────────────────────────┤
│ 上游服务宕机     │ ✅ 健康检查自动摘除,故障转移         │
├─────────────────┼─────────────────────────────────────┤
│ 整机房故障      │ ✅ DNS/GTM 切换到另一机房             │
└─────────────────┴─────────────────────────────────────┘

总结

集群特性

说明

水平扩展

数据面无状态,加节点即扩容,无上限

无中心节点

所有 APISIX 节点对等,无单点故障

配置一致性

etcd Watch 机制,毫秒内全集群同步

etcd 容灾

etcd 故障时数据面本地缓存兜底,流量不中断

集群限流

Redis Cluster 共享计数,全局精准限流

K8s 原生

Helm 一键部署,HPA 自动扩缩容

滚动升级

K8s 滚动发布,零停机升级

异地多活

支持多机房部署,etcd 跨机房同步

一句话:APISIX 集群是真正的生产级高可用架构 —— 数据面无状态可无限水平扩展,控制面 etcd 集群保证配置一致性,任何单点故障都不会影响流量处理,是企业级 API 网关的标准部署方式。