K8s网络连接拒绝监控与排查实战指南
1. 为什么需要关注K8s中被拒绝的网络连接?
在Kubernetes集群中,网络连接被拒绝的情况每天都在发生。这些被拦截的流量可能包含重要安全事件的前兆信号——比如未授权的服务发现尝试、横向移动攻击或异常的API调用。去年我们生产环境就遇到过这类情况:某个微服务突然开始频繁连接其他命名空间的数据库,正是防火墙日志帮我们及时发现了被入侵的Pod。
网络策略(NetworkPolicy)作为K8s原生的防火墙机制,默认采用白名单模式。任何不符合规则的连接都会被静默丢弃,这种"静默拒绝"特性使得排查问题变得困难。想象一下开发人员报告"服务A无法访问服务B"时,如果你连基本的拒绝记录都拿不出来,故障排查就会变成一场噩梦。
2. 关键日志来源全景分析
2.1 网络插件层面的日志宝藏
不同CNI插件的日志位置和格式差异很大。以Calico为例,其Felix组件会在各个节点生成包含详细拦截记录的日志:
# 查看Calico的拒绝连接日志 journalctl -u calico-felix --no-pager | grep "Dropped packet"典型日志条目如下:
2023-08-20 09:15:23.123 [WARNING][1234] felix/int_dataplane.go 1024: Dropped packet, src_ip=10.244.1.5, dst_ip=10.244.2.8, proto=TCP, src_port=54321, dst_port=6379, policy_namespace=default, policy_name=redis-access关键字段解析:
src_ip/dst_ip:显示通信双方的Pod IPproto/ports:协议和端口信息policy_namespace/name:触发拒绝的网络策略名称
注意:Calico默认日志级别可能不记录所有丢弃事件,需要通过FelixConfiguration调整日志级别:
apiVersion: operator.tigera.io/v1 kind: LogSeverity metadata: name: cluster-wide spec: severity: Info
2.2 内核防火墙的原始视角
当使用iptables模式时,可以直接查询Linux内核的防火墙日志。首先确保启用日志记录:
# 在每台节点上执行 sudo iptables -I INPUT -j LOG --log-prefix "[IPTABLES-DENY] " sudo iptables -I FORWARD -j LOG --log-prefix "[IPTABLES-DENY] "日志会出现在系统日志中,通过以下命令查看:
dmesg | grep "IPTABLES-DENY"典型输出示例:
[IPTABLES-DENY] IN=cali1234 OUT= MAC=... SRC=10.244.1.5 DST=10.244.2.8 LEN=60 TOS=0x00 PREC=0x00 TTL=63 ID=54321 PROTO=TCP SPT=41892 DPT=6379 WINDOW=64860 RES=0x00 SYN URGP=02.3 K8s审计日志的补充价值
虽然审计日志(Audit Log)主要记录API Server活动,但它能捕获NetworkPolicy的变更事件。当突然出现大量拒绝连接时,可以交叉检查是否有策略被意外修改:
kubectl logs -n kube-system kube-apiserver-node1 | grep networkpolicies.networking.k8s.io3. 实战:构建拒绝连接监控体系
3.1 日志收集架构设计
推荐采用以下架构实现全集群覆盖:
Pod -> CNI日志 -> Fluentd -> Elasticsearch -> Kibana -> iptables日志 ->配置示例(Fluentd部分):
<source> @type tail path /var/log/calico/felix.log tag calico.deny format /(?<logtime>[^ ]* [^ ]*) \[(?<loglevel>[^\]]*)\]\[(?<thread>[^\]]*)\] (?<file>[^ ]*) (?<line>\d+): Dropped packet, src_ip=(?<src_ip>[^,]*), dst_ip=(?<dst_ip>[^,]*), proto=(?<proto>[^,]*), src_port=(?<src_port>[^,]*), dst_port=(?<dst_port>[^,]*), policy_namespace=(?<policy_ns>[^,]*), policy_name=(?<policy_name>[^ ]*)/ </source>3.2 关键监控指标定义
建议监控这些核心指标:
- 拒绝连接速率:单位时间内被拒连接数
- 高频拒绝来源:统计源IP排名
- 热点目标端口:被拒连接的目标端口分布
- 策略拦截排行:触发拒绝最多的网络策略
对应的PromQL示例:
# 按命名空间统计拒绝次数 sum by (policy_ns) (rate(calico_denied_packets[5m])) # 检测突发性拒绝激增 deriv(calico_denied_packets[1h]) > 1003.3 告警规则最佳实践
根据严重程度分级告警:
- 紧急:关键业务服务被持续拒绝(如数据库端口)
- 重要:来自非信任命名空间的连接尝试
- 警告:新部署服务首次出现拒绝
Alertmanager配置片段:
- name: network-denial-alerts rules: - alert: CriticalServiceDenied expr: sum by (dst_port) (rate(calico_denied_packets{dst_port=~"6379|5432|3306"}[5m])) > 10 for: 10m labels: severity: critical annotations: summary: "Critical database port {{ $labels.dst_port }} denied"4. 高级排查技巧与案例分析
4.1 真实问题诊断流程
案例现象:订单服务突然无法访问支付服务
确认基础连通性:
kubectl exec -it order-service-pod -- curl -v http://payment-service:8080检查网络策略:
kubectl get networkpolicy -n payment kubectl describe networkpolicy payment-access -n payment查询实时拒绝日志:
# 在支付服务所在节点执行 sudo tcpdump -i cali+ host 10.244.3.5 and port 8080策略模拟测试: 使用
calicoctl的模拟工具:calicoctl policy-tracer -n payment --src order-service --dst payment-service --port 8080
4.2 性能优化注意事项
当日志量过大时需要注意:
- 在Felix配置中启用日志采样:
apiVersion: projectcalico.org/v3 kind: FelixConfiguration metadata: name: default spec: logSeverityScreen: Info logDropAction: Log logDropInterval: 5s - 对iptables日志添加速率限制:
sudo iptables -A INPUT -m limit --limit 10/min -j LOG
4.3 安全事件关联分析
将拒绝日志与安全工具集成:
- 在Falco中创建规则检测可疑拒绝模式:
- rule: "Unexpected Database Connection Attempt" desc: "Pod trying to connect to database port without label" condition: > k8s.pod.name != "" and jevt.value[/proto] = "TCP" and jevt.value[/dst_port] in ("3306", "5432", "6379") and not k8s.pod.label.dbclient = "true" output: > Unauthorized DB access attempt from %k8s.pod.name to port %jevt.value[/dst_port] priority: WARNING- 与SIEM系统集成,将拒绝事件与登录日志关联分析
5. 工具链推荐与配置模板
5.1 可视化看板配置
Grafana看板JSON模板核心部分:
{ "panels": [ { "title": "Top Denied Sources", "type": "table", "targets": [{ "expr": "topk(10, sum by (src_ip) (rate(calico_denied_packets[1h])))", "legendFormat": "{{src_ip}}" }] }, { "title": "Denial Trend", "type": "graph", "targets": [{ "expr": "sum by (policy_name) (rate(calico_denied_packets[5m]))", "legendFormat": "{{policy_name}}" }] } ] }5.2 命令行诊断工具包
常用命令速查表:
| 场景 | 命令 |
|---|---|
| 实时监控拒绝 | `watch -n 1 'kubectl logs -n kube-system -l k8s-app=calico-node |
| 策略影响评估 | calicoctl policy-tracer --namespace demo --src frontend --dst backend --port 8080 |
| 历史日志分析 | `journalctl -u calico-felix --since "1 hour ago" |
| 网络拓扑检查 | calicoctl get hep -o wide |
5.3 策略调试工作流
- 创建临时放行策略:
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: temp-allow-debug namespace: problematic-ns spec: podSelector: {} ingress: - from: - podSelector: {} ports: - protocol: TCP port: 8080- 逐步收紧策略时检查连通性:
while kubectl apply -f stricter-policy.yaml; do kubectl exec test-pod -- curl -I http://target-service:8080 sleep 2 done- 最终策略确认后删除临时策略:
kubectl delete networkpolicy temp-allow-debug -n problematic-ns在实施网络策略时,我习惯先设置deny-all作为安全基线,然后像剥洋葱一样逐层添加允许规则。每次变更后,通过自动化测试验证关键业务流不受影响。记住,好的防火墙策略应该像瑞士奶酪——有严格控制的孔洞,而不是完全封闭或完全开放。