Hi~朋友,关注置顶防止错过消息
基于AWS EKS的K8S实践系列文章是基于企业级的实战文章,一些设置信息需要根据公司自身要求进行设置,如果大家有问题讨论或咨询可以加我微信(公众号后台回复 程序员修炼笔记 可获取联系方式)。
当前日志的解决方案
云供应商的平台一般都可以通过 SDK 的方式进行投递解决,所以其实无关乎我们的应用部署方式,只要按照云供应商的所需配置进行配置即可。
今天我们主要说一下如果是自建的 ES 的日志的收集方案的解决。
Kubernetes的日志收集的集中方案
关于第一种方案这种方案虽然可以降低资源的消耗(无需为每个 Pod 配置一个 Sidecar 容器),但是他的灵活程度比较低,因为在我们实际的使用场景中,每个日志推送到es 的 index 名称往往不同,并且日志保存周期也可能不同,而 Sidecar 可以根据每个 Pod 进行定制化相对灵活,当然最灵活的方式还是第三种,这种方式无关乎你的底层服务架构,都是基于 HTTP 或者 RPC 进行的数据的直接推送。
Sidecar 容器的解决方案
kind: ConfigMap
apiVersion: v1
metadata:
name: xxx-internal-filebeat-config
namespace: application-test
data:
filebeat.yml: |
filebeat.inputs:
- type: filestream
paths:
- "/docker/log/*.log"
parsers:
- multiline:
type: pattern
pattern: '^\d{4}-\d{2}-\d{2}\s\d{2}\:\d{2}\:\d{2}\.\d{3}'
negate: true
match: after
fields:
project: xxx-internal
env: test
pipeline: ys-application-log-pipeline
output.elasticsearch:
hosts: ["test.es.xxx.com:9200"]
indices:
- index: "%{[fields.project]}-%{[fields.env]}-%{+yyyy.MM.dd}"
我上面的配置的含义就是代表了我的日志开头是个时间戳,在logback中的配置是%d{yyyy-MM-dd HH:mm:ss.SSS},如果不以yyyy-MM-dd HH:mm:ss.SSS开始的连续行将会被追加到匹配的前一行。
Ingest Node相比 LogStash 的缺点主要是他的输出只能到 ES(不能再输出到 Kafka 队列),没有缓冲机制,不像 LogStash 有缓冲机制在一定程度上可以防止数据的丢失,其次是他支持的 Processor 相对较少,没有 LogStash 种类丰富,但在我们的使用场景下,日志量没有明显的波峰,而且我们的日志写到 es的情况下我这里就直接利用Ingest pipeline进行处理,这样也会少一个 LogStash 组件的维护,这里牵涉到一个技术选型的核心思想:在你的人力和基础系统不够扎实的前提下,一定要将你的技术架构简单化,组件越少越好,以最低成本的最合适的方式满足你的当下需求,整的花里胡哨没用只是皮毛而且也会增加运维人员开发人员的负担,系统先跑起来,其次稳下来,最后投入一定的人力开发基础系统(包含 DevOps 、监控),这些支持系统虽然不能为公司带来明面上的收益,但是他是提高研发效率,保障系统跑的快跑的好提高问题排查效率的关键。
ys-application-log-pipeline用做什么?
es 的里面的时间默认是 filebeat 投递日志的时间,不是日志里面的时间,我们的有些应用对这个时间比较敏感,必须是日志里面的时间,因此ys-application-log-pipeline主要做的就是将日志里面的时间取出来,单独再存储到一个field 中,方便进行排序查询。
PUT _ingest/pipeline/ys-application-log-pipeline
{
"processors": [
{
"grok": {
"field": "message",
"patterns": [
"%{MY_DATETIME:log_time}"
],
"pattern_definitions": {
"MY_DATE": "%{YEAR}[/-]%{MONTHNUM}[/-]%{MONTHDAY}",
"MY_TIME": "[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]",
"MY_DATETIME": "%{MY_DATE} %{MY_TIME}"
}
}
},
{
"date": {
"field": "log_time",
"formats": [
"yyyy-MM-dd HH:mm:ss.SSS"
],
"target_field": "log_time",
"output_format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
}
},
{
"script": {
"lang": "painless",
"source": "String datetime = ctx.log_time;\nZonedDateTime zdt = ZonedDateTime.parse(datetime);\nzdt = zdt.minusHours(7);\nctx.log_time = zdt;"
}
},
{
"date": {
"field": "log_time",
"formats": [
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
],
"target_field": "log_time",
"output_format": "yyyy-MM-dd HH:mm:ss.SSS"
}
}
]
}
Deployments配置
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: application-test
name: xxx-internal
labels:
app: xxx-internal
spec:
...
template:
metadata:
labels:
app: xxx-internal
spec:
restartPolicy: Always
containers:
- name: xxx-internal
image: DEPLOY_IMAGE
imagePullPolicy: Always
....
volumeMounts:
- mountPath: /docker/log
name: application-log
- name: filebeat
image: docker.elastic.co/beats/filebeat:8.6.1
imagePullPolicy: Always
volumeMounts:
- name: application-log
mountPath: /docker/log
- name: filebeat-config
mountPath: /usr/share/filebeat/filebeat.yml
subPath: filebeat.yml
volumes:
- name: application-log
emptyDir: {}
- name: filebeat-config
configMap:
name: xxx-internal-filebeat-config
items:
- key: filebeat.yml
path: filebeat.yml
可以看到在我们的 Pod 中我们除了本身的业务应用容器,我们还启动了一个fielbeat 容器专门用来收集我们的业务日志,具体的关于 Volume 的挂载后续我这边有时间单独写,这里就不专门写了,熟悉 Kubernetes 的同学肯定不会陌生,经过上述配置我们的业务日志就会被投递到我们的 es 中。