Files
Kubernetes/网关/Ingress/Ingress流量问题排查指南.md
offends 05791351c3
All checks were successful
continuous-integration/drone Build is passing
新增Ingress流量控制文档
2025-10-31 21:02:15 +08:00

16 KiB
Raw Blame History

本文作者:丁辉

Ingress流量问题排查指南

排查流程图

流量异常 → 云监控确认 → 定位异常IP → 分析请求路径 → 检查User-Agent → 判断问题类型 → 制定解决方案

核心排查命令集共

1. 快速定位问题范围

  • 查看最近1小时最活跃的客户端IP

    kubectl logs <ingress-controller-pod> --since=1h | awk '{print $1}' | sort | uniq -c | sort -nr | head -10
    
  • 查看最近1小时最频繁的请求路径

    kubectl logs <ingress-controller-pod> --since=1h | awk '{print $7}' | sort | uniq -c | sort -nr | head -10
    

2. 深入分析特定IP行为

  • 查看特定IP的详细访问记录

    kubectl logs <ingress-controller-pod> --since=1h | grep '可疑IP'
    
  • 分析特定IP的User-Agent

    kubectl logs <ingress-controller-pod> --since=1h | grep '可疑IP' | awk -F'"' '{print $6}' | sort | uniq
    
  • 查看特定IP访问的路径分布

    kubectl logs <ingress-controller-pod> --since=1h | grep '可疑IP' | awk '{print $7}' | sort | uniq -c | sort -nr
    

3. 分析特定接口/路径

  • 查看特定接口的访问详情

    kubectl logs <ingress-controller-pod> --since=1h | grep "接口路径" | head -20
    
  • 统计接口的响应状态码分布

    kubectl logs <ingress-controller-pod> --since=1h | grep "接口路径" | awk '{print $9}' | sort | uniq -c
    

4. 实时监控

  • 实时查看Ingress访问日志

    kubectl logs -f <ingress-controller-pod>
    
  • 实时查看特定服务的日志

    kubectl logs -f <后端服务pod>
    

日志字段解析指南

关键字段说明:

  • $1 - 客户端IP地址
  • $7 - 请求路径和参数
  • $9 - HTTP状态码
  • 引号内第6个字段 - User-Agent
  • 倒数第6个字段 - 请求处理时间(秒)
  • 方括号内字段 - 转发的K8s服务

常见问题模式识别

1. 爬虫/自动化脚本特征

  • 单一IP高频访问
  • User-Agent包含botcrawlerpythongo
  • 规律的请求间隔

2. API滥用特征

  • 针对特定API接口的高频调用
  • 异常的POST/PUT请求模式
  • 大量4xx状态码

3. 性能问题特征

  • 请求处理时间普遍较长(>5秒
  • 大量5xx状态码
  • 特定的慢接口

4. 安全威胁特征

  • 扫描行为(访问不存在的路径)
  • 注入攻击特征SQL、XSS等
  • 暴力破解(大量登录尝试)

解决方案工具箱

1. 紧急限流措施

# ===============================================
# 🧱 Ingress 限流配置(通过注解实现)
# 使用 NGINX Ingress Controller 的内建限流功能,
# 可有效防止暴力请求、爬虫或瞬时流量过载。
# ===============================================
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  annotations:
    # 🎯 每秒请求数限制 (Requests Per Second)
    # 定义每个客户端 IP 每秒允许的最大请求数。
    # 超过该值的请求会被拒绝(返回 limit-status-code 指定的状态码)。
    # ⚙️ 实现方式:使用 NGINX 的 limit_req_zone + limit_req。
    # 💡 建议范围:
    #   - 普通API: 5~20
    #   - 静态资源: 50~200
    nginx.ingress.kubernetes.org/limit-rps: "10"
    
    # ⚡ 每秒连接数限制 (Connections Per Second)
    # 定义每个客户端 IP 每秒可新建的最大连接数。
    # 对于 HTTP/1.1 Keep-Alive 长连接影响较小,但能防御连接泛洪攻击。
    # ⚙️ 实现方式:使用 limit_conn_zone + limit_conn。
    # 💡 建议范围:
    #   - 一般网站: 10~50
    #   - 高并发API: 100+
    nginx.ingress.kubernetes.org/limit-connections: "20"
    
    # 🛡️ 白名单设置(免限流)
    # 指定 IP 或网段不受限流影响。
    # 可用于信任的反向代理、内部系统或监控探针。
    # 支持单个 IP 或 CIDR逗号分隔
    # ⚠️ 建议仅加入受信任来源,否则可能绕过防护。
    nginx.ingress.kubernetes.org/limit-whitelist: "192.168.0.0/24,10.0.0.1"
    
    # 🚀 突发请求缓冲(突发容忍)
    # 允许在短时间内超出 limit-rps 的请求数量。
    # 适用于偶发瞬时高峰(如页面资源集中加载)。
    # ⚙️ 内部机制:令牌桶算法 (burst capacity)。
    # 💡 建议burst 通常设为 limit-rps 的 2~3 倍。
    nginx.ingress.kubernetes.org/limit-burst: "20"
    
    # 🚫 限流响应码
    # 当请求被限流时返回的 HTTP 状态码。
    # 通常设置为 429Too Many Requests或 503Service Unavailable
    # 💡 若你的客户端或上游依赖特定响应行为,可自定义此状态码。
    nginx.ingress.kubernetes.org/limit-status-code: "503"

# ===============================================
# 📋 提示:
# - 若同一个 Ingress 使用多个路径,限流策略对整个 Ingress 生效。
# - 如需区分路径限流,可分别定义多个 Ingress。
# - 可配合 nginx.ingress.kubernetes.org/limit-rpm (每分钟请求数)。
# - 修改后执行:
#     kubectl apply -f example-ingress.yaml
#     kubectl describe ingress example-ingress
#   以确认注解生效。
# ===============================================

2. IP封禁

# ===============================================
# 🧱 NGINX Ingress Controller IP 封禁与访问控制配置
# 通过 ConfigMap 对客户端 IP 进行白名单、黑名单或基于地理位置的控制。
# ===============================================
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
  namespace: ingress-nginx
data:
  # 🔒 全局访问控制(白名单/黑名单)
  # allow-snippet 使用原生 NGINX 语法控制访问:
  #   - allow <IP/CIDR>:允许访问
  #   - deny all拒绝所有其他访问
  # ⚙️ 使用场景:
  #   - 内网服务只允许特定网段访问
  allow-snippet: |
    allow 192.168.0.0/16;
    allow 10.0.0.0/8;
    deny all;

3. 优化配置

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-configuration
  namespace: ingress-nginx
data:
  # ================================
  # 🌐 NGINX Ingress Controller 全局配置
  # 此 ConfigMap 控制 ingress-nginx 控制器内 NGINX 实例的行为。
  # 修改后通常需要重新加载 Ingress Controller 才会生效。
  # ================================

  # ⏱️ 连接超时时间(秒)
  # 定义 NGINX 与上游后端Service Pod建立 TCP 连接的超时。
  # 若上游响应缓慢或网络不稳定,可适当调大。
  # 建议范围5~30秒
  proxy-connect-timeout: "10"

  # ⏱️ 读取超时时间(秒)
  # 定义 NGINX 在与上游通信时,等待上游响应数据的最长时间。
  # 超时后会返回 504 Gateway Timeout。
  # 建议范围10~60秒取决于上游处理逻辑耗时。
  proxy-read-timeout: "30"

  # ⏱️ 发送超时时间(秒)
  # 定义 NGINX 向上游发送请求数据的超时。
  # 对上传大文件或慢速后端可适当调大。
  # 建议与 proxy-read-timeout 一致。
  proxy-send-timeout: "30"

  # ⏱️ 客户端请求头超时
  # 定义 NGINX 等待客户端(例如浏览器或负载均衡器)
  # 发送完整请求头的超时时间。
  # 过低可能影响慢速客户端,过高可能被滥用进行慢速攻击。
  client-header-timeout: "10"

  # 📦 客户端请求体大小限制
  # 限制客户端请求体(例如上传文件)的最大大小。
  # 超出时返回 413 Request Entity Too Large。
  # 例如 "10m" 表示最大 10MB。
  # 建议根据业务场景调整:普通 API 可设为 1~5m大文件上传可放宽。
  proxy-body-size: "10m"

  # 🔄 保持连接超时
  # 定义客户端与 NGINX 之间的 keep-alive 持续时间(秒)。
  # 影响 HTTP 连接复用性能和资源占用。
  # 值过低会增加连接重建开销;过高可能导致空闲连接占用资源。
  # 建议范围30~120秒。
  keep-alive: "75"

  # 📊 缓冲区设置
  # 控制 NGINX 在代理上游响应时的内存缓冲。
  # 调整这些值可优化大响应体(例如 JSON、大型页面的性能。
  # proxy-buffer-size: 单个缓冲区大小。
  # proxy-buffers-number: 缓冲区数量。
  # 默认通常足够,除非你的后端返回非常大的头部或响应。
  proxy-buffer-size: "8k"
  proxy-buffers-number: "4"

  # ====================================
  # 🧩 补充说明:
  # - 修改 ConfigMap 后需触发 ingress-nginx 控制器 reload。
  #   可执行: kubectl rollout restart deployment ingress-nginx-controller -n ingress-nginx
  # - 所有 timeout 值均为秒(字符串形式)。
  # - 若使用 AWS/GCP LB还需确保 LB 层超时 >= 这些值。
  # ====================================

4. 安全加固配置

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
  namespace: ingress-nginx
data:
  # 🔐 隐藏 NGINX 版本信息
  # 设置为 "false" 可防止 NGINX 在响应头中显示 Server: nginx/版本号
  # ⭐ 注意:部分版本可能仍在某些情况下显示 Server 字段,建议验证生成的 nginx.conf。
  server-tokens: "false"
  
  # 🔍 是否允许 HTTP 请求头中包含下划线 (_) 字符
  # 若设置为 "false"Nginx 会拒绝或忽略带下划线的头部字段。
  # 若你的客户端或上游服务使用 “X_Custom_Header” 这类头部,请设置为 "true"。
  enable-underscores-in-headers: "false"
  
  # 🔒 是否忽略无效的 HTTP 头部字段
  # 设置为 "true" 时Nginx 遇到格式错误或不合法的头部,将会忽略而不是拒绝。
  ignore-invalid-headers: "true"

  # 🛡️ SSL 强化配置 — 协议版本
  # 只启用 TLS v1.2 和 v1.3,禁用旧版本(如 TLS1.0/1.1)以提高安全性。
  ssl-protocols: "TLSv1.2 TLSv1.3"

  # 🛡️ SSL 强化配置 — 加密套件 (Cipher Suites)
  # 指定特定的、安全性较强的加密套件。请参考你所用 NGINX 版本所支持的套件列表。
  ssl-ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256,ECDHE-RSA-AES128-GCM-SHA256"

# 📋 提示:修改后请滚动重启 ingress-nginx 控制器 Pod例如
# kubectl rollout restart deployment ingress-nginx-controller -n ingress-nginx
# 并使用 kubectl exec 查看 /etc/nginx/nginx.conf 中是否包含你配置的指令。

5. 日志与监控配置

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
  namespace: ingress-nginx
data:
  # 📝 自定义日志格式(上游代理请求日志)
  # 用于记录更多有用的调试信息,如:客户端地址、上游地址、请求时间、响应时间等。
  # ⚠️ 生效条件:确保使用的 ingressnginx 版本支持 log-format-upstream并且正在使用该 ConfigMap。 :contentReference[oaicite:5]{index=5}
  log-format-upstream: |
    '$remote_addr - $remote_user [$time_local] "$request" '
    '$status $body_bytes_sent "$http_referer" '
    '"$http_user_agent" "$http_x_forwarded_for" '
    'upstream_addr: $upstream_addr '
    'request_time: $request_time '
    'upstream_response_time: $upstream_response_time'

  # 📊 访问日志设置 — **需确认键是否被支持**
  # enable-access-log: 若设置为 “true”希望启用访问日志。
  # access-log-path: 指定访问日志文件路径(例如 /var/log/nginx/access.log
  # ⚠️ 文档未明确将这两项列为标准 ConfigMap 键,实际生效需验证。
  enable-access-log: "true"
  access-log-path: "/var/log/nginx/access.log"

  # 🔍 错误日志级别
  # 可选值debug|info|notice|warn|error|crit|alert|emerg
  # 推荐生产环境使用 “warn” 或 “error” 以减少噪声,调试期可用 “info” 或 “debug”。
  error-log-level: "warn"

# 📋 提示:
# - 修改后需要滚动重启 ingressnginx 控制器 Podkubectl rollout restart deployment <controller> -n ingress-nginx  
# - 若 log-formatupstream 未生效,可查看 /etc/nginx/nginx.conf 中是否包含你的自定义格式。  
# - 若 enableaccesslog / accesslogpath 无效果,请查阅当前版本支持的键列表或用 `access-log-off`、`disable-access-log` 等键进行切换。 

6. 高级限流策略

方法 A使用注解推荐

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  annotations:
    # 每个IP每秒最多10个请求
    nginx.ingress.kubernetes.org/limit-rps: "10"
    # 突发请求允许数量
    nginx.ingress.kubernetes.org/limit-burst: "20"
    # 并发连接限制
    nginx.ingress.kubernetes.org/limit-connections: "5"
  • 优点:官方支持,简单。
  • 缺点:无法直接实现 $request_uri 分路径的限流。

方法 BServer / Configuration Snippet

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  annotations:
    nginx.ingress.kubernetes.io/server-snippet: |
      limit_req_zone $binary_remote_addr zone=global:10m rate=10r/s;
      limit_req_zone $request_uri zone=api:10m rate=5r/s;
      limit_conn_zone $binary_remote_addr zone=addr:10m;
  • 这里可以写原生 NGINX 指令,并在 ingress-nginx 的 server 块中生效。
  • 注意:需要确认你使用的 ingress-nginx 版本允许 server-snippet 注解。

7. 实际应用示例

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: protected-app
  annotations:
    # =========================================
    # ⚡ 基础限流每个IP每秒允许的请求数
    # nginx.ingress.kubernetes.org/limit-rps
    # - 控制每个客户端 IP 的请求频率
    # - 超过此速率的请求将被限流
    # - 建议值5~20视业务请求量而定
    nginx.ingress.kubernetes.org/limit-rps: "10"
    
    # 🚀 突发流量允许值burst
    # nginx.ingress.kubernetes.org/limit-burst
    # - 短时间内允许超过 limit-rps 的请求数
    # - 可缓解瞬时高峰流量
    # - 建议值limit-rps 的 2~3 倍
    nginx.ingress.kubernetes.org/limit-burst: "20"
    
    # 🔗 并发连接限制
    # nginx.ingress.kubernetes.org/limit-connections
    # - 每个客户端 IP 的最大并发连接数
    # - 防止单个IP占用过多连接导致资源耗尽
    # - 建议值5~20视服务并发能力而定
    nginx.ingress.kubernetes.org/limit-connections: "10"
    
    # 🛡️ 白名单(免限流)
    # nginx.ingress.kubernetes.org/limit-whitelist
    # - 指定 IP 或网段不受限流影响
    # - 可用于内部网络或可信代理
    # - 支持逗号分隔的 CIDR 或单个 IP
    nginx.ingress.kubernetes.org/limit-whitelist: "10.0.0.0/8,192.168.0.0/16"
    
    # ⏱️ 超时设置:避免长连接占用资源
    # nginx.ingress.kubernetes.org/proxy-read-timeout / proxy-send-timeout
    # - 分别控制 NGINX 读取上游响应和发送请求的超时时间
    # - 建议值10~60秒视后端响应时间而定
    nginx.ingress.kubernetes.org/proxy-read-timeout: "30"
    nginx.ingress.kubernetes.org/proxy-send-timeout: "30"
    
    # 🚫 限流响应码
    # nginx.ingress.kubernetes.org/limit-status-code
    # - 当请求被限流时返回的 HTTP 状态码
    # - 常用 429 (Too Many Requests) 或 503 (Service Unavailable)
    nginx.ingress.kubernetes.org/limit-status-code: "429"

# =========================================
# 📋 使用提示:
# 1. 修改注解后无需修改 ConfigMap直接 kubectl apply -f ingress.yaml 即可生效。
# 2. 对于高峰业务,可适当调高 limit-burst 和 limit-rps避免误伤正常用户。
# 3. 白名单只应包含可信内部 IP防止绕过限流。
# 4. 若配合负载均衡器或 CDN确保 LB 层超时时间 >= proxy-read/send-timeout。

配验证命令

# 验证配置语法是否正确
kubectl exec -it <ingress-pod> -n ingress-nginx -- nginx -t

# 重新加载配置(不中断服务)
kubectl exec -it <ingress-pod> -n ingress-nginx -- nginx -s reload

# 查看当前生效的配置
kubectl exec -it <ingress-pod> -n ingress-nginx -- cat /etc/nginx/nginx.conf

# 实时监控限流效果
kubectl logs -f <ingress-pod> -n ingress-nginx | grep "limiting requests"

监控和告警设置

1. 关键监控指

  • QPS每秒请求数
  • 错误率4xx/5xx
  • 响应时间P95/P99
  • 带宽使用率

2. 告警阈值建议

# 异常流量检测规则示例
- QPS突增 > 50%
- 5xx错误率 > 5%
- 平均响应时间 > 3s
- 单一IP请求占比 > 20%

💡 经验总结

快速诊断清单:

  1. 先看IP分布 - 找到异常源头
  2. 再看请求路径 - 定位问题接口
  3. 分析User-Agent - 判断请求性质
  4. 检查响应时间和状态码 - 确认影响范围
  5. 关联后端服务日志 - 深入根本原因