Deploying an Application on ECS within Control Tower environment

Overview

In this lab we will deploy an Application on ECS using Fargate with CI/CD using Code Pipeline in Control Tower environment. We will be working with multiple accounts setup within Control Tower as mentioned below:
A. Tools Account
Used for Container repositories, Code Commit and setting up Code pipeline to build, push and deploy new images.
B. Application Account
Account where application will be deployed.

Ref-Architecture

Lab Pre-Requisites

Before we start this lab, it’ll require:

  • At-least one AWS account with an internet accessible subnet, created as part of Account Factory Lab. For this lab purpose it’ll be used as Application Account. Please use this account info wherever application account is referred. If you don’t have an account, please complete the Account Factory lab.
  • We’ll use Log Archive account within Control Tower as a Tools Account for this lab purpose. Please use log archive account info wherever tools account is referred.
  • Download and extract ECS-Control-Tower.zip file. It’ll create a directory named ECS-Control-Tower.

Setup Cloud9 environment

For running commands, we’ll be using Cloud9 environment.
If you don’t have Cloud9 continue with next step to launch Cloud9 otherwise skip to setup Cloud9 environment:

Launch Cloud9

Setup Cloud9 Environment

  • Once Cloud9 environment is ready to use, in the cloud9 terminal, download and extract ECS-Control-Tower.zip file.
  • It’ll create a directory named ECS-Control-Tower. Copy below commands and run in cloud9 terminal.

    wget https://marketplace-sa-resources.s3.amazonaws.com/ctlabs/ECS-Control-Tower.zip
    unzip ECS-Control-Tower.zip
    

    Cloud9-Terminal

Cross account trust setup

Services used in Tools Account:

  • Code Commit, Code Pipeline, Code Build
  • S3 bucket used by Code Pipeline
  • ECR repositories

Services used in Application Account:

  • CloudFormation (Used by code pipeline to deploy application)
  • ECS
  • KMS key for Code Pipeline artifact Bucket

As Code Pipeline uses S3 bucket with encryption to store artifacts, we need to update the IAM role used by code pipeline with permission to the KMS key used. And an IAM role in application account which can be consumed by code pipeline to deploy app. For this cross-account setup, IAM roles with cross account trust for used resources are required. So as prerequisite, first we’ll create KMS key to use with code pipeline and IAM roles in application account.

Follow below instructions to create CloudFormation stack set instance in tools and application account to create KMS, S3 bucket and IAM.

  1. Login to Master account with AWSAdministratorAccess role from SSO portal Login

  2. Navigate to the StackSet console under CloudFormation in the master account

  3. Click Create StackSet

  4. Select Upload a template file and select pre_req.yaml template under ct-lab folder from ECS-Control-Tower folder unzipped as part of pre-requisite.

  5. Set the StackSet name as ECSPreReq. (If using a shared account, use aliasECSPreReq).

  6. Enter tools account number, where pipeline for ECS deployment will be created, for ToolsAccount parameter.

  7. Click Next

  8. Under Permissions, select AWSControlTowerStackSetRole from the list under IAM Admin Role ARN. Type AWSControlTowerExecution for IAM Execution Role Name and click on Next.

  9. For Deployment locations choose Deploy stacks in accounts and enter account number of Application account.

  10. Under Specify regions, choose the primary region where you launched Control Tower service.

  11. Click Next

  12. Acknowledge the Capabilities

  13. Click Submit

  14. Wait for the stack instance to be created successfully. Status for the stack instance should be CURRENT.This template created below resource in Application account:

    • CodePipelineRole to be assumed by code pipeline from tools account
    • CloudFormationExecutionRole to execute CF in application account
    • KMS key and alias
  15. Login to Application account from SSO portal. (You can close the previous inactive aws tab/window)

  16. Go to CloudFormation service and search for the stack name ECSPreReq. Get the output value for CMKArn from this CloudFormation stack, for later use.

Create Repositories

We’ll need to create Code commit repository to push application code and ECR repository to push docker images for application in Tools Account

  1. Setup programmatic access on cloud9 terminal for tools account from SSO portal
    programmatic access programmatic access

  2. Paste copied commands from above step into cloud9 terminal.

  3. Create an ECR repository, run below command. Pick the region same as Control Tower deployment and repo name as mydemoapp

    aws ecr create-repository --repository-name mydemoapp --region <same as CT region>
    

    command-execution

  4. Create Code Commit repo, run below command. Pick the region same as Control Tower deployment and repo name as mydemoapp

    aws codecommit create-repository --repository-name mydemoapp --region <same as CT region>
    

    command-execution

  5. Copy the cloneUrlHttp value from above command’s output.

  6. Before we are able to push code to our CodeCommit repo, we will need to configure our code commit credentials, run below commands

    git config --global credential.helper '!aws codecommit credential-helper $@'
    
    git config --global credential.UseHttpPath true
    
  7. Go to ECS-Control-Tower directory

  8. Run below git commands to initialize the repo and to commit files

    git init
    git add .
    git commit -m "first commit"
    
  9. Add code commit remote to directory

    git remote add origin < cloneUrlHttp copied earlier in step 21>
    
  10. Push code to code commit

    git push origin master
    

Update ECR repository permission to allow Application Account to pull docker images

  1. Login to Tools account from SSO portal

  2. Go to ECR service, select the mydemoapp repository created in step 19.

  3. Click on permissions on left side menu. ecr-permissions

  4. Click on Edit policy JSON, on right top corner. ecr-permissions

  5. Replace the account number of Application account and paste this JSON into policy document and click save.

    {
    "Version": "2008-10-17",
    "Statement": [
    {
      "Sid": "AllowPull",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::<ApplicationAccountNum>:root"
      },
      "Action": [
        "ecr:BatchCheckLayerAvailability",
        "ecr:BatchGetImage",
        "ecr:GetDownloadUrlForLayer"
      ]
    }
    ]
    }
    

    ecr-permissions

Deploy Pipeline

Now we’ll deploy the code pipeline and resources required in tools account.

  1. Login to Application Account from SSO portal.

  2. Go to VPC, copy public subnet ids and vpc id

  3. Login to Master Account from SSO portal. (You can close the previous inactive aws tab/window)

  4. Navigate to the StackSet console under CloudFormation in the master account

  5. Click Create StackSet

  6. Select Upload a template file and select pipeline.yaml template under ct-lab folder from ECS-Control-Tower directory and click next.

  7. Set the StackSet name as ECSPipeline. (If using a shared account, use aliasECSPipeline).

  8. Enter mydemoapp for CodeCommitRepositoryName parameter

  9. Enter mydemoapp for ApplicationName parameter

  10. Enter mydemoapp for ECRRepositoryName parameter

  11. Enter VPC id from Application Account, copied in step 33, for VpcId parameter

  12. Enter account number for application account, where ECS will be deployed, for ApplicationAccount parameter

  13. For CMKARN parameter enter KMS key ARN copied earlier in step 16.

  14. Enter comma separated (no spaces) subnet ids of public subnets from Application Account, copied in step 33, for PublicSubnets parameter

  15. Click Next

  16. Under Permissions, select AWSControlTowerStackSetRole from the list under IAM Admin Role ARN. Type AWSControlTowerExecution for IAM Execution Role Name and click on Next

  17. For Deployment locations choose Deploy stacks in accounts and enter account number of Tools account.

  18. Under Specify regions, choose the primary region where you launched Control Tower service.

  19. Click Next

  20. Acknowledge the Capabilities.

  21. Click Submit

  22. Wait for the stack instance to be created successfully. Status for the stack instance should be CURRENT. This template created below resource in tools accounts:

    • Code Pipeline Role and policy
    • Code Build Role and policy
    • Code Commit Role and Policy
    • S3 bucket for Pipeline and bucket policy
    • Code Pipeline and Code Build project

pipeline-resources

What will code pipeline do?

  1. The pipeline checks out code from the AWS Code Commit repository to S3.

  2. Then AWS Code Build will decrypt artifacts in the S3 bucket and run build steps.

  3. Code build will build new docker image and push to ECR repositories.

  4. Then Code build will generate a parameter JSON file with newly built images URI, which will be used with CloudFormation to deploy/update ECS resources. (Look at buildspec.yml file for steps executed by Code Build)

  5. Once code build has finished successfully, code pipeline assumes IAM of application account and deploy CloudFormation template to application account.

  6. As part of ECS CloudFormation deployment below mentioned resources are created for given application:

  7. ECS Cluster

  8. Task Definition

  9. Application Load Balancer

  10. Security groups for ALB and ECS Service

  11. ECS Fargate Service (Look at ecs.yml file for resources being created)

ecs-resources

Validation

To verify the pipeline, go to tools account and CodePipeline service. You should find the pipeline created for the application (pipeline name is same as ApplicationName parameter used earlier in step 9 in Deploy Pipeline section, per lab instructions, mydemoapp) and check its execution stages.

Once pipeline is done executing successfully, login to Application account and go to CloudFormation. You should find the cloudformation stack for the application (stack name is same as ApplicationName parameter used earlier in step 9 in Deploy Pipeline section, per lab instructions, mydemoapp). Check the outputs and copy the AppDNSName value and paste into the browser. You should see the deployed application.
You can also verify that a FARGATE cluster named mydemoapp is running in Amazon ECS.