在AWS FireLens中定制fluentbit容器的具体方法是什么?
关于ECS日志的情况
使用AWS的ECS进行容器运营时,默认情况下只能将日志输出到CloudWatch。这意味着ECS的日志驱动程序是awslogs,但从实用角度来看,可以说它是不够强大的。
如果要将日志流转到S3或Elasticsearch,或者将日志流转到Datadog等第三方工具,有什么解决方案呢?
作为解决方法,AWS官方介绍了名为FireLens的方法。
- Firelens の発表 – コンテナログの新たな管理方法
FireLens是一种将Fluent Bit容器作为sidecar启动,并使用其功能来收集日志的解决方案。
(也可以选择Fluentd)

实际上,在AWS控制台的ECS任务定义设置页面中,有以下这些配置选项。

选择启用FireLens集成后,将自动将906394416424.dkr.ecr.ap-northeast-1.amazonaws.com/aws-for-fluent-bit:latest容器作为边车附加。
此容器为AWS官方容器。
在这篇文章中,我们介绍了一个应用程序的例子,该应用程序自定义了该容器。
容器定义
我们现在来用Terraform看一下如何定义一个容器。
data "template_file" "default" {
template = <<EOF
[
{
"image": "${var.aws-account-id}.dkr.ecr.ap-northeast-1.amazonaws.com/firelens-sample/go:latest",
"name": "go",
"essential": false,
"logConfiguration": {
"logDriver": "awsfirelens"
},
"portMappings": [],
"cpu": 64,
"memoryReservation": 128
},
{
"image": "${var.aws-account-id}.dkr.ecr.ap-northeast-1.amazonaws.com/firelens-sample/nginx:latest",
"name": "nginx",
"essential": true,
"logConfiguration": {
"logDriver": "awsfirelens"
},
"portMappings": [
{
"hostPort": 80,
"protocol": "tcp",
"containerPort": 80
}
],
"cpu": 64,
"memoryReservation": 128
},
{
"image": "${var.aws-account-id}.dkr.ecr.ap-northeast-1.amazonaws.com/firelens-sample/fluentbit:latest",
"name": "log_router",
"essential": true,
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/firelens-sample",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "ecs"
}
},
"firelensConfiguration": {
"type": "fluentbit",
"options": {
"config-file-type": "file",
"config-file-value": "/fluent-bit/etc/fluent-bit_custom.conf"
}
},
"portMappings": [],
"cpu": 128,
"memoryReservation": 256
}
]
EOF
}
我定义了一个Go容器、一个Nginx容器和一个fluentbit容器。请验证一下。
"logConfiguration": {
"logDriver": "awsfirelens"
}
请将logDriver设置为awsfirelens。
另外,请将fluentbit容器本身的日志驱动设置为awslogs。
以下是值得注意的定义。
"firelensConfiguration": {
"type": "fluentbit",
"options": {
"config-file-type": "file",
"config-file-value": "/fluent-bit/etc/fluent-bit_custom.conf"
}
}
请在config-file-value中指定。
在/fluent-bit/etc/fluent-bit_custom.conf文件中,写入自定义的fluentbit配置。
流畅比特的配置设置
常见的设定
我們將根據範例代碼進行操作。現在讓我們填寫之前的/fluent-bit/etc/fluent-bit_custom.conf文件。
[SERVICE]
Flush 1
Grace 30
Log_Level info
[OUTPUT]
Name cloudwatch
Match *
log_key log
region ap-northeast-1
log_group_name /ecs/firelens-sample
log_stream_name container
[OUTPUT]
Name firehose
Match *
delivery_stream my-firehose
region ap-northeast-1
请注意,此处的OUTPUT指定了cloudwatch和firehose。
正如后续所述,我们将基于amazon/aws-for-fluent-bit的容器进行操作,因此默认情况下会安装上述的插件。
好的,根据这个设置,日志将被输出到CloudWatch和Firehose,但有一点需要注意,那就是Match *。
这会使FireLens输出收集到的所有日志,对于诸如DataLake之类的日志流来说并没有问题,但可能还有一些需求希望在流出之前对日志进行一些格式化。
我们可以尝试使用解析器将日志分配到每个容器的CloudWatch流中。
分析器
我刚刚将上述的conf更改为以下方式。
[SERVICE]
Flush 1
Grace 30
Log_Level info
Streams_File stream_processor.conf
Parsers_File parser.conf
[FILTER]
Name parser
Match *
Key_Name container_name
Parser container
Reserve_Data true
[OUTPUT]
Name cloudwatch
Match combine.nginx
log_key log
region ap-northeast-1
log_group_name /ecs/firelens-sample
log_stream_name nginx
[OUTPUT]
Name cloudwatch
Match combine.go
log_key log
region ap-northeast-1
log_group_name /ecs/firelens-sample
log_stream_name go
[OUTPUT]
Name firehose
Match container
delivery_stream my-firehose
region ap-northeast-1
在以下部分进行日志解析。
[FILTER]
Name parser
Match *
Key_Name container_name
Parser container
Reserve_Data true
现在,首先我们要了解FireLens究竟收集了哪些日志。当然,我们可以想象它收集了我们自身生成的应用程序日志以及Nginx的访问日志。但实际上,它还收集了其他附加的元数据信息。请查看以下内容。
{
"container_id": "abcde12345",
"container_name": "/ecs-firelens-sample-1-nginx-xxxyyyzzz",
"ecs_cluster": "arn:aws:ecs:ap-northeast-1:1234567890123:cluster/firelens-sample",
"ecs_task_arn": "arn:aws:ecs:ap-northeast-1:1234567890123:task/aaa-bbb-ccc-ddd-eee",
"ecs_task_definition": "firelens-sample:1",
"log": "10.0.0.0 - - [14/Mar/2020:10:00:00 +0000] \"GET /healthcheck HTTP/1.1\" 200 0 \"-\" \"ELB-HealthChecker/2.0\" \"-\"",
"source": "stdout"
}
以下是firelens收集的日志示例。日志输出包含一个名为”log”的键,还包括任务定义信息和容器名称等其他信息。
我们将在本次任务中对这些信息进行解析。
解析 container_name 以抽取出“nginx”部分。
对于 Go 容器,则抽取出“go”这个字符。
[PARSER]
Name container
Format regex
Regex ^\/(?<task_name>(ecs-firelens-sample))-(?<task_revision>\d+)-(?<container_name>.+)-(?<target_name>.+)$
我用正则表达式提取了它。它被解析为以下内容。
{
"task_name": "ecs-firelens-sample",
"task_revision": 1,
"container_name": "nginx",
"target_name": "xxxyyyzzz",
}
可以通过设置container_name为”nginx”来将日志的输出路径区分到不同的容器中。
当然,如果能对日志本身进行解析并将日志分类,就可以应对各种需求。请考虑各种情况并设计符合需求的方案。
流处理器
我们可以根据日志的类型给它们打上标签。让我们给之前的container_name分别加上名为”combine.nginx”和”combine.go”的标签。
[STREAM_TASK]
Name nginx
Exec CREATE STREAM nginx WITH (tag='combine.nginx') AS SELECT log FROM TAG:'*-firelens-*' WHERE container_name = 'nginx';
[STREAM_TASK]
Name go
Exec CREATE STREAM go WITH (tag='combine.go') AS SELECT log FROM TAG:'*-firelens-*' WHERE container_name = 'go';
# すべてのログ
[STREAM_TASK]
Name container
Exec CREATE STREAM container WITH (tag='container') AS SELECT * FROM TAG:'*-firelens-*';
以类似SQL的格式进行编写。
FireLens日志最初已标记为*-firelens-*。
通过添加条件WHERE container_name = ‘nginx’等等,可以添加nginx的新标记。
请在[OUTPUT]部分指定添加的标签。
[OUTPUT]
Name cloudwatch
Match combine.nginx
log_key log
region ap-northeast-1
log_group_name /ecs/firelens-sample
log_stream_name nginx
Docker的含義
接下来是Docker的定义。
选择使用 Amazon/AWS for Fluent Bit 容器为基础。
FROM amazon/aws-for-fluent-bit:2.1.1
COPY ./docker/fluentbit/fluent-bit_custom.conf /fluent-bit/etc/fluent-bit_custom.conf
COPY ./docker/fluentbit/stream_processor.conf /fluent-bit/etc/stream_processor.conf
COPY ./docker/fluentbit/parser.conf /fluent-bit/etc/parser.conf
如果这样推送到 ECR,它将作为一个出色的日志收集容器发挥作用。
$ aws ecr get-login-password | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com
$ docker build -t firelens-sample-fluentbit:latest -f docker/fluentbit/Dockerfile .
$ docker tag firelens-sample-fluentbit:latest ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/firelens-sample/fluentbit:latest
$ docker push ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/firelens-sample/fluentbit:latest
结束
我对使用FluentBit进行日志收集的容器定制进行了解释。
如果对某人有帮助,我会感到幸福。