Read first:
As mentioned in the last part, we have already setup and deployed our three services, but we don’t want to keep pulling the changes every time we make a small change in the codebase, that’s why we need to setup our CI/CD Pipeline.
Let’s get started…
Let’s first treat all our services as Monolithic, and deploy them to the instance.
Create IAM Roles for CodeDeploy and EC2 Instance.
- Go to 
IAM → Rolesin your AWS Console - Create an IAM Role with 
AmazonEC2RoleforAWSCodeDeployandAutoScalingNotificationAccessRolepolicies. - Let’s name this IAM Role as 
CodeDeployInstanceRole - Create another IAM Role with 
AWSCodeDeployRolepolicy. - Let’s name this one as 
CodeDeployServiceRole 
Configure EC2 Instance for the application
Make sure you already have an instance running.
You just gotta modify the tags to let the CodeDeploy Agent know which instances to deploy the code on.
- Let’s put two tags: 
env: productionandname: my-application 
Create S3 Bucket for application revision
This bucket will be used to store our revised application before it is deployed to the instance.
Note: Creating this bucket is necessary if you want to add some files to the codebase that you couldn’t store in the Github repository, such as
_.env_files.If you don’t have any such thing, then you can skip this step.
- You may name the bucket whatever you like.
 - Make sure 
Block all public accessoption is checked. 
Configure CodeDeploy
- Navigate to 
CodeDeployin AWS Management Console. - Create an application and give it a name.
 - Under 
Compute PlatformchooseEC2/On-premises - Create Application.
 
- After creating the application, create a deployment group
 - Name it whatever you’d like, and under 
Service RolechooseCodeDeployServiceRole. 
- Under 
Deployment TypechooseIn-place. - For 
Environment ConfigurationchooseAmazon EC2 instancesand specify the tags that we specified previously for our instances:env: productionandname: my-application - For 
Deployment SettingschooseCodeDeployDefault.OneAtATime. 
- Deselect 
Enable Load Balancing - Create Deployment Group.
 
Phew, we are done with setting up on the AWS side, now let’s get to the good stuff.
Setting up on the Code Repository Side
Create an appspec.yml file, and place it in the root of the directory.
| version: 0.0 | |
| os: linux | |
| files: | |
| - source: / | |
| destination: /home/ubuntu/my-application | |
| hooks: | |
| BeforeInstall: | |
| - location: ./scripts/init.sh | |
| timeout: 300 | |
| runas: root | |
| ApplicationStart: | |
| - location: ./scripts/start_app.sh | |
| timeout: 300 | |
| runas: root | |
| ApplicationStop: | |
| - location: ./scripts/cleanup.sh | |
| timeout: 300 | |
| runas: root | 
Let’s setup our CI workflow now. I am using Github Actions for my CI/CD setup.
Create a .github/workflow/deploy.yml file
| name: CI/CD Deployment | |
| on: [push] | |
| jobs: | |
| buildAndTest: | |
| name: CI Pipeline | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| node-version: ['12.x'] | |
| steps: | |
| - uses: actions/checkout@v2 | |
| # Initialize Node.js | |
| - name: Install Node.js ${{ matrix.node-version }} | |
| uses: actions/setup-node@v1 | |
| with: | |
| node-version: ${{ matrix.node-version }} | |
| # Install project dependencies and test | |
| - name: Install dependencies | |
| run: npm install | |
| - name: Run tests | |
| run: npm run test | |
| deploy: | |
| name: Deploy | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| python-version: [3.8] | |
| node-version: ['12.x'] | |
| appname: ['my-application-codedeploy'] | |
| deploy-group: ['production'] | |
| s3-bucket: ['my-application-codedeploys'] | |
| s3-filename: ['prod-aws-codedeploy-${{ github.sha }}'] | |
| needs: buildAndTest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v2 | |
| # Configure AWS Credentials | |
| - 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: ${{ secrets.AWS_REGION }} | |
| # Fetch secrets from S3 Bucket | |
| - name: Configure Secrets | |
| run: | | |
| aws s3 cp s3://my-application-secrets/production/env/ ./env/ --recursive | |
| # Deploy push to AWS S3 | |
| - name: AWS Deploy push | |
| run: | | |
| aws deploy push \ | |
| --application-name ${{ matrix.appname }} \ | |
| --description "Revision for the ${{ matrix.appname }}-${{ github.sha }}" \ | |
| --no-ignore-hidden-files \ | |
| --s3-location s3://${{ matrix.s3-bucket }}/${{ matrix.s3-filename }}.zip \ | |
| --source . | |
| # Create deployment using AWS CodeDeploy | |
| - name: AWS Create Deployment | |
| run: | | |
| aws deploy create-deployment \ | |
| --application-name ${{ matrix.appname }} \ | |
| --deployment-config-name CodeDeployDefault.OneAtATime \ | |
| --deployment-group-name ${{ matrix.deploy-group }} \ | |
| --file-exists-behavior OVERWRITE \ | |
| --s3-location bucket=${{ matrix.s3-bucket }},key=${{ matrix.s3-filename }}.zip,bundleType=zip \ | 
Note: In the
_Configure Secrets_step, we are fetching our secrets from a AWS S3 Bucket where we have stored to_.env_files, as those can not be stored on the Github repository.If you don’t have any secrets to configure, you can deploy directly from Github repository. Instead
_s3-location_, you'd need to specify_github-location_: reference
Now, we just have to configure AWS Credentials that we used above.
Setting up CodeDeploy IAM User
- Go to 
IAM -> Usersin your AWS Console. - Create a new IAM User, let’s name it 
CodeDeployUser, and give itProgrammatic Access 
- We need 2 sets of permissions: 
AmazonS3FullAccessandAWSCodeDeployDeployerAccess 
- Create the user, and save the user’s credentials 
ACCESS_KEY_IDandSECRET_ACCESS_KEY 
Set those secrets in your Github Repository and you are all good to go!
Great! now, every push you do to your repository will be deployed to your EC2 instance.
But, wait. If you push to your repository after modifying just one of the services, all of them need to be restarted, that’s not how a Microservice Architecture works.
We need to decouple all our services from each other for all of them to operate separately.
Let’s get to that stuff in PART 3…
Read Next:
