Elastic Stack 广泛的被使用在收集 Logs、Metrics、Traces、Uptime 等资料,其中一个最大的目的,就是为了让散落在各处的资料,能集中化的收集,可以更轻易的存取这些资料,而当资料收集在一起的时候,混乱的格式,就会是遇到的下一个问题,Elastic Common Schema (ECS) 就是被设计出来解决这件事。
Elastic Common Schema (ECS) 是一个规范 (Specification),同时这个规范也是 Open Source 的,是在 Elastic 使用者社群支持之下所开发的,主要定义了存放在 Elasticsearch 之中的 Event (事件) 类型资料常用的栏位,这些栏位的型态、描述、使用与呈现方式,而所谓的 Events 即包含就像是 Logs 或是 Metrics 这样的资料。
ECS 设计的目的,是为了鼓励使用 Elasticsearch 存放 Event 类型资料的使用者们,能够将这些 event 的资料『正规化』,透过正规化之後的资料,在後续的资料分析、资料视觉化呈现、显示与 event 有关联的资讯上都能更容易的使用。
ECS 的规范横跨了以下的范围:
透过资料正规化,让查询可以变得简单,举例来说,一般大型架构中,可能有各种的服务元件、第三方产品或工具,每个产生的 Logs 的格式都不同,同样是针对 IP
的地址,栏位都不一样,在没有正规化之前,为了要从 src
、client_ip
、apache.access.remote_ip
、context.user.ip
等各种服务所定义的 IP
栏位查询是否有存在 10.42.42.42
这个地址,KQL (Kibana Query Language) 的查询会长成这样:
src:10.42.42.42 OR client_ip:10.42.42.42 OR apache.access.remote_ip:10.42.42.42 OR
context.user.ip:10.42.42.42 OR src_ip:10.42.42.42
但透过正规化之後,会将这些栏位全部存放至 source.ip
的栏位,查询就变成:
source.ip:10.42.42.42
简单,能加快查询的速度,也能减少犯错的机会。
透过资料正规化,在制作图表,让资料以视觉化方式来呈现时,也会变得更简单,而且在分析上也有更好的能力,例如透过同一个 IP 的位置,在同一个栏位之中,轻易的就能将各种来源 (如:Web Server、IDS/IPS 装置、防火墙) 所收集到的资料,透过图表呈现出时间历程中的变化,又或是能将资料要进行深入的分析时的资料呈现方式,像是枢纽分析。
在 Data Ingestion Pipeline 的过程之中,能将原始的资料透过 ECS 的定义,转换成正规化之後的结果,同时 Elastic Stack 中已经在 Beats、Logstash 等 Data Ingest 的工具,实作了许多第三方产品及工具的整合模组,能将这些 Logs 的格式转换到 ECS 之中。
例如 Apache Logs 原始的内容如下:
10.42.42.42 - - [15/Jul/2020:20:48:32 +0000] "GET /content HTTP/1.1" 200 2571 "-"
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/83.0.4103.106 Safari/537.36"
首先会将这些原始的内容转换到 ECS 定义的栏位之中:
Field Name | Value |
---|---|
@timestamp | 2020-07-15T20:48:32.000Z |
event.original | 10.42.42.42 - - [15/Jul/2020:20:48:32 +0000] "GET /content HTTP/1.1" 200 2571 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36 |
http.request.method | GET |
http.response.body.bytes | 2571 |
http.response.status_code | 200 |
http.version | 1.1 |
message | GET /content HTTP/1.1" 200 2571 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36 |
source.address | 10.42.42.42 |
source.ip | 10.42.42.42 |
url.original | /content |
user_agent.original | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36 |
除此之外,ECS 还有定义其他的栏位,也是在转换过程中会增加的资讯:
ecs.version
:ECS 的版本event.dataset
、event.module
:记录这个 event 是从哪里来的,是透过哪个模组所处理的。event.kind
、event.cateogry
、event.type
、event.outcome
:包含 ECS Categorization Fields (分类栏位),透过定义好的类别,描述这个 event 是什麽样的 event。ECS 定义了一些准则与最佳实践的规范,接下来我们将介绍这些规范。
ECS 的栏位定义成以下两种:
@timestamp
栏位。ecs.version
的栏位之中。host
相关的栏位,都要加上 host.
的前缀,当成是 host
类的栏位集 (field sets),进行分类管理。.
而不是使用 _
来描述。host.name
就不要去一般化变成 name
,这样太一般化会导致使用时不知如何解读,甚至会发生许多冲突。host.host_ip
应该取名 host.ip
,不过也有例外,如果 hostname
就是一个一般认知的名字,host.hostname
就应该保留使用 hostname
,不要刻意改掉。ip
、geo
、os
等。除非有特别的备注,否则所有的整数的数值型态,应该定义成 long
。
IDs 指的是识别字串,例如 User Id
、Product Id
,而 Codes 指的是编码,例如 Error Code
,这些都应该使用 keyword
的资料型态。
不过有一些特别的 Codes 只要是大家都共识为数字的,就应该使用数字类型,例如 HTTP Status Code
,这个就应该使用数字。
Elasticsearch 预设的 Dynamic Mapping 会将文字类型的栏位,指定成 text
的资料型态,并且包含 keyword
的子栏位。
这部份 ECS 和 Elasticsearch 相反,预设的文字类型栏位,会指定成 keyword
的资料型态,而另外定义子栏位 text
。
原因是 ECS 处理的资料大部份都是 Logs 与 Metrics,在这样的应用情境中,大部份的文字栏位都会较适用 keyword
的方式来处理,才能支援较快速的完整比对、Aggregation、Sorting、prefix search…等。
不过也有例外,就是 Logs 当中一般会存放大量文字,要用来做全文检索的 message
与 error.message
栏位,这两个栏位预设就是指定 text
并且不会另外宣告 keyword
的子栏位。
在实务的使用上,我们往往会因为实际的需求与情境,会要在结构化的 Logs 之中定义自己的栏位,由於 ECS 还持续在发展中,以下会有一些自订栏位的使用建议,减少与未来 ECS 新版本发生冲突的机会。
labels
栏位一些简单的 keyword
类型的资料,可以直接定义在 labels
栏位之中,例如:
{ "labels": { "foo_id": "beef42", "env": "production" },
"message": "...",
"event": { ... }
}
labels
里的定义,就是完全依照使用者自己来管理。
ECS 在命名时,会使尽量使用概念的名字,而不是工具的名字或是专案的名字,一般在资料的整理时,就会先使用通用的方式来归类,剩下的才会用特定方式来描述,例如 HAProxy 的 log,属於 HTTP 相关的资讯,就会先定义在 http
与 url
的 field sets 之中,而剩下的才会放在 haproxy
里:
{ "http": { "request": { "method": "get", ... },
"response": { "status_code": 200, ... } },
"url": { "original": "/favicon.ico", ... },
"haproxy": { "frontend_name": "myfrontend", "backend_name": "mybackend_prod",
"backend_queue": 0, ... }
}
如果真的要避免与未来的 ECS 版本发生冲突,有一个做法,虽然丑丑的,但是可以考虑,就是打破 ECS 的命名规则,使用大写开头的方式来命名栏位:
{ "http": { "request": { "method": "get", ... } },
"url": { "original": "/favicon.ico", ... },
"Proxy": { "FrontendName": "myfrontend", "BackendName": "mybackend_prod" },
"event": { "module": "haproxy" }
}
在上述官方文件提出的例子,Proxy
就是一个自订的栏位,并且为了避免未来与 proxy
这样的 ECS 栏位发生冲突,所以使用大写开头。
备注:我自己是觉得这部份有点丑,如果真的要使用,以上述的子来说,会命名成
Proxy
,一定是因为想要在自己的领域中定义一个通用的栏位,而刚好这个栏位还没有被定义在 ECS 之中,如果真的是够通用,可以接受未来 ECS 推出时再进行转换,可以这样考虑,否则是自己领域当中的应用的栏位定义时,最好还是能定义更明确的名字,避免发生冲突。
基本上若是使用我们这系列文章前面介绍到的 Heartbeat、Metricbeat、Filebeat 当中的各种 Modules,所收集到的资料就已经是依照 ECS 的格式存入 Elasticsearch 当中,若是有需要增加客制的栏位用,可以使用先前介绍过 Beats 里的 properties
来进行设定,以下会先针对 ECS 产生的栏位进行简介,若是要想查看 Beats 实际产生哪些 ECS 的栏位,可以直接使用 _search
或是 Kibana Discover 的功能来查看。
ECS 栏位的参考,可以参考 官方文件 - ECS Field Reference 里的定义,包含非常多已经收录的各种栏位集 (field sets),这部份在这边就不细部说明。
若是想要一览 ECS 所有栏位的总表的话,可以查看 ECS GitHub - fields.csv [2]。
ECS Categorization (分类) 栏位,目的是透过一组事先定义的值,用来描述这个栏位是什麽样的栏位,其中包含了:
event.kind
:用来描述这个 event 包含什麽样的资讯,可使用的值有 alert
、enrichement
、event
、metric
、state
、pipeline_error
、signal
。event.category
:定义了 ECS 中的主要分类,可使用的值包含 authentication
、configuration
、database
、driver
、file
、host
、iam
、intrusion_detection
、malware
、network
、package
、process
、registry
、session
、threat
、web
。event.type
:这里面定义的,是基於 cateogry
底下的子分类,可使用的值包含 access
、admin
、allowed
、change
、connection
、creation
、deletion
、denied
、end
、error
、group
、indicator
、info
、installation
、protocol
、start
、user
。event.outcome
:这是定义 event 代表的状态,可使用的值包含 failure
、succes
、unknown
。透过这些事先定义好的分类,可以协助我们将 events 有效的正规划,每个栏位可设定的值的说明,可以参考 官方文件 - ECS Categorization Field 的细节说明。
这篇文章所介绍的 Elastic Common Schema,除了让我们了解 ECS 的能力以及里面所包含的定义,更重要的一个参考价值,就是 Elastic 发展出这份 Common Schema 的设计重点,相信在许多领域之中,也应该会有类似定义领域内通用 Schema 的需求,这里所介绍的做法就非常值得参考。
查看最新 Elasticsearch 或是 Elastic Stack 教育训练资讯: https://training.onedoggo.com
欢迎追踪我的 FB 粉丝页: 乔叔 - Elastic Stack 技术交流
不论是技术分享的文章、公开线上分享、或是实体课程资讯,都会在粉丝页通知大家哦!
<<: D3JsDay23 三枪侠的电磁炮,三个变数的气泡—气泡图(上)
>>: Day24:今天我们来聊一下Azure Sentinel中使用的关注清单
开发前的新手纠结 商学院出身,非资工背景,团队内也没有熟悉 app 开发的人才 决定做 app 接触...
OK,说好本章结要来说一下页面,那就说一下页面能干嘛,首先要提到的是有页面功能又有文章功能,同时都可...
Abstract 我们前面讲了许多Spring应用开发,但当我们开发好一套系统,势必要有一套API手...
自前两天范例中,我们看到受众目标与假想使用者之重要性。 现在,我们能设身处地的以使用者的角度来设计...
目标 主题是【从资料库到资料分析视觉化】, 希望可以更深入的了解data, 从资料库的架构,资料的...