在 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-dp
kubectl -n aisix-dp 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。Dev 文档会将 Chart 的已发布网关镜像替换为 dev 镜像:
helm repo add api7 https://charts.api7.ai
helm repo update
helm install aisix-dp api7/aisix --namespace aisix-dp \
--set image.repository=ghcr.io/api7/aisix \
--set image.tag=dev \
--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
Chart 源码发布在 api7/api7-helm-chart 仓库中。
暴露网关
Chart 默认为代理创 建 ClusterIP 类型的 Service。如需通过云负载均衡器发布:
service:
type: LoadBalancer
port: 80
# 保留客户端源 IP,按模型配置的 IP 允许列表会使用该地址进行匹配。
externalTrafficPolicy: Local
Chart 默认只给网关一个明文 HTTP 代理监听器:它在容器内绑定 containerPorts.proxy(端口 3000),由 Service 以 service.port 发布。Service 可以暴露 端口 80 或 443,无需让进程绑定特权容器端口。
同时提供 HTTPS 和明文 HTTP
配置 listeners 即可同时提供多个代理端口,每个端口有各自的 TLS:
listeners:
- name: https # 端口名称,容器端口和 Service 端口共用。
containerPort: 3443
servicePort: 443
# nodePort: 30443 # 可选;仅适用于非 ClusterIP 类型的 Service。
tls:
secretName: aisix-proxy-tls
- name: http
containerPort: 3000
servicePort: 80
非空的 listeners 就是代理监听器的完整集合,并取代默认的那一个监听器。此时没有任何东西绑定 containerPorts.proxy,service.port 和 service.nodePort 也不会被读取,因为每个条目都带有自己的配置。代理 Service 仍然只有一个,它为每个条目发布一个端口,并按名称指向该条目的容器端口。
每个监听器提供相同的路由,包括 /livez 和 /readyz,因此 startup、readiness 和 liveness 探针都指向第一个条目——当该条目终止 TLS 时探针使用 HTTPS,且 kubelet 不会校验证书。Chart 会把这组监听器以 proxy.listeners 写入网关的配置文件。它仍然会写入 proxy.addr,网关会忽略该值并记录一行 INFO 日志,这行日志无需处理。此功能需要支持 proxy.listeners 的网关镜像。
这些 values 背后的网关侧规则,包括明文监听器为什么只能绑定到可信网络接口,参阅同时提供 HTTPS 和 HTTP。
网关从文件读取 TLS 证书材料,因此每个启用 TLS 的监听器都需要各自的 kubernetes.io/tls Secret,键名为 tls.crt 和 tls.key。Chart 会把它以只读方式挂载到 /etc/aisix/tls/<name>。使用你已有的证书和私钥创建:
kubectl -n aisix-dp create secret tls aisix-proxy-tls \
--cert=./tls.crt --key=./tls.key
或者由 cert-manager 签发该 Secret 并自动续期:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: aisix-proxy-tls
namespace: aisix-dp
spec:
secretName: aisix-proxy-tls
dnsNames:
- gateway.example.com
issuerRef:
name: letsencrypt
kind: ClusterIssuer
轮换后的证书会以挂载点中文件变更的形式到达网关。请使用 Chart 安装后提示中的 Deployment 名称重启 Pod,以使其生效。包含 aisix 的 Release 名通常会原样使用;名称覆盖可能会改变结果:
kubectl rollout restart deployment/<deployment-name> -n <namespace>
绑定特权容器端口
只有当网关必须直接监听某个低于 1024 的端口时,才在容器内绑定该端口。发布的镜像以非 root 用户 UID 10001 运行,网关二进制文件具有生效的 CAP_NET_BIND_SERVICE 文件能力:
containerPorts:
proxy: 80
配置了 listeners 时,请把特权端口写在应当绑定它的那个条目的 containerPort 上,此时 containerPorts.proxy 不会被读取。
如果你自定义渲染后的 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 而失败。
只有当网关必须直接绑定节点且集群策略允许时,才使用 hostNetwork 或 hostPort。这些选项会引入节点端口冲突并降低网络隔离;Baseline 和 Restricted Pod Security Standard 也不允许使用它们。
完整的网络暴露和凭证模型请参阅网络与安全。
在 OpenShift 上运行
该 chart 可以在 OpenShift 默认的 restricted-v2 security context constraint 下安装,既不需要自定义 SCC,也不需要改动 ServiceAccount。
chart 不再固定 UID。它的默认 Pod 安全上下文就是 runAsNonRoot: true 加 seccompProfile.type: RuntimeDefault,因此 restricted-v2 会从命名空间分配的区间中提供 runAsUser 和 fsGroup。网关镜像声明了数字用户,并可在分配到的任意 UID 搭配 GID 0 下运行;运行期唯一被写入的路径是一个 emptyDir 卷。容器级安全上下文本身已满足 restricted-v2:除 NET_BIND_SERVICE 外丢弃全部 capability、只读根文件系统、禁止提权。
如果需要改为固定 UID,把这些 values 设置回去即可:
podSecurityContext:
runAsNonRoot: true
runAsUser: 10001
runAsGroup: 10001
fsGroup: 10001
seccompProfile:
type: RuntimeDefault
控制面在 OpenShift 上的安装,请参见在 OpenShift 上安装。
在副本间共享限流计数器
限流计数器默认存储在每个网关自己的内存中,因此 N 个副本实际会执行每项已配置请求、Token 和并发限制的 N 倍。在运行多个副本前——包括自动扩缩容器新增的任何副本——请让所有副本指向同一个 Redis:
rateLimit:
backend: redis
redis:
url: redis://redis.default.svc:6379
当连接 URL 包含密码时,请改用 rateLimit.redis.existingSecret。若要与 URL 分开提供 Redis 用户名和密码,请通过 configSecrets 从 Secret 读取,详见设置其他网关配置。共享 Redis 连接的其他设置,例如 mode、nodes 或 timeout_secs,写在 config.ratelimit.redis 下。
所有副本都指向同一个 Redis 部署后,再提高 replicaCount 或启用下面的一种自动扩缩容方式。如果部署不使用请求、Token 或并发限制,也可以有意识地接受每个副本独立的内存后端。