Имеется уже созданный стек с Application Load Balancer, для которого требуется включить сбор логов в S3 корзину.
Общая документация — тут>>>.
CloudFormation стек и ресурсы уже созданы, поэтому тут просто пример добавления необходимых параметров и новых ресурсов для включения логгирования запросов балансировщика.
Запуск CloudFormation выполняется из Ansible с помощью модуля cloudformation, и значения параметров будут заданы в файлах group_vars/envname.yml.
Содержание
Параметры
ALBLogsBucketName
Добавляем первый параметр, который будет указывать имя корзины для логов:
...
"ALBLogsBucketName": {
"Description": "S3 bucket name for ALB logs",
"Type": "String"
}
...
В Ansible задаём значение, например файл group_vars/mobilebackend-dev.yml:
... alb_logs_bucket_name: "mobilebackend-dev-alb-logs" ...
ALBRegionAccountID
Второй необходимый параметр — ALBRegionAccountID, в котором задаём ALB Account ID, который зависит от региона. Полный список ID есть тут>>>.
Т.к. тут есть явная зависимость от региона — то его лучше задать в Mappings шаблона.
Задаём маппинг для трёх регионов (у нас стеки могут быть только в них):
...
"Mappings": {
"ALBRegionAccountIDs": {
"us-east-2": {
"ALBRegionAccountID": "033677994240"
},
"us-east-1": {
"ALBRegionAccountID": "127311923021"
},
"eu-west-1": {
"ALBRegionAccountID": "156460612806"
}
},
...
Далее используем Fn::FindInMap для получения значений.
AWSAccountID
Для создания политики доступа к корзине — потребуется AWS Account ID, добавляем параметр для него:
...
"AWSAccountID": {
"Description": "AWS Console Account ID for S3 Bucket Policy",
"Type": "String"
}
...
И добавляем в Ansible.
Т.к. значение не зависит от рабочего окружения — передаём через group_vars/all.yml:
... aws_account_id: "534***385" ...
Можно зашифровать с помощью ansible-vault.
С параметрами вроде всё — переходим к ресурсам.
Ресурсы
Application Load Balancer attributes
Тут потребуется добавить несколько аттрибутов:
...
"LoadBalancerAttributes" : [
{
"Key": "idle_timeout.timeout_seconds",
"Value": 50
},
{
"Key": "routing.http2.enabled",
"Value": true
},
{
"Key": "access_logs.s3.prefix"
},
{
"Key": "deletion_protection.enabled",
"Value": true
},
{
"Key": "access_logs.s3.bucket",
"Value": {"Ref": "ALBLogsBucketName"}
},
{
"Key": "access_logs.s3.enabled",
"Value": true
}
],
...
В access_logs.s3.bucket передаём собственно имя корзины, в которую ALB будет складывать логи.
Кроме того — добавляем явное указание на зависимость ресурса ALB от корзины и её политики через аттрибут DependsOn:
...
"MBApploadBalancer" : {
"Type": "AWS::ElasticLoadBalancingV2::LoadBalancer",
"DependsOn": ["AlbLogsBucket", "BucketPolicy"],
"Properties": {
"Scheme": "internet-facing",
...
AWS::S3::Bucket
Добавляем создание корзины:
...
"AlbLogsBucket": {
"Type": "AWS::S3::Bucket",
"DeletionPolicy": "Delete",
"Properties": {
"BucketName": {
"Ref": "ALBLogsBucketName"
}
}
},
...
AWS::S3::BucketPolicy
Что бы ALB имел доступ на запись логов в корзину — создаём политику доступа к корзине:
...
"BucketPolicy": {
"Type": "AWS::S3::BucketPolicy",
"Properties": {
"PolicyDocument": {
"Id": "MyPolicy",
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": {
"Fn::Sub": [
"arn:aws:iam::${ALBRegionAccountID}:root", { "ALBRegionAccountID": {
"Fn::FindInMap": [ "ALBRegionAccountIDs", {"Ref" : "StackRegion"}, "ALBRegionAccountID" ] }
}
]
}
},
"Action": "s3:PutObject",
"Resource": {
"Fn::Join" : [ "",
[
"arn:aws:s3:::", {"Ref" : "ALBLogsBucketName"}, "/AWSLogs/", {"Ref" : "AWSAccountID"}, "/*"
]
]
}
}
]
},
"Bucket": {
"Ref": "AlbLogsBucket"
}
}
},
...
Principal: тут используемFn::Sub, из которой формируем строку вида arn:aws:iam::033677994240:root, используя параметрStackRegionдля выборки значенияALBRegionAccountIDизMappings, который создали выше- Resource: используя Fn::Join — формируем строку вида arn:aws:s3:::mobilebackend-dev-alb-logs/AWSLogs/534***385/*
Вроде ОК?
Тут я использую скрипт, аналогичный этому>>> — запускаем проверку:
[simterm]
$ ./ansible_exec.sh -c Tags: infra Env: mobilebackend-dev ... Running dry-run... ... Dry-run check passed. ... PLAY RECAP **** dev.backend-bastion.example.world : ok=3 changed=1 unreachable=0 failed=0 Provisioning done.
[/simterm]
Проверяем аттрибуты ALB:
И корзину с логами:
Готово.
P.S. Позже сюда ещё добавил LifecycleConfiguration с ExpirationInDays:
...
"AlbLogsBucket": {
"Type": "AWS::S3::Bucket",
"DeletionPolicy": "Delete",
"Properties": {
"BucketName": {
"Ref": "ALBLogsBucketName"
},
"LifecycleConfiguration": {
"Rules": [
{
"Id": "CleanLogs",
"Prefix": "",
"Status": "Enabled",
"ExpirationInDays": { "Ref": "ALBLogsExpirationInDays" }
}
]
}
}
},
...
ALBLogsExpirationInDays опять-таки передаём в Ansible роль:
...
ALBLogsExpirationInDays: "{{ alb_logs_expiration_in_days }}"
...
Из файлов в group_vars:
... alb_logs_expiration_in_days: 3 ...
Вот теперь — точно готово.

