在AWS FireLens中定制fluentbit容器的具体方法是什么?

关于ECS日志的情况

使用AWS的ECS进行容器运营时,默认情况下只能将日志输出到CloudWatch。这意味着ECS的日志驱动程序是awslogs,但从实用角度来看,可以说它是不够强大的。
如果要将日志流转到S3或Elasticsearch,或者将日志流转到Datadog等第三方工具,有什么解决方案呢?
作为解决方法,AWS官方介绍了名为FireLens的方法。

    Firelens の発表 – コンテナログの新たな管理方法

FireLens是一种将Fluent Bit容器作为sidecar启动,并使用其功能来收集日志的解决方案。
(也可以选择Fluentd)

firelens.png

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

スクリーンショット 2020-03-14 15.01.08.png

选择启用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进行日志收集的容器定制进行了解释。
如果对某人有帮助,我会感到幸福。

bannerAds