{
    "componentChunkName": "component---src-pages-blog-post-tsx",
    "path": "/blog/2021-03-30/terraform-aws-ecs",
    "result": {"data":{"site":{"siteMetadata":{"siteUrl":"https://www.architect.io"}},"allMdx":{"edges":[{"node":{"body":"var _excluded = [\"components\"];\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"title\": \"Create and Manage an AWS ECS Cluster with Terraform\",\n  \"description\": \"Follow this tutorial to deploy a simple load balanced “Hello World” application to AWS ECS with Terraform.\",\n  \"keywords\": \"terraform aws ecs\",\n  \"slug\": \"terraform-aws-ecs\",\n  \"date\": \"2021-03-30T00:00:00.000Z\",\n  \"author\": \"Ryan Cahill\",\n  \"image\": \"./aws-ecs-and-terraform.png\"\n};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, _excluded);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"AWS ECS with Fargate is a serverless computing platform that makes running containerized services on\\nAWS easier than ever before. Before Fargate, users who would like to deploy services to an AWS ECS\\ncluster would need to manage one or many EC2 instances of similar or varying sizes and figure out\\nhow to scale them as necessary. With Fargate, a user simply defines the compute resources such as\\nCPU and memory that a service will need to run, and Fargate will manage where to run the container\\nbehind the scenes. There is no point where setting up an EC2 instance is required.\"), mdx(\"p\", null, \"Terraform is an infrastructure-as-code tool created by Hashicorp to make handling infrastructure\\nmore straightforward and manageable. Terraform files use a declarative syntax where the user\\nspecifies resources and their properties such as pods, deployments, services, and ingresses. Users\\nthen leverage the Terraform CLI to preview and apply expected infrastructure. When changes are\\ndesired, a user simply updates and reapplies the same file or set of files; then, Terraform handles\\nresource creation, updates, and deletion as required.\"), mdx(\"p\", null, \"By following this tutorial, you'll learn how to define AWS resources using Terraform and how\\nresource definitions translate to actual resources created on AWS. When everything is up and\\nrunning, you'll have your own scalable \\\"Hello World\\\" service running on the cloud!\"), mdx(\"h2\", {\n    \"id\": \"project-dependencies-for-terraform-and-aws-fargate\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, \"Project dependencies for Terraform and AWS Fargate\", mdx(\"a\", {\n    parentName: \"h2\",\n    \"href\": \"#project-dependencies-for-terraform-and-aws-fargate\",\n    \"aria-label\": \"project dependencies for terraform and aws fargate permalink\",\n    \"className\": \"anchor after\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  })))), mdx(\"p\", null, \"You'll be using \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://learn.hashicorp.com/tutorials/terraform/install-cli\"\n  }, \"Terraform\"), \" to deploy\\nall of the required resources to the ECS cluster. Be sure to have signed up for an AWS account. The\\nAWS Terraform provider will require credentials to access your account programmatically, so generate\\nthem according to\\n\", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys\"\n  }, \"these docs\"), \"\\nif you haven't already. If your user doesn't have any policies attached yet, feel free to add the\\npolicy below. This policy should allow access to all AWS resources so that you don't need to worry\\nabout those for this tutorial.\"), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"json\"\n  }, mdx(\"pre\", {\n    parentName: \"div\",\n    \"className\": \"language-json\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-json\"\n  }, mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"\\\"Version\\\"\"), mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token operator\"\n  }, \":\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"2012-10-17\\\"\"), mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \",\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"\\\"Statement\\\"\"), mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token operator\"\n  }, \":\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"[\"), \"\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n      \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"\\\"Effect\\\"\"), mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token operator\"\n  }, \":\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"Allow\\\"\"), mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \",\"), \"\\n      \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"\\\"Action\\\"\"), mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token operator\"\n  }, \":\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"[\"), mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"*\\\"\"), mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"]\"), mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \",\"), \"\\n      \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"\\\"Resource\\\"\"), mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token operator\"\n  }, \":\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"*\\\"\"), \"\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"]\"), \"\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\")))), mdx(\"p\", null, \"You can optionally install the\\n\", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html\"\n  }, \"AWS CLI\"), \" if you'd like to gain\\nmore insight into the Terraform deployment without heading to the AWS Dashboard.\"), mdx(\"h2\", {\n    \"id\": \"define-aws-ecs-resources-with-terraform\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, \"Define AWS ECS resources with Terraform\", mdx(\"a\", {\n    parentName: \"h2\",\n    \"href\": \"#define-aws-ecs-resources-with-terraform\",\n    \"aria-label\": \"define aws ecs resources with terraform permalink\",\n    \"className\": \"anchor after\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  })))), mdx(\"p\", null, \"Terraform requires that the user uses its special language called HCL, which stands for Hashicorp\\nConfiguration Language. Create a folder called terraform-example where the HCL files will live, then\\nchange directories to that folder. Terraform providers will need to be defined and installed to use\\ncertain types of resources. This tutorial will use only the\\n\", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://registry.terraform.io/providers/hashicorp/aws/latest/docs\"\n  }, \"AWS provider\"), \". Providers are\\neasily downloaded and installed with a few lines of HCL and a single command. Create a file called\\n\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"versions.tf\"), \" where providers will be defined and add the following code:\"), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"hcl\"\n  }, mdx(\"pre\", {\n    parentName: \"div\",\n    \"className\": \"language-hcl\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-hcl\"\n  }, mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"terraform\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"required_providers\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"aws\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n      \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"source\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"hashicorp/aws\\\"\"), \"\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\"), \"\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\"), \"\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"provider\", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"token type variable\"\n  }, \" \\\"aws\\\" \")), mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"region\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"us-east-2\\\"\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"access_key\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"<your_aws_access_key>\\\"\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"secret_key\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"<your_aws_secret_key>\\\"\"), \"\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\"), \"\\n\"))), mdx(\"p\", null, \"Be sure to replace \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"<your_aws_access_key>\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"<your_aws_secret_key>\"), \" with the keys for your\\naccount. Now that the required provider is defined, it can be installed by running the command\\n\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"terraform init\"), \". Ensure that the command is run in the same folder that \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"versions.tf\"), \" is in. The\\ncommand should print something like what's below, which lets you know that Terraform is ready to\\nbegin creating AWS resources:\"), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"text\"\n  }, mdx(\"pre\", {\n    parentName: \"div\",\n    \"className\": \"language-text\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-text\"\n  }, \"Initializing the backend...\\n\\nInitializing provider plugins...\\n- Reusing previous version of hashicorp/aws from the dependency lock file\\n- Installing hashicorp/aws v3.32.0...\\n- Installed hashicorp/aws v3.32.0 (signed by HashiCorp)\\n\\nTerraform has been successfully initialized!\\n\\nYou may now begin working with Terraform. Try running \\\"terraform plan\\\" to see\\nany changes that are required for your infrastructure. All Terraform commands\\nshould now work.\\n\\nIf you ever set or change modules or backend configuration for Terraform,\\nrerun this command to reinitialize your working directory. If you forget, other\\ncommands will detect it and remind you to do so if necessary.\"))), mdx(\"p\", null, \"Note that a folder has been created alongside \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"versions.tf\"), \" called .terraform. This folder is where\\nthe installed providers are stored to be used for later Terraform processes. Now that the\\nprerequisites to run Terraform are out of the way, the AWS resource definitions can be created. Add\\na file alongside \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"versions.tf\"), \" called \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"variables.tf\"), \". This file will contain the definition for a\\nsingle variable that will be passed in on the command line later when resources will be scaled. Add\\nthe following to \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"variables.tf\"), \":\"), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"hcl\"\n  }, mdx(\"pre\", {\n    parentName: \"div\",\n    \"className\": \"language-hcl\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-hcl\"\n  }, mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"variable\", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"token type variable\"\n  }, \" \\\"app_count\\\" \")), mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"type\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" number\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"default\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token number\"\n  }, \"1\"), \"\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\")))), mdx(\"p\", null, \"Save and close the file. Create another file called \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"main.tf\"), \" in the same directory as\\n\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"variables.tf\"), \" where the resource definitions for the AWS resources will live. Start by adding a\\ndata block for AWS availability zones like so:\"), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"hcl\"\n  }, mdx(\"pre\", {\n    parentName: \"div\",\n    \"className\": \"language-hcl\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-hcl\"\n  }, mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"data \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"token type variable\"\n  }, \"\\\"aws_availability_zones\\\"\")), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"available_zones\\\"\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"state\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"available\\\"\"), \"\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\")))), mdx(\"p\", null, \"This block will grab availability zones that are available to your account. These will be used for\\nother resource definitions, and to keep a small footprint for this tutorial, only two availability\\nzones will be used. It's best practice to use multiple availability zones when deploying tasks to an\\nAWS ECS Fargate cluster because Fargate will ensure high availability by spreading tasks of the same\\ntype as evenly as possible between availability zones. Next, add the resource definition to\\n\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"main.tf\"), \" with this code:\"), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"hcl\"\n  }, mdx(\"pre\", {\n    parentName: \"div\",\n    \"className\": \"language-hcl\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-hcl\"\n  }, mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"resource \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"token type variable\"\n  }, \"\\\"aws_vpc\\\"\")), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"default\\\"\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"cidr_block\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"10.32.0.0/16\\\"\"), \"\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\")))), mdx(\"p\", null, \"Resources that will be created will be defined inside of the VPC. An AWS VPC provides logical\\nisolation of resources from one another. All of the resources that will be defined will live within\\nthe same VPC. Four subnets will be created next. Two will be public and the other two will be\\nprivate, where each availability zone will have one of each. Add the subnet resource definitions to\\n\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"main.tf\"), \":\"), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"hcl\"\n  }, mdx(\"pre\", {\n    parentName: \"div\",\n    \"className\": \"language-hcl\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-hcl\"\n  }, mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"resource \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"token type variable\"\n  }, \"\\\"aws_subnet\\\"\")), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"public\\\"\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"count\"), \"                   \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token number\"\n  }, \"2\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"cidr_block\"), \"              \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" cidrsubnet(aws_vpc.default.cidr_block, \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token number\"\n  }, \"8\"), \", \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token number\"\n  }, \"2\"), \" + count.index)\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"availability_zone\"), \"       \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" data.aws_availability_zones.available_zones.names\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"[\"), \"count.index\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"]\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"vpc_id\"), \"                  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" aws_vpc.default.id\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"map_public_ip_on_launch\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token boolean\"\n  }, \"true\"), \"\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\"), \"\\n\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"resource \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"token type variable\"\n  }, \"\\\"aws_subnet\\\"\")), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"private\\\"\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"count\"), \"             \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token number\"\n  }, \"2\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"cidr_block\"), \"        \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" cidrsubnet(aws_vpc.default.cidr_block, \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token number\"\n  }, \"8\"), \", count.index)\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"availability_zone\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" data.aws_availability_zones.available_zones.names\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"[\"), \"count.index\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"]\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"vpc_id\"), \"            \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" aws_vpc.default.id\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\")))), mdx(\"p\", null, \"Things that should be public-facing, such as a load balancer, will be added to the public subnet.\\nOther things that don't need to communicate with the internet directly, such as a Hello World\\nservice defined inside an ECS cluster, will be added to the private subnet. Define six networking\\nresources with the following blocks of HCL:\"), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"hcl\"\n  }, mdx(\"pre\", {\n    parentName: \"div\",\n    \"className\": \"language-hcl\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-hcl\"\n  }, mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"resource \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"token type variable\"\n  }, \"\\\"aws_internet_gateway\\\"\")), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"gateway\\\"\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"vpc_id\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" aws_vpc.default.id\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\"), \"\\n\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"resource \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"token type variable\"\n  }, \"\\\"aws_route\\\"\")), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"internet_access\\\"\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"route_table_id\"), \"         \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" aws_vpc.default.main_route_table_id\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"destination_cidr_block\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"0.0.0.0/0\\\"\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"gateway_id\"), \"             \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" aws_internet_gateway.gateway.id\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\"), \"\\n\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"resource \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"token type variable\"\n  }, \"\\\"aws_eip\\\"\")), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"gateway\\\"\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"count\"), \"      \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token number\"\n  }, \"2\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"vpc\"), \"        \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token boolean\"\n  }, \"true\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"depends_on\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"[\"), \"aws_internet_gateway.gateway\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"]\"), \"\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\"), \"\\n\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"resource \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"token type variable\"\n  }, \"\\\"aws_nat_gateway\\\"\")), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"gateway\\\"\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"count\"), \"         \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token number\"\n  }, \"2\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"subnet_id\"), \"     \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" element(aws_subnet.public.*.id, count.index)\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"allocation_id\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" element(aws_eip.gateway.*.id, count.index)\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\"), \"\\n\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"resource \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"token type variable\"\n  }, \"\\\"aws_route_table\\\"\")), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"private\\\"\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"count\"), \"  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token number\"\n  }, \"2\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"vpc_id\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" aws_vpc.default.id\\n\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"route\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"cidr_block\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"0.0.0.0/0\\\"\"), \"\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"nat_gateway_id\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" element(aws_nat_gateway.gateway.*.id, count.index)\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\"), \"\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\"), \"\\n\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"resource \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"token type variable\"\n  }, \"\\\"aws_route_table_association\\\"\")), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"private\\\"\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"count\"), \"          \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token number\"\n  }, \"2\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"subnet_id\"), \"      \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" element(aws_subnet.private.*.id, count.index)\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"route_table_id\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" element(aws_route_table.private.*.id, count.index)\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\")))), mdx(\"p\", null, \"These six resources handle networking and communication to and from the internet outside of the VPC.\\nThe internet gateway, for example, is what allows communication between the VPC and the internet at\\nall. The NAT gateway allows resources within the VPC to communicate with the internet but will\\nprevent communication to the VPC from outside sources. That is all tied together with the route\\ntable association, where the private route table that includes the NAT gateway is added to the\\nprivate subnets defined earlier. Security groups will need to be added next to allow or reject\\ntraffic in a more fine-grained way both from the load balancer and the application service. Add the\\nload balancer security group resource to \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"main.tf\"), \" like so:\"), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"hcl\"\n  }, mdx(\"pre\", {\n    parentName: \"div\",\n    \"className\": \"language-hcl\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-hcl\"\n  }, mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"resource \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"token type variable\"\n  }, \"\\\"aws_security_group\\\"\")), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"lb\\\"\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"name\"), \"        \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"example-alb-security-group\\\"\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"vpc_id\"), \"      \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" aws_vpc.default.id\\n\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"ingress\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"protocol\"), \"    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"tcp\\\"\"), \"\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"from_port\"), \"   \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token number\"\n  }, \"80\"), \"\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"to_port\"), \"     \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token number\"\n  }, \"80\"), \"\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"cidr_blocks\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"[\"), mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"0.0.0.0/0\\\"\"), mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"]\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\"), \"\\n\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"egress\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"from_port\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token number\"\n  }, \"0\"), \"\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"to_port\"), \"   \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token number\"\n  }, \"0\"), \"\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"protocol\"), \"  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"-1\\\"\"), \"\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"cidr_blocks\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"[\"), mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"0.0.0.0/0\\\"\"), mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"]\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\"), \"\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\")))), mdx(\"p\", null, \"The load balancer's security group will only allow traffic to the load balancer on port 80, as\\ndefined by the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ingress\"), \" block within the resource block. Traffic from the load balancer will be\\nallowed to anywhere on any port with any protocol with the settings in the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"egress\"), \" block. Add the\\nthree resources for the load balancer next with the following code:\"), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"hcl\"\n  }, mdx(\"pre\", {\n    parentName: \"div\",\n    \"className\": \"language-hcl\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-hcl\"\n  }, mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"resource \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"token type variable\"\n  }, \"\\\"aws_lb\\\"\")), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"default\\\"\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"name\"), \"            \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"example-lb\\\"\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"subnets\"), \"         \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" aws_subnet.public.*.id\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"security_groups\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"[\"), \"aws_security_group.lb.id\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"]\"), \"\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\"), \"\\n\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"resource \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"token type variable\"\n  }, \"\\\"aws_lb_target_group\\\"\")), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"hello_world\\\"\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"name\"), \"        \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"example-target-group\\\"\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"port\"), \"        \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token number\"\n  }, \"80\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"protocol\"), \"    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"HTTP\\\"\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"vpc_id\"), \"      \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" aws_vpc.default.id\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"target_type\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"ip\\\"\"), \"\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\"), \"\\n\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"resource \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"token type variable\"\n  }, \"\\\"aws_lb_listener\\\"\")), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"hello_world\\\"\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"load_balancer_arn\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" aws_lb.default.id\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"port\"), \"              \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"80\\\"\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"protocol\"), \"          \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"HTTP\\\"\"), \"\\n\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"default_action\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"target_group_arn\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" aws_lb_target_group.hello_world.id\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"type\"), \"             \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"forward\\\"\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\"), \"\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\")))), mdx(\"p\", null, \"The first block defines the load balancer itself and attaches it to the public subnet in each\\navailability zone with the load balancer security group. The target group, when added to the load\\nbalancer listener tells the load balancer to forward incoming traffic on port 80 to wherever the\\nload balancer is attached. In this case, it will be the ECS service defined later. Define the ECS\\ncluster with the block below:\"), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"hcl\"\n  }, mdx(\"pre\", {\n    parentName: \"div\",\n    \"className\": \"language-hcl\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-hcl\"\n  }, mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"resource \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"token type variable\"\n  }, \"\\\"aws_ecs_task_definition\\\"\")), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"hello_world\\\"\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"family\"), \"                   \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"hello-world-app\\\"\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"network_mode\"), \"             \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"awsvpc\\\"\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"requires_compatibilities\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"[\"), mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"FARGATE\\\"\"), mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"]\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"cpu\"), \"                      \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token number\"\n  }, \"1024\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"memory\"), \"                   \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token number\"\n  }, \"2048\"), \"\\n\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"container_definitions\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token heredoc string\"\n  }, \"<<DEFINITION\\n[\\n  {\\n    \\\"image\\\": \\\"heroku/nodejs-hello-world\\\",\\n    \\\"cpu\\\": 1024,\\n    \\\"memory\\\": 2048,\\n    \\\"name\\\": \\\"hello-world-app\\\",\\n    \\\"networkMode\\\": \\\"awsvpc\\\",\\n    \\\"portMappings\\\": [\\n      {\\n        \\\"containerPort\\\": 3000,\\n        \\\"hostPort\\\": 3000\\n      }\\n    ]\\n  }\\n]\\nDEFINITION\"), \"\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\")))), mdx(\"p\", null, \"The task definition defines how the hello world application should be run. This is where it's\\nspecified that the platform will be Fargate rather than EC2, so that managing EC2 instances isn't\\nrequired. This means that CPU and memory for the running task should be specified. The image used is\\na simple API that returns \\\"Hello World!\\\" and is available as\\n\", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://hub.docker.com/r/heroku/nodejs-hello-world\"\n  }, \"a public Docker image\"), \". The Docker container\\nexposes the API on port 3000, so that's specified as the host and container ports. The network mode\\nis set to \\\"awsvpc\\\", which tells AWS that an elastic network interface and a private IP address\\nshould be assigned to the task when it runs. Create the security group for the ECS service next with\\nthe following HCL:\"), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"hcl\"\n  }, mdx(\"pre\", {\n    parentName: \"div\",\n    \"className\": \"language-hcl\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-hcl\"\n  }, mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"resource \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"token type variable\"\n  }, \"\\\"aws_security_group\\\"\")), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"hello_world_task\\\"\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"name\"), \"        \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"example-task-security-group\\\"\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"vpc_id\"), \"      \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" aws_vpc.default.id\\n\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"ingress\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"protocol\"), \"        \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"tcp\\\"\"), \"\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"from_port\"), \"       \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token number\"\n  }, \"3000\"), \"\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"to_port\"), \"         \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token number\"\n  }, \"3000\"), \"\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"security_groups\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"[\"), \"aws_security_group.lb.id\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"]\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\"), \"\\n\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"egress\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"protocol\"), \"    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"-1\\\"\"), \"\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"from_port\"), \"   \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token number\"\n  }, \"0\"), \"\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"to_port\"), \"     \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token number\"\n  }, \"0\"), \"\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"cidr_blocks\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"[\"), mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"0.0.0.0/0\\\"\"), mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"]\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\"), \"\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\")))), mdx(\"p\", null, \"The security group for the application task specifies that it should be added to the default VPC and\\nonly allow traffic over TCP to port 3000 of the application. The ingress settings also include the\\nsecurity group of the load balancer as that will allow traffic from the network interfaces that are\\nused with that security group. It allows all outbound traffic of any protocol as seen in the egress\\nsettings. Finally, add the ECS service and cluster blocks as shown below:\"), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"hcl\"\n  }, mdx(\"pre\", {\n    parentName: \"div\",\n    \"className\": \"language-hcl\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-hcl\"\n  }, mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"resource \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"token type variable\"\n  }, \"\\\"aws_ecs_cluster\\\"\")), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"main\\\"\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"name\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"example-cluster\\\"\"), \"\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\"), \"\\n\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"resource \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"token type variable\"\n  }, \"\\\"aws_ecs_service\\\"\")), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"hello_world\\\"\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"name\"), \"            \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"hello-world-service\\\"\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"cluster\"), \"         \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" aws_ecs_cluster.main.id\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"task_definition\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" aws_ecs_task_definition.hello_world.arn\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"desired_count\"), \"   \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" var.app_count\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"launch_type\"), \"     \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"FARGATE\\\"\"), \"\\n\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"network_configuration\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"security_groups\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"[\"), \"aws_security_group.hello_world_task.id\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"]\"), \"\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"subnets\"), \"         \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" aws_subnet.private.*.id\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\"), \"\\n\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"load_balancer\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"target_group_arn\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" aws_lb_target_group.hello_world.id\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"container_name\"), \"   \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token string\"\n  }, \"\\\"hello-world-app\\\"\"), \"\\n    \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"container_port\"), \"   \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token number\"\n  }, \"3000\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\"), \"\\n\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"depends_on\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"[\"), \"aws_lb_listener.hello_world\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"]\"), \"\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\")))), mdx(\"p\", null, \"The ECS service specifies how many tasks of the application should be run with the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"task_definition\"), \"\\nand \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"desired_count\"), \" properties within the cluster. The launch type is Fargate so that no EC2\\ninstance management is required. The tasks will run in the private subnet as specified in the\\n\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"network_configuration\"), \" block and will be reachable from the outside world through the load balancer\\nas defined in the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"load_balancer\"), \" block. Finally, the service shouldn't be created until the load\\nbalancer has been, so the load balancer listener is included in the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"depends_on\"), \" array.\"), mdx(\"p\", null, \"One final step remains in the Terraform configuration to make the deployed resources easier to test.\\nYou'll know that everything is running properly if the application running on ECS returns a blank\\npage with the text \\\"Hello World!\\\". To reach the service, the URL of the load balancer is required.\\nYou could find it on the AWS dashboard, but Terraform can make it easier. Add a file called\\n\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"outputs.tf\"), \" in the same directory as \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"main.tf\"), \", then add the following code:\"), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"hcl\"\n  }, mdx(\"pre\", {\n    parentName: \"div\",\n    \"className\": \"language-hcl\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-hcl\"\n  }, mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token keyword\"\n  }, \"output\", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"token type variable\"\n  }, \" \\\"load_balancer_ip\\\" \")), mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"{\"), \"\\n  \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token property\"\n  }, \"value\"), \" \", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"=\"), \" aws_lb.default.dns_name\\n\", mdx(\"span\", {\n    parentName: \"code\",\n    \"className\": \"token punctuation\"\n  }, \"}\")))), mdx(\"p\", null, \"This file will be included in the Terraform configuration when commands are run, and the output will\\ninstruct Terraform to print the URL of the load balancer when the plan has been applied. With the\\nentire Terraform configuration complete, run the command \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"terraform plan -out=\\\"tfplan\\\"\"), \" to see what\\nwill be created when the configuration is applied. It should look something like this:\"), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"text\"\n  }, mdx(\"pre\", {\n    parentName: \"div\",\n    \"className\": \"language-text\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-text\"\n  }, \"An execution plan has been generated and is shown below.\\nResource actions are indicated with the following symbols:\\n  + create\\n\\nTerraform will perform the following actions:\\n\\n  # aws_ecs_cluster.main will be created\\n  + resource \\\"aws_ecs_cluster\\\" \\\"main\\\" {\\n      + arn  = (known after apply)\\n      + id   = (known after apply)\\n\\n...\\n\\n      + main_route_table_id              = (known after apply)\\n      + owner_id                         = (known after apply)\\n    }\\n\\nPlan: 23 to add, 0 to change, 0 to destroy.\\n\\nChanges to Outputs:\\n  + load_balancer_ip = (known after apply)\\n\\n------------------------------------------------------------------------\\n\\nThis plan was saved to: tfplan\\n\\nTo perform exactly these actions, run the following command to apply:\\n    terraform apply \\\"tfplan\\\"\"))), mdx(\"p\", null, \"If you're satisfied with the plan, apply the configuration to AWS by running\\n\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"terraform apply \\\"tfplan\\\"\"), \". This step will likely take a few minutes. Once Terraform is done\\napplying the plan, the bottom of the output should look like the text below:\"), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"text\"\n  }, mdx(\"pre\", {\n    parentName: \"div\",\n    \"className\": \"language-text\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-text\"\n  }, \"Apply complete! Resources: 23 added, 0 changed, 0 destroyed.\\n\\nThe state of your infrastructure has been saved to the path\\nbelow. This state is required to modify and destroy your\\ninfrastructure, so keep it safe. To inspect the complete state\\nuse the `terraform show` command.\\n\\nState path: terraform.tfstate\\n\\nOutputs:\\n\\nload_balancer_ip = \\\"example-lb-1284172108.us-east-2.elb.amazonaws.com\\\"\"))), mdx(\"p\", null, \"Notice that the load balancer IP has been printed last because the output was defined as part of the\\nconfiguration. Copy the URL and paste it into a browser. You should see the text \\\"Hello World!\\\"\\nprinted at the top left of the page. Well done! You now have a public-facing application created by\\nTerraform running on AWS ECS.\"), mdx(\"h2\", {\n    \"id\": \"use-terraform-to-modify-existing-aws-resources\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, \"Use Terraform to modify existing AWS resources\", mdx(\"a\", {\n    parentName: \"h2\",\n    \"href\": \"#use-terraform-to-modify-existing-aws-resources\",\n    \"aria-label\": \"use terraform to modify existing aws resources permalink\",\n    \"className\": \"anchor after\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  })))), mdx(\"p\", null, \"Now, what happens when more traffic to the application is expected? It might be useful to be able to\\nscale the application horizontally without downtime. The variable \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"app_count\"), \" is included in the\\n\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"variables.tf\"), \" file of the configuration for that reason. The ECS service resource sets the\\n\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"desired_count\"), \" property to the value of the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"app_count\"), \" variable, so all that you need to do is set\\nthat to a higher number and reapply the configuration to scale the application horizontally. Try\\nplanning the change first with the command below:\"), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"text\"\n  }, mdx(\"pre\", {\n    parentName: \"div\",\n    \"className\": \"language-text\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-text\"\n  }, \"terraform plan -var app_count=3 -out=tfplan\"))), mdx(\"p\", null, \"The most important part of the output is towards the bottom and should look like this:\"), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"text\"\n  }, mdx(\"pre\", {\n    parentName: \"div\",\n    \"className\": \"language-text\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-text\"\n  }, \"An execution plan has been generated and is shown below.\\nResource actions are indicated with the following symbols:\\n  ~ update in-place\\n\\nTerraform will perform the following actions:\\n\\n  # aws_ecs_service.hello_world will be updated in-place\\n  ~ resource \\\"aws_ecs_service\\\" \\\"hello_world\\\" {\\n      ~ desired_count                      = 1 -> 3\\n        id                                 = \\\"arn:aws:ecs:us-east-2:914808004132:service/example-ecs-cluster/hello-world-service\\\"\\n        name                               = \\\"hello-world-service\\\"\\n        tags                               = {}\\n        # (12 unchanged attributes hidden)\\n\\n\\n\\n        # (3 unchanged blocks hidden)\\n    }\\n\\nPlan: 0 to add, 1 to change, 0 to destroy.\\n\\n------------------------------------------------------------------------\\n\\nThis plan was saved to: tfplan\\n\\nTo perform exactly these actions, run the following command to apply:\\n    terraform apply \\\"tfplan\\\"\"))), mdx(\"p\", null, \"Applying this plan will increase the number of application containers to three, therefore increasing\\ncapacity. Apply the plan with the command \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"terraform apply \\\"tfplan\\\"\"), \". The output of the plan should\\nshow that only the ECS service resource was modified, and look similar to the output below:\"), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"text\"\n  }, mdx(\"pre\", {\n    parentName: \"div\",\n    \"className\": \"language-text\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-text\"\n  }, \"aws_ecs_service.hello_world: Modifying... [id=arn:aws:ecs:us-east-2:914808004132:service/example-ecs-cluster/hello-world-service]\\naws_ecs_service.hello_world: Modifications complete after 1s [id=arn:aws:ecs:us-east-2:914808004132:service/example-ecs-cluster/hello-world-service]\\n\\nApply complete! Resources: 0 added, 1 changed, 0 destroyed.\\n\\nThe state of your infrastructure has been saved to the path\\nbelow. This state is required to modify and destroy your\\ninfrastructure, so keep it safe. To inspect the complete state\\nuse the `terraform show` command.\\n\\nState path: terraform.tfstate\\n\\nOutputs:\\n\\nload_balancer_ip = \\\"example-lb-1448833153.us-east-2.elb.amazonaws.com\\\"\"))), mdx(\"p\", null, \"If you'd like to confirm that the scaling has been completed, feel free to head over to the AWS ECS\\ndashboard, then select the cluster named \\\"example-ecs-cluster\\\". Note that \\\"Running tasks count\\\"\\nshould be set to \\\"3 Fargate, 0 EC2\\\". Your application has now been scaled horizontally to handle\\nmore traffic!\"), mdx(\"p\", null, \"When you're ready, you should clean up the resources used in this tutorial. To see what will be\\ndestroyed without actually taking any action yet, run the command\\n\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"terraform plan -destroy -out=tfplan\"), \". The output should look something like this:\"), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"text\"\n  }, mdx(\"pre\", {\n    parentName: \"div\",\n    \"className\": \"language-text\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-text\"\n  }, \"An execution plan has been generated and is shown below.\\nResource actions are indicated with the following symbols:\\n  - destroy\\n\\nTerraform will perform the following actions:\\n\\n  # aws_ecs_cluster.main will be destroyed\\n  - resource \\\"aws_ecs_cluster\\\" \\\"main\\\" {\\n      - arn                = \\\"arn:aws:ecs:us-east-2:914808004132:cluster/example-ecs-cluster\\\" -> null\\n      - capacity_providers = [] -> null\\n\\n...\\n\\n      - owner_id                         = \\\"914808004132\\\" -> null\\n      - tags                             = {} -> null\\n    }\\n\\nPlan: 0 to add, 0 to change, 23 to destroy.\\n\\nChanges to Outputs:\\n  - load_balancer_ip = \\\"example-lb-1448833153.us-east-2.elb.amazonaws.com\\\" -> null\\n\\n------------------------------------------------------------------------\\n\\nThis plan was saved to: tfplan\\n\\nTo perform exactly these actions, run the following command to apply:\\n    terraform apply \\\"tfplan\\\"\"))), mdx(\"p\", null, \"Run the command \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"terraform apply \\\"tfplan\\\"\"), \" when you're ready to tear everything down. This step will\\nlikely take a few minutes, but when complete, the last line of the output should signal that\\neverything has been destroyed as expected, and look like so:\"), mdx(\"div\", {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"text\"\n  }, mdx(\"pre\", {\n    parentName: \"div\",\n    \"className\": \"language-text\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-text\"\n  }, \"Apply complete! Resources: 0 added, 0 changed, 23 destroyed.\"))), mdx(\"h2\", {\n    \"id\": \"learn-more-about-how-architect-can-deploy-your-application-to-aws-and-elsewhere\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, \"Learn more about how Architect can deploy your application to AWS and elsewhere\", mdx(\"a\", {\n    parentName: \"h2\",\n    \"href\": \"#learn-more-about-how-architect-can-deploy-your-application-to-aws-and-elsewhere\",\n    \"aria-label\": \"learn more about how architect can deploy your application to aws and elsewhere permalink\",\n    \"className\": \"anchor after\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  })))), mdx(\"p\", null, \"Terraform can deploy your application to AWS easily once templates are written, and all of the\\nresources are defined. What happens when the next best thing comes along, though? Surely Terraform\\nwould be able to handle deploying your application to another platform, but that would require more\\nmaintenance, and likely an entire rewrite of all Terraform templates. With Architect, your\\napplication only needs to be defined once to be deployed anywhere. Find out more about deploying\\nArchitect components in our \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://www.architect.io/docs/\"\n  }, \"docs\"), \" and\\n\", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://cloud.architect.io/signup\"\n  }, \"try it out\"), \"!\"), mdx(\"p\", null, \"For more reading, have a look at some of our other tutorials!\"), mdx(\"p\", null, mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://www.architect.io/blog/terraform-kubernetes-tutorial\"\n  }, \"Get Started with the Terraform Kubernetes provider\")), mdx(\"p\", null, mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://www.architect.io/blog/kafka-docker-tutorial\"\n  }, \"Get Started with Kafka and Docker in 20 Minutes\")), mdx(\"p\", null, mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://www.architect.io/blog/gitops-developers-guide\"\n  }, \"A Developer\\u2019s Guide to GitOps\")), mdx(\"p\", null, \"If you have any questions or comments, don\\u2019t hesitate to reach out to the team on Twitter\\n\", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://twitter.com/architect_team\"\n  }, \"@architect_team\"), \"!\"));\n}\n;\nMDXContent.isMDXComponent = true;","excerpt":"AWS ECS with Fargate is a serverless computing platform that makes running containerized services on\nAWS easier than ever before. Before Fargate, users who would like to deploy services to an AWS ECS…","tableOfContents":{"items":[{"url":"#project-dependencies-for-terraform-and-aws-fargate","title":"Project dependencies for Terraform and AWS Fargate"},{"url":"#define-aws-ecs-resources-with-terraform","title":"Define AWS ECS resources with Terraform"},{"url":"#use-terraform-to-modify-existing-aws-resources","title":"Use Terraform to modify existing AWS resources"},{"url":"#learn-more-about-how-architect-can-deploy-your-application-to-aws-and-elsewhere","title":"Learn more about how Architect can deploy your application to AWS and elsewhere"}]},"frontmatter":{"title":"Create and Manage an AWS ECS Cluster with Terraform","description":"Follow this tutorial to deploy a simple load balanced “Hello World” application to AWS ECS with Terraform.","author":"Ryan Cahill","date":"2021-03-30","image":{"childImageSharp":{"gatsbyImageData":{"layout":"constrained","images":{"fallback":{"src":"/static/545dd9c0ef2cc81f7928b1bad16fa239/7a23e/aws-ecs-and-terraform.png","srcSet":"/static/545dd9c0ef2cc81f7928b1bad16fa239/4ca58/aws-ecs-and-terraform.png 250w,\n/static/545dd9c0ef2cc81f7928b1bad16fa239/0251a/aws-ecs-and-terraform.png 500w,\n/static/545dd9c0ef2cc81f7928b1bad16fa239/7a23e/aws-ecs-and-terraform.png 1000w,\n/static/545dd9c0ef2cc81f7928b1bad16fa239/fca1d/aws-ecs-and-terraform.png 2000w","sizes":"(min-width: 1000px) 1000px, 100vw"},"sources":[{"srcSet":"/static/545dd9c0ef2cc81f7928b1bad16fa239/002ed/aws-ecs-and-terraform.webp 250w,\n/static/545dd9c0ef2cc81f7928b1bad16fa239/15bdf/aws-ecs-and-terraform.webp 500w,\n/static/545dd9c0ef2cc81f7928b1bad16fa239/27c85/aws-ecs-and-terraform.webp 1000w,\n/static/545dd9c0ef2cc81f7928b1bad16fa239/0dc98/aws-ecs-and-terraform.webp 2000w","type":"image/webp","sizes":"(min-width: 1000px) 1000px, 100vw"}]},"width":1000,"height":563}}}}},"next":null,"previous":null}]}},"pageContext":{"slug":"terraform-aws-ecs"}},
    "staticQueryHashes": ["764694655"]}