486 lines
16 KiB
Markdown
486 lines
16 KiB
Markdown
> 本文作者:丁辉
|
||
|
||
# Ingress流量问题排查指南
|
||
|
||
## 排查流程图
|
||
|
||
```text
|
||
流量异常 → 云监控确认 → 定位异常IP → 分析请求路径 → 检查User-Agent → 判断问题类型 → 制定解决方案
|
||
```
|
||
|
||
## 核心排查命令集共
|
||
|
||
### 1. 快速定位问题范围
|
||
|
||
- 查看最近1小时最活跃的客户端IP
|
||
|
||
```bash
|
||
kubectl logs <ingress-controller-pod> --since=1h | awk '{print $1}' | sort | uniq -c | sort -nr | head -10
|
||
```
|
||
|
||
- 查看最近1小时最频繁的请求路径
|
||
|
||
```bash
|
||
kubectl logs <ingress-controller-pod> --since=1h | awk '{print $7}' | sort | uniq -c | sort -nr | head -10
|
||
```
|
||
|
||
### 2. 深入分析特定IP行为
|
||
|
||
- 查看特定IP的详细访问记录
|
||
|
||
```bash
|
||
kubectl logs <ingress-controller-pod> --since=1h | grep '可疑IP'
|
||
```
|
||
|
||
- 分析特定IP的User-Agent
|
||
|
||
```bash
|
||
kubectl logs <ingress-controller-pod> --since=1h | grep '可疑IP' | awk -F'"' '{print $6}' | sort | uniq
|
||
```
|
||
|
||
- 查看特定IP访问的路径分布
|
||
|
||
```bash
|
||
kubectl logs <ingress-controller-pod> --since=1h | grep '可疑IP' | awk '{print $7}' | sort | uniq -c | sort -nr
|
||
```
|
||
|
||
### 3. 分析特定接口/路径
|
||
|
||
- 查看特定接口的访问详情
|
||
|
||
```bash
|
||
kubectl logs <ingress-controller-pod> --since=1h | grep "接口路径" | head -20
|
||
```
|
||
|
||
- 统计接口的响应状态码分布
|
||
|
||
```bash
|
||
kubectl logs <ingress-controller-pod> --since=1h | grep "接口路径" | awk '{print $9}' | sort | uniq -c
|
||
```
|
||
|
||
### 4. 实时监控
|
||
|
||
- 实时查看Ingress访问日志
|
||
|
||
```bash
|
||
kubectl logs -f <ingress-controller-pod>
|
||
```
|
||
|
||
- 实时查看特定服务的日志
|
||
|
||
```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 <IP/CIDR>:允许访问
|
||
# - 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 <controller> -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 <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. 告警阈值建议
|
||
|
||
```bash
|
||
# 异常流量检测规则示例
|
||
- QPS突增 > 50%
|
||
- 5xx错误率 > 5%
|
||
- 平均响应时间 > 3s
|
||
- 单一IP请求占比 > 20%
|
||
```
|
||
|
||
## 💡 经验总结
|
||
|
||
### 快速诊断清单:
|
||
|
||
1. ✅ 先看IP分布 - 找到异常源头
|
||
2. ✅ 再看请求路径 - 定位问题接口
|
||
3. ✅ 分析User-Agent - 判断请求性质
|
||
4. ✅ 检查响应时间和状态码 - 确认影响范围
|
||
5. ✅ 关联后端服务日志 - 深入根本原因 |