本文发布时间超过一年。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否仍然正确。
介绍 kube-iptables-tailer:提升 Kubernetes 集群的网络可见性
在 Box,我们使用 Kubernetes 赋能我们的工程师掌控微服务的整个生命周期。在网络方面,我们的工程师使用 Tigera 的 Project Calico 来声明式地管理运行在我们 Kubernetes 集群中的应用的各种网络策略。应用所有者定义一个 Calico 策略以使其 Pod 能够发送/接收网络流量,该策略被实例化为 iptables 规则。
然而,有时网络策略可能会缺失或被应用所有者错误地声明。在这种情况下,iptables 规则会导致受影响的 Pod 之间的网络数据包丢失,这些丢失被记录在一个应用所有者无法访问的文件中。我们需要一种机制,能够根据网络策略无缝地传递有关这些 iptables 数据包丢失的警报,以帮助应用所有者快速诊断相应的问题。为了解决这个问题,我们开发了一个名为 kube-iptables-tailer 的服务,用于从 iptables 日志中检测数据包丢失并将其报告为 Kubernetes 事件。我们很荣幸能够开源 kube-iptables-tailer,供您在自己的集群中使用,无论您是否使用 Calico 或其他网络策略工具。
改进的应用所有者体验
应用所有者无需进行任何额外更改即可使用 kube-iptables-tailer。他们只需运行 kubectl describe pods
来检查他们的任何 Pod 的流量是否因 iptables 规则而丢失。所有从 kube-iptables-tailer 发送的结果将显示在 *Events* 部分下,相比于阅读原始 iptables 日志,这为开发者提供了更好的体验。
$ kubectl describe pods --namespace=YOUR_NAMESPACE
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning PacketDrop 5s kube-iptables-tailer Packet dropped when receiving traffic from example-service-2 (IP: 22.222.22.222).
Warning PacketDrop 10m kube-iptables-tailer Packet dropped when sending traffic to example-service-1 (IP: 11.111.11.111).
* 从 kube-iptables-tailer 发送到有网络问题的 Kubernetes Pod 的事件输出
kube-iptables-tailer 的原理流程
在我们拥有 kube-iptables-tailer 之前,Box 的工程师获取与其网络策略相关的数据包丢失信息的唯一方法是解析原始 iptables 日志并匹配其服务 IP。这是一种欠佳的体验,因为 iptables 日志仅包含基本的 IP 地址信息。将这些 IP 映射到特定的 Pod 可能很痛苦,尤其是在 Kubernetes 世界中,Pod 和容器是短暂的,并且 IP 经常变化。这个过程涉及许多手动命令。此外,iptables 日志可能因为许多丢失而很嘈杂,并且如果 IP 地址被重复使用,应用所有者甚至可能获得一些过时的数据。借助 kube-iptables-tailer,现在开发人员的工作变得轻松多了。如下图所示,该服务的原理可分为三个步骤:
* kube-iptables-tailer 序列图
1. 监控 iptables 日志文件变化
不再需要人工工程师手动解析原始 iptables 日志,我们现在使用 kube-iptables-tailer 帮助识别该文件中的变化。我们将该服务作为 **DaemonSet** 运行在集群中的每个主机节点上,并定期追踪 iptables 日志文件。服务本身是用 Go 编写的,它有多个 Goroutine 并发运行不同的服务组件。我们使用通道 (channel) 在各个组件之间共享信息。例如,在这一步,服务会将检测到的 iptables 日志文件中的任何变化发送到 Go 通道以供后续解析。
2. 根据日志前缀解析 iptables 日志
一旦解析器通过特定的 Go 通道接收到新的日志消息,它将首先通过解析日志前缀检查日志消息是否包含任何与网络策略相关的数据包丢失信息。基于我们的 Calico 策略的数据包丢失将以“calico-drop:”作为日志前缀记录在 iptables 日志文件中。在这种情况下,解析器将创建一个对象,并将日志消息中的数据存储为对象的字段。这些方便的对象稍后将用于定位在 Kubernetes 中运行的相关 Pod,并直接向它们发布通知。解析器还能够识别重复日志并进行过滤,以避免造成混淆和消耗额外资源。解析过程完成后,将进入 kube-iptables-tailer 发送结果的最后一步。
3. 定位 Pod 并发送事件
使用 Kubernetes API,kube-iptables-tailer 将尝试通过匹配上一步解析对象中存储的 IP 来定位集群中的发送方和接收方。如果成功定位,结果是将一个事件发布到这些受影响的 Pod。Kubernetes 事件是设计用于提供 Kubernetes 组件内部发生的事情的信息的对象。在 Box,Kubernetes 事件的一个用例是将错误直接报告给相应的应用程序(详情请参考这篇博客文章)。kube-iptables-tailer 生成的事件包含有用的信息,例如流量方向、IP 以及对端 Pod 的 Namespace。我们还添加了 DNS 查询,因为我们的 Pod 也与裸金属主机和虚拟机上运行的服务发送和接收流量。此外,还实现了指数退避以避免使 Kubernetes API 服务器过载。
总结
在 Box,kube-iptables-tailer 为许多不同团队的开发人员节省了时间,也让他们更轻松。不再对基于网络策略的数据包丢失一无所知,该服务能够帮助检测 iptables 日志文件中的变化,并将相应的信息直接传递给 Kubernetes 集群内的 Pod。如果您没有使用 Calico,您仍然可以使用任何其他日志前缀(在服务中配置为环境变量)来匹配您的 iptables 规则中定义的任何内容,并获取与网络策略相关的数据包丢失通知。您可能还会发现其他情况,通过 Kubernetes API 将主机系统的信息提供给 Pod 是很有用的。作为一个开源项目,非常欢迎任何贡献来共同改进项目。您可以在 Github 上找到该项目:https://github.com/box/kube-iptables-tailer
特别感谢 Kunal Parmar、Greg Lyons 和 Shrenik Dedhia 对本项目的贡献。