DAEMONを動かすことはできず、 fluentd logdriverもサポートされていないFargateで、 サイドカーとしてFluentdのコンテナを動かしてアプリケーションのログをS3に送る。 全体のコードはGitHubにある。
Kubernetesの1PodでAppとfluentdコンテナを動かしてBigQueryに送る - sambaiz-net
Fluentd
必要なプラグインと設定ファイルを入れたイメージを作る。
FROM fluent/fluentd:v1.4-1
USER root
COPY ./fluent.conf /fluentd/etc/
# install plugin
RUN apk add --update-cache --virtual .build-deps sudo build-base ruby-dev \
&& gem install fluent-plugin-s3 -v 1.0.0 --no-document \
&& gem install uuidtools \
&& gem sources --clear-all \
&& apk del .build-deps \
&& rm -rf /var/cache/apk/* \
/home/fluent/.gem/ruby/*/cache/*.gem
# set timezone (Alpine)
RUN apk --update-cache add tzdata && \
cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
apk del tzdata && \
rm -rf /var/cache/apk/*
fluent.confはこんな感じ。
<source>
@type tail
format json
path /var/log/test.log
pos_file /var/log/test.log.pos
tag test
<parse>
@type json
time_type string
time_format '%Y-%m-%dT%H:%M:%S%:z'
keep_time_key true
</parse>
</source>
<match test>
@type s3
s3_bucket my-test-logs-bbbbbb
s3_region ap-northeast-1
path test-log/
time_slice_format ymd=%Y-%m-%d/hour=%-H/
s3_object_key_format %{path}%{time_slice}%{uuid_flush}.json.%{file_extension}
<buffer tag,time>
@type file
path /var/log/fluent/test
timekey 60
timekey_wait 60
chunk_limit_size 30m
</buffer>
<format>
@type json
</format>
</match>
pushするとCircleCIでビルドしECRにpushされるようにした。
CircleCI 2.1からのOrbでdocker buildしてECRにpushし、Slackに通知させる - sambaiz-net
workflows:
build-push:
jobs:
- aws-ecr/build_and_push_image:
name: 'build-latest'
executor: default
repo: '${ECR_REPO}'
tag: latest
Role
ECRからPullできるExecutionRoleとS3にPutできるTaskRoleを作る。
ExecutionRole:
Type: 'AWS::IAM::Role'
Properties:
RoleName: 'test-execution-role'
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: 'Allow'
Principal:
Service: 'ecs-tasks.amazonaws.com'
Action:
- 'sts:AssumeRole'
Policies:
- PolicyName: 'test-execution-role'
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: 'Allow'
Action:
- ecr:GetAuthorizationToken
- ecr:BatchCheckLayerAvailability
- ecr:GetDownloadUrlForLayer
- ecr:BatchGetImage
- logs:CreateLogStream
- logs:PutLogEvents
Resource: '*'
TaskRole:
Type: 'AWS::IAM::Role'
Properties:
RoleName: 'test-task-role'
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: 'Allow'
Principal:
Service: 'ecs-tasks.amazonaws.com'
Action:
- 'sts:AssumeRole'
Policies:
- PolicyName: 'test-task-role'
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: 'Allow'
Action: 's3:ListBucket'
Resource: !GetAtt Bucket.Arn
- Effect: 'Allow'
Action:
- 's3:GetObject'
- 's3:PutObject'
Resource: !Join [ '/', [ !GetAtt Bucket.Arn, '*' ] ]
TaskDefinition
Fargateで動かすのでNetworkModeはawsvpcになる。K8sのときと同様にvolumeをmountしてファイルを共有する。
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
RequiresCompatibilities:
- 'EC2'
- 'FARGATE'
NetworkMode: 'awsvpc'
ExecutionRoleArn: !Ref ExecutionRole
TaskRoleArn : !Ref TaskRole
Cpu: '256'
Memory: '512'
ContainerDefinitions:
- Name: 'app'
Image: 'busybox'
EntryPoint:
- 'sh'
- '-c'
Command:
- 'while true; do echo "{\"foo\":1000,\"time\":\"2019-05-09T20:00:00+09:00\"}" >> /var/log/test.log; sleep 1; done'
Essential: 'true'
LogConfiguration:
LogDriver: 'awslogs'
Options:
awslogs-group: !Ref LogGroup
awslogs-region: 'ap-northeast-1'
awslogs-stream-prefix: 'app'
Environment:
- Name: 'TZ'
Value: 'Asia/Tokyo'
MountPoints:
- SourceVolume: "varlog"
ContainerPath: "/var/log"
- Name: 'fluentd'
Image: !Join [ '/', [ '<your_account_id>.dkr.ecr.ap-northeast-1.amazonaws.com', !Ref Repository ] ]
Essential: 'true'
LogConfiguration:
LogDriver: 'awslogs'
Options:
awslogs-group: !Ref LogGroup
awslogs-region: 'ap-northeast-1'
awslogs-stream-prefix: 'fluentd'
MountPoints:
- SourceVolume: "varlog"
ContainerPath: "/var/log"
Volumes:
- Name: 'varlog'
Service
VPCやサブネットはこのスタックでは作らない。
CloudFormationでVPCを作成してLambdaをデプロイしAurora Serverlessを使う - sambaiz-net
Service:
Type: AWS::ECS::Service
Properties:
Cluster: !Ref Cluster
LaunchType: FARGATE
DesiredCount: 1
TaskDefinition: !Ref TaskDefinition
NetworkConfiguration:
AwsvpcConfiguration:
# If private subnet is placed, set 'DISABLED' to pull images
AssignPublicIp: 'ENABLED'
Subnets: !Ref Subnets
ServiceName: 'test-service'
確認
スタックを上げるとServiceからTaskが動き、S3の正しいパスにログが保存される。
保存されないときはfluent.confとCloudWatchにあるFluentdのログを、ymd=1970-01-01
になってしまった場合はtime_formatの内容や場所を、
時間がずれている場合はFluentdコンテナのタイムゾーンが正しいか確認する。