【摘要】Kubernetes 中的应用出了问题, 往往需要进行网络抓包分析. 本文介绍了在Kubernetes 中网络调试分析的4种方法。

【作者】崔凯东

前言

在当今世界,分布式系统,微服务/SOA架构遍地,服务之间的许多交互和通信都不再是同一主机的不同线程或进程,而是跨主机,甚至跨网络区域。那么一旦相关服务出现问题,我们就会需要调试服务间的通讯、主机间的网络……

流量数据分析公式 流量分析方法_restful

Kubernetes 中的应用出了问题,往往需要进行网络抓包分析。本文介绍了在 Kubernetes 中网络调试分析的4种方法。

1、使用 sidecar

2、使用 netshoot - 一个 Docker + Kubernetes网络故障排除的瑞士军刀容器

3、利用Network Namespace

4、使用 kubectl 插件 - ksniff

方法一:使用 Sidecar

Sidecar应用范围不仅仅止于此,比如:APM监控的agent就可以通过这种方式来挂载。

Sidecar 前来救援!

在过去的几个月里,我尝试了各种方法来克服这个问题,最终形成了我将在本文中概述的方法。它是捕获Kubernetes/OpenShift pods之间的网络流量数据的简单方法,允许开发人员更好地分析和调试容器化应用程序中的通信问题,并更快、更有效地解决问题。

我们将使用tcpdump捕获一个所谓的PCAP(packet capture)文件,该文件将包含pod的网络流量。然后可以将这个PCAP文件加载到Wireshark之类的工具中来分析流量,在本例中,分析在pod中运行的服务的RESTful通信。在本文中,我将使用Red Hat Process Automation Manager产品的KIE服务器(执行服务器)作为示例,但是这种方法应该适用于任何类型的容器化应用程序。

要克服的第一个问题是Kubernetes pod中tcpdump命令的可用性。KIE服务器容器映像没有安装tcpdump。其次,容器不提供从Red Hat存储库安装tcpdump的实用程序。为了克服这个问题,我们使用了“sidecar容器”的概念。

Sidecar 概念

sidecar容器是与实际服务/应用程序运行在相同pod中的容器,能够为服务/应用程序提供附加功能。sidecar容器的一个例子是Istio的Envoy sidecar,它使pod成为服务网格的一部分。在本例中,我们将部署一个sidecar容器,该容器提供tcpdump实用程序。由于pod中的多个容器共享相同的网络层,所以我们可以使用sidecar来捕获进出KIE服务器的网络流量。

部署 Sidecar

在这个例子中,我部署了 Red Hat Process Automation Manager 7 Mortgage Demo ,它将在我的OpenShift namespace中创建两个pod。一个pod运行Business Central workbench,另一个pod是执行服务器的pod。这两个组件之间的通信是通过REST完成的,这是我们将要捕获的流量。

流量数据分析公式 流量分析方法_k8s_02

我们的目标是捕获KIE服务器pod上的网络流量,以便分析Business Central workbench 发送给KIE服务器的RESTful命令。要做到这一点,我们首先需要附加(attach)一个 sidecar 到KIE服务器的pod.

1、在Overview页面中,单击要分析的pod的名称。这将打开_部署配置(Deployment Config, 简称DC)_页面。

2、在_部署配置_屏幕的右上角,单击Actions -> Edit YAML。这将打开DC 的YAML配置。

流量数据分析公式 流量分析方法_k8s_03

3、向下滚动,直到看到单词 containers 。我们将添加一个额外的容器,安装了tcpdump的sidecar到pod中。直接在 containers 定义下添加以下YAML片段:

流量数据分析公式 流量分析方法_流量数据分析公式_04


流量数据分析公式 流量分析方法_k8s_05

4、保存配置。这将部署一个新的pod,它现在由两个容器组成:一个容器包含KIE服务器,另一个容器包含我们的tcpdump工具,它将无限期地持续运行。

捕获和分析流量

随着sidecar的部署和运行,我们现在可以开始捕获数据了。我尝试的方法之一是使用oc rsh命令远程执行sidecar中的tcpdump命令,将网络数据流输出到FIFO文件,并将数据直接导入Wireshark。由于各种原因,这种方法失败了。其中一个问题是,tcpdump向stderr发送信息消息,但是这些消息与stdout在相同的流中, 并且是通过SSH接收,从而破坏了进入Wireshark的数据。

我最后使用的方法是登录到sidecar容器,并在sidecar中运行tcpdump命令来创建PCAP文件。当您捕获了足够的数据后,就可以停止捕获过程并将PCAP文件复制到您希望使用Wireshark进行网络流量分析的机器上。具体步骤如下:

1、在您的开发机器上,用oc 客户端连接到OpenShift实例,并激活正确的项目(project, 即namespace),运行oc get pods命令来列出您的pods:

流量数据分析公式 流量分析方法_python_06

2、使用以下命令登录到我们的KIE服务器pod的tcpdump容器中:oc rsh -c tcpdump rhpam7-mortgage-kieserver-2-zcpsn

3、在tcpdump容器中,运行此命令以启动网络流量捕获过程: tcpdump -s 0 -n -w /tmp/kieserver.pcap

4、运行要分析的网络流量的测试。在本例中,我将从Business Central workbench中启动一个业务流程,它将向KIE服务器发送一个RESTful请求。

5、捕获足够的数据后,在tcpdump容器中使用Ctrl+C完成捕获过程。

6、回到本地机器。将PCAP文件从pod复制到本地机器: oc cp -c tcpdump rhpam7-mortgage-kieserver-2-zcpsn:tmp/kieserver.pcap kieserver.pcap

7、用Wireshark打开PCAP文件并分析网络流量。在这个例子中,我正在分析我的HTTP POST方法,它创建了Mortgage 进程的一个新实例:

流量数据分析公式 流量分析方法_python_07

总结

在容器环境(如Kubernetes和/或OpenShift)中分析pod之间的网络通信可能比在非容器环境中更困难一些。然而,sidecar容器的概念为开发人员提供了一种简单的工具,可以将容器连同所需的开发工具和实用程序附加到微服务pod上。 这避免了开发人员必须在应用程序容器映像本身中安装这些调试工具,从而保持容器的轻便和干净。 使用像 oc rsh 和 oc cp 这样的OpenShift工具,我展示了如何轻松地从pod捕获网络流量数据并将数据带到开发机器进行分析。

方法二:使用 netshoot

Netshoot - Docker + Kubernetes网络故障排除的瑞士军刀容器

流量数据分析公式 流量分析方法_流量数据分析公式_08

用途

Docker和Kubernetes网络故障排除变得复杂。通过正确理解Docker和Kubernetes网络的工作方式和正确的工具集,您可以排除故障并解决这些网络问题。netshoot容器有一组强大的网络troubleshoot工具,可以用来排除Docker网络问题。与这些工具一起出现的还有一组用例,展示了如何在真实场景中使用这个容器。

Network Namespaces - 网络名称空间

在开始使用这个工具之前,有一点很重要:网络名称空间。网络名称空间提供与网络相关的系统资源的隔离。Docker使用网络和其他类型的名称空间(pid、mount、user…)为每个容器创建一个隔离的环境。从接口、路由到ip的所有内容都完全隔离在容器的网络名称空间中。

Kubernetes也使用网络名称空间。Kubelets为每个pod创建一个网络名称空间,其中该pod中的所有容器共享相同的网络名称空间(eths、IP、tcp套接字……)。这是Docker容器和Kubernetes pod之间的关键区别。

名称空间很酷的一点是您可以在它们之间进行切换。您可以输入不同容器的网络名称空间,使用甚至没有安装在该容器上的工具在其网络堆栈上执行一些故障排除。此外,netshoot可以通过使用主机的网络名称空间来对主机本身进行故障排除。这允许您在不直接在主机或应用程序包上安装任何新包的情况下执行任何故障排除。

针对容器的用法

  • 容器的网络名称空间:如果您的应用程序的容器存在网络问题,您可以像这样使用容器的网络名称空间启动netshoot: $ docker run
    -it --net container: nicolaka/netshoot
  • 主机的网络名称空间:如果您认为网络问题在于主机本身,那么可以使用该主机的网络名称空间启动netshoot。命令: $ docker run
    -it --net host nicolaka/netshoot
  • 网络的网络名称空间:如果要对Docker网络进行故障排除,可以使用nsenter输入网络的名称空间。这将在下面的nsenter部分进行解释。

针对 Kubernetes 的用法

流量数据分析公式 流量分析方法_restful_09

网络问题

许多网络问题可能导致应用程序性能下降。其中一些问题可能与底层网络基础设施有关。其他问题可能与主机或Docker级别的配置错误有关。让我们来看看常见的网络问题:

  • 延迟(latency)
  • 路由(routing)
  • DNS解析(DNS resolution)
  • 防火墙(firewall)
  • 不完整的ARP(incomplete ARPs)

为了解决这些问题,netshoot包含了一组强大的工具,如图所示。

流量数据分析公式 流量分析方法_python_10

被包含的包

流量数据分析公式 流量分析方法_容器_11

方法三:利用Network Namespace

正如方法二中提到的Network Namespace概念,实际上,不同的容器,只是在宿主机上不同 namespace 运行的进程而已。因此要在不同的容器抓包可以简单地使用命令切换 network namespace 即可,可以使用在宿主机上的 tcpdump 等应用进行抓包。

流量数据分析公式 流量分析方法_容器_12

具体操作步骤如下:

1、查看指定 pod 运行在哪个宿主机上: kubctl describe pod -n mservice

2、获得容器的 pid: docker inspect -f {{.State.Pid}}

3、进入该容器的 network namespace: nsenter --target -n

4、使用宿主机的tcpdump 抓包, 指定 eth0 网卡: tcpdump -i eth0 tcp and port 80 -vvv

5、或者直接抓包并导出到文件: tcpdump -i eth0 -w /tmp/out.cap

6、从远程 scp 到本地: scp ipaddr:/tmp/out.cap ./

7、之后在 Wireshark 中可以打开文件非常直观得查看过滤抓到的数据。

方法四:使用 kubectl 插件ksniff

流量数据分析公式 流量分析方法_restful_13

题外话:krew - kubectl 插件包管理器

流量数据分析公式 流量分析方法_restful_14

Krew是kubectl插件的包管理器。(后续会使用krew来安装 ksniff , 方便很多)

什么是 krew?

krew是一个使kubectl插件易于使用的工具。krew可以帮助发现插件,并在机器上安装和管理它们。类似于apt、dnf或brew等工具。

krew 易于使用:

流量数据分析公式 流量分析方法_k8s_15

查看在krew上可用的kubectl插件列表,或者运行kubectl krew search来发现可用的插件。

安装 krew

Bash 和 ZSH:

1、确保git 已安装;

2、运行如下命令, 下载并安装krew

流量数据分析公式 流量分析方法_python_16

3、添加 流量数据分析公式 流量分析方法_k8s_17{KREW_ROOT:-KaTeX parse error: Expected 'EOF', got '}' at position 11: HOME/.krew}̲/bin:PATH" 并重启下shell生效。

安装ksniff

通过 krew : kubectl krew install sniff

使用方法

kubectl < 1.12:
kubectl plugin sniff <POD_NAME> [-n <NAMESPACE_NAME>] [-c <CONTAINER_NAME>] [-i <INTERFACE_NAME>] [-f <CAPTURE_FILTER>] [-o OUTPUT_FILE] [-l LOCAL_TCPDUMP_FILE] [-r REMOTE_TCPDUMP_FILE]

kubectl >= 1.12:
kubectl sniff <POD_NAME> [-n <NAMESPACE_NAME>] [-c <CONTAINER_NAME>] [-i <INTERFACE_NAME>] [-f <CAPTURE_FILTER>] [-o OUTPUT_FILE] [-l LOCAL_TCPDUMP_FILE] [-r REMOTE_TCPDUMP_FILE]

POD_NAME: Required. the name of the kubernetes pod to start capture it's traffic.
NAMESPACE_NAME: Optional. Namespace name. used to specify the target namespace to operate on.
CONTAINER_NAME: Optional. If omitted, the first container in the pod will be chosen.
INTERFACE_NAME: Optional. Pod Interface to capture from. If omited, all Pod interfaces will be captured.
CAPTURE_FILTER: Optional. specify a specific tcpdump capture filter. If omitted no filter will be used.
OUTPUT_FILE: Optional. if specified, ksniff will redirect tcpdump output to local file instead of wireshark.
LOCAL_TCPDUMP_FILE: Optional. if specified, ksniff will use this path as the local path of the static tcpdump binary.
REMOTE_TCPDUMP_FILE: Optional. if specified, ksniff will use the specified path as the remote path to upload static tcpdump to.

举例:
kubectl sniff mypod -n myproject -o /tmp/mypod.pcap

总结

为了在容器或K8S中进行网络调试和分析,本文列举了4种方法,现在进行总结归纳:

1、使用 sidecar - sidecar 容器所在的pod中的多个容器共享相同的网络层,且sidecar容器可以包含tcpdump等工具;

2、利用Network Namespace - 不同的容器,**只是在宿主机上不同 namespace 运行的进程而已。**容器的网络也是如此。

3、使用netshoot - netshoot 其实是包含一系列的常用网络分析调试工具集的容器,真正的使用方法其实还是以上2种:

1)通过 sidecar挂载

2)利用Network Namespace分析调试

4、使用 kubectl 插件 - ksniff,个人猜想,这个只是一个通过 kubectl 插件的封装,底层原理应该还是 Network Namespace.

以上这些方法,有不同的前提条件和使用场景,希望本文读完会让你的K8S调试技能有所提升。