跳到主要内容
版本:1.2.0

在 Kubernetes 上部署 AISIX 网关

使用 api7/aisix Helm Chart 在 Kubernetes 集群中部署、暴露和扩缩 AISIX 网关。网关在你的环境中承载实时 AI 流量,并连接现有 AISIX Cloud 控制面以接收配置。

该 Chart 需要数据面管理器端点,以及为目标环境签发的网关证书包。连接后,网关会从控制面接收模型、调用方 API Key 和策略。

前提条件

  • 一个 Kubernetes 集群,已配置 kubectl 访问权限并安装 Helm 3。
  • 可以访问一个能够签发网关证书的 AISIX Cloud 环境。
  • 集群可以通过网络访问 AISIX Cloud 数据面管理器端点。如果使用 On-Premises,请先完成 On-Premises 安装

安装 Chart

在控制台中打开目标环境的 Data planes 视图并签发网关证书。Kubernetes (Helm) 标签页会提供下文使用的数据面管理器端点和证书包。本示例还将初始部署固定为一个副本。私钥只显示一次。

将证书包存储在 Secret 中,避免私钥出现在 values 文件中:

kubectl create namespace aisix

kubectl -n aisix create secret generic aisix-gateway-certificate \
--from-file=cert.pem=./cert.pem \
--from-file=key.pem=./key.pem \
--from-file=ca.pem=./ca.pem

使用同一视图中的数据面管理器端点安装 Chart:

helm repo add api7 https://charts.api7.ai
helm repo update

helm install aisix api7/aisix --namespace aisix --version 1.2.0 \
--set controlPlane.baseURL=https://dp-manager.example.com:7944 \
--set controlPlane.certificate.existingSecret=aisix-gateway-certificate \
--set replicaCount=1

网关首次上报心跳后,会出现在环境的 Data planes 视图中。Chart 默认为两个副本,但此初始命令只启动一个副本,因为在配置共享 Redis 之前,限流计数器使用每个副本各自的内存。控制台 Helm 代码片段省略了 replicaCount,因此原样安装会启动两个副本。如上所示,请在配置 Redis 前添加 --set replicaCount=1。增加副本数或启用自动扩缩容器前,请先在副本间共享限流计数器

每个副本会注册为独立实例,并共享同一个证书。

查看 Chart 接受的所有值:

helm show values api7/aisix --version 1.2.0

Chart 源码和软件包发布在 aisix-1.2.0 Helm Chart Release 中。

暴露网关

Chart 默认为代理创建 ClusterIP 类型的 Service。如需通过云负载均衡器发布:

service:
type: LoadBalancer
port: 80
# 保留客户端源 IP,按模型配置的 IP 允许列表会使用该地址进行匹配。
externalTrafficPolicy: Local

网关默认在容器内绑定端口 3000。Service 可以暴露端口 80443,无需让进程绑定特权容器端口。

只有当网关必须直接监听某个低于 1024 的端口时,才在容器内绑定该端口。发布的镜像以非 root 用户 UID 10001 运行,网关二进制文件具有生效的 CAP_NET_BIND_SERVICE 文件能力:

containerPorts:
proxy: 80

如果你自定义渲染后的 Pod 并丢弃所有 capability,请为 AISIX 容器重新添加 NET_BIND_SERVICE

spec:
containers:
- name: aisix
securityContext:
capabilities:
drop: ["ALL"]
add: ["NET_BIND_SERVICE"]

Kubernetes Restricted Pod Security Standard 允许此 capability。由于二进制文件的文件 capability 已设置 effective bit,如果运行时阻止授予该 capability,容器可能会因 exec: Operation not permitted 而失败。

只有当网关必须直接绑定节点且集群策略允许时,才使用 hostNetworkhostPort。这些选项会引入节点端口冲突并降低网络隔离;Baseline 和 Restricted Pod Security Standard 也不允许使用它们。

完整的网络暴露和凭证模型请参阅网络与安全

在副本间共享限流计数器

限流计数器默认存储在每个网关自己的内存中,因此 N 个副本实际会执行每项已配置请求、Token 和并发限制的 N 倍。在运行多个副本前——包括自动扩缩容器新增的任何副本——请让所有副本指向同一个 Redis:

rateLimit:
backend: redis
redis:
url: redis://redis.default.svc:6379

当连接 URL 包含密码时,请改用 rateLimit.redis.existingSecret

所有副本都指向同一个 Redis 部署后,再提高 replicaCount 或启用下面的一种自动扩缩容方式。如果部署不使用请求、Token 或并发限制,也可以有意识地接受每个副本独立的内存后端。

基于 CPU 或内存扩缩容

autoscaling 会为网关 Deployment 创建 HorizontalPodAutoscaler

autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 20
targetCPUUtilizationPercentage: 70

目标值是 Pod 资源 requests 的百分比,因此 Chart 默认设置 CPU request。它特意不设置 CPU limit:限流会增加代理的长尾延迟,并抑制自动扩缩容器读取的信号。基于 CPU 扩缩容要求集群中安装 metrics-server

在 Linux 上,proxy.workers 默认使用网关进程可用的 CPU 并行度。Kubernetes CPU request 不会限制该值,但 CPU limit 会限制。如果每个副本需要稳定的 Worker 数量,由于 Chart 不设置 CPU limit,请显式设置 AISIX_PROXY__WORKERS,并确保该值不超过为副本规划的 CPU 容量。有关 Worker 配置和容量规划注意事项,请参阅每核一线程 Worker

启用自动扩缩容后,Deployment 会省略 spec.replicas,避免后续 helm upgrade 重置自动扩缩容器选择的副本数。此后会忽略 replicaCount 值。

所有 behavior 策略都会原样传递,例如让缩容比 Kubernetes 默认行为更平缓:

autoscaling:
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Pods
value: 1
periodSeconds: 60

对于 Pods、Object 或 External 指标(例如通过 Prometheus adapter 暴露的序列),请使用 autoscaling.extraMetrics

使用 KEDA 基于请求负载扩缩容

CPU 是负载的间接指标。如需改为根据网关自身流量扩缩容,请使用 KEDA,并针对网关指标执行 Prometheus 查询。

启用示例前,请准备以下集群组件:

  • 安装 KEDA,包括 ScaledObject CRD 和控制器。
  • 提供可查询网关指标的 Prometheus 服务器。
  • 如果需要由 Chart 创建下文所示的抓取配置,请安装 Prometheus Operator 或其他能够消费 ServiceMonitor 对象的控制器。仅安装 CRD 会让 Helm 能够创建对象,但不会有组件将其转换为抓取配置。当 Prometheus 实例按标签选择 ServiceMonitor 时,请设置 metrics.serviceMonitor.labels。如果 Prometheus 通过其他方式发现指标 Service,请将 metrics.serviceMonitor.enabled 保持为 false,并省略该配置块。

确认所启用值依赖的 CRD 已经存在:

kubectl get crd scaledobjects.keda.sh
# 仅当 metrics.serviceMonitor.enabled 为 true 时需要。
kubectl get crd servicemonitors.monitoring.coreos.com

这些前提条件就绪后再配置 Chart:

metrics:
serviceMonitor:
enabled: true

keda:
enabled: true
minReplicas: 2
maxReplicas: 20
pollingInterval: 15
cooldownPeriod: 300
triggers:
- type: prometheus
metadata:
serverAddress: http://prometheus.monitoring.svc:9090
query: sum(rate(aisix_llm_requests_total[2m]))
threshold: "100"

aisix_llm_requests_total 统计模型推理请求,例如 /v1/chat/completions,但不包括 MCP 或 A2A 调用。如果这类流量才是扩缩容依据,请使用 aisix_proxy_requests_total

autoscalingkeda 互斥。同时启用两者会使 Helm 渲染失败,避免两个控制器同时写入 spec.replicas

扩缩容事件期间的行为

自动扩缩容器新增的副本在能够提供服务前不会接收流量。网关应用控制面配置之前根本不会绑定代理监听器,因此 Chart 指向该监听器的所有探针得到的都是被拒绝的连接,而不是响应。

覆盖这段等待的是 Chart 的 startupProbe。在启动探针成功之前,Kubernetes 会挡住就绪和存活探针,因此等待期间就绪探针根本不会执行,Pod 只是一直不进入就绪状态——Kubernetes 会让它保持在 Service 端点之外,存活探针也不会重启仍在连接控制面的 Pod。启动探针的预算是 periodSeconds x failureThreshold,需要覆盖连接控制面并应用其中内容的时间。控制面连接持续不可达、超过该预算的 Pod,其容器会被杀掉并重启,反复重启会表现为 CrashLoopBackOff——对于从来没有可提供服务内容的实例,这是预期结果。就绪契约以及如何设置该预算,请参阅启动与第一个配置

副本缩容时,Kubernetes 会同时开始将其从 Service 端点移除并终止 Pod。以下两个 Chart 配置会在此过程中保护进行中的请求。

preStopSleepSeconds 在容器收到 SIGTERM 前先暂停一段时间,让端点移除在网关开始关闭之前传播到每个节点。它覆盖的是监听 Kubernetes API 的负载均衡器;通过轮询健康检查感知的负载均衡器在整个暂停期间看到的仍是就绪的 Pod,由网关自身的排空窗口 shutdown.min_drain_secs 覆盖。

terminationGracePeriodSeconds 为整个终止流程设置上限——暂停、排空窗口、随后的在途请求排空,以及再之后最多 5 秒的快照缓存排空——因为网关排空本身没有截止时间。Kubernetes 对该值的默认是 30 秒,会中断流式响应,因此 Chart 采用了更长的取值。

两者都带有与该流程匹配的默认值,helm show values api7/aisix --version 1.2.0 会显示此版本的默认值。如果工作负载的流式传输时间超过暂停和排空窗口结束后剩余的预算,请提高 terminationGracePeriodSeconds

观察扩缩容决策及其依据的指标:

kubectl -n aisix get hpa aisix --watch
kubectl -n aisix describe hpa aisix

应对节点中断

PodDisruptionBudget 可防止节点排空、集群升级等主动中断一次性停止所有网关。分布约束可以避免副本集中在单个故障域:

podDisruptionBudget:
enabled: true
minAvailable: 50%

topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app.kubernetes.io/name: aisix

Chart 使用 emptyDir 卷挂载 /var/lib/aisix,因此其中的状态是临时的,且只属于单个 Pod。Pod 重启后会重新注册,并在接收流量前从控制面下载配置。请跨故障域保留多个副本,使现有副本可以在其他副本重启期间继续提供服务。如果网关必须在控制面不可用时使用缓存配置重启,请自定义工作负载,为每个副本提供独立的持久化状态目录。

更完整的部署模式请参阅高可用

设置其他网关配置

控制面负责动态资源,Chart 负责 Pod。对于 Chart 没有作为 value 暴露的启动配置,请直接设置环境变量;每个配置字段都可以通过 AISIX_<SECTION>__<FIELD> 访问:

extraEnvVars:
- name: AISIX_OBSERVABILITY__LOG_LEVEL
value: "debug"
- name: AISIX_UPSTREAM__POOL_MAX_IDLE_PER_HOST
value: "32"

命名规则请参阅环境变量