> 本文作者:丁辉 # Ingress流量问题排查指南 ## 排查流程图 ```text 流量异常 → 云监控确认 → 定位异常IP → 分析请求路径 → 检查User-Agent → 判断问题类型 → 制定解决方案 ``` ## 核心排查命令集共 ### 1. 快速定位问题范围 - 查看最近1小时最活跃的客户端IP ```bash kubectl logs --since=1h | awk '{print $1}' | sort | uniq -c | sort -nr | head -10 ``` - 查看最近1小时最频繁的请求路径 ```bash kubectl logs --since=1h | awk '{print $7}' | sort | uniq -c | sort -nr | head -10 ``` ### 2. 深入分析特定IP行为 - 查看特定IP的详细访问记录 ```bash kubectl logs --since=1h | grep '可疑IP' ``` - 分析特定IP的User-Agent ```bash kubectl logs --since=1h | grep '可疑IP' | awk -F'"' '{print $6}' | sort | uniq ``` - 查看特定IP访问的路径分布 ```bash kubectl logs --since=1h | grep '可疑IP' | awk '{print $7}' | sort | uniq -c | sort -nr ``` ### 3. 分析特定接口/路径 - 查看特定接口的访问详情 ```bash kubectl logs --since=1h | grep "接口路径" | head -20 ``` - 统计接口的响应状态码分布 ```bash kubectl logs --since=1h | grep "接口路径" | awk '{print $9}' | sort | uniq -c ``` ### 4. 实时监控 - 实时查看Ingress访问日志 ```bash kubectl logs -f ``` - 实时查看特定服务的日志 ```bash kubectl logs -f <后端服务pod> ``` ## 日志字段解析指南 **关键字段说明:** - `$1` - 客户端IP地址 - `$7` - 请求路径和参数 - `$9` - HTTP状态码 - 引号内第6个字段 - User-Agent - 倒数第6个字段 - 请求处理时间(秒) - 方括号内字段 - 转发的K8s服务 ## 常见问题模式识别 ### 1. 爬虫/自动化脚本特征 - 单一IP高频访问 - User-Agent包含`bot`、`crawler`、`python`、`go`等 - 规律的请求间隔 ### 2. API滥用特征 - 针对特定API接口的高频调用 - 异常的POST/PUT请求模式 - 大量4xx状态码 ### 3. 性能问题特征 - 请求处理时间普遍较长(>5秒) - 大量5xx状态码 - 特定的慢接口 ### 4. 安全威胁特征 - 扫描行为(访问不存在的路径) - 注入攻击特征(SQL、XSS等) - 暴力破解(大量登录尝试) ## 解决方案工具箱 ### 1. 紧急限流措施 ```yaml # =============================================== # 🧱 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 状态码。 # 通常设置为 429(Too Many Requests)或 503(Service 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封禁 ```yaml # =============================================== # 🧱 NGINX Ingress Controller IP 封禁与访问控制配置 # 通过 ConfigMap 对客户端 IP 进行白名单、黑名单或基于地理位置的控制。 # =============================================== apiVersion: v1 kind: ConfigMap metadata: name: nginx-config namespace: ingress-nginx data: # 🔒 全局访问控制(白名单/黑名单) # allow-snippet 使用原生 NGINX 语法控制访问: # - allow :允许访问 # - deny all:拒绝所有其他访问 # ⚙️ 使用场景: # - 内网服务只允许特定网段访问 allow-snippet: | allow 192.168.0.0/16; allow 10.0.0.0/8; deny all; ``` ### 3. 优化配置 ```yaml 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. 安全加固配置 ```yaml 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. 日志与监控配置 ```yaml apiVersion: v1 kind: ConfigMap metadata: name: nginx-config namespace: ingress-nginx data: # 📝 自定义日志格式(上游代理请求日志) # 用于记录更多有用的调试信息,如:客户端地址、上游地址、请求时间、响应时间等。 # ⚠️ 生效条件:确保使用的 ingress‑nginx 版本支持 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" # 📋 提示: # - 修改后需要滚动重启 ingress‑nginx 控制器 Pod:kubectl rollout restart deployment -n ingress-nginx # - 若 log-format‑upstream 未生效,可查看 /etc/nginx/nginx.conf 中是否包含你的自定义格式。 # - 若 enable‑access‑log / access‑log‑path 无效果,请查阅当前版本支持的键列表或用 `access-log-off`、`disable-access-log` 等键进行切换。 ``` ## 6. 高级限流策略 ### 方法 A:使用注解(推荐) ```yaml 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` 分路径的限流。 ### 方法 B:Server / Configuration Snippet ```yaml 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. 实际应用示例 ```yaml 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。 ``` ## 配验证命令 ```bash # 验证配置语法是否正确 kubectl exec -it -n ingress-nginx -- nginx -t # 重新加载配置(不中断服务) kubectl exec -it -n ingress-nginx -- nginx -s reload # 查看当前生效的配置 kubectl exec -it -n ingress-nginx -- cat /etc/nginx/nginx.conf # 实时监控限流效果 kubectl logs -f -n ingress-nginx | grep "limiting requests" ``` ## 监控和告警设置 ### 1. 关键监控指 - QPS(每秒请求数) - 错误率(4xx/5xx) - 响应时间P95/P99 - 带宽使用率 ### 2. 告警阈值建议 ```bash # 异常流量检测规则示例 - QPS突增 > 50% - 5xx错误率 > 5% - 平均响应时间 > 3s - 单一IP请求占比 > 20% ``` ## 💡 经验总结 ### 快速诊断清单: 1. ✅ 先看IP分布 - 找到异常源头 2. ✅ 再看请求路径 - 定位问题接口 3. ✅ 分析User-Agent - 判断请求性质 4. ✅ 检查响应时间和状态码 - 确认影响范围 5. ✅ 关联后端服务日志 - 深入根本原因