三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

如何在 K8s Ingress 中配置全局 API Key 鉴权中间件?

如何在 K8s Ingress 中配置全局 API Key 鉴权中间件?

K8s Ingress 资源本身仅定义路由规则,不具备鉴权逻辑。要实现全局 API Key 鉴权,必须依赖 Ingress Controller 的具体实现能力。原生 Nginx Ingress Controller 不支持直接的 API Key 注解,标准方案是配合外部认证服务(External Auth)或使用支持插件的网关控制器(如 Kong、APISIX)。

先说结论:标准的 Kubernetes Ingress 规范不包含鉴权字段,实现全局 API Key 鉴权取决于你安装的 Ingress Controller 类型。

  • 核心方案:若使用 Nginx Controller,必须部署独立认证服务并通过 auth-url 注解对接;若需原生支持,建议切换至 Kong 或 APISIX 等网关型控制器。
  • 全局生效:Ingress 资源是命名空间隔离的,要实现“全局”强制鉴权,需通过 Kustomize 补丁或 Mutating Admission Webhook 自动注入注解,而非手动逐个配置。
  • 安全红线:生产环境必须启用 HTTPS,避免 API Key 在传输层明文泄露;认证服务本身应限制仅 Ingress Controller 可访问。

核心方案:Nginx Ingress + 外部认证服务

由于 Nginx Ingress Controller 原生不支持 API Key 校验,最通用的做法是部署一个轻量级认证服务。该服务负责解析请求头中的 X-API-Key,并返回相应的 HTTP 状态码。

1. 部署简易认证服务(Python 示例)

以下是一个基于 Python Flask 的极简认证服务示例,用于验证 X-API-Key。生产环境请使用更 robust 的框架(如 Go/Java)并集成缓存。

from flask import Flask, request, jsonifyapp = Flask(__name__)
VALID_API_KEY = "your-secret-key"  # 建议从环境变量加载@app.route('/validate', methods=['GET', 'POST'])
def validate():api_key = request.headers.get('X-API-Key')if api_key == VALID_API_KEY:return '', 200  # 认证通过return '', 401      # 认证失败if __name__ == '__main__':app.run(host='0.0.0.0', port=8000)

将该服务部署在集群内部(例如 auth-service.default.svc.cluster.local),并确保其 Service 类型为 ClusterIP,不直接对外暴露。

2. 配置 Ingress 注解

在需要鉴权的 Ingress 资源中添加 auth-url 注解。Ingress Controller 会在转发请求前向该 URL 发起子请求。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: example-ingressannotations:nginx.ingress.kubernetes.io/auth-url: http://auth-service.default.svc.cluster.local/validatenginx.ingress.kubernetes.io/auth-method: GETnginx.ingress.kubernetes.io/auth-response-headers: X-API-Key
spec:tls:- hosts:- example.comsecretName: example-tls-secretrules:- host: example.comhttp:paths:- path: /pathType: Prefixbackend:service:name: web-serviceport:number: 80

如何实现集群级全局强制鉴权

Ingress 资源是 Namespaced 的,不存在真正的“集群全局”配置。手动在每个 Ingress 上添加注解容易遗漏且维护成本高。推荐以下两种自动化方案:

方案 A:Kustomize 补丁(推荐)

如果你使用 Kustomize 管理部署,可以通过补丁批量注入鉴权注解。

# ingress-auth-patch.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: all-ingressesannotations:nginx.ingress.kubernetes.io/auth-url: http://auth-service.default.svc.cluster.local/validate# kustomization.yaml
patches:
- path: ingress-auth-patch.yamltarget:kind: Ingress

方案 B:Mutating Admission Webhook

对于更严格的管控,可编写或部署现有的 Mutating Webhook(如 OPA Gatekeeper 或专用准入控制器),在 Ingress 创建时自动注入鉴权注解。这能确保任何新创建的 Ingress 都无法绕过鉴权。

验证方法与安全测试

配置完成后,务必通过 HTTPS 协议进行验证,防止密钥泄露。

# 1. 不带 Key 请求,应返回 401 Unauthorized
curl -k -i https://example.com/# 2. 带有效 Key 请求,应返回 200 OK
curl -k -i -H "X-API-Key: your-secret-key" https://example.com/# 3. 带无效 Key 请求,应返回 401 Unauthorized
curl -k -i -H "X-API-Key: wrong-key" https://example.com/

注意:生产环境中请使用正式 CA 证书,去掉 -k 参数。上述命令仅用于自签名证书测试环境。

常见坑与安全建议

1. 认证服务自身的安全保护

认证服务不应直接暴露在公网。建议配置 NetworkPolicy,仅允许 Ingress Controller 的 Pod 访问认证服务的 8000 端口,防止攻击者绕过 Ingress 直接调用认证接口。

2. 避免循环重定向

如果认证服务本身也通过同一个 Ingress 暴露,且配置了相同的鉴权规则,会导致死循环。认证服务必须通过 ClusterIP 直接访问,或其 Ingress 路径排除鉴权注解。

3. 性能损耗评估

使用 auth-url 意味着每个请求都会增加一次内部 HTTP 调用。在高并发场景下,认证服务可能成为瓶颈。建议认证服务实现本地缓存或使用 Redis 共享状态,并监控其延迟。

4. 密钥管理

不要在代码中硬编码 API Key。应使用 Kubernetes Secret 存储密钥,并通过环境变量注入到认证服务 Pod 中。

替代方案:支持原生插件的控制器

如果外部认证服务维护成本过高,可考虑更换 Ingress Controller:

  • Kong Ingress: 支持原生 key-auth 插件,无需额外部署认证服务。
  • APISIX: 支持丰富的认证插件,性能优异,适合高并发场景。

切换控制器涉及架构变更,建议在评估现有 Nginx Controller 性能瓶颈后再行决策。

原文链接:https://www.zjcp.cc/ask/11362.html

← 返回列表