在 Kubernetes 上部署和运维网关
api7/aisix Helm Chart 用于在 Kubernetes 中部署、暴露和扩缩 AISIX 网关。无论网关从 AISIX Enterprise、AISIX Cloud 还是 AISIX OSS 资源文件接收资源,监听器、Service、自动扩缩容、共享 Redis、中断处理、排空和应用设置的工作方式都相同。本页先介绍连接控制面的安装流程,再介绍这些共通的 Kubernetes 运维操作。
连接 AISIX Enterprise 或 AISIX Cloud 的网关需要数据面管理器端点,以及为目标环境签发的网关证书包。连接后,网关会从控制面接收模型、调用方 API Key 和策略。对于 AISIX OSS,请先使用资源文件部署网关,再从本页的暴露网关继续。
前提条件
- 一个 Kubernetes 集群,已配置
kubectl访问权限并安装 Helm 3。 - 对于 OpenShift 或 OKD,需要 cURL,以及能够在网关项目中管理工作负载、Service、Secret 和 Route、读取 Pod 日志并运行
oc exec的oc会话。 - 对于 OpenShift 或 OKD Route 示例,需要应用域名和入口 CA 证书,或有权读取集群 Ingress 配置及
openshift-config-managed中的default-ingress-certConfigMap。集群管理员也可以提供域名和 CA。 - 可以访问一个能够签发网关证书的 AISIX Enterprise 或 AISIX Cloud 环境。
- 集群可以通过网络访问 AISIX Enterprise 或 AISIX Cloud 数据面管理器端点。对于 AISIX Enterprise,请先完成部署 AISIX Enterprise 控制面。
部署网关
在控制台中打开目标环境的 数据面 视图并签发网关证书。Kubernetes (Helm) 标签页会提供下文使用的数据面管理器端点和证书包。本示例还将初始部署固定为一个副本。私钥只显示一次。
在 OpenShift 或 OKD 上,使用 oc project aisix-dp 或 oc new-project aisix-dp 选择或创建 aisix-dp 项目。本流程中请用 oc 代替 kubectl,并省略下方的 kubectl create namespace 命令。
将证书包存储在 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:
helm repo add api7 https://charts.api7.ai
helm repo update
helm install aisix-dp api7/aisix --namespace aisix-dp --version 1.10.0 \
--set controlPlane.baseURL=https://dp-manager.example.com:7944 \
--set controlPlane.certificate.existingSecret=aisix-gateway-certificate \
--set replicaCount=1
网关首次上报心跳后,会出现在环境的 数据面 视图中。Chart 默认为两个副本,但此初始命令只启动一个副本,因为在配置共享 Redis 之前,限流计数器使用每个副本各自的内存。控制台 Helm 代码片段省略了 replicaCount,因此原样安装会启动两个副本。如上所示,请在配置 Redis 前添加 --set replicaCount=1。增加副本数或启用自动扩缩容器前,请先在副本间共享限流计数器。
每个副本会注册为独立实例,并共 享同一个证书。
查看 Chart 接受的所有值:
helm show values api7/aisix --version 1.10.0
Chart 源码和发布包见 aisix-1.10.0 Helm Chart 发布版本。
在 OpenShift 或 OKD 上,请从在 OpenShift 上运行继续,不要使用下方的通用暴露方式。
暴露网关
Chart 默认为代理创建 ClusterIP 类型的 Service。如需通过云负载均衡器发布:
service:
type: LoadBalancer
port: 80
# 保留客户端源 IP,按模型配置的 IP 允许列表会使用该地址进行匹配。
externalTrafficPolicy: Local
如果负载均衡器改为发送 PROXY protocol 头,请把网关看到的 TCP 对端地址加入 config.proxy.real_ip.trusted_proxies。在默认的 externalTrafficPolicy: Cluster 下,该对端是节点地址。参见客户端 IP 解析。
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 上运行
以下平台步骤适用于已获得环境数据面管理器端点和网关证书、连接 AISIX Enterprise 或 AISIX Cloud 的网关。AISIX Cloud 的接入和连接信息由 API7 协调,网关仍由客户自行运维。
Chart 可在默认的 restricted-v2 安全上下文约束(SCC)下运行,无需自定义 SCC 或修改 ServiceAccount。它不设置 runAsUser、runAsGroup 和 fsGroup,由项目分配这些值。容器使用只读根文件系统、禁止提权,并丢弃除 NET_BIND_SERVICE 之外的所有 capability;运行期可写路径使用 emptyDir 卷。
不要向网关 ServiceAccount 授予 anyuid。如果集群管理员因组织策略或自定义卷分配了固定 ID,请将 podSecurityContext.runAsUser、podSecurityContext.runAsGroup 和 podSecurityContext.fsGroup 设为所分配的值。除非镜像 UID 10001 位于项目允许的范围内,否则不要复用它。
为默认的明文 HTTP proxy Service 端口创建 edge Route。如果集群管理员提供了应用域名,请将 ROUTE_DOMAIN 设为该域名,并省略下方第一条 export:
export ROUTE_DOMAIN="$(oc get ingresses.config.openshift.io cluster \
-o jsonpath='{.spec.domain}')"
export GATEWAY_ROUTE_HOST="aisix-gateway.$ROUTE_DOMAIN"
oc create route edge aisix-dp \
--service=aisix-dp \
--port=proxy \
--hostname="$GATEWAY_ROUTE_HOST" \
--namespace aisix-dp
该命令使用默认 Release 名和 proxy Service 端口。如果 Release 覆盖了名称或使用自定义监听器,请运行 oc get service -n aisix-dp,并替换为实际 Service 名和命名端口。
默认应用域名通常使用由集群内部入口 CA 签发的通配符证书。如果工作站尚不信任该 CA,请导出它供验证请求使用:
oc get configmap default-ingress-cert -n openshift-config-managed \
-o jsonpath='{.data.ca-bundle\.crt}' > ingress-ca.crt
export CURL_CA_BUNDLE="$PWD/ingress-ca.crt"
如果管理员提供了 CA 文件,请将其保存为 ingress-ca.crt,并只运行 CURL_CA_BUNDLE 的 export 命令。如果 Route 或默认 Ingress Controller 使用工作站已信任的证书,请跳过该 export。
等待 Deployment 就绪,然后确认分配的 SCC、UID、就绪状态和控制面心跳:
oc rollout status deployment/aisix-dp -n aisix-dp --timeout=5m
export GATEWAY_POD="$(oc get pod -n aisix-dp \
-l 'app.kubernetes.io/instance=aisix-dp,app.kubernetes.io/component=gateway' \
-o jsonpath='{.items[0].metadata.name}')"
oc get pod -n aisix-dp "$GATEWAY_POD" \
-o jsonpath='{.metadata.annotations.openshift\.io/scc}{"\n"}'
oc exec -n aisix-dp "$GATEWAY_POD" -- id -u
curl -fsS "https://$GATEWAY_ROUTE_HOST/readyz"
第一行输出应为 restricted-v2,第二行显示进程实际使用的 UID,就绪请求应返回 ok。确认该 UID 位于项目分配的范围内,并且托管控制面报告网关健康且心跳正常更新。
在 OKD 上运行
OpenShift 步骤同样适用于 OKD,无需修改。AISIX Cloud 客户仍需通过 API7 协调托管控制面的接入和连接信息。
在副本间共享限流计数器
限流计数器默认存储在每个网关自己的内存中,因此 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 或并发限制,也可以有意识地接受每个副本独立的内存后端。