Stack

November 1, 2017 · View on GitHub

The stack module combines sub modules to create a complete stack with vpc, a default ecs cluster with auto scaling and a bastion node that enables you to access all instances.

Usage:

module "stack" {
  source      = "github.com/segmentio/stack"
  name        = "mystack"
  environment = "prod"
}

Available Modules

Inputs

NameDescriptionDefaultRequired
namethe name of your stack, e.g. "segment"-yes
environmentthe name of your environment, e.g. "prod-west"-yes
key_namethe name of the ssh key to use, e.g. "internal-key"-yes
domain_namethe internal DNS name to use with servicesstack.localno
domain_name_serversthe internal DNS servers, defaults to the internal route53 server of the VPC``no
regionthe AWS region in which resources are created, you must set the availability_zones variable as well if you define this value to something other than the defaultus-west-2no
cidrthe CIDR block to provision for the VPC, if set to something other than the default, both internal_subnets and external_subnets have to be defined as well10.30.0.0/16no
internal_subnetsa list of CIDRs for internal subnets in your VPC, must be set if the cidr variable is defined, needs to have as many elements as there are availability zones<list>no
external_subnetsa list of CIDRs for external subnets in your VPC, must be set if the cidr variable is defined, needs to have as many elements as there are availability zones<list>no
use_nat_instancesuse NAT EC2 instances instead of the NAT gateway servicefalseno
use_eip_with_nat_instancesuse Elastic IPs with NAT instances if use_nat_instances is truefalseno
nat_instance_typethe EC2 instance type for NAT instances if use_nat_instances is truet2.nanono
nat_instance_ssh_key_namethe name of the ssh key to use with NAT instances if use_nat_instances is true""no
availability_zonesa comma-separated list of availability zones, defaults to all AZ of the region, if set to something other than the defaults, both internal_subnets and external_subnets have to be defined as well<list>no
bastion_instance_typeInstance type for the bastiont2.microno
ecs_cluster_namethe name of the cluster, if not specified the variable name will be used``no
ecs_instance_typethe instance type to use for your default ecs clusterm4.largeno
ecs_instance_ebs_optimizeduse EBS - not all instance types support EBStrueno
ecs_min_sizethe minimum number of instances to use in the default ecs cluster3no
ecs_max_sizethe maximum number of instances to use in the default ecs cluster100no
ecs_desired_capacitythe desired number of instances to use in the default ecs cluster3no
ecs_root_volume_sizethe size of the ecs instance root volume25no
ecs_docker_volume_sizethe size of the ecs instance docker volume25no
ecs_docker_auth_typeThe docker auth type, see https://godoc.org/github.com/aws/amazon-ecs-agent/agent/engine/dockerauth for the possible values``no
ecs_docker_auth_dataA JSON object providing the docker auth data, see https://godoc.org/github.com/aws/amazon-ecs-agent/agent/engine/dockerauth for the supported formats``no
ecs_security_groupsA comma separated list of security groups from which ingest traffic will be allowed on the ECS cluster, it defaults to allowing ingress traffic on port 22 and coming from the ELBs``no
ecs_amiThe AMI that will be used to launch EC2 instances in the ECS cluster``no
extra_cloud_config_typeExtra cloud config typetext/cloud-configno
extra_cloud_config_contentExtra cloud config content``no

Outputs

NameDescription
regionThe region in which the infra lives.
bastion_ipThe bastion host IP.
zone_idThe internal route53 zone ID.
internal_elbSecurity group for internal ELBs.
external_elbSecurity group for external ELBs.
internal_subnetsComma separated list of internal subnet IDs.
external_subnetsComma separated list of external subnet IDs.
iam_roleECS Service IAM role.
iam_role_default_ecs_role_idDefault ECS role ID. Useful if you want to add a new policy to that role.
log_bucket_idS3 bucket ID for ELB logs.
domain_nameThe internal domain name, e.g "stack.local".
environmentThe environment of the stack, e.g "prod".
clusterThe default ECS cluster name.
availability_zonesThe VPC availability zones.
vpc_security_groupThe VPC security group ID.
vpc_idThe VPC ID.
ecs_cluster_security_group_idThe default ECS cluster security group ID.
internal_route_tablesComma separated list of internal route table IDs.
external_route_tablesThe external route table ID.

bastion

The bastion host acts as the "jump point" for the rest of the infrastructure. Since most of our instances aren't exposed to the external internet, the bastion acts as the gatekeeper for any direct SSH access. The bastion is provisioned using the key name that you pass to the stack (and hopefully have stored somewhere). If you ever need to access an instance directly, you can do it by "jumping through" the bastion.

terraform output # print the bastion ip ssh -i <path/to/key> ubuntu@ ssh ubuntu@

Usage:

module "bastion" {
  source            = "github.com/segmentio/stack/bastion"
  region            = "us-west-2"
  security_groups   = "sg-1,sg-2"
  vpc_id            = "vpc-12"
  key_name          = "ssh-key"
  subnet_id         = "pub-1"
  environment       = "prod"
}

Inputs

NameDescriptionDefaultRequired
instance_typeInstance type, see a list at: https://aws.amazon.com/ec2/instance-types/t2.microno
regionAWS Region, e.g us-west-2-yes
security_groupsa comma separated lists of security group IDs-yes
vpc_idVPC ID-yes
key_nameThe SSH key pair, key name-yes
subnet_idA external subnet id-yes
environmentEnvironment tag, e.g prod-yes

Outputs

NameDescription
external_ipBastion external IP address.

defaults

This module is used to set configuration defaults for the AWS infrastructure. It doesn't provide much value when used on its own because terraform makes it hard to do dynamic generations of things like subnets, for now it's used as a helper module for the stack.

Usage:

module "defaults" {
  source = "github.com/segmentio/stack/defaults"
  region = "us-east-1"
  cidr   = "10.0.0.0/16"
}

Inputs

NameDescriptionDefaultRequired
regionThe AWS region-yes
cidrThe CIDR block to provision for the VPC-yes
default_ecs_ami<map>no
default_log_account_ids# http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/enable-access-logs.html#attach-bucket-policy<map>no

Outputs

NameDescription
domain_name_servers
ecs_ami
s3_logs_account_id

dhcp

Inputs

NameDescriptionDefaultRequired
nameThe domain name to setup DHCP for-yes
vpc_idThe ID of the VPC to setup DHCP for-yes
serversA comma separated list of the IP addresses of internal DHCP servers-yes

dns

The dns module creates a local route53 zone that serves as a service discovery utility. For example a service resource with the name auth and a dns module with the name stack.local, the service address will be auth.stack.local.

Usage:

module "dns" {
  source = "github.com/segment/stack"
  name   = "stack.local"
}

Inputs

NameDescriptionDefaultRequired
nameZone name, e.g stack.local-yes
vpc_idThe VPC ID (omit to create a public zone)``no

Outputs

NameDescription
nameThe domain name.
zone_idThe zone ID.
name_serversA comma separated list of the zone name servers.

ecs-cluster

ECS Cluster creates a cluster with the following features:

  • Autoscaling groups
  • Instance tags for filtering
  • EBS volume for docker resources

Usage:

 module "cdn" {
   source               = "github.com/segmentio/stack/ecs-cluster"
   environment          = "prod"
   name                 = "cdn"
   vpc_id               = "vpc-id"
   image_id             = "ami-id"
   subnet_ids           = ["1" ,"2"]
   key_name             = "ssh-key"
   security_groups      = "1,2"
   iam_instance_profile = "id"
   region               = "us-west-2"
   availability_zones   = ["a", "b"]
   instance_type        = "t2.small"
 }

Inputs

NameDescriptionDefaultRequired
nameThe cluster name, e.g cdn-yes
environmentEnvironment tag, e.g prod-yes
vpc_idVPC ID-yes
image_idAMI Image ID-yes
subnet_idsList of subnet IDs-yes
key_nameSSH key name to use-yes
security_groupsComma separated list of security groups-yes
iam_instance_profileInstance profile ARN to use in the launch configuration-yes
regionAWS Region-yes
availability_zonesList of AZs-yes
instance_typeThe instance type to use, e.g t2.small-yes
instance_ebs_optimizedWhen set to true the instance will be launched with EBS optimized turned ontrueno
min_sizeMinimum instance count3no
max_sizeMaxmimum instance count100no
desired_capacityDesired instance count3no
associate_public_ip_addressShould created instances be publicly accessible (if the SG allows)falseno
root_volume_sizeRoot volume size in GB25no
docker_volume_sizeAttached EBS volume size in GB25no
docker_auth_typeThe docker auth type, see https://godoc.org/github.com/aws/amazon-ecs-agent/agent/engine/dockerauth for the possible values``no
docker_auth_dataA JSON object providing the docker auth data, see https://godoc.org/github.com/aws/amazon-ecs-agent/agent/engine/dockerauth for the supported formats``no
extra_cloud_config_typeExtra cloud config typetext/cloud-configno
extra_cloud_config_contentExtra cloud config content``no

Outputs

NameDescription
nameThe cluster name, e.g cdn
security_group_idThe cluster security group ID.

elb

The ELB module creates an ELB, security group a route53 record and a service healthcheck. It is used by the service module.

Inputs

NameDescriptionDefaultRequired
nameELB name, e.g cdn-yes
subnet_idsComma separated list of subnet IDs-yes
environmentEnvironment tag, e.g prod-yes
portInstance port-yes
security_groupsComma separated list of security group IDs-yes
dns_nameRoute53 record name-yes
healthcheckHealthcheck path-yes
protocolProtocol to use, HTTP or TCP-yes
zone_idRoute53 zone ID to use for dns_name-yes
log_bucketS3 bucket name to write ELB logs into-yes

Outputs

NameDescription
nameThe ELB name.
idThe ELB ID.
dnsThe ELB dns_name.
fqdnFQDN built using the zone domain and name
zone_idThe zone id of the ELB

iam-user

The module creates an IAM user.

Usage:

module "my_user" {
  name = "user"
  policy = <<EOF
  {}
EOF
}

Inputs

NameDescriptionDefaultRequired
nameThe user name, e.g my-user-yes
policyThe raw json policy-yes

Outputs

NameDescription
access_keyThe aws access key id.
secret_keyThe aws secret access key.
arnThe user ARN

rds-cluster

Inputs

NameDescriptionDefaultRequired
nameThe name will be used to prefix and tag the resources, e.g mydb-yes
environmentThe environment tag, e.g prod-yes
vpc_idThe VPC ID to use-yes
zone_idThe Route53 Zone ID where the DNS record will be created-yes
security_groupsA list of security group IDs-yes
subnet_idsA list of subnet IDs-yes
availability_zonesA list of availability zones-yes
database_nameThe database name-yes
master_usernameThe master user username-yes
master_passwordThe master user password-yes
instance_typeThe type of instances that the RDS cluster will be running ondb.r3.largeno
instance_countHow many instances will be provisioned in the RDS cluster1no
preferred_backup_windowThe time window on which backups will be made (HH:mm-HH:mm)07:00-09:00no
backup_retention_periodThe backup retention period5no
publicly_accessibleWhen set to true the RDS cluster can be reached from outside the VPCfalseno
dns_nameRoute53 record name for the RDS database, defaults to the database name if not set``no
portThe port at which the database listens for incoming connections3306no
skip_final_snapshotWhen set to false deletion will be delayed to take a snapshot from which the database can be recoveredtrueno

Outputs

NameDescription
idThe cluster identifier.
endpoint
fqdn
port

s3-logs

Inputs

NameDescriptionDefaultRequired
name-yes
environment-yes
account_id-yes

Outputs

NameDescription
id

security-groups

Creates basic security groups to be used by instances and ELBs.

Inputs

NameDescriptionDefaultRequired
nameThe name of the security groups serves as a prefix, e.g stack-yes
vpc_idThe VPC ID-yes
environmentThe environment, used for tagging, e.g prod-yes
cidrThe cidr block to use for internal security groups-yes

Outputs

NameDescription
external_sshExternal SSH allows ssh connections on port 22 from the world.
internal_sshInternal SSH allows ssh connections from the external ssh security group.
internal_elbInternal ELB allows internal traffic.
external_elbExternal ELB allows traffic from the world.

service

The service module creates an ecs service, task definition elb and a route53 record under the local service zone (see the dns module).

Usage:

 module "auth_service" {
   source    = "github.com/segmentio/stack/service"
   name      = "auth-service"
   image     = "auth-service"
   cluster   = "default"
 }

Inputs

NameDescriptionDefaultRequired
environmentEnvironment tag, e.g prod-yes
imageThe docker image name, e.g nginx-yes
nameThe service name, if empty the service name is defaulted to the image name``no
versionThe docker image versionlatestno
subnet_idsComma separated list of subnet IDs that will be passed to the ELB module-yes
security_groupsComma separated list of security group IDs that will be passed to the ELB module-yes
portThe container host port-yes
clusterThe cluster name or ARN-yes
dns_nameThe DNS name to use, e.g nginx-yes
log_bucketThe S3 bucket ID to use for the ELB-yes
healthcheckPath to a healthcheck endpoint/no
container_portThe container port3000no
commandThe raw json of the task command[]no
env_varsThe raw json of the task env vars[]no
desired_countThe desired count2no
memoryThe number of MiB of memory to reserve for the container512no
cpuThe number of cpu units to reserve for the container512no
protocolThe ELB protocol, HTTP or TCPHTTPno
iam_roleIAM Role ARN to use-yes
zone_idThe zone ID to create the record in-yes
deployment_minimum_healthy_percentlower limit (% of desired_count) of # of running tasks during a deployment100no
deployment_maximum_percentupper limit (% of desired_count) of # of running tasks during a deployment200no

Outputs

NameDescription
nameThe name of the ELB
dnsThe DNS name of the ELB
elbThe id of the ELB
zone_idThe zone id of the ELB
fqdnFQDN built using the zone domain and name

task

The task module creates an ECS task definition.

Usage:

module "nginx" {
  source = "github.com/segmentio/stack/task"
  name   = "nginx"
  image  = "nginx"
}

Inputs

NameDescriptionDefaultRequired
imageThe docker image name, e.g nginx-yes
nameThe worker name, if empty the service name is defaulted to the image name-yes
cpuThe number of cpu units to reserve for the container512no
env_varsThe raw json of the task env vars[]no
commandThe raw json of the task command[]no
entry_pointThe docker container entry point[]no
portsThe docker container ports[]no
image_versionThe docker image versionlatestno
memoryThe number of MiB of memory to reserve for the container512no

Outputs

NameDescription
nameThe created task definition name
arnThe created task definition ARN

vpc

Inputs

NameDescriptionDefaultRequired
cidrThe CIDR block for the VPC.-yes
external_subnetsList of external subnets-yes
internal_subnetsList of internal subnets-yes
environmentEnvironment tag, e.g prod-yes
availability_zonesList of availability zones-yes
nameName tag, e.g stackstackno

Outputs

NameDescription
idThe VPC ID
external_subnetsA comma-separated list of subnet IDs.
internal_subnetsA list of subnet IDs.
security_groupThe default VPC security group ID.
availability_zonesThe list of availability zones of the VPC.
internal_rtb_idThe internal route table ID.
external_rtb_idThe external route table ID.
internal_nat_ipsThe list of EIPs associated with the internal subnets.

web-service

The web-service is similar to the service module, but the it provides a public ELB instead.

Usage:

 module "auth_service" {
   source    = "github.com/segmentio/stack/service"
   name      = "auth-service"
   image     = "auth-service"
   cluster   = "default"
 }

Inputs

NameDescriptionDefaultRequired
environmentEnvironment tag, e.g prod-yes
imageThe docker image name, e.g nginx-yes
nameThe service name, if empty the service name is defaulted to the image name``no
versionThe docker image versionlatestno
subnet_idsComma separated list of subnet IDs that will be passed to the ELB module-yes
security_groupsComma separated list of security group IDs that will be passed to the ELB module-yes
portThe container host port-yes
clusterThe cluster name or ARN-yes
log_bucketThe S3 bucket ID to use for the ELB-yes
ssl_certificate_idSSL Certificate ID to use-yes
iam_roleIAM Role ARN to use-yes
external_dns_nameThe subdomain under which the ELB is exposed externally, defaults to the task name``no
internal_dns_nameThe subdomain under which the ELB is exposed internally, defaults to the task name``no
external_zone_idThe zone ID to create the record in-yes
internal_zone_idThe zone ID to create the record in-yes
healthcheckPath to a healthcheck endpoint/no
container_portThe container port3000no
commandThe raw json of the task command[]no
env_varsThe raw json of the task env vars[]no
desired_countThe desired count2no
memoryThe number of MiB of memory to reserve for the container512no
cpuThe number of cpu units to reserve for the container512no
deployment_minimum_healthy_percentlower limit (% of desired_count) of # of running tasks during a deployment100no
deployment_maximum_percentupper limit (% of desired_count) of # of running tasks during a deployment200no

Outputs

NameDescription
nameThe name of the ELB
dnsThe DNS name of the ELB
elbThe id of the ELB
zone_idThe zone id of the ELB
external_fqdnFQDN built using the zone domain and name (external)
internal_fqdnFQDN built using the zone domain and name (internal)

worker

The worker module creates an ECS service that has no ELB attached.

Usage:

module "my_worker" {
  source       = "github.com/segmentio/stack"
  environment  = "prod"
  name         = "worker"
  image        = "worker"
  cluster      = "default"
}

Inputs

NameDescriptionDefaultRequired
environmentEnvironment tag, e.g prod-yes
imageThe docker image name, e.g nginx-yes
nameThe worker name, if empty the service name is defaulted to the image name``no
versionThe docker image versionlatestno
clusterThe cluster name or ARN-yes
commandThe raw json of the task command[]no
env_varsThe raw json of the task env vars[]no
desired_countThe desired count1no
memoryThe number of MiB of memory to reserve for the container512no
cpuThe number of cpu units to reserve for the container512no
deployment_minimum_healthy_percentlower limit (% of desired_count) of # of running tasks during a deployment100no
deployment_maximum_percentupper limit (% of desired_count) of # of running tasks during a deployment200no