配置上游健康检查
健康检查帮助网关识别能正常响应的上游节点,并检测节点何时发生故障或恢复。
健康检查分为两类:
- 主动检查:网关主动、定期向上游服务发送请求,并根据这些请求的响应判断上游服务 健康状态。
- 被动检查:网关不主动探测,而是根据上游服务对客户端请求的响应判断健康状态。
以下示例针对两个 NGINX 服务配置这两类检查,并区分探针失败与端点移除。
前置条件
启动示例上游服务
创建 Kubernetes manifest 文件,部署两个 NGINX 实例作为示例上游服务:
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: aic
name: nginx1
spec:
replicas: 1
selector:
matchLabels:
app: nginx1
template:
metadata:
labels:
app: nginx1
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: nginx1
spec:
selector:
app: nginx1
ports:
- name: http
port: 8080
targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: aic
name: nginx2
spec:
replicas: 1
selector:
matchLabels:
app: nginx2
template:
metadata:
labels:
app: nginx2
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: nginx2
spec:
selector:
app: nginx2
ports:
- name: http
port: 8081
targetPort: 80
将配置应用到集群:
kubectl apply -f nginx.yaml
通过端口转发将 NGINX Service 端口暴露到本地:
kubectl port-forward svc/nginx1 -n aic 8080:8080 &
kubectl port-forward svc/nginx2 -n aic 8081:8081 &
验证两个 NGINX 实例是否正常运行:
for port in 8080 8081; do
curl -s "http://127.0.0.1:$port" | grep -q "Welcome to nginx" &&
echo "NGINX welcome page available on port $port."
done
你应看到以下响应:
NGINX welcome page available on port 8080.
NGINX welcome page available on port 8081.
启用 Control API
升级网关以启用 Control API。
- APISIX 网关
- API7 网关
导出所有 values(包括默认值):
helm get values -n aic apisix --all > values.yaml
在 values 文件中按如下方式更新配置:
apisix:
enabled: true
control:
enabled: true
升级 Helm release:
helm upgrade -n aic apisix apisix/apisix --version 2.18.0 -f values.yaml
转发 Control API 端口:
kubectl port-forward service/apisix-control -n aic 9090:9090 &
默认情况下,Control API 会在 9090 端口启用:
control:
enabled: true
ip: 127.0.0.1
port: 9090
转发 Control API 端口:
kubectl port-forward pod/<api7-gateway-pod-name> -n aic 9090:9090 &
配置主动健康检查
主动检查会定期向上游服务发送请求或探针,并根据响应判断上游服务的健康状态。
本节通过两个示例帮助你理解:
- 主动检查如何检测上游状态变化。
- 当所有上游状态均为不健康时,网关如何向上游服务转发客户端请求。
示例:上游服务状态变化
以下示例区分四种状态:两个上游都健康、端点仍可用时主动探针失败并恢复、端点被移除,以及上游恢复。
创建指向两个服务的路由。将健康节点的探针配置为每 2 秒运行一次,不健康节点的探针配置为每秒运行一次:
- Gateway API
- APISIX CRD
apiVersion: apisix.apache.org/v1alpha1
kind: BackendTrafficPolicy
metadata:
namespace: aic
name: nginx1
spec:
targetRefs:
- name: nginx1
kind: Service
group: ""
# 仅将此策略应用到命名的 Service 端口。
sectionName: http
healthCheck:
active:
type: http
httpPath: /
healthy:
interval: 2s
successes: 1
unhealthy:
interval: 1s
timeouts: 3
---
apiVersion: apisix.apache.org/v1alpha1
kind: BackendTrafficPolicy
metadata:
namespace: aic
name: nginx2
spec:
targetRefs:
- name: nginx2
kind: Service
group: ""
sectionName: http
healthCheck:
active:
type: http
httpPath: /
healthy:
interval: 2s
successes: 1
unhealthy:
interval: 1s
timeouts: 3
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: example-hc-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /
backendRefs:
- name: nginx1
port: 8080
weight: 1
- name: nginx2
port: 8081
weight: 1
将配置应用到集群:
kubectl apply -f active-health-checks.yaml
sectionName 通过 spec.ports[].name 选择 Service 端口。若命名端口不存在,策略不会挂载,其状态会报告 Accepted=False,并显示类似 No section name http found in Service aic/nginx1 的消息。可使用以下命令检查策略状态:
kubectl describe backendtrafficpolicy nginx1 -n aic
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: nginx1
spec:
ingressClassName: apisix
healthCheck:
active:
type: http
httpPath: /
healthy:
interval: 2s
successes: 1
unhealthy:
interval: 1s
timeout: 3
---
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: nginx2
spec:
ingressClassName: apisix
healthCheck:
active:
type: http
httpPath: /
healthy:
interval: 2s
successes: 1
unhealthy:
interval: 1s
timeout: 3
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: example-hc-route
spec:
ingressClassName: apisix
http:
- name: nginx-hc
match:
paths:
- /
backends:
- serviceName: nginx1
servicePort: 8080
weight: 100
- serviceName: nginx2
servicePort: 8081
weight: 100
❶ type:主动健康检查的类型。
❷ httpPath:主动探测使用的 HTTP 请求路径。
❸ healthy.interval:定期检查健康节点的时间间隔,单位为秒。
❹ healthy.successes:判定上游节点健康所需的成功次数阈值。
❺ unhealthy.interval:定期检查不健康节点的时间间隔,单位为秒。
❻ unhealthy.timeout:判定上游节点不健康所需的超时次数阈值。
将配置应用到集群:
kubectl apply -f active-health-checks.yaml
验证
网关通常选择健康节点。当所有节点都被标记为不健康但端点仍然存在时,负载均衡器仍可回退到这些节点;这与完全没有端点不同。
你将验证以上配置,以了解上游健康检查在不同场景下的响应方式:
继续之前,先将网关 Service 端口暴露到本地:
# 替换为你的网关 Service 名称
kubectl port-forward svc/<gateway-service-name> -n aic 9080:80 &
验证两个上游服务均健康
在 Controller 应用配置并初始化上游检查器时,通过路由生成流量。轮询 http://127.0.0.1:9090/v1/healthcheck,直到两个 Service 上游都存在健康节点。一次请求不能保证每个 worker 都已初始化检查器。
for attempt in $(seq 10); do
curl -sS --max-time 5 "http://127.0.0.1:9080/" -o /dev/null
curl -sS --max-time 5 "http://127.0.0.1:9090/v1/healthcheck"
sleep 2
done
如果检查器仍在初始化,请重复请求。开始故障测试前,确认两个上游都处于健康状态。
响应包含 nginx1 和 nginx2 各自独立的上游检查器条目,每个条目都有自己的节点和计数器。名称和 Pod IP 会动态生成;不要预期看到一个以路由命名、同时包含两个 Service 的检查器。
验证探针失败与恢复
保持两个 Deployment 运行,使其端点继续存在。请为已应用配置的选项卡选择对应资源类型:
# Gateway API:
export HEALTH_RESOURCE="backendtrafficpolicies.apisix.apache.org"
# 对于 APISIX CRD 选项卡,请改用:
# export HEALTH_RESOURCE="apisixupstreams.apisix.apache.org"
让第一个上游的探针请求 /404(返回不健康的 HTTP 状态),并设置失败阈值:
kubectl patch "$HEALTH_RESOURCE" nginx1 -n aic --type merge \
-p '{"spec":{"healthCheck":{"active":{"httpPath":"/404","unhealthy":{"httpFailures":2}}}}}'
curl -i "http://127.0.0.1:9080/"
curl "http://127.0.0.1:9090/v1/healthcheck"
重复发送流量并查询检查器,直到 nginx1 检查器报告 HTTP 失败并变为不健康,而 nginx2 保持健康。EndpointSlice 此时仍应包含两个后端。计数和时间会有差异;一次请求不保证状态一定完成转换。
对第二个上游应用相同变更:
kubectl patch "$HEALTH_RESOURCE" nginx2 -n aic --type merge \
-p '{"spec":{"healthCheck":{"active":{"httpPath":"/404","unhealthy":{"httpFailures":2}}}}}'
curl -i "http://127.0.0.1:9080/"
curl "http://127.0.0.1:9090/v1/healthcheck"
轮询直到两个检查器都报告不健康节点。由于服务器及其端点仍然可用,对 / 的请求仍可通过“全部不健康”回退机制成功。
恢复两个资源的探针路径:
for service in nginx1 nginx2; do
kubectl patch "$HEALTH_RESOURCE" "$service" -n aic --type merge \
-p '{"spec":{"healthCheck":{"active":{"httpPath":"/"}}}}'
done
curl -i "http://127.0.0.1:9080/"
curl "http://127.0.0.1:9090/v1/healthcheck"
开始端点移除测试前,请等待两个上游健康检查器恢复健康。这验证的是 HTTP 探针失败与恢复,而不是超时计数或端点移除。
验证端点移除
将一个后端缩容到零:
kubectl scale deployment nginx1 -n aic --replicas=0
等待其 EndpointSlice 与网关配置收敛。被移除的端点会从上游消失;移除端点并不能证明发生了三次探针失败,也不会增加超时计数器。
使用 HTTPRoute 时,剩余的可用后端可以继续处理请求。在 ApisixRoute 示例中,空后端仍保留权重,因此重复请求时可能同时出现成功响应和 503 响应。
将第二个后端缩容到零:
kubectl scale deployment nginx2 -n aic --replicas=0
收敛后,两个后端都没有可用端点,请求将返回 503 而不是 502。若要演示探针超时,请保持端点存在,同时阻止其探针响应。
恢复上游
kubectl scale deployment nginx1 -n aic --replicas=1
kubectl scale deployment nginx2 -n aic --replicas=1
kubectl rollout status deployment/nginx1 -n aic --timeout=120s
kubectl rollout status deployment/nginx2 -n aic --timeout=120s
等待端点、网关配置和健康的检查器状态全部就绪后再继续。仅 Pod 就绪并不能证明网关已应用恢复的端点。