CI/CD Pipeline: GitHub Actions with AWS ECS

CI/CD Pipeline: GitHub Actions with AWS ECS

Introduction

CI/CD are parts of the DevOps process for delivering new software as soon as possible with help of automated test and automation build tools like Jenkins, GitHub-Actions.
Few benefits of implementing CI/CD in your organization:

  • Faster Delivery

  • Observability

  • Smaller Code Change

  • Easier Rollbacks

  • Reduce Costs

AWS Elastic Container Service it gives you a managed set of tools to run Docker containers over AWS maintained compute resources.
In this blog post, I will explain "how to Dockerize a flask hello-world application that takes a message from an env variable and pushes it to AWS ECR"

Prerequisites

  • AWS Components

    Identity and Access Management (IAM)
    Elastic Container Registry (ECR)
    Elastic Container Service (ECS)
    Elastic Compute Cloud (EC2)

Creating IAM users (console)

You can use the AWS Management Console to create IAM users.

  1. Sign in to the AWS Management Console and open the IAM console

  2. In the navigation pane, choose Users and then choose Add users

  3. Type the user name for the new user. This is the sign-in name for AWS

  4. Select the type of access the user will have. Programmatic access is enough.

  5. Choose Next: Permissions

  6. Tags is Optional, you can skip this

  7. Now, Review to see all of the choices you made up to this point. When you are ready to proceed, choose Create user

  8. To save the access keys, choose Download .csv and then save the file to a safe location

AmazonEC2FullAccess
AmazonEC2ContainerRegistryFullAccess
AmazonECS_FullAccess
EC2InstanceProfileForImageBuilderECRContainerBuilds

Elastic Container Registry (ECR)

Now we are going to create an image repository

  • Open the Amazon ECR console

  • Choose to Get Started

  • For Visibility settings, choose Private

  • For Repository name, specify a name for the repository

  • Choose to Create a repository

Elastic Container Service (ECS)

Components:

  • Task definition

  • Cluster

  • Service

Create Task definition

A task definition is required to run Docker containers in Amazon ECS.
Let's create Task definition:

  • Open the Amazon ECS console

  • Choose EC2

  • In the navigation pane, choose Task Definitions, Create a new task definition.

  • For the Task definition family, specify a unique name for the task definition.

  • Assign a Task role, if don't have a Task role then skip it.

  • Container definitions, click on Add container. In container name add ECR repo name and at the place of Image add ECR repo URI link. And other details are shown below in the image

Create Cluster

  • Open the Amazon ECS console

  • In the navigation pane, choose Clusters.

  • On the Clusters page, choose Create Cluster.

  • Select cluster template: EC2 Linux + Networking

  • On the Configure cluster page, enter a Cluster name.

  • On Instance configuration, go with (t2.micro) it is under free tier. And create an SSH key for your instance as well.

  • Choose to Create

Create Service

  • In Configure service, set Launch type (EC2), Service Name, and Number of tasks(1). For other options stay with default.

GitHub secrets

Now we are going to put our AWS credentials in GitHub secrets in the working repository.

  • Under your repository name, click Settings

  • In the left sidebar, click Secrets

  • Under Secrets, click on Actions

  • Now set New repository secret

AWS_ACCESS_KEY_ID= xxxxxxxxxxxxx
AWS_REGION= xxxxxxxxxxxx
AWS_SECRET_ACCESS_KEY=xxxxxxxx

For running our CI/CD we need task-definition, it is the requirement for the CI/CD pipeline with GitHub-actions.
Go to the Cluster, click on the “Tasks Definitions ” tab, and then open the running “Task”. Click on the “JSON” and copy all the JSON text and put into a .json file and push it on GitHub

GitHub Actions

What is GitHub action?

GitHub Actions is a continuous integration and continuous delivery platform that allows you to automate your development workflow. GitHub Actions allows you to create, test, and deploy your code all from within GitHub in a fast, safe, and scalable manner. Every time you push, a build is immediately generated and executed, allowing you to quickly test each and every commit.

GitHub-Actions Workflow:

Workflow is a configurable, automated process that we can use in our repository to build, test, package, release, or deploy your project. Workflows are made up of one or more “jobs" and can be triggered by GitHub events

Create your pipeline with Github Actions
On your GitHub repository select the Actions tab.
In search bar search for Deploy to Amazon ECS and configure it.

name: Deploy to Amazon ECS

on:
  push:
    branches: [ "main" ]

jobs:
  deploy:
    name: Deploy
    runs-on: ubuntu-latest
    environment: production

    steps:
    - name: Checkout
      uses: actions/checkout@v4

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: ap-south-1

    - name: Login to Amazon ECR
      id: ecr-login
      uses: aws-actions/amazon-ecr-login@v1
      with:
          mask-password: 'true'

    - name: Build, tag, and push image to Amazon ECR
      id: build-image
      env:
        ECR_REGISTRY: ${{ steps.ecr-login.outputs.registry }}
        ECR_REPOSITORY: nodejs-repo
        IMAGE_TAG: latest
      run: |
        # Build a docker container and
        # push it to ECR so that it can
        # be deployed to ECS.
        docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
        docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
        echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT
    - name: Fill in the new image ID in the Amazon ECS task definition
      id: task-def
      uses: aws-actions/amazon-ecs-render-task-definition@v1
      with:
        task-definition: nodejs-td.json
        container-name: nodejs-container
        image: ${{ steps.build-image.outputs.image }}

    - name: Deploy Amazon ECS task definition
      uses: aws-actions/amazon-ecs-deploy-task-definition@v1
      with:
        task-definition: ${{ steps.task-def.outputs.task-definition }}
        service: nodejs-service
        cluster: nodejs-cluster
        wait-for-service-stability: true

    - name: Rollback on Failure 
      if: failure()
      run: |
        chmod +x rollback.sh
        ./rollback.sh

Environment Variables:

  1. AWS_REGION — Operating region of AWS services.

  2. ECR_REPOSITORY — Name of the ECR repository that you have created.

  3. ECS_SERVICE — Service name of the ECS Cluster.

  4. ECS_CLUSTER — Name of the ECS Cluster.

  5. ECS_TASK_DEFINITION — Path of the ECS task definition in JSON format which is stored in GitHub repository.

  6. CONTAINER_NAME — Docker container name under the ECS task definition.

  7. After setting all of this env's start committing the .yaml

Deployment & Result

First deployment

Deployment :

###