本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。

介绍 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 发送的结果都将显示在“事件”部分,这比阅读原始 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 可能很痛苦,尤其是在 Pod 和容器是短暂的、IP 频繁变化的 Kubernetes 世界中。这个过程涉及我们工程师大量的手动命令。此外,由于大量丢弃,iptables 日志可能会很嘈杂,如果 IP 地址被重复使用,应用所有者甚至可能拥有过时的数据。有了 kube-iptables-tailer 的帮助,我们开发人员的生活现在变得轻松多了。如下图所示,这项服务的原理可以分为三个步骤: kube-iptables-tailer 的序列图

* kube-iptables-tailer 的序列图

1. 监控 iptables 日志文件变化

我们现在使用 kube-iptables-tailer 帮助识别 iptables 日志文件中的变化,而不是要求人工工程师手动解读原始 iptables 日志。我们将该服务作为 DaemonSet 运行在集群中的每个主机节点上,并定期跟踪 iptables 日志文件。服务本身是用 Go 编写的,它有多个 goroutine 用于同时运行的不同服务组件。我们使用通道在这些不同的组件之间共享信息。例如,在此步骤中,服务将把在 iptables 日志文件中检测到的任何更改发送到 Go 通道,以便稍后进行解析。

2. 根据日志前缀解析 iptables 日志

一旦解析器通过特定的 Go 通道接收到新的日志消息,它将首先通过解析日志前缀来检查日志消息是否包含任何与网络策略相关的数据包丢弃信息。基于我们的 Calico 策略的数据包丢弃将记录为在 iptables 日志文件中包含“calico-drop:”作为日志前缀。在这种情况下,解析器将创建一个对象,其中日志消息中的数据作为对象的字段存储。这些方便的对象稍后将用于定位 Kubernetes 中运行的相关 Pod 并直接向它们发布通知。解析器还能够识别重复日志并对其进行过滤,以避免造成混淆和消耗额外的资源。在解析过程之后,kube-iptables-tailer 将进入发送结果的最后一步。

3. 定位 Pod 并发送事件

利用 Kubernetes API,kube-iptables-tailer 将通过匹配上一步解析出的对象中存储的 IP,尝试定位集群中的发送方和接收方。如果成功定位,一个事件将被发布到这些受影响的 Pod。Kubernetes 事件是旨在提供有关 Kubernetes 组件内部发生情况信息的对象。在 Box,Kubernetes 事件的一个用例是直接向相应的应用程序报告错误(更多详情,请参阅这篇博客文章)。由 kube-iptables-tailer 生成的事件包含有用的信息,例如流量方向、IP 地址以及另一侧 Pod 的命名空间。我们还添加了 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 ParmarGreg LyonsShrenik Dedhia 对该项目的贡献。