跳到主要内容
版本:3.10.x

在 Kubernetes 上部署 API7 企业版

本指南介绍如何使用 Helm Chart 在 Kubernetes 上部署 API7 企业版。部署包含两个主要组件:

  • 控制面(CP):控制台、DP Manager 和 PostgreSQL 数据库。
  • 数据面(DP):处理 API 流量的 API7 网关实例。

架构概览​

前置条件​

开始前,请确保具备:

  • 运行 1.25 或更高版本的 Kubernetes 集群,例如 EKS、GKE、AKS 或自建集群。
  • 已配置集群访问权限的 kubectl 1.25 或更高版本。
  • Helm 3.10 或更高版本。请参阅安装 Helm。
  • PostgreSQL 12 或更高版本。生产环境建议使用外部数据库。
  • API7 企业版许可证。请参阅获取试用许可证。
StorageClass

PostgreSQL 和 Prometheus 默认启用持久化存储。如果集群未配置 StorageClass,将出现 PVC 绑定错误。请配置 StorageClass,或禁用持久化(生产环境不建议)。

内置 Jaeger 不使用持久化存储,在内存中保存调试会话链路。请参阅调试会话链路存储。

第 1 步:添加 API7 Helm 仓库​

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

验证仓库是否添加成功:

helm search repo api7/

预期输出包含 api7/api7ee3(控制面)和 api7/gateway(数据面)。

第 2 步:创建命名空间​

为所有 API7 组件创建专用命名空间:

kubectl create namespace api7

第 3 步:准备 PostgreSQL 数据库​

生产部署应使用外部 PostgreSQL 数据库(例如 Amazon RDS、Cloud SQL、Azure Database for PostgreSQL),以获得持久性和高可用。

如果正在评估 API7 或运行非生产环境,Helm Chart 可以部署内置 PostgreSQL 实例。此时跳过本步骤,并在第 4 步的控制面配置文件中设置 postgresql.builtin: true。

对于外部 PostgreSQL,请创建数据库和用户:

CREATE DATABASE api7ee;
CREATE USER api7ee WITH ENCRYPTED PASSWORD 'YOUR_DB_PASSWORD';
GRANT ALL PRIVILEGES ON DATABASE api7ee TO api7ee;

第 4 步:配置控制面​

为避免将包含数据库密码的 DSN 写入 Helm Values 和控制面 ConfigMap, 请先将 DSN 保存到与控制面相同命名空间的 Kubernetes Secret:

read -rsp "Database DSN: " DATABASE_DSN && echo

kubectl create secret generic api7-database-dsn \
--from-literal=DATABASE_DSN="${DATABASE_DSN}" \
-n api7

unset DATABASE_DSN

输入完整的 PostgreSQL 连接字符串,例如 postgres://api7ee:YOUR_DB_PASSWORD@YOUR_PG_HOST:5432/api7ee。 上述命令不会将实际 DSN 写入 Shell 历史记录。

创建 cp-values.yaml 文件:

cp-values.yaml
# -- 禁用内置 PostgreSQL Chart,并将控制台指向外部数据库。
postgresql:
# 1
builtin: false

dashboard_configuration:
database:
# 2
dsn: '${DATABASE_DSN}'

dp_manager_configuration:
database:
# 2
dsn: '${DATABASE_DSN}'

developer_portal_configuration:
database:
# 2
dsn: '${DATABASE_DSN}'

dashboard:
# 3
extraEnvVars:
- name: DATABASE_DSN
valueFrom:
secretKeyRef:
name: api7-database-dsn
key: DATABASE_DSN

dp_manager:
# 3
extraEnvVars:
- name: DATABASE_DSN
valueFrom:
secretKeyRef:
name: api7-database-dsn
key: DATABASE_DSN

developer_portal:
# 3
extraEnvVars:
- name: DATABASE_DSN
valueFrom:
secretKeyRef:
name: api7-database-dsn
key: DATABASE_DSN

dashboard_service:
# 4
type: ClusterIP
  1. 使用外部数据库时禁用内置 PostgreSQL Chart。
  2. 控制台、DP Manager 和开发者门户从配置文件中的 ${DATABASE_DSN} 引用环境变量。Helm 渲染后的 ConfigMap 只包含该占位符,不包含实际 DSN。
  3. 三个组件分别通过 valueFrom.secretKeyRef 将同一个 Secret Key 注入为 DATABASE_DSN 环境变量。Secret 必须与 Helm Release 位于同一个命名空间。 如果禁用开发者门户,可以省略 developer_portal_configuration 和 developer_portal 配置。
  4. 初始安装建议使用 ClusterIP,通过 kubectl port-forward 访问控制台。 需要长期访问时,改用 LoadBalancer 或 Ingress Controller。
警告

Kubernetes Secret 中的数据默认仅经过 Base64 编码,并不等同于加密。 生产环境中应限制 Secret 和 Pod Exec 的 RBAC 权限、启用 Kubernetes Secret 静态加密, 并考虑使用 External Secrets Operator、Secrets Store CSI Driver 或其他外部密钥管理系统。不要将包含明文 DSN 的 Secret Manifest 提交到源代码仓库。

快速评估配置

要使用内置 PostgreSQL 快速评估(不适用于生产环境):

cp-values-eval.yaml
postgresql:
# 1
builtin: true
primary:
persistence:
enabled: true
size: 10Gi

dashboard_service:
# 2
type: ClusterIP
  1. 在评估环境中启用内置 PostgreSQL Chart。
  2. 将控制台 Service 保持为 ClusterIP,并使用 kubectl port-forward 访问。

第 5 步:安装控制面​

helm install api7ee3 api7/api7ee3 \
-f cp-values.yaml \
-n api7

此处 Helm Release 名称和 Chart 名称均为 api7ee3,与 Chart 自身的 Chart.yaml 一致。可以选择其他 Release 名称,但修改后也要相应调整下方验证命令中的 Helm 选择器。

第 6 步:验证控制面 Pod​

等待所有控制面 Pod 进入 Ready 状态:

kubectl -n api7 wait \
--for=condition=Ready pod \
-l app.kubernetes.io/name=api7ee3 \
--timeout=900s

镜像拉取期间也可以持续观察 Pod 状态:

kubectl get pods -n api7 -w

预期输出:

NAME READY STATUS RESTARTS AGE
api7ee3-dashboard-xxxxx-yyyyy 1/1 Running 0 2m
api7ee3-dp-manager-xxxxx-yyyyy 1/1 Running 0 2m
api7ee3-developer-portal-xxxxx-yyyyy 1/1 Running 0 2m

如果使用内置 PostgreSQL,还应看到:

api7-postgresql-0 1/1 Running 0 2m
备注

冷启动时,内置 PostgreSQL 镜像仍在拉取或初始化,api7ee3-dp-manager 或 api7ee3-developer-portal 可能短暂重启。如果 Pod 日志显示数据库拒绝连接且 api7-postgresql-0 尚未就绪,请等待 PostgreSQL 就绪后重新检查控制面 Pod。数据库可用后,此暂时状态应自动恢复,无需手动操作。

第 7 步:验证控制面 Service​

kubectl get svc -n api7 -l app.kubernetes.io/name=api7ee3 -o wide

预期输出:

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
api7ee3-dashboard ClusterIP 10.100.25.236 <none> 7080/TCP,7443/TCP 3m
api7ee3-developer-portal ClusterIP 10.100.88.101 <none> 4321/TCP 3m
api7ee3-dp-manager ClusterIP 10.100.239.32 <none> 7900/TCP,7943/TCP 3m

关键 Service:

Service端口用途
api7ee3-dashboard7443控制台 UI 和 Admin API
api7ee3-dashboard7080控制台 HTTP 端点
api7ee3-developer-portal4321开发者门户 Service
api7ee3-dp-manager7900DP Manager HTTP 端点
api7ee3-dp-manager7943DP Manager mTLS 端点(网关连接)

第 8 步:访问控制台​

将控制台端口转发到本地计算机:

kubectl -n api7 port-forward svc/api7ee3-dashboard 7443:7443

在浏览器中打开 https://localhost:7443,使用默认凭证(admin / admin)登录。首次登录时,控制台会提示重置密码,随后打开 Activate License 页面,可在此上传并激活许可证。

第 9 步:配置 DP Manager 地址​

在 API7 控制台中进入 Gateway Settings,将 DP Manager Address 设置为 Kubernetes 内部 Service DNS:

https://api7ee3-dp-manager:7943

数据面实例将使用此地址连接控制面。

第 10 步:添加网关实例(生成数据面证书)​

在 API7 控制台中选择网关组(例如 default),进入 Gateway Instances 并点击 Add Gateway Instance。选择 Kubernetes,填写目标命名空间并生成部署脚本。控制台将生成:

  1. 数据面的 TLS 证书(tls.crt)。
  2. TLS 私钥(tls.key)。
  3. 用于验证控制面的 CA 证书(ca.crt)。
  4. 为生成证书创建 Secret 的 kubectl create secret 命令。
  5. 包含所有必需参数的完整 Helm 安装命令。

复制生成的脚本,其中包含证书、Secret 创建命令,以及安装数据面的准确 Helm 命令。

第 11 步:创建 mTLS Secret​

从生成的脚本提取证书并创建 Kubernetes Secret:

# 将生成脚本中的证书保存到文件,然后创建 Secret:
kubectl create secret generic api7-ee-3-gateway-tls \
--from-file=tls.crt=/tmp/tls.crt \
--from-file=tls.key=/tmp/tls.key \
--from-file=ca.crt=/tmp/ca.crt \
-n api7
警告

每个网关组的证书都是唯一的。如果有多个网关组,每组都需要自己的证书和独立 Kubernetes Secret。

第 12 步:安装数据面​

使用控制台生成的 Helm 命令,或将生成的配置写入 dp-values.yaml,再使用 Helm 安装数据面。

dp-values.yaml
etcd:
auth:
tls:
enabled: true
existingSecret: api7-ee-3-gateway-tls
certFilename: tls.crt
certKeyFilename: tls.key
verify: true
host:
# ❶
- https://api7ee3-dp-manager:7943

gateway:
tls:
existingCASecret: api7-ee-3-gateway-tls
certCAFilename: ca.crt

apisix:
extraEnvVars:
- name: API7_GATEWAY_GROUP_SHORT_ID
# ❷
value: default
# ❸
replicaCount: 2
image:
repository: api7/api7-ee-3-gateway
tag: ${GATEWAY_VERSION}

❶ 将数据面指向集群内部的 DP Manager mTLS Service。

❷ 如果不使用默认组,请将 default 替换为网关组短 ID。

❸ 根据可用性要求和与控制面兼容的网关镜像版本设置副本数及 ${GATEWAY_VERSION}。生产环境必须固定明确版本,不要使用 latest。

helm upgrade --install api7-ee-3-gateway api7/gateway \
-f dp-values.yaml \
-n api7

第 13 步:验证数据面 Pod​

kubectl get pods -n api7 -l app.kubernetes.io/name=gateway -w

预期输出:

NAME READY STATUS RESTARTS AGE
api7-ee-3-gateway-xxxxx-yyyyy 1/1 Running 0 1m
api7-ee-3-gateway-xxxxx-zzzzz 1/1 Running 0 1m

第 14 步:验证数据面 Service​

kubectl get svc -n api7 -l app.kubernetes.io/name=gateway

预期输出:

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
api7-ee-3-gateway-gateway NodePort 10.100.50.100 <none> 80:31080/TCP,443:31443/TCP 1m

第 15 步:在控制台中验证连接​

登录 API7 控制台并进入 Gateway Groups,数据面实例应显示为 Healthy。

如果实例未出现:

  1. 检查数据面 Pod 日志:kubectl logs -n api7 -l app.kubernetes.io/name=gateway --tail=50。
  2. 确认 mTLS Secret 存在:kubectl get secret api7-ee-3-gateway-tls -n api7。
  3. 确认 Secret 包含全部必需文件:kubectl get secret api7-ee-3-gateway-tls -n api7 -o json | jq '.data | keys'。
  4. 确认数据面 Pod 可以访问控制面地址。出现 TLS 握手错误属于预期现象,此检查仅验证 DNS 和网络连通性:kubectl exec -n api7 <gateway-pod> -- curl -sk --connect-timeout 5 "https://api7ee3-dp-manager:7943/" -o /dev/null -w "%{http_code}"。

第 16 步:暴露网关​

选择以下一种方式,为外部流量暴露网关:

方式 A:NodePort Service(默认)​

网关 Helm Chart 默认创建 NodePort Service。可以通过节点 IP 访问,也可以端口转发该 Service 进行本地验证。

# 使用端口转发访问默认 Service
kubectl port-forward -n api7 svc/api7-ee-3-gateway-gateway 9080:80

方式 B:LoadBalancer Service​

在云提供商环境中,将 Service 改为 LoadBalancer 以分配外部地址:

helm upgrade api7-ee-3-gateway api7/gateway \
--set "gateway.type=LoadBalancer" \
-n api7 --reuse-values

更新 Service 后,检查外部地址:

kubectl get svc -n api7 api7-ee-3-gateway-gateway \
-o jsonpath='{.status.loadBalancer.ingress[0].ip}'

方式 C:Ingress Controller​

如果已有 Ingress Controller(例如 NGINX Ingress、AWS ALB Controller),请创建指向网关 Service 的 Ingress 资源。

第 17 步:测试部署​

向网关发送测试请求:

curl -i "http://127.0.0.1:9080/"

如果尚未配置路由,应收到 API7 网关返回的 404 响应,表明网关正在运行并接收流量。

可以在自动冒烟测试中使用以下最小断言:

kubectl -n api7 wait \
--for=condition=Ready pod \
-l app.kubernetes.io/name=gateway \
--timeout=600s

kubectl -n api7 get secret api7-ee-3-gateway-tls \
-o json | jq '.data | keys'

curl -i "http://127.0.0.1:9080/"

预期结果包括:网关 Pod 已就绪;Secret 包含 ca.crt、tls.crt 和 tls.key;配置路由前返回 HTTP 404。

云平台专用指南​

AWS EKS​

负载均衡器配置​

使用 AWS Load Balancer Controller 支持网络负载均衡器(NLB):

Additional values for EKS
apisix:
service:
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "external"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"
service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"

节点组建议​

对于性能敏感的部署,请使用专用节点组:

节点组实例类型用途
api7-cpm5.xlarge(4 vCPU、16 GB)控制面组件
api7-dpc5.2xlarge(8 vCPU、16 GB)网关数据面

使用节点选择器或节点亲和性将组件调度到适当节点:

DP values with node selector
apisix:
nodeSelector:
nodeName: api7-dp

EKS 专用前置条件​

  1. 使用 NLB 时安装 AWS Load Balancer Controller。
  2. 为 PostgreSQL 持久化存储创建 EBS CSI 驱动插件。
  3. 配置 kubectl 访问 EKS 集群:
aws eks update-kubeconfig --region <region-code> --name <cluster-name>

GCP GKE​

负载均衡器配置​

GKE 会自动为 LoadBalancer Service 创建 TCP 负载均衡器。要使用带 Google Cloud Armor 的 HTTP(S) 负载均衡:

Additional values for GKE
apisix:
service:
annotations:
cloud.google.com/l4-rls: "enabled"
networking.gke.io/load-balancer-type: "Internal" # 仅允许内部访问

防火墙规则​

确保以下防火墙规则允许流量进入 GKE 节点:

端口协议来源用途
9080TCP客户端 CIDR网关 HTTP 流量
9443TCP客户端 CIDR网关 HTTPS 流量
7443TCP管理员 CIDR控制台访问
7943TCP集群内部控制面与数据面 mTLS 通信

GKE 专用前置条件​

  1. PostgreSQL 使用 Cloud SQL 时启用 GKE Workload Identity。
  2. 创建 Cloud SQL PostgreSQL 实例,并为 VPC 配置私有 IP。

Azure AKS​

负载均衡器配置​

AKS 默认使用 Standard SKU 负载均衡器。要配置内部访问:

Additional values for AKS
apisix:
service:
annotations:
service.beta.kubernetes.io/azure-load-balancer-internal: "true"

AKS 专用前置条件​

  1. 使用 Azure Disk CSI 驱动(AKS 1.21+ 默认启用)提供 PostgreSQL 持久化存储。
  2. 使用外部 PostgreSQL 时,创建 Azure Database for PostgreSQL Flexible Server。
  3. 生产环境使用 Azure CNI,以获得可预测的 Pod IP 分配。

生产环境加固​

CPU 资源和 Worker 进程​

CPU 请求、CPU 限制和 NGINX Worker 进程分别控制网关 Pod 运行时的不同方面。请将它们结合配置,在考虑容器中其他进程的同时,为每个 Worker 提供充足的 CPU 容量。

CPU 限制建议​

如果 Kubernetes 集群策略允许,请不要设置 apisix.resources.limits.cpu,以免 CPU 配额限制网关进程。

如果集群策略要求设置 CPU 限制,其值不得低于 Worker 进程数:

apisix.resources.limits.cpu >= nginx.workerProcesses

每个 NGINX Worker 都是单线程进程。流量增加时,同一个 Worker 也无法使用大约一个 CPU 核心以上的资源。因此,高于 Worker 数量的 CPU 限制不会让单个 Worker 突破一个核心;额外容量主要供容器中的辅助进程和其他 CPU 开销使用。

CPU 请求和 Worker 进程建议​

apisix.resources.requests.cpu 主要用于 Kubernetes 调度和资源保障,并不是单个进程的硬性 CPU 限制。

对于没有持续高负载或严格性能要求的工作负载,建议先为每个 Worker 进程请求至少一个 CPU 核心:

nginx.workerProcesses建议的 apisix.resources.requests.cpu 基准值
11
22
44
88

这一 1:1 比例是以 Worker 进程为中心的实用基准,并非容器中每个进程都必须遵循的严格资源等式。特权进程和缓存管理器等辅助进程也会消耗 CPU。对于高负载或性能敏感环境,请在基准值之上预留 CPU 余量,并根据性能测试结果和运行时监控确定最终的 CPU 请求,以及必要时的 CPU 限制。

例如,以下配置为 4 个固定 Worker 使用标准基准值:

四个固定 Worker 的数据面配置
nginx:
workerProcesses: 4

apisix:
resources:
requests:
cpu: "4"

如果集群策略还要求设置 CPU 限制,以下配置额外提供一个 CPU 核心作为容器级余量:

需要 CPU 限制的数据面配置
nginx:
workerProcesses: 4

apisix:
resources:
requests:
cpu: "4"
limits:
cpu: "5"

Kubernetes 支持 500m(0.5 个 CPU 核心)等小数形式的 CPU 请求和限制,但 API7 网关使用 NGINX 单线程 Worker 模型。如果每个 Worker 可用的 CPU 显著少于一个核心,网关性能可能会受限。

实际生效的 Worker 进程数也决定许可的数据面核心数用量。请参阅网关 Worker 进程如何影响许可核心数。

内存请求和限制​

请单独配置内存与 CPU 资源及 Worker 进程。以下是起始示例值,并非 Chart 默认值:

数据面内存资源配置
apisix:
resources:
requests:
memory: "4Gi"
limits:
memory: "8Gi"

请根据流量特征、已启用插件、性能测试结果和运行时监控调整内存请求与限制。有关数据面的一般容量基准,请参阅系统要求。

PodDisruptionBudget​

创建 PodDisruptionBudget(PDB),确保节点维护期间网关保持可用:

pdb.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: api7-gateway-pdb
namespace: api7
spec:
minAvailable: 1
selector:
matchLabels:
app.kubernetes.io/name: gateway
kubectl apply -f pdb.yaml

配置水平扩缩容​

启用基于 CPU 利用率的自动扩缩容:

hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api7-gateway-hpa
namespace: api7
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api7-ee-3-gateway
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
kubectl apply -f hpa.yaml

反亲和性规则​

将网关 Pod 分散到多个节点,以提高容错能力:

DP values with anti-affinity
apisix:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app.kubernetes.io/name
operator: In
values:
- gateway
topologyKey: kubernetes.io/hostname

调试会话链路存储​

控制面将调试会话的链路存储在 Jaeger 中。默认情况下(jaeger.builtin: true),Chart 会部署一个内置 Jaeger,它使用 Jaeger 默认的 all-in-one 配置,在内存中保存链路,不使用持久化存储:

  • Jaeger Pod 重启或被重新调度后,所有链路都会丢失,例如节点排空或升级替换了该 Pod 时。
  • Jaeger 最多保存 100,000 条链路。达到上限后,每条新链路都会淘汰最早的一条。

控制面在数据库中保存每个会话的链路列表,因此即使链路数据已不在 Jaeger 中,会话仍可能列出这些链路。请参阅链路保留。

在生产环境中,请部署使用持久化存储后端的 Jaeger,禁用内置 Jaeger,并将控制面指向你的部署:

使用外部 Jaeger 的 CP values
jaeger:
builtin: false

dashboard_configuration:
jaeger:
# 1
addr: "http://jaeger.observability.svc:16686"

dp_manager_configuration:
jaeger:
# 2
collector_addr: "http://jaeger.observability.svc:4318"
  1. 控制台从该 Jaeger Query 端点读取链路。该端点必须通过 HTTP 提供 Jaeger Query API v3(/api/v3/traces)。请替换为你自己的地址。
  2. DP Manager 通过 OTLP over HTTP 向该端点发送链路。请替换为你自己的地址。

如果继续使用内置 Jaeger,请在捕获重要链路后立即通过 Download OTLP JSON 导出。

故障排查​

控制面 Pod 在初次启动期间重启​

现象:api7ee3-dp-manager 或 api7ee3-developer-portal 短暂进入 CrashLoopBackOff,日志显示数据库拒绝连接。

原因:使用内置 PostgreSQL Chart 时,控制面组件可能在 PostgreSQL 完成镜像拉取并开始接受连接前启动。

解决方法:

kubectl get pods -n api7 -w
kubectl logs -n api7 statefulset/api7-postgresql --tail=100
kubectl logs -n api7 deploy/api7ee3-dp-manager --tail=100

等待 api7-postgresql-0 变为 1/1 Running,然后验证所有控制面 Pod 均已就绪:

kubectl -n api7 wait \
--for=condition=Ready pod \
-l app.kubernetes.io/name=api7ee3 \
--timeout=900s

如果 PostgreSQL 就绪后控制面 Pod 仍持续重启,请检查 Pod 事件和数据库 DSN 配置。

Pod 停留在 Pending 状态​

现象:控制面或数据面 Pod 一直处于 Pending 状态。

原因:集群资源不足,或持久卷声明缺少 StorageClass。

解决方法:

# 检查 Pod 事件
kubectl describe pod <pod-name> -n api7

# 按时间顺序检查命名空间事件
kubectl get events -n api7 --sort-by=.lastTimestamp

# 如果与 PVC 相关,请检查存储类
kubectl get storageclass

数据面无法连接控制面​

现象:数据面 Pod 处于 Running,但日志显示 connection refused 或 certificate verify failed。

解决方法:

  1. 验证 mTLS Secret 存在且包含全部三个文件:
kubectl get secret api7-ee-3-gateway-tls -n api7 -o json | jq '.data | keys'
# 预期输出:["ca.crt", "tls.crt", "tls.key"]
  1. 验证数据面 Pod 能够解析控制面地址:
kubectl exec -n api7 <gateway-pod> -- nslookup api7ee3-dp-manager
  1. 检查数据面 Pod 日志中的具体错误:
kubectl logs -n api7 <gateway-pod> --tail=100

无法访问控制台​

现象:配置端口转发或 LoadBalancer 后仍无法访问控制台。

解决方法:

  1. 验证控制台 Pod 正在运行:kubectl get pods -n api7 -l app.kubernetes.io/component=dashboard。
  2. 检查 Service 端点:kubectl get endpoints -n api7 api7ee3-dashboard。
  3. 确保网络策略或安全组未阻止 7443 端口。

后续步骤​