容器网络可视化:Weave Scope

Scope

简介

scope 是 weavework 开源的一款容器集群网络可视化监控方案,可以提供整个集群的实时网络拓扑,能具体到容器内进程这一粒度,同时还能提供对容器进行简单的详情查看、销毁、远程登录等管理功能。

功能 Overview

下图是 scope 的管理后台,打开可以看到图中有很多个六边形,代表一个个容器,而容器之间的连线则代表它们之间当前存在网络连接,鼠标悬浮到线条之上还能看到连接发起的方向,这样我们就能直观地观察到整个集群的网络流量拓扑了,哪几个服务之间有流量依赖,一目了然。

image-20220508193905687

容器六边形里的阴影部分代表该容器的内存使用量,也可以切换成 CPU。

最上面正中间我们可以看到还能切换网络中节点的视角,当前我们选择的是容器,也可以切换到进程、主机、DNS 名、容器名称(服务)、镜像等视角,比如进程视角:

image-20220508195042933

另外除了图,也能切换到表格视图:

image-20220508195334702

部署

这一段我们介绍一下如何快速部署 scope 进行体验,scope 同时支持 k8s 容器集群和非 k8s 容器集群的部署模式。

裸 Docker

Docker 单机版部署体验可以直接使用官网提供的脚本:

sudo curl -L git.io/scope -o /usr/local/bin/scope
sudo chmod a+x /usr/local/bin/scope
# 这里的 'scope' 是个辅助脚本
scope launch

这个脚本会判断当前的操作系统来拼接不同的 docker 启动参数,如果是在 linux 下,最终会使用如下参数启动一个容器,我们可以直接复制这条命令启动:

# 因为 agent 需要采集宿主机信息,所以需要共用宿主机网络和PID空间,以及映射一些重要的挂载点
docker run -d --name=weavescope --privileged --userns=host --net=host --pid=host -v /var/run/docker.sock:/var/run/docker.sock -v /sys/kernel/debug:/sys/kernel/debug -e CHECKPOINT_DISABLE weaveworks/scope:1.13.2 --probe.docker=true

.

然后容器启动后打开地址:http://localhost:4040 即可访问。

Kubernetes

可能绝大部分 scope 的用户都是基于 k8s 的方式部署,官网也准备好了对应的部署脚本,直接运行即可:

# 这里的 version 变量主要是要将 k8s 集群的版本 base64 之后传过去,然后它会重定向到对应 scope 版本的资源地址
kubectl apply -f "https://cloud.weave.works/k8s/scope.yaml?k8s-version=$(kubectl version | base64 | tr -d '\n')"

除开最基本的 Namespace 和 RBAC 类资源,这里会创建三个计算资源:

  • DaemonSet: weave-scope-agent
  • Deployment: weave-scope-cluster-agent
  • Deployment: weave-scope-app

另外这个资源描述文件中的镜像是存放在 ghcr.io上的,国内理论上能拉下来但是会比较慢,可以直接改成 DockerHub 上的镜像,内容摘要是一样的:

ghcr.io/weaveworks/launcher/scope:1.13.2 -> weaveworks/scope:1.13.2

实现原理

架构

这里以 Kubernetes 集群内部署架构为例来分析 scope 的实现原理。

代码上,scope 由 app 和 probe 两部分组成,probe 负责采集机器上的信息,然后上报给 app,app 聚合后提供 UI 展示。

app 和 probe 会对应到部署时的 App 和 Agent 这两个组件,agent 还有一个特殊的版本:cluster-agent 专门采集 k8s 相关信息。它们用的都是同一个编译二进制产物,只是传入的启动参数不一样:

  • app: /home/weave/scope --mode=app
  • agent: /home/weave/scope --mode=probe --probe.kubernetes.role=host
  • cluster-agent: /home/weave/scope --mode=probe --probe.kubernetes.role=cluster

架构图:

image-20220509023150325

App

App 会实时接收来自 agent 上报的信息,然后聚合。

scope 在设计上是只展示实时信息的,app 中有一个参数:app.window,scope 只会保存在这个窗口大小内的数据,默认是十五秒钟,即管理后台图上的拓扑关系是根据最近十五秒内存在过的网络连接分析出来的。

临时数据的存储介质上支持: 内存存储(默认)、文件存储和 AWS DynamoDB,通过参数app.collector设置。

App 相关代码逻辑的入口位于:/prog/app.go文件的appMain函数。

Agent

Agent 负责采集信息通过 WebSockt 上报给 app,在 agent 的内部,要采集的信息都抽象成了一个个的 Repoter,scope 目前实现了的 reporter 如下:

  • CRI / Docker: 采集该容器运行时托管的所有容器信息,包括容器ID、状态、名称、创建时间、镜像等,支持 Docker 和标准 CRI 接口,不过这也使得需要将宿主机上的 CRI Socket 文件挂载到 agent 容器中

  • Endpoint: 最核心的模块,采集机器上的网络连接相关信息,找到每个进程都在和哪些 IP 连接,然后上报的时候会附带上这个进程对应的容器信息,然后 app 端聚合,根据连接的 IP 分析是不是集群中的其他组件,这样就能分析出来整个集群的网络拓扑关系。

支持两种实现方式:

  • eBPF:性能更好,占用资源更少,但是至少需要内核 4.4 版本
  • 遍历 proc 文件系统中每个进程的 /proc//net/tcp 文件,里面有 TCP 连接信息

  • Host: 采集宿主机自身相关信息:

    • CPU / 内存 / Load
    • 内核信息
    • 网络设备
  • Process: 采集宿主机上所有的进程信息:pid, command, parent pid, threads, cpu, memory, open files

  • Weave: overlay 架构时可以用到

  • Kubernetes: cluster agent 会用到,调用 k8s 的 apiserver 采集集群拓扑