关于监视容器我们了解的5件事
本文将介绍如何构建一个管理上万容器的可扩展的,高可靠的监控系统。本文是基于 Sysdig 容器监控工具的构建经历编写,如果您决定开发自己的工具,以下的设计决策可能会对您有所启发。接下来我将分享一下我们的架构设计以及我们所做的权衡,主要包括以下5个方面:
- 检测系统
- 将数据映射到您的应用程序,主机和容器
- 利用编排
- 决定要存储什么数据
- 在容器环境中启用排错功能
好了,接下来我们先来看一下容器对监控系统的影响。
为什么容器会改变监控游戏的规则?
首先,容器非常强大。他们:
- 简单:大多只有单个进程
- 小:只有虚拟机的十分之一大小
- 隔离:较少的依赖关系
- 动态:可以快速扩缩容、停止、迁移
容器是一种简单优秀的构建微服务的方式,但是它们的简单性需要付出一定的代价。容器的短暂特性增加了监测的复杂性。只知道部分容器存在是不够的:深层容器的可见性对于运维团队监控和排错至关重要。让我们开始分解这些监控挑战。
结构需要透明化
在静态或虚拟环境中,监控代理通常在运行在主机上并且针对特定应用程序进行配置。但是,这种方法不适用于容器环境:
- 你不能在每个容器中部署监控代理。
- 动态应用程序使手动配置代理插件来收集指标变得非常困难。
在容器环境中,为了尽可能减少人工干预,应用结构需要尽可能的透明。基础设施指标,应用程序指标,服务响应时间,自定义指标以及资源/网络利用率数据应该在不用引入额外的容器或在容器内做任何改造采集的情况下采集。为达到这样的目的有两种办法。
第一种方式是 pod(由Kubernetes创造的一个概念)。每个 pod 内的容器可以看到其他容器正在做什么。对于监视代理,这被称为“边车”容器。在Kubernetes中相对容易实现,但是如果在一台机器上有许多 pod,这可能会消耗大量的资源。如果您的监控边车出现性能,稳定性或安全问题,将可能会对应用造成严重破坏。
第二种模式是主机。这将捕获每个主机上的所有应用、容器、统计信息和主机指标,并将其发送到每个主机上的容器中进行处理和传输。这种方式消除了通过
statsd 转换指标的需要。与边车模型不同,按主机监控大大减少了监控代理的资源消耗,并且不需要修改应用代码。通过Sysdig,我们创建了一个非阻塞的内核模块来实现这一点。
不过,这需要一个特殊的容器。
通过引入“ContainerVision”,Sysdig 选择了第二种方案,这是我们必须做出的最大的妥协。尽管将监视代理作为内核模块运行提高了风险和实施的复杂性,但这使我们能够以较低的开销——即使在高密度容器环境中收集更多的数据,并减少对环境的影响。最后,为了解决作为第三方软件提供商的问题,我们将内核模块作为 Sysdig Linux和容器可见性命令行工具的一部分进行开源。如果你构建的是内部工具,那么最后后一点可能不是你需要关心的。
如何将数据映射到应用程序,主机,容器和编排
随着环境复杂性的增加,基于元数据过滤,分割和组合指标的能力至关重要。除了容器正在运行的物理关系之外,标签还允许您表示应用体系结构的逻辑蓝图。
有两个标签指标:显式(要存储的属性)与隐式(编排)标记。显式标签可以由您的团队根据具体情况添加,但隐式标签应默认采集。后者是编排的一个关键要素。每个独特的标签组合都是一个单独的指标,您需要存储,处理,然后根据用户需求来调用。我们将在下面“决定要存储什么数据”一节中详细讨论。
利用协编排
编排从根本上改变了容器的调度管理方法,并影响了用户的监控策略。当服务的性能十分重要时,个别容器将变得没那么重要。一个服务是由若干容器组成,编排将根据性能和健康需求来调度容器。
这对一个监控系统有两点启示:
- 您的监控系统必须根据编排元数据隐式地标记所有指标。包括系统,容器,应用程序组件,甚至自定义的指标。开发人员应输出自定义指标,并且监控系统应保留每个指标的状态。关于这个主题你可以在这里了解更多。
- 您的监控代理应自动发现应用程序并收集相关指标。这可能需要您更新您的监控系统以提供这些功能。
有两种方法可以实现这一点:根据编排启动特定容器的事件,或者根据容器启发式的确定应用程序。sysdig选择了后一种方法,它需要监控系统更加智能,但也产生了更可靠的结果。你可以在这里阅读更多关于监视kubernetes和编排的信息。
决定要存储什么数据:“所有的数据”
分布式系统增加了监测数据和结果指标。尽管它降低了成本非常有吸引力,但您会发现基础架构越复杂,获取所有数据以进行分析和排错就越重要。例如,如果缺少监控数据该如何确定应用的间歇慢响应是什么原因?你怎么知道这是代码中的系统性问题,还是 fritz 上的容器的问题,还是 AWS 的问题?通过微服务汇总所有这些信息不会给你足够的了解来解决问题。
这意味着我们将收集大量的指标和事件数据。为了让这些数据持续存在且可访问,我们决定:
- 构建水平可伸缩的后端,使我们的应用程序能够根据用户或服务隔离数据,仪表板,警报等。
- 存储全量数据长达六个小时,然后进行汇总。我们的后端由 Cassandra(指标),Elasticsearch(事件)和 Redis(内部代理)等可水平伸缩的集群组成。这为长期存储数据进行分析提供了高可靠性和可扩展性。所有的数据都可以通过 REST API 访问。如果你要构建自己的系统,您可能会最终构建相同的组件。
如何在容器环境中启用排错
容器是部署和复用的理想选择,但是对它们进行排错则是一大挑战。常用的排错工具(ssh,top,ps和ifconfig)既不能在 PaaS 控制的环境中访问,也不能在容器中使用,容器的短暂特性更是让工作变得复杂。能够捕获主机上的每次系统调用,从而深入了解任何应用程序,容器,主机或网络的运行情况,这只是个开始。
编排主节点提供的相关元数据接口不仅限于机器的状态,还提供了捕获分布式系统的状态和上下文的能力。所有这些数据都被捕获到一个文件中,使您能够在笔记本电脑上的排错并轻松进行事后分析。
例如,当特定容器上的网络连接峰值触发警报时,主机上的所有系统调用都将被记录下来。你可以通过 cSysdig 提供的所有相关的上下文进行排错,并通过深入到网络连接来确定根本原因:
结论
构建高度可扩展的分布式监控系统并不是一件容易的事情。无论你选择自己做还是利用别人的系统,我相信你都不得不做出许多与我们所做的相同的选择。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 五. css 布局之 position(定位)
- 【译】Rust与智能指针
- 根据坐标在基因组上面拿到碱基序列来设计引物
- 18款Webpack插件,总会有你想要的!
- Linux下如何查看硬件信息?
- 最通俗易懂的一篇文章了解JVM、JRE、JDK的关系是什么?
- 六. CSS 样式补充之 font & background
- 七 .Html的表格
- rollup + typescript 构建 ts 包
- node 写爬虫,原来这么简单
- 计时器 hook
- 自定义eslint 配置包
- 【61期】MySQL行锁和表锁的含义及区别(MySQL面试第四弹)
- 关于死锁你了解多少,通过“让APP随手机壳改变颜色,程序员和产品经理大家”这一事,了解下死锁可好?
- 三阴性乳腺癌表达矩阵探索笔记之GSEA