Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(logging): using init-fluent-bit images #140

Merged
merged 8 commits into from
May 6, 2024
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ for example.
| [aws_iam_policy.acm](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
| [aws_iam_policy.cloudwatch_logs_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
| [aws_iam_policy.enable_execute_command](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
| [aws_iam_policy.fluent_bit_config_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
| [aws_iam_policy.otel](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
| [aws_iam_role.ecs_task_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role.task_execution_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
Expand All @@ -194,6 +195,7 @@ for example.
| [aws_iam_role_policy_attachment.appmesh](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_iam_role_policy_attachment.cloudwatch_logs_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_iam_role_policy_attachment.enable_execute_command](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_iam_role_policy_attachment.fluent_bit_config_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_iam_role_policy_attachment.otel](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_security_group_rule.trusted_egress_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
| [aws_service_discovery_service.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/service_discovery_service) | resource |
Expand All @@ -205,6 +207,7 @@ for example.
| [aws_iam_policy_document.cloudwatch_logs_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.ecs_task_assume_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.enable_execute_command](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.fluent_bit_config_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.otel](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.task_execution_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_lb.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/lb) | data source |
Expand Down Expand Up @@ -258,7 +261,7 @@ for example.
| <a name="input_ecr_repository_name"></a> [ecr\_repository\_name](#input\_ecr\_repository\_name) | Existing repo to register to use with this service module, e.g. creating deployment pipelines. | `string` | `""` | no |
| <a name="input_efs_volumes"></a> [efs\_volumes](#input\_efs\_volumes) | Configuration block for EFS volumes. | `any` | `[]` | no |
| <a name="input_enable_execute_command"></a> [enable\_execute\_command](#input\_enable\_execute\_command) | Specifies whether to enable Amazon ECS Exec for the tasks within the service. | `bool` | `false` | no |
| <a name="input_firelens"></a> [firelens](#input\_firelens) | Configuration for optional custom log routing using FireLens over fluentbit sidecar. | <pre>object({<br> container_name = optional(string, "fluentbit")<br> container_definition = optional(any, {})<br> enabled = optional(bool, false)<br> opensearch_host = optional(string, "")<br> })</pre> | `{}` | no |
| <a name="input_firelens"></a> [firelens](#input\_firelens) | Configuration for optional custom log routing using FireLens over fluentbit sidecar. Enable `attach_init_config_s3_policy` to attach an IAM policy granting access to the init config files on S3. | <pre>object({<br> attach_init_config_s3_policy = optional(bool, false)<br> container_name = optional(string, "fluentbit")<br> container_definition = optional(any, {})<br> enabled = optional(bool, false)<br> init_config_files = optional(list(string), [])<br> log_level = optional(string, "info")<br> opensearch_host = optional(string, "")<br> })</pre> | `{}` | no |
| <a name="input_force_new_deployment"></a> [force\_new\_deployment](#input\_force\_new\_deployment) | Enable to force a new task deployment of the service. This can be used to update tasks to use a newer Docker image with same image/tag combination (e.g. myimage:latest), roll Fargate tasks onto a newer platform version, or immediately deploy ordered\_placement\_strategy and placement\_constraints updates. | `bool` | `false` | no |
| <a name="input_health_check_grace_period_seconds"></a> [health\_check\_grace\_period\_seconds](#input\_health\_check\_grace\_period\_seconds) | Seconds to ignore failing load balancer health checks on newly instantiated tasks to prevent premature shutdown, up to 2147483647. Only valid for services configured to use load balancers. | `number` | `0` | no |
| <a name="input_https_listener_rules"></a> [https\_listener\_rules](#input\_https\_listener\_rules) | A list of maps describing the Listener Rules for this ALB. Required key/values: actions, conditions. Optional key/values: priority, https\_listener\_index (default to https\_listeners[count.index]) | `any` | `[]` | no |
Expand Down
1 change: 1 addition & 0 deletions container_definition.tf
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ locals {
name = var.service_name
readonlyRootFilesystem = true
mountPoints = []
systemControls = []
user = startswith(upper(var.operating_system_family), "WINDOWS") ? null : "0"
volumesFrom = []

Expand Down
1 change: 1 addition & 0 deletions envoy.tf
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ locals {
mountPoints = []
portMappings = []
readonlyRootFilesystem = false
systemControls = []
user = startswith(upper(var.operating_system_family), "WINDOWS") ? null : "1337:1337"
volumesFrom = []

Expand Down
74 changes: 60 additions & 14 deletions fluentbit.tf
Original file line number Diff line number Diff line change
@@ -1,40 +1,52 @@
locals {
s3_arn_regex = "^arn:.*:s3:"

// additional init config files from S3 or files inside a custom image
// which are added to the FluentBit container as environment variables, see
// https://github.com/aws/aws-for-fluent-bit/tree/develop/use_cases/init-process-for-fluent-bit
init_config_files = [
for idx, file_or_arn in var.firelens.init_config_files : {
name = format(can(regex(local.s3_arn_regex, file_or_arn)) ? "aws_fluent_bit_init_s3_%s" : "aws_fluent_bit_init_file_%s", idx)
value = file_or_arn
}
]

// default image tag for the FluentBit container
image_tag = length(local.init_config_files) > 0 ? "init-2.32.2.20240425" : "2.32.2.20240425"

// additional init config files ARNs from S3 to be used in an IAM policy for the task role
s3_init_file_arns = [for conf in local.init_config_files : conf.value if can(regex(local.s3_arn_regex, conf.value))]
s3_init_bucket_arns = distinct([for arn in local.s3_init_file_arns : split("/", arn)[0]])

// optional FluentBit container for log aggregation
fluentbit_container_defaults = {
name = var.firelens.container_name
image = "${data.aws_caller_identity.current.account_id}.dkr.ecr.${data.aws_region.current.name}.amazonaws.com/ecr-public/aws-observability/aws-for-fluent-bit:2.32.0"
image = "${data.aws_caller_identity.current.account_id}.dkr.ecr.${data.aws_region.current.name}.amazonaws.com/ecr-public/aws-observability/aws-for-fluent-bit:${local.image_tag}"
environment = concat([{ name = "FLB_LOG_LEVEL", value = var.firelens.log_level }], local.init_config_files)
essential = true
mountPoints = []
portMappings = []
readonlyRootFilesystem = false
systemControls = []
user = startswith(upper(var.operating_system_family), "WINDOWS") ? null : "0:1337"
volumesFrom = []

environment = [
// Valid values are: debug, info and error
{ name = " FLB_LOG_LEVEL", value = "error" }
],

healthCheck = {
retries = 3
command = [
"CMD-SHELL",
"curl -s http://localhost:2020/api/v1/uptime | grep uptime_hr | grep -q running"
length(local.init_config_files) > 0 ? "curl --fail localhost:2020/api/v1/uptime" : "curl -s http://localhost:2020/api/v1/uptime | grep uptime_hr | grep -q running"
]
timeout = 2
interval = 5
startPeriod = 10
}


firelensConfiguration = {
type = "fluentbit"
options = {
enable-ecs-log-metadata : "true",
config-file-type : "file",
config-file-value : "/fluent-bit/config/envoy-json.conf"
}
type = "fluentbit"
options = { enable-ecs-log-metadata : "true" }
}

logConfiguration = var.cloudwatch_logs.enabled ? {
logDriver = "awslogs"
options = {
Expand All @@ -58,3 +70,37 @@ module "fluentbit_container_definition" {
var.firelens.container_definition
]
}

data "aws_iam_policy_document" "fluent_bit_config_access" {
count = var.firelens.enabled && var.task_role_arn == "" && length(local.s3_init_file_arns) > 0 && var.firelens.attach_init_config_s3_policy ? 1 : 0

// allow reading the init config files from S3
statement {
effect = "Allow"
actions = ["s3:GetObject"]
resources = local.s3_init_file_arns
}

// allow listing the S3 buckets containing the init config files
statement {
effect = "Allow"
actions = ["s3:GetBucketLocation"]
resources = local.s3_init_bucket_arns
}

}

resource "aws_iam_policy" "fluent_bit_config_access" {
count = var.firelens.enabled && var.task_role_arn == "" && length(local.s3_init_file_arns) > 0 && var.firelens.attach_init_config_s3_policy ? 1 : 0

name = "fluent-bit-config-access-${var.service_name}-${data.aws_region.current.name}"
path = "/ecs/task-role/"
policy = data.aws_iam_policy_document.fluent_bit_config_access[count.index].json
}

resource "aws_iam_role_policy_attachment" "fluent_bit_config_access" {
count = var.firelens.enabled && var.task_role_arn == "" && length(local.s3_init_file_arns) > 0 && var.firelens.attach_init_config_s3_policy ? 1 : 0

role = aws_iam_role.ecs_task_role[count.index].name
policy_arn = aws_iam_policy.fluent_bit_config_access[count.index].arn
}
1 change: 1 addition & 0 deletions otel.tf
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ locals {
readonlyRootFilesystem = false
mountPoints = []
portMappings = []
systemControls = []
ulimits = []
user = startswith(upper(var.operating_system_family), "WINDOWS") ? null : "0:1337"
volumesFrom = []
Expand Down
24 changes: 13 additions & 11 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,18 @@ variable "app_mesh" {
})
}

variable "appautoscaling_settings" {
default = null
description = "Autoscaling configuration for this service."
type = map(any)
}

variable "assign_public_ip" {
default = false
description = "Assign a public IP address to the ENI of this service."
type = bool
}

variable "appautoscaling_settings" {
default = null
description = "Autoscaling configuration for this service."
type = map(any)
}

variable "capacity_provider_strategy" {
default = null
description = "Capacity provider strategies to use for the service. Can be one or more."
Expand Down Expand Up @@ -323,13 +322,16 @@ variable "efs_volumes" {
}

variable "firelens" {
description = "Configuration for optional custom log routing using FireLens over fluentbit sidecar."
description = "Configuration for optional custom log routing using FireLens over fluentbit sidecar. Enable `attach_init_config_s3_policy` to attach an IAM policy granting access to the init config files on S3."
default = {}
type = object({
container_name = optional(string, "fluentbit")
container_definition = optional(any, {})
enabled = optional(bool, false)
opensearch_host = optional(string, "")
attach_init_config_s3_policy = optional(bool, false)
container_name = optional(string, "fluentbit")
container_definition = optional(any, {})
enabled = optional(bool, false)
init_config_files = optional(list(string), [])
log_level = optional(string, "info")
opensearch_host = optional(string, "")
})
}

Expand Down