云原生之深入解析Kubernetes Pod的网络状态监控

一、前言

  • 在 Kubernetes 系统里,由 kubelet 内置的 cadvisor 组件收集每个容器资源监控信息,但官方基于性能相关的考虑,如果抓取这些每个容器中网络相关的指标,将会耗费大量的 CPU 内存资源,cadvisor 中默认给关掉了网络等相关指标的收集。
    • https://github.com/google/cadvisor/blob/master/docs/runtime_options.md#metrics
    • https://github.com/kubernetes/kubernetes/issues/60279
  • 因此在 prometheus 默认抓取的 kubelet cadvisor metrics 端点,监控上报的数据中,容器网络相关的指标 container_network_tcp_usage_total 和 container_network_udp_usage_total 等都为0,但实际业务监控中可能需要这些指标的收集,用于监控告警以及排查问题。

二、方案①

  • 如果想要从 cadvisor 中获取这些指标,需要修改 kubelet 文件里的配置,即需要修改 kubelet 源码并重新编译,这个并不 native。
  • 另一种方案是自己部署 cadvisor daemonset,并开启 tcp网络指标的收集,使用 prometheus 来抓取这些指标,但这样就是重复部署了 cadvisor 组件,并且经过测试,部署的 cadvisor 在 64C384G 运行有 300 个 container 的物理机上占用了5核CPU和5G内存的资源,资源占用巨大,这也是 cadvisor 默认关闭网络指标收集的原因。同时 prometheus 的抓取配置文件也需要修改,不然会同时抓取生成两份 cadvisor 指标。
  • 经过以上测试,采用额外 cadvisor 部署并使用 prometheus 抓取的方案资源消耗巨大,会有重复指标的收集,并且需要自己再次从 prometheus 中查询处理并上传到 open-falcon 监控平台。

三、方案②

  • 想要获取每个容器内的网络连接指标,在每个容器中内置监控组件并不现实,并且容器的网络指标收集与虚拟机的网络指标收集有差异,监控 agent 并不通用。
  • 我们知道容器的虚拟化是利用 namespace 把每个进程的网络做了隔离,使用 nsenter 工具可以在每个进程的网络空间内执行相关的网络操作命令,请参考:Docker: any way to list open sockets inside a running docker container?。
  • 另外,项目容器名与宿主上设备的映射关系可以通过 docker 的 api 来查到,比如 pid 进程对应关系以及网卡设备对应关系等。
  • 通过以上可知,自己手动编写脚本,只抓取需要的网络指标数据,在宿主机上定时执行获取每个应用容器的网络状态并格式化为监控数据格式上传到 open-falcon 监控平台中,做统一的监控告警。
  • 以 ss --summary 为例,显示了各种状态的 tcp 连接情况,以及 udp 等连接情况,读取统计到的数据字段:
Total: 141267 (kernel 7503901)
TCP:   28090 (estab 80, closed 27999, orphaned 139, synrecv 0, timewait 6586/0), ports 0

Transport Total     IP        IPv6
*   7503901   -         -
RAW   0         0         0
UDP   3         3         0
TCP   91        91        0
INET   94        94        0
FRAG   0         0         0
  • 在上述配置的机器(64C384G 运行有 300 个 container 的物理机)中执行效率在分钟级。
  • 使用 ss 命令获取网络状态信息较慢,考虑两个优化:
    • 将串行执行每个容器的网络状态命令,改为多线程并发执行,控制并发数并注意 CPU 的消耗使用;
    • 将通过 ss 命令获取信息改为直接读取 /proc/{pid}/net/sockstat 文件获取对应进程的网络状态统计信息。

四、方案③

  • 使用方案②的优化版本,不使用 ss 命令来获取每个容器网络空间的网络状态,直接读取每个容器对应 pid 下的 sockstat 文件,即 /proc/{pid}/net/sockstat 文件,效率比 ss 命令快很多,并且通过 docker api 与 docker 交换,获取运行的每个容器对应的 pod name 和 pid 信息,效率比执行命令快很多。
  • sockstat 文件信息:
sockets: used 141118
TCP: inuse 89 orphan 96 tw 7181 alloc 21341 mem 13896
UDP: inuse 3 mem 116
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 0 memory 0
  • TCP inuse 是的值是取自 tcp4_hashed+tcp6_hashed,是正在使用的 TCP 套接字的数量,而不是 establish 状态的 tcp 连接;establish 状态的 tcp 连接状态需要从 /proc/net/snmp 文件中获取,读取 CurrEstab 字段。
  • 该方案将网络连接的 Establish、InUse、TimeWait、Orphan、Total、UDP 六个状态值上报到 open-falcon 监控平台中,从而获得 prometheus 监控中没有的容器内部网络连接状态,做数据监控告警。
  • 在上述配置的机器(64C384G 运行有 300 个 container 的物理机)中执行效率在毫秒级 (300ms 左右),内存消耗约 40M,所以该项目使用方案③实现。

你可能感兴趣的:(人工智能与云原生,云原生,kubernetes,cadvisor部署,open-falcon,sockstat)