Skip to content

Commit

Permalink
OpenTracing, Worker Healthcheck, Filter EIPs by a service name, fix D…
Browse files Browse the repository at this point in the history
…atadog, Balancer-less EC apps

- Added OpenTracing configuration for Datadog
- Added healthcheck parameter for worker apps
- Filter EIPs by service name during instance launch
- Fix datadog agent hostname to work in host network mode
- EC2 port mappings exposure and Balancer-less instances
  • Loading branch information
AutomationD committed May 25, 2022
1 parent 99be7b5 commit ce9d119
Show file tree
Hide file tree
Showing 10 changed files with 123 additions and 46 deletions.
2 changes: 2 additions & 0 deletions autoscaling.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ resource "aws_eip" "autoscaling" {
# If ec2_eip_count is set, use that number for number of EIPs, otherwise use var.max_size + 1 (but that might not be the best during downscaling and deletion of EIPs
count = var.ec2_eip_enabled ? (var.ec2_eip_count > 0 ? var.ec2_eip_count : var.max_size + 1) : 0
public_ipv4_pool = "amazon"
vpc = true

tags = {
Name = "${local.name}-${count.index + 1}"
env = var.env
service = local.name
}
}

Expand Down
1 change: 1 addition & 0 deletions data.tf
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ data "template_file" "asg_ecs_ec2_user_data" {

vars = {
ecs_cluster_name = local.ecs_cluster_name
service = local.name
env = var.env
ec2_service_group = var.ec2_service_group
ec2_eip_enabled = tostring(var.ec2_eip_enabled)
Expand Down
22 changes: 12 additions & 10 deletions ecs-modules/ecs-service/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ module "task" {
env = var.env
name = var.name

ecs_task_family_name = var.ecs_service_name != "" ? var.ecs_service_name : ""
ecs_launch_type = var.ecs_launch_type
ecs_network_mode = var.ecs_network_mode
ecs_volumes_from = var.ecs_volumes_from
ecs_exec_enabled = var.ecs_exec_enabled
ecs_task_family_name = var.ecs_service_name != "" ? var.ecs_service_name : ""
ecs_launch_type = var.ecs_launch_type
ecs_network_mode = var.ecs_network_mode
ecs_volumes_from = var.ecs_volumes_from
ecs_exec_enabled = var.ecs_exec_enabled
ecs_task_health_check_command = var.ecs_task_health_check_command

docker_image_name = var.docker_image_name
docker_image_tag = var.docker_image_tag
Expand Down Expand Up @@ -81,7 +82,7 @@ resource "aws_ecs_service" "this" {


dynamic "service_registries" {
for_each = (var.ecs_launch_type == "FARGATE" && var.ecs_service_discovery_enabled) ? [
for_each = (var.ecs_launch_type == "FARGATE" && var.ecs_service_discovery_enabled && var.app_type == "web") ? [
1
] : []
content {
Expand All @@ -102,14 +103,14 @@ resource "aws_ecs_service" "this" {
}

dynamic "load_balancer" {
for_each = [
for_each = var.app_type == "web" ? [
for p in var.port_mappings : {
container_name = p.container_name
target_group_arn = p.target_group_arn
container_port = p.container_port

}
]
]: []

content {
target_group_arn = load_balancer.value.target_group_arn
Expand Down Expand Up @@ -176,13 +177,14 @@ resource "aws_ecs_service" "this_deployed" {
}

dynamic "load_balancer" {
for_each = [
for_each = var.app_type == "web" ? [
for p in var.port_mappings : {
container_name = p.container_name
container_port = p.container_port
target_group_arn = p.target_group_arn
}
]
] : []


content {
target_group_arn = load_balancer.value.target_group_arn
Expand Down
16 changes: 16 additions & 0 deletions ecs-modules/ecs-service/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@ variable "name" {
description = "ECS app name"
}

variable "app_type" {
type = string
description = "ECS application type. Valid values: web (with load balancer), worker (scheduled task without ALB)."
default = "web"

validation {
condition = var.app_type == "web" || var.app_type == "worker"
error_message = "The app_type value must be a valid type: web or worker."
}
}

variable "namespace" {
type = string
description = "Namespace name within the infrastructure"
Expand Down Expand Up @@ -284,6 +295,11 @@ variable "aws_service_discovery_private_dns_namespace" {
default = ""
}

variable "ecs_task_health_check_command" {
type = string
description = "Command to check for the health of the container"
}

variable "ecs_network_mode" {
type = string
description = "Corresponds to networkMode in an ECS task definition. Supported values are none, bridge, host, or awsvpc"
Expand Down
17 changes: 16 additions & 1 deletion ecs-modules/ecs-task/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ locals {
cpu = var.ecs_launch_type == "FARGATE" ? var.cpu : null
memoryReservation = var.memory_reservation
essential = true
healthCheck = length(var.ecs_task_health_check_command) > 0 ? {
retries = 3
timeout = 5
interval = 30
startPerid = null
command = [
"CMD-SHELL",
var.ecs_task_health_check_command
]
} : null

linuxParameters = {
sharedMemorySize = (var.shared_memory_size > 0 && var.ecs_launch_type != "FARGATE") ? var.shared_memory_size : null
Expand Down Expand Up @@ -74,7 +84,7 @@ locals {
"Name" = "datadog"
"Host" = "http-intake.logs.datadoghq.com"
"apiKey" = data.aws_ssm_parameter.dd_api_key[0].value
"dd_service" = "${var.name}"
"dd_service" = var.name
"dd_source" = "ecs"
"dd_tags" = "fluentbit:true,env:${var.env},service:${var.env}-${var.name}"
"dd_message_key" = "log"
Expand Down Expand Up @@ -338,6 +348,11 @@ variable "ecs_volumes_from" {
default = []
}

variable "ecs_task_health_check_command" {
type = string
description = "Command to check for the health of the container"
}

variable "resource_requirements" {
type = list(any)
description = "The ResourceRequirement property specifies the type and amount of a resource to assign to a container. The only supported resource is a GPU"
Expand Down
2 changes: 1 addition & 1 deletion ecs_ec2_user_data.sh.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ aws_get_instance_environment() {
}

aws_get_unassigned_eips() {
local describe_addreses_response=$(aws ec2 describe-addresses --region $instance_region --filters "Name=tag:env,Values=$instance_environment" --query "Addresses[?AssociationId==null].AllocationId" --output text)
local describe_addreses_response=$(aws ec2 describe-addresses --region $instance_region --filters "Name=tag:env,Values=$instance_environment" "Name=tag:service,Values=${service}" --query "Addresses[?AssociationId==null].AllocationId" --output text)
eips=($${describe_addreses_response///})
if [ -n "$describe_addreses_response" ]; then return 0; else return 1; fi
}
Expand Down
55 changes: 32 additions & 23 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -98,21 +98,23 @@ module "service" {
env = var.env
name = var.name
namespace = var.namespace
app_type = var.app_type
ecs_cluster_name = local.ecs_cluster_name
ecs_service_name = local.ecs_service_name

ecs_platform_version = var.ecs_launch_type == "FARGATE" ? var.ecs_platform_version : null
ecs_launch_type = var.ecs_launch_type
ec2_service_group = var.ec2_service_group
docker_container_port = var.docker_container_port
ecs_network_mode = var.ecs_network_mode
ecs_volumes_from = var.ecs_volumes_from
cpu = var.cpu
memory = var.memory
memory_reservation = var.memory_reservation
volumes = local.volumes
assign_public_ip = var.assign_public_ip
security_groups = var.security_groups
ecs_platform_version = var.ecs_launch_type == "FARGATE" ? var.ecs_platform_version : null
ecs_launch_type = var.ecs_launch_type
ecs_task_health_check_command = var.ecs_task_health_check_command
ec2_service_group = var.ec2_service_group
docker_container_port = var.docker_container_port
ecs_network_mode = var.ecs_network_mode
ecs_volumes_from = var.ecs_volumes_from
cpu = var.cpu
memory = var.memory
memory_reservation = var.memory_reservation
volumes = local.volumes
assign_public_ip = var.assign_public_ip
security_groups = var.security_groups

web_proxy_enabled = var.web_proxy_enabled
ecs_exec_enabled = var.ecs_exec_enabled
Expand Down Expand Up @@ -189,35 +191,42 @@ module "service" {
# TODO: instead of hardcoding the index, better use dynamic lookup by a canonical name
target_group_arn = var.app_type == "web" && length(module.alb[*].target_group_arns) >= 1 ? module.alb[0].target_group_arns[0] : null

port_mappings = var.app_type == "web" ? [
port_mappings = jsondecode(var.app_type == "web" ? jsonencode([
{
container_name = var.web_proxy_enabled ? "nginx" : var.name
container_port = var.web_proxy_enabled ? var.web_proxy_docker_container_port : var.docker_container_port
host_port = var.ecs_network_mode == "awsvpc" ? (var.web_proxy_enabled ? var.web_proxy_docker_container_port : var.docker_container_port) : var.docker_host_port
target_group_arn = length(module.alb[*].target_group_arns) >= 1 ? module.alb[0].target_group_arns[0] : ""
}
] : []
]) : jsonencode(var.port_mappings))

environment = merge(var.environment, local.datadog_env_vars, local.ecs_exec_env_vars, {
APP_NAME = var.name
ENV = var.env
PROXY_ENABLED = var.web_proxy_enabled ? "true" : "false"
}, var.ecs_launch_type == "EC2" ? {
DD_AGENT_HOST = "datadog-agent"
} : {}
}
)
}

resource "aws_route53_record" "this" {
resource "aws_route53_record" "alb" {
count = var.app_type == "web" ? length(local.domain_names) : 0
zone_id = var.zone_id
name = local.domain_names[count.index]
type = "A"

alias {
name = module.alb[0].this_lb_dns_name
zone_id = module.alb[0].this_lb_zone_id
evaluate_target_health = true
}
alias {
name = module.alb[0].this_lb_dns_name
zone_id = module.alb[0].this_lb_zone_id
evaluate_target_health = true
}
}

resource "aws_route53_record" "ec2" {
count = (var.ecs_launch_type == "EC2" && var.ec2_eip_enabled && var.ec2_eip_dns_enabled) ? length(local.domain_names) : 0
zone_id = var.zone_id
name = local.domain_names[count.index]
type = "A"

records = var.ec2_eip_enabled ? aws_eip.autoscaling.*.public_ip : []
}

4 changes: 2 additions & 2 deletions monitoring.tf
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Datadog Logging/Monitoring Module (can be enabled/disabled via datadog_enabled)
module "datadog" {
source = "hazelops/ecs-datadog-agent/aws"
version = "~> 3.0"
version = "~> 3.2"

app_name = var.name
env = var.env
Expand All @@ -20,7 +20,7 @@ module "route_53_health_check" {

enabled = var.route53_health_check_enabled
env = var.env
fqdn = var.app_type == "web" ? aws_route53_record.this[0].name : null
fqdn = var.app_type == "web" ? aws_route53_record.alb[0].name : null
domain_name = var.root_domain_name
name = var.name
subscription_endpoint_protocol = var.sns_service_subscription_endpoint_protocol
Expand Down
8 changes: 8 additions & 0 deletions outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,11 @@ output "efs" {
output "eips" {
value = var.ec2_eip_enabled ? aws_eip.autoscaling.*.public_ip : []
}

output "public_ip" {
value = (var.ec2_eip_enabled && length(aws_eip.autoscaling)>0) ? aws_eip.autoscaling.0.public_ip : ""
}

output "ec2_dns_name" {
value = var.ec2_eip_dns_enabled ? aws_route53_record.ec2.0.fqdn : ""
}
42 changes: 33 additions & 9 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,21 @@ locals {
# Datadog Environment Variables: https://docs.datadoghq.com/agent/guide/environment-variables/
# https://docs.datadoghq.com/agent/docker/apm/?tab=linux#docker-apm-agent-environment-variables
datadog_env_vars = var.datadog_enabled ? {
DD_PROFILING_ENABLED = "true"
DD_TRACE_ENABLED = "true"
DD_RUNTIME_METRICS_ENABLED = "true"
DD_APM_ENABLED = "true"
DD_SERVICE = var.name
DD_SERVICE_NAME = var.name
DD_ENV = var.env
DD_PROFILING_ENABLED = "true"
DD_TRACE_ENABLED = "true"
DD_RUNTIME_METRICS_ENABLED = "true"
DD_APM_ENABLED = "true"
DD_SERVICE = var.name
DD_SERVICE_NAME = var.name
DD_ENV = var.env
DD_AGENT_HOST = local.datadog_agent_host
OTEL_EXPORTER_OTLP_ENDPOINT = "http://${local.datadog_agent_host}:4318"
OTEL_TRACES_EXPORTER = "otlp"
OTEL_RESOURCE_ATTRIBUTES = "service.name=${var.name}"
} : {}

datadog_agent_host = (var.ecs_network_mode != "host" && var.ecs_network_mode != "awsvpc") ? "datadog-agent" : "localhost"

ecs_exec_env_vars = var.ecs_exec_custom_prompt_enabled ? {
PS1 = var.ecs_exec_prompt_string
} : {}
Expand Down Expand Up @@ -115,7 +121,7 @@ variable "name" {

variable "app_type" {
type = string
description = "ECS application type. Valid values: web (with load balancer), worker (scheduled task without ALB)."
description = "ECS application type. Valid values: web (with ALB), worker (without ALB)."
default = "web"

validation {
Expand Down Expand Up @@ -146,7 +152,7 @@ variable "ec2_service_group" {
variable "instance_type" {
type = string
description = "EC2 instance type for ECS"
default = "t3.micro"
default = "t3.small"
}

variable "environment" {
Expand Down Expand Up @@ -298,6 +304,12 @@ variable "docker_host_port" {
default = 0
}

variable "port_mappings" {
description = "List of ports to open from a service"
type = list(any)
default = []
}

variable "docker_container_entrypoint" {
type = list(string)
description = "Docker container entrypoint"
Expand Down Expand Up @@ -382,6 +394,12 @@ variable "ec2_eip_count" {
default = 0
}

variable "ec2_eip_dns_enabled" {
type = bool
description = "Whether to manage DNS records to be attached to the EIP"
default = false
}


variable "ecs_cluster_name" {
type = string
Expand All @@ -395,6 +413,12 @@ variable "autoscaling_health_check_type" {
default = "EC2"
}

variable "ecs_task_health_check_command" {
type = string
description = "Command to check for the health of the container"
default = ""
}

variable "alb_health_check_path" {
type = string
description = "ALB health check path"
Expand Down

0 comments on commit ce9d119

Please sign in to comment.