这篇文章已发布超过一年。较旧的文章可能包含过时的内容。请检查页面上的信息自发布以来是否已变得不正确。

引入 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 也从在裸机主机和 VM 上运行的服务发送和接收流量。此外,还实现了指数退避,以避免 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 LyonsShrenik Dedhia 为该项目做出的贡献。