[技术分享]面向SecDevOps七种武器

2020-05-29 00:00:00 数据 分析 异常 组合 日志

如果数字世界是一个江湖,技术人员则是自各门派侠士,例如: 拥有一双慧眼洞察一切蛛丝马迹的SecOps 手持各种脚本掌握线上大权的Net/Site Ops * 以敲击机械键盘比拼手速为乐的DevOps

纵观他们的工作会有一些共同点: 关键(Mission Critical):一个命令决定生杀大权,一个操作决定业务走向。面对问题时需要作出关键决策与判断,压力巨大 数据驱动(Data Driven):坚持理性,天天与数据打交道,善于从数据中拿到客观公正结果 * 高危(With Responsibilty):“人在江湖走,哪能不挨刀”,谁没经过几个故障?没处理过几个攻击?被撸过几手羊毛?

与此同时,他们也在工作中Share非常多的问题与工具,与一致的目标(确保系统稳定运行):

在Gartner 《Align NetOps and SecOps Tool Objectives With Shared Use Cases》提到: Network operations (NetOps) and security operations (SecOps) teams coexist as largely separate entities in many organizations, but they share a common goal — a well-performing and secure network infrastructure that optimizes the end-to-end user experience for networked applications.



行走江湖靠本事,但过去几年行业/环境等都在悄悄变化,使得门槛越来越高:


1. 快速发展IT基础设施

IT领域一方面受到成本降低的反对力量的挑战,另一方面运营的复杂性在不断增加。近些年来可以看到如下趋势: 云原生或其他Serverless技术发展不断演化IT技术架构 架构和应用程序产生的数据量快速增长(每年增长2到3倍) 机器和人类生成的数据类型越来越多(例如指标、日志、网络数据和文档) IT运营成本、运营的复杂性在不断增加,需要更短时间相应

以一个典型计算类集群(固定大小)为例,2013年一天产生数据在2GB,类型以监控数据为主。随着自动化运维、运营水平提高数据量增长了50倍,参与者也在变多:


2. 业务稳定后的细节

航空航天中有一条定律:海恩法则(Heinrich's Law)指出: 每一起严重事故背后,必然有29次轻微事故和300起未遂先兆以及1000起事故隐患。按照海恩法则分析,当一件重大事故发生后,我们在处理事故本身的同时,还要及时对同类问题的“事故征兆”和“事故苗头”进行排查处理,把问题解决在萌芽状态。

与20世纪电力一样,今日信息技术已经成了社会运转的关键一环,而信息系统的稳定运转除了架构设计外,日常的运维与运营也是稳定性重要一环。 我们可以通过监控、日常分析、A-B Test 运转下的数据对比、质量测试等环节保障系统的稳定性。


3. 对工具能力更高要求

在处理海量、多样化和更低延时要求下,现有工具在数据量、延时和分析能力上收到了挑战:


3.1 更快的响应

Ops面向是偏向真刀真枪的复杂业务,需要快速的洞察。何为快速?

  1. 快速采集线上数据
  2. 快速通过观察、假设、拿到分析结果
  3. 快速找到规律、发现异常
  4. 采取行动,止损

其中2、3是一个循环过程,为了贴近真相需要多次迭代。如果能把这三个过程控制在分钟、甚至是秒级,会大大加快速度。




3.2 更灵活的洞察

  • 拿放大镜洞察到不易发生的现象,例如对于系统负载、延时、请求的Burst,往往会有被分钟级被平均,但在秒的精度下却波涛汹涌的景象;对于小业务而言,也经常会在线上遇到被平均的现象,命名有大量的失败,从整体大盘上看却又是正常。



  • 能够灵活切换视角。例如对于安全攻击而言,攻击Pattern、来源、地址等信息都在不停地变化,预先定义的各种统计可能,因此要在分析过程中不断改变分析的模式,并且所见即所得拿到结果。解决这个问题的思路就变成了:尽可能全保留原始数据(不进行预聚合降低精度),通过即时方式来构建分析视图。




典型问题背后的七种分析手段

既然Sec、Dev、Ops 有着同样的目标,处理同样规模的问题,那么在工作中是否会Share相同的工具?

我们2009年开始写飞天行代码一刻起,就一直在经历和机器、系统、应用的搏斗过程。期间经历集群从70台增长到5000台过程,也经历了支撑W级用户背后的痛苦和摸索。

从我们的视角把日常工作中高频的问题,抽象成了七种分析的手段,分别是:
查找 上下文探索 对数据统计 聚类 异常发现 根因分析 * 领域建模与本体构建(Knowledge Base)


1. 查找:Grep大法好

从业界统计《50 Most Frequently Used Unix Command》看,Grep是使用多的命令之一(的是tar、第二就是它),也是发现+定位问题常用方法。Grep提供了一种“简单暴力”方式过滤掉无用的信息。由于是文本处理,它能适配于各种格式以快的速度拿到结果。Grep与其他命令的组合与扩展也丰富了查找的场景能力,例如: * 面对分布式场景时,可以通过pssh + grep方式来化解

  • 面对实时场景时,tail -f | grep 组合似乎也不错
  • 稍微复杂一些的条件,egrep扩展的正则表达式似乎也不错
  • 面对组合条件时,grep + sed(行列转换)似乎也能解决问题

这么好的神器有哪些缺陷呢? 1. 暴力:将数据从磁盘上读取,从头到尾过一遍消耗巨大资源。Grep诞生于90年代,O(N)的时间复杂度随着日志膨胀已开始延时不可控,并可能会给线上应用带来较大的开销。 2. 不支持较复杂的逻辑组合:在grep命令中,有OR和NOT操作符的等价选项,但是并没有grep AND这种操作符。但表达能力是一维的,例如我们希望拿到 "A and B not C or D" 这样的逻辑就会比较难。 3. 支持数据类型有限:主要基于文本表达上,例如对于数值类、布尔、JSON等格式就无法支持,只能退化成为简单的文本形式。例如我们希望拿到 (Latency>500000 and Method:Post ) not Type:internal 的结果时,大部分人是无能为力的。

复杂度从O(N)降低成为 O(1):把扫描变成搜索

提到搜索可能小部分人知道Lucene,但提到Elastic Search和ELK Stack应该大部分人都不会陌生。Lucene是Doug Cutting 2001年贡献(Doug也是Hadoop创始人),2012年Elastic Co这家公司把Lucene这套Apache基础库包装一遍,在2015年推出ELK Stack(Elastic Logstash Kibana)解决了集中式日志采集、存储和查询问题。从ES、Splunk近几年快速发展也能够印证“查找”从搜索引擎逐步变成DevOps常用操作。
我们在2013年开始在飞天平台研发过程中,为够解决大规模(例如5000台)上研发效率、问题诊断等问题研发面向日志、Metric、Event等存储的SLS产品,目前每日索引PB级数据,处理来自上万研发工程师的百万次查询。关于SLS可以参考《SLS vs ELK》。


2. 上下文(Tail/Less/More):线索的串联

有了grep定位到后,一个很自然的问题是原因(上下文)是什么?

上下文是围绕问题展开的线索: 一个错误,同一个日志文件中的前后数据 一行LogAppender中输出,同一个进程顺序输出到日志模块前后顺序 一次请求,同一个Session组合 一次跨服务请求,同一个TraceId组合

例如一个很常见操作是grep拿到文件后,跳转到对应机器用vim打开文件,上下翻阅查查找这些线索。在这个过程中,有不少程序员贡献过一些vim插件帮助标记(不同颜色标记error、info、level等级别)。纵观整个过程,我们为了拿到前后几行的数据,做了很多不必要的操作。

我们把上下文定义下:

在一个小区分粒度上能够准确还原出原始的序列,不受日志存储、采集等环节影响 小区分粒度:区分上下文的小空间划分,例如同一个线程、同一个文件等。在定位阶段非常关键,能够使得我们在调查过程中避免很多干扰 保序:在小区分粒度下保证原子有序,及时一秒内有几万次操作,也要保证顺序是严格的

例如面向不同的数据源的小区分粒度如下:

为支持上下文,我们在采集协议中对每个小区分单元会带上一个全局并且单调递增的游标,这个游标对单机日志、Docker、K8S以及移动端SDK、Log4J/LogBack等输出中有不一样的形式。


上下文功能1:上下文跳转

查找到具体错误后,不用登陆机器还原原始日志文件中前后内容




上下文功能2:实时下文(Livetail)类似 Tail -F

通过查找定位到具体日志后,可以直接tail -f 该机器上实时流日志数据。




3. 交互式分析:从统计中发现规律(AWK/SORT/SED/UNIQ)

在稍复杂一些场景中,我们需要对日志中的数据进行统计发现其中规律。在Linux理念中,任何复杂任务都是可以用一组命令的组合来达到(运维大法的一个入门的例子就是对Nginx访问日志进行命令行处理)。

例如单位窗口的访问Status统计:

cat access.log | cut -d '"' -f3 | cut -d ' ' -f2 | sort | uniq -c | sort -rn

Sample Output:
 210433 200
  38587 302
  17571 304
   4544 502
   2616 499

相关文章