Skip to content
This repository has been archived by the owner on Apr 19, 2024. It is now read-only.

Commit

Permalink
Merge pull request #102 from michaelaw320/aws-ecs-discovery-example
Browse files Browse the repository at this point in the history
Add working example of aws ecs service discovery deployment
  • Loading branch information
thrawn01 authored Aug 19, 2021
2 parents 5ead080 + f4b5a0e commit c797905
Show file tree
Hide file tree
Showing 12 changed files with 377 additions and 0 deletions.
65 changes: 65 additions & 0 deletions examples/aws-ecs-service-discovery-deployment/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# examples/ecs-service-discovery-deployment

This example deploys Gubernator into AWS ECS with AWS ECS Service Discovery as peer discovery service.

This will set up an ECS Cluster that runs AWS Fargate Spot (which is very cheap to run).

To test this, you'd need to be inside the VPC that this example creates or somehow peer the VPC you're going to use with this example.

Also don't forget to add NS records generated from this to your main Hosted Zone.
e.g. your main hosted zone is `example.com` and you input `dns_namespace` as `gubernator.example.com`, this will create a new Hosted Zone in Route53 with NS record (`gubernator.example.com`) and make sure to add those NS record to `example.com` else when you query `gubernator.example.com` it won't work.
Real gubernator would be accessible in `app.gubernator.example.com`

## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.12.26 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 3.35.0 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | 3.54.0 |

## Modules

| Name | Source | Version |
|------|--------|---------|
| <a name="module_app_security_group"></a> [app\_security\_group](#module\_app\_security\_group) | terraform-aws-modules/security-group/aws | ~> 3.0 |
| <a name="module_ecs_cluster"></a> [ecs\_cluster](#module\_ecs\_cluster) | HENNGE/ecs/aws | ~> 2.0 |
| <a name="module_gubernator_service"></a> [gubernator\_service](#module\_gubernator\_service) | HENNGE/ecs/aws//modules/simple/fargate-spot | ~> 2.0 |
| <a name="module_vpc"></a> [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 3.0 |

## Resources

| Name | Type |
|------|------|
| [aws_cloudwatch_log_group.gubernator](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource |
| [aws_iam_role.ecs_agent_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role.ecs_task_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role_policy.ecs_agent](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource |
| [aws_iam_role_policy.ecs_exec_permissions](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource |
| [aws_iam_role_policy.ecs_task_cloudwatch_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource |
| [aws_service_discovery_public_dns_namespace.namespace](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/service_discovery_public_dns_namespace) | resource |
| [aws_service_discovery_service.gubernator](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/service_discovery_service) | resource |
| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source |
| [aws_region.current_region](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_dns_namespace"></a> [dns\_namespace](#input\_dns\_namespace) | The domain name the service should run. Your Gubernator instances will be available at `app.<your inputted fqdn>.` | `string` | n/a | yes |
| <a name="input_gubernator_config"></a> [gubernator\_config](#input\_gubernator\_config) | Map of ECS Configuration for gubernator service. map(cpu, memory) | `any` | <pre>{<br> "cpu": 256,<br> "memory": 512<br>}</pre> | no |
| <a name="input_gubernator_debug_mode"></a> [gubernator\_debug\_mode](#input\_gubernator\_debug\_mode) | Enable GUBER\_DEBUG env flag | `bool` | `false` | no |
| <a name="input_gubernator_repository"></a> [gubernator\_repository](#input\_gubernator\_repository) | Gubernator Docker Repository. e.g. thrawn01/gubernator | `string` | n/a | yes |
| <a name="input_gubernator_version"></a> [gubernator\_version](#input\_gubernator\_version) | Gubernator docker tag to use | `string` | n/a | yes |
| <a name="input_prefix"></a> [prefix](#input\_prefix) | Prefix of created resources | `string` | n/a | yes |
| <a name="input_vpc_cidr"></a> [vpc\_cidr](#input\_vpc\_cidr) | IPv4 CIDR Notation for VPC IP range. e.g. 10.3.0.0/16 | `string` | n/a | yes |

## Outputs

No outputs.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
resource "aws_cloudwatch_log_group" "gubernator" {
name = "${var.prefix}/gubernator"

retention_in_days = 90

lifecycle {
ignore_changes = [retention_in_days]
}
}
8 changes: 8 additions & 0 deletions examples/aws-ecs-service-discovery-deployment/ecs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module "ecs_cluster" {
source = "HENNGE/ecs/aws"
version = "~> 2.0"

name = "${var.prefix}-cluster"

enable_container_insights = true
}
66 changes: 66 additions & 0 deletions examples/aws-ecs-service-discovery-deployment/ecs_gubernator.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
data "aws_region" "current_region" {}

module "gubernator_service" {
source = "HENNGE/ecs/aws//modules/simple/fargate-spot"
version = "~> 2.0"

ignore_desired_count_changes = true

name = "${var.prefix}-gubernator-service"
cluster = module.ecs_cluster.name
cpu = var.gubernator_config["cpu"]
memory = var.gubernator_config["memory"]
desired_count = lookup(var.gubernator_config, "desired_count", 1)

iam_daemon_role = aws_iam_role.ecs_agent_role.arn
iam_task_role = aws_iam_role.ecs_task_role.arn

security_groups = [module.app_security_group.this_security_group_id]
vpc_subnets = module.vpc.public_subnets
assign_public_ip = true

service_registry = {
registry_arn = aws_service_discovery_service.gubernator.arn
}

container_definitions = jsonencode(
[
{
name = "gubernator",
image = "${var.gubernator_repository}:${var.gubernator_version}",
cpu = var.gubernator_config["cpu"],
memory = var.gubernator_config["memory"],
essential = true,
linuxParameters = {
initProcessEnabled = true
},
portMappings = [
{ containerPort = 80 },
{ containerPort = 81 },
],
logConfiguration = {
logDriver = "awslogs",
options = {
awslogs-group = aws_cloudwatch_log_group.gubernator.name,
awslogs-region = data.aws_region.current_region.name,
awslogs-stream-prefix = var.gubernator_version
}
},
environment = [
for env_key, env_value in local.gubernator_env_vars :
{
name = env_key,
value = env_value
}
],
}
]
)

enable_deployment_circuit_breaker_with_rollback = true
wait_for_steady_state = true
enable_execute_command = true

propagate_tags = "SERVICE"
enable_ecs_managed_tags = true
}
107 changes: 107 additions & 0 deletions examples/aws-ecs-service-discovery-deployment/ecs_iam.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
resource "aws_iam_role" "ecs_task_role" {
name = "${var.prefix}-ecs-task-role"

assume_role_policy = jsonencode(
{
Version = "2008-10-17",
Statement = [
{
Sid = "",
Effect = "Allow",
Principal = {
Service = "ecs-tasks.amazonaws.com"
},
Action = "sts:AssumeRole"
}
]
}
)
}

resource "aws_iam_role" "ecs_agent_role" {
name = "${var.prefix}-ecs-agent-role"

assume_role_policy = jsonencode(
{
Version = "2008-10-17",
Statement = [
{
Sid = "",
Effect = "Allow",
Principal = {
Service = "ecs-tasks.amazonaws.com"
},
Action = "sts:AssumeRole"
}
]
}
)
}

resource "aws_iam_role_policy" "ecs_task_cloudwatch_access" {
name = "${var.prefix}-ecs-task-cloudwatch-access"
role = aws_iam_role.ecs_task_role.id

policy = jsonencode(
{
Version = "2012-10-17",
Statement = [
{
Effect = "Allow",
Action = [
"sts:AssumeRole",
"logs:CreateLogStream",
"logs:PutLogEvents",
"logs:DescribeLogStreams",
"logs:GetLogEvents",
"cloudwatch:PutMetricData"
],
Resource = "*"
}
]
}
)
}

resource "aws_iam_role_policy" "ecs_exec_permissions" {
name = "${var.prefix}-ecs-exec-permissions"
role = aws_iam_role.ecs_task_role.id
policy = jsonencode(
{
Version = "2012-10-17",
Statement = [
{
Effect = "Allow",
Action = [
"ssmmessages:CreateControlChannel",
"ssmmessages:CreateDataChannel",
"ssmmessages:OpenControlChannel",
"ssmmessages:OpenDataChannel"
],
Resource = "*"
}
]
}
)
}

resource "aws_iam_role_policy" "ecs_agent" {
name = "${var.prefix}-ecs-agent"
role = aws_iam_role.ecs_agent_role.id

policy = jsonencode(
{
Version = "2012-10-17",
Statement = [
{
Effect = "Allow",
Action = [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
Resource = "*"
}
]
}
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
resource "aws_service_discovery_public_dns_namespace" "namespace" {
name = local.service_namespace
}

resource "aws_service_discovery_service" "gubernator" {
name = local.gubernator_service_discovery
dns_config {
namespace_id = aws_service_discovery_public_dns_namespace.namespace.id
dns_records {
ttl = 10
type = "A"
}
routing_policy = "MULTIVALUE"
}
health_check_custom_config {
failure_threshold = 1
}
}
12 changes: 12 additions & 0 deletions examples/aws-ecs-service-discovery-deployment/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
locals {
service_namespace = var.dns_namespace
gubernator_service_discovery = "app"
gubernator_service_host = "${local.gubernator_service_discovery}.${local.service_namespace}"
gubernator_env_vars = {
GUBER_GRPC_ADDRESS = "0.0.0.0:81"
GUBER_HTTP_ADDRESS = "0.0.0.0:80"
GUBER_PEER_DISCOVERY_TYPE = "dns"
GUBER_DNS_FQDN = local.gubernator_service_host
GUBER_DEBUG = var.gubernator_debug_mode ? "true" : "false"
}
}
Empty file.
22 changes: 22 additions & 0 deletions examples/aws-ecs-service-discovery-deployment/sg.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module "app_security_group" {
source = "terraform-aws-modules/security-group/aws"
version = "~> 3.0"

name = "${var.prefix}-app-sg"
vpc_id = module.vpc.vpc_id

# Ingress from this SG
ingress_with_self = [
{
rule = "all-all"
},
]

ingress_ipv6_cidr_blocks = [module.vpc.vpc_ipv6_cidr_block]
ingress_rules = ["all-all"]

# Allow all egress
egress_cidr_blocks = ["0.0.0.0/0"]
egress_ipv6_cidr_blocks = ["::/0"]
egress_rules = ["all-all"]
}
37 changes: 37 additions & 0 deletions examples/aws-ecs-service-discovery-deployment/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
variable "prefix" {
type = string
description = "Prefix of created resources"
}

# VPC Options
variable "vpc_cidr" {
description = "IPv4 CIDR Notation for VPC IP range. e.g. 10.3.0.0/16"
type = string
}

variable "dns_namespace" {
description = "The domain name the service should run. Your Gubernator instances will be available at `app.<your inputted fqdn>."
type = string
}

variable "gubernator_repository" {
type = string
description = "Gubernator Docker Repository. e.g. thrawn01/gubernator"
}

variable "gubernator_version" {
type = string
description = "Gubernator docker tag to use"
}

variable "gubernator_config" {
description = "Map of ECS Configuration for gubernator service. map(cpu, memory)"
default = { cpu = 256, memory = 512 }
type = any
}

variable "gubernator_debug_mode" {
description = "Enable GUBER_DEBUG env flag"
default = false
type = bool
}
10 changes: 10 additions & 0 deletions examples/aws-ecs-service-discovery-deployment/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
terraform {
required_version = ">= 0.12.26"

required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 3.35.0"
}
}
}
23 changes: 23 additions & 0 deletions examples/aws-ecs-service-discovery-deployment/vpc.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
data "aws_availability_zones" "available" {}

module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 3.0"

name = "${var.prefix}-vpc"
cidr = var.vpc_cidr
azs = data.aws_availability_zones.available.names

public_subnets = [for i in range(length(data.aws_availability_zones.available.names)) : cidrsubnet(var.vpc_cidr, 8, i)]

enable_nat_gateway = false
enable_dhcp_options = true
enable_dns_hostnames = true
enable_dns_support = true
dhcp_options_domain_name_servers = ["AmazonProvidedDNS"]

enable_ipv6 = true
assign_ipv6_address_on_creation = true
public_subnet_assign_ipv6_address_on_creation = true
public_subnet_ipv6_prefixes = range(length(data.aws_availability_zones.available.names))
}

0 comments on commit c797905

Please sign in to comment.