容器周边开源工具新秀:Sysdig和Calico

November 15, 2015

伴随着容器技术的普及和落地,许多围绕在容器与微服务生态圈周边的开源工具也逐渐获得社区的关注和投入。其中有许多工具的名字已经广为人知,比如服务发现工具Etcd和Consul,日志收集工具组合Elasticsearch、Logstash和Kibana,任务编排工具Fleet、Kubernetes和Mesos等。这些工具之所以出名,一方面是由于它们解决了实际生产中遇到的问题,另一方面则是由于项目主导者和参与者的大力宣传。与此相对的,在社区中同样存在着许多十分优秀但出镜率并不高的开源项目。

在今年CoreOS Fest大会接近尾声的时候,会场上出现了两个值得关注的话题,演讲者分别展示了Sysdig和Calico在CoreOS系统中的运用,这两个产品都是与容器密切相关的开源工具,它们分别补充了现有容器技术在特定功能领域方面的不足。即使是在CoreOS Fest已经过去几个月的现在看来,在Sysdig和Calico各自所处的领域内,它们都依然是无可替代的选择。本文将从安装和使用两个方面分别介绍这两个工具的使用场景。

容器监控器Sysdig

Sysdig【1】是Sysdig Cloud司开发的一款开源的系统运行信息和网络流监控软件,早先在网络上的一些文章也对它有所介绍,但几乎都只关注于它对主机的监控和管理功能。而Sysdig之所以能够出现在CoreOS Fest上,一个重要的原因,就是它在近期的版本中【2】将容器的监控纳入了其首位支持的特性。

Sysdig工具,用户能够很方便地查看到主机上所有应用程序的CPU、文I/O、网络访问状况,这个工具最初的产生就是为了取代传统服务器上的一系列系统检测工具如strace、tcpdump、htop、iftop、lsof等。它的Logo被设计为一个铲子的轮廓,寓意着Sysdig对系统信息的强大挖掘能力。


新版本的Sysdig在设计上充分运用了容器技术的成果,这主要体现在两个方面。一方面Sysdig提供了可以快速运行的Docker容器镜像,这使得用户能够很方便地在任何安装了Docker的Linux环境中快速使用它进行系统数据的收集和分析。另一方面是Sysdig专门提供了容器级别的信息采集命令,支持查看指定容器之间的网络流量、查看特定容器的CPU使用量等。

对于大多数的Linux发行版,都可以通过下面这个命令直接安装Sysdig工具。

$ curl -s https://s3.amazonaws.com/download.draios.com/stable/install-sysdig | sudo bash
或者通过以下命令 ,用 Docker快速启动一个包含有Sysdig命令的控制台【3】。

$ docker run -i -t --name sysdig --privileged -v /var/run/docker.sock:/host/var/run/docker.sock -v /dev:/host/dev -v /proc:/host/proc:ro -v /boot:/host/boot:ro -v /lib/modules:/host/lib/modules:ro -v /usr:/host/usr:ro sysdig/sysdig

安装完Sysdig后,下面介绍一下它的使用。Sysdig令的默认作用域是整个主机,用户需要通过container.name”参数将作用域限定为指定容器,我们将重点讨论这种情况的应用场景。

首先运行一交互模式的Ubuntu容器,命名为ubuntu01,它将作为被监控的容器

$ docker run -it --rm --name ubuntu01 ubuntu /bin/bash

在接下来的所有命令中,都会使用“container.name=ubuntu01”参数,这样就将监控的作用域限定在这个容器相关的系统资源上。

不加其他参数sysdig命令的作用相当于tcpdump,它将打印出指定容器中所有的网络数据到控制台上,可以使用-w将捕获的数据写入指定的文件中。保存的抓包文件除了通过专用软件如wireshark进行分析,也可以直接用sysdig的-r参数读取出来再打印到控制台。

$ sysdig container.name=ubuntu01
默认情况下,这个命令的 输出显示的是容器中运行的进程在主机上的实际 PID号。使用-p参数可以改变输 出内容的格式,给命令加上 -pcontainer参数(可简写 -pc),就 会额外打印出进程所处的容器名称,以及在容器中的 PID信息。

此外,使用-c参数可以指定监控的操作类型,Sysdig提供了几十种客供查看和监控的系统数据。包括CPU使用率、文件I/O、网络流量、系统错误、系统日志、性能瓶颈甚至监控指定用户的行为。例如,在Sysdig的Shell输入:

$ sysdig -pc -c topprocs_cpu container.name=ubuntu01
Sysdig将显示属于ubuntu01容器中的所有进程的CPU使用情况,并以CPU使用率排序。显示内容举例如下:

CPU%  Process  Host_pid  Container_pid  container.name

--------------------------------------------------------------------------------

0.00%  bash  3997  1  ubuntu01

此时如果在ubuntu01容器中开始“apt-getupdate”的操作,同时在Sysdig的Shell输入:

$ sysdig -pc -c topprocs_net container.name=ubuntu01

就能够看到容器中所有进程的网络使用情况了。显示内容举例如下:

Bytes  Process  Host_pid  Container_pid  container.name

--------------------------------------------------------------------------------

62.58KB  http  4491  22  ubuntu01

Sysdig还支持一些复杂的数据过滤操作,例如下面这个命令能够监控ubuntu01容器中所有由cat进程发起的“open”系统调用。

$ sysdig -pc proc.name=cat and evt.type=open and container.name=ubuntu01
在Sysdig提供的 命令中,有个十分有趣的“ spy_ users ”功能,可以实时监控指定容器的用户输入内 容。例如,在 Sysdig的Shell输入以下命令:

$ sysdig -pc -c spy_users container.name=ubuntu01

回到ubuntu01容器中,执行一个“ ls —color=auto”命令,然后就会看到刚刚输入命令实时的回显在了Sysdig的Shell里面。显示内容举例如下:

3997 11:30:19 root@ubuntu01) ls --color=auto

这些示例仅仅是展示了Sysdig能力的冰山一角,在目前的其他系统监控类工具中,笔者还没有看到像Sysdig这样功能如此强大、而又对容器支持这样好的。所以,对于经常使用容器作为产品运行方式的用户,这是一款值得深入了解的“故障排查神器”。

容器级防火墙Calico

在传统的服务应用架构设计中,通常会将各种服务模块按照功能类型进行分层,例如Web应用服务、核心业务服务、数据库服务等,在层与层之间通过防火墙限定上层服务对下层服务的访问规则。如图1所示。


图1  传统应用架构通用的分层设计

而对于容器化的服务场景,许多用户往往倾向于构建由大量可横向扩展的、独立的小单元组成的微服务式架构。在这样的架构中,主机节点的个数和IP地址都是快速变化的,且在业务服务单元之间存在很多相互调用的情况,也需要进行访问的安全控制,这使得分层防火墙的思路不再可行。

Calico【4】是Metaswitch Networks公司提供的一种容器级路由和防火墙工具,它能够在容器级别上为每个容器实例或Kubernetes的Pod实例指定访问规则,达到服务间可控的访问。从原理上说,Calico是通过修改每个主机节点上的iptables和路由表规则实现容器间数据路由和访问控制,并通过Etcd协调节点配置信息的。因此Calico服务本身和许多分布式服务一样,需要运行在集群的每一个节点上。


Calico的Logo被设计成一只玩毛线球的斑点猫,仿佛说明它能够将乱如毛线团的容器网络通信整理得规规整整。由于不同的容器调度框架对网络结构和容器调度单元的实现上并不一致,Calico针对许多主流的应用场景分别进行了定制,例如直接用于Docker、直接用于Rkt、作为libnetwork插件、作为Kubernetes插件、作为Mesos插件等场景。与Kubernetes结合使用时,它还能够替代其他网络规划工具,例如Flannel,直接接管集群不同节点间的网络通信路由功能。

下面重点介绍Calico直接用于Docker的场景,它是Calico最基本、也最具代表性的一种使用方法。

Calico的安装可以通过它的控制客户端工具完成,这个命令行工具可以从Calico的Github仓库直接下载。下面的命令将其放到系统的/opt/bin/目录中,以方便使用:

$ wget -O /opt/bin/calicoctl https://github.com/projectcalico/calico-docker/releases/download/v0.6.0/calicoctl
$ chmod +x /opt/bin/calicoctl

为了演示Calico提供的跨节点路由功能,下面将在两个主机节点上分别启动Calico服务。启动的命令为“calicoctl node”,这个命令会在当前节点通过Docker启动一个部署有Calico服务的容器,并在后台保持运行。

$ hostname
core-01
$ sudo calicoctl node
No IP provided. Using detected IP: 10.0.2.15
Calico node is running with id: …
$ docker ps
CONTAINER ID     IMAGE                   COMMAND      …    NAMES
d0388bcdca86   calico/node:v0.6.0   "/sbin/my_init"  …    calico-node

在另一个节点也将Calico服务启动起来。

$ hostname
core-02
$ sudo calicoctl node
No IP provided. Using detected IP: 10.0.2.16
Calico node is running with id: …

在每个节点上分别运行两个Docker容器,并将网络模式设置为none,然后通过“calicoctlcontaineradd”命令将容器添加到Calico服务的管理之下,首先是节点core-01:

$ hostname
core-01
$ docker run --net=none --name docker-01-A -tid ubuntu:15.10
$ docker run --net=none --name docker-01-B -tid ubuntu:15.10
$ sudo calicoctl container add docker-01-A 192.168.0.1
$ sudo calicoctl container add docker-01-B 192.168.0.2

然后在节点core-02做相同操作,注意容器的命名差异。

$ hostname
core-02
$ docker run --net=none --name docker-02-A -tid ubuntu:15.10
$ docker run --net=none --name docker-02-B -tid ubuntu:15.10
$ sudo calicoctl container add docker-02-A 192.168.0.3
$ sudo calicoctl container add docker-02-B 192.168.0.4

于目前还未在Calico中添加任何规则,这四个容器之间是无法ping通的。接下来,先创建两个访问组“GROUP_A”和“GROUP_01”,这个操作可以在任意的一个节点上完成。

$ calicoctl profile add GROUP_A
Created profile GROUP_A
$ calicoctl profile add GROUP_01
Created profile GROUP_01

最后将容器docker-01-A和docker-02-A添加到访问组GROUP_A中,将容docker-01-A和docker-01-B添加到访问中GROUP_01中。注意“calicoctl container”命令必须在运行有指定容器的主机上运行,首先是主机core-01。

$ hostname
core-01
$ calicoctl container docker-01-A profile append GROUP_A
Profiles GROUP_A appended
$ calicoctl container docker-01-A profile append GROUP_01
Profiles GROUP_01 appended
$ calicoctl container docker-01-B profile append GROUP_01
Profiles GROUP_01 appended

然后是主机core-02。

$ hostname
core-02
$ calicoctl container docker-02-A profile append GROUP_A
Profiles GROUP_A appended


图2  示例配置形成的网络结构

以上配置形成的网络结构如图2所示。若使用ping命令验证容器两两之间的可访问性,可以现只要同属一个访问组的两个容器之间,不论它们是否处在相同物理节点,相互访问都是成功,反之则无法连接。

  • 容器docker-01-A能够同时和docker-02-A和docker-01-B通信
  • 容器docker-01-B和docker-02-A都只能与docker-01-A通信
  • 容器docker-02-B与其他任何容器之间都不能通信

上面这个案例很好的解释了“容器级防火墙”的含义。实际上,对于比较大型的服务集群,手工修改每一个容器的IP地址和访问规则是不现实的,Calico内置了对常见的容器扩展库(例如libnetwork)和调度框架(例如Kubernetes和Mesos)的插件方式支持,

其底层工作原理与上面演示的直接用于Docker的情况基本一致,同时利用这些扩展和框架的功能简化了访问规则的配置方法。比如将Calico与Kubernetes进行集成时,仅需要安装Kubernetes的Calico插件,并在启动Kubernetes Node节点kubelet进程时,添加network_plugin参数指定Calico作为其网络层的地址分配工具即可。Calico将允许用户在创建Pod和Service描述文件时,使用Kubernetes内置的标签功能和特殊的“projectcalico.org/policy”属性【5】设置基于标签过滤数据的防火墙访问规则。这样就很容易将防火墙规则通过Pod和Service描述文件的方式固化起来,从而免去每次手工配置,达到基础实施即代码(InfrastructureasCode)的作用。

小结

任何一项趋于成熟的技术领域,总是伴随着生态圈周边众多工具的支持。目前,容器技术领域已经形成了围绕集群编排、服务部署、监控管理等方面的一整套体系。组成这个体系的设施,除了Docker、Rkt、Intel Clear这些核心容器组件,还有包括许多的辅助工具。它们有些作为独当一面的系统工具形式存在,例如Sysdig,有些则主要以其他核心组件的插件形式存在,例如Calico。

这篇文章中介绍的两种容器辅助工具虽然仅仅是这一庞大生态圈中的冰山一角,然而它们很好地扩扩展了容器技术在监控和安全方面的能力,在实际生产中的作用不容小觑。

参考资料

【1】http://www.sysdig.org/
【2】准确地说是2015年3月2日发布的0.1.98版本
【3】在比较特殊的CoreOS系统中,由于系统目录是只读的,必须使用这种方法运行Sysdig
【4】http://www.projectcalico.org/
【5】https://github.com/projectcalico/calico-docker/blob/master/docs/kubernetes/KubernetesPolicy.md

作者简介

林帆,生在80后尾巴的IT攻城狮,ThoughtWorks成都办公室CloudOps小组成员,平时喜欢在业余时间研究DevOps相关的应用,目前在备考AWS认证和推广Docker相关技术。

(责编/周建丁 zhoujd at csdn dot net)

本文选自程序员电子版2015年11月A刊,该期更多文章请查看这里。2000年创刊至今所有文章目录请查看程序员封面秀。欢迎订阅程序员电子版(含iPad版、Android版、PDF版)。