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 IP
  • proto/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=0

2.3 K8s审计日志的补充价值

虽然审计日志(Audit Log)主要记录API Server活动,但它能捕获NetworkPolicy的变更事件。当突然出现大量拒绝连接时,可以交叉检查是否有策略被意外修改:

kubectl logs -n kube-system kube-apiserver-node1 | grep networkpolicies.networking.k8s.io

3. 实战:构建拒绝连接监控体系

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 关键监控指标定义

建议监控这些核心指标:

  1. 拒绝连接速率:单位时间内被拒连接数
  2. 高频拒绝来源:统计源IP排名
  3. 热点目标端口:被拒连接的目标端口分布
  4. 策略拦截排行:触发拒绝最多的网络策略

对应的PromQL示例:

# 按命名空间统计拒绝次数 sum by (policy_ns) (rate(calico_denied_packets[5m])) # 检测突发性拒绝激增 deriv(calico_denied_packets[1h]) > 100

3.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 真实问题诊断流程

案例现象:订单服务突然无法访问支付服务

  1. 确认基础连通性

    kubectl exec -it order-service-pod -- curl -v http://payment-service:8080
  2. 检查网络策略

    kubectl get networkpolicy -n payment kubectl describe networkpolicy payment-access -n payment
  3. 查询实时拒绝日志

    # 在支付服务所在节点执行 sudo tcpdump -i cali+ host 10.244.3.5 and port 8080
  4. 策略模拟测试: 使用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 安全事件关联分析

将拒绝日志与安全工具集成:

  1. 在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
  1. 与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 策略调试工作流

  1. 创建临时放行策略:
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
  1. 逐步收紧策略时检查连通性:
while kubectl apply -f stricter-policy.yaml; do kubectl exec test-pod -- curl -I http://target-service:8080 sleep 2 done
  1. 最终策略确认后删除临时策略:
kubectl delete networkpolicy temp-allow-debug -n problematic-ns

在实施网络策略时,我习惯先设置deny-all作为安全基线,然后像剥洋葱一样逐层添加允许规则。每次变更后,通过自动化测试验证关键业务流不受影响。记住,好的防火墙策略应该像瑞士奶酪——有严格控制的孔洞,而不是完全封闭或完全开放。