Skip to content

Latest commit

 

History

History
346 lines (242 loc) · 18.3 KB

deployment-aws.md

File metadata and controls

346 lines (242 loc) · 18.3 KB

AWS Deployment

Setup IAM User

Setup IAM users

  • Create the users: "Attach existing policies directly" with "Administrator Access" and "Billing" to view billing

Screen Shot 2020-04-15 at 1 15 14 PM

- Write down the `AWS Access Key ID` and `AWS Secret Access Key` - Do not forget to enable the billing console access: [instruction](https://aws.amazon.com/blogs/security/dont-forget-to-enable-access-to-the-billing-console/)

Configure AWS CLI

  • Install awscli
$ pip3 install awscli
$ aws --version
aws-cli/1.18.39 Python/3.7.7 Darwin/19.4.0 botocore/1.15.39
  • Configure AWS CLI:
    • AWS regions and codes: doc
      • US East (N. Virginia), code: us-east-1, slightly cheaper than Singapore
      • Asia Pacific (Singapore), code ap-southeast-1
    • AWS CLI uses two files to store the sensitive credential information (in ~/.aws/credentials) separated from the less sensitive configuration options (in ~/.aws/config). See the doc.
    • Run the following commands to setup and check cli is working (s3 does not have region)
    $ aws configure
    AWS Access Key ID [None]: A6NxxxxxZDKKB
    AWS Secret Access Key [None]: VLxxxx2fZWhr
    Default region name [None]: us-east-1
    Default output format [None]: json
    
    $ ls ~/.aws
    config		credentials
    
    $ aws s3 ls
    

Configure ECR and Dev Build Images

AWS ECR (Elastic Container Registry) is part of AWS ECS (Elastic Container Service):

Screen Shot 2020-04-15 at 1 34 04 PM

Go to Amazon ECS, click "Repositories", and then add two new repositories:

  • fred-backend: aws ecr create-repository --repository-name fred-backend --region us-east-1
  • fred-frontend: aws ecr create-repository --repository-name fred-frontend --region us-east-1

Screen Shot 2020-04-15 at 1 36 54 PM

Get the <AWS_ACCOUNT_ID> and the related URIs as shown in the screenshot above and build the images locally with tags (dev in this case):

docker build \
  -f services/backend/Dockerfile \
  -t <ECR-fred-backend-repo-URI>:dev \
  ./services/backend

  docker build \
    -f services/frontend/Dockerfile \
    -t <ECR-fred-frontend-repo-URI>:dev \
    ./services/frontend

After this, do docker image ls locally, you should see the two newly built images:

Screen Shot 2020-04-15 at 1 58 52 PM

Now, we are going to push the dev build images to ECR. If you check the repositories your created above, they should be empty: Screen Shot 2020-04-15 at 2 07 05 PM

Next, let's push the two images you just built locally on your computer to the repositories.

First, you need to login to AWS ECR by using the following command: aws ecr get-login-password --region us-east-1 generates the long password, which is piped to docker login to login with default username "AWS" - don't forget to change the account id or the region you chose. See doc

aws ecr get-login-password --region us-east-1 \
      | docker login --username AWS --password-stdin \
      <AWS_ACCOUNT_ID>.dkr.ecr.us-east-1.amazonaws.com

Next, use the following commands to push the images to the ECR repositories (it may take a while given the image sizes are about 400M and 800M):

docker push <AWS_ACCOUNT_ID>.dkr.ecr.us-east-1.amazonaws.com/fred-backend:dev
docker push <AWS_ACCOUNT_ID>.dkr.ecr.us-east-1.amazonaws.com/fred-frontend:dev

Once this is done, you should be able to the images in ECR: Screen Shot 2020-04-15 at 2 21 09 PM

Configure Production Build Images

Create/update the following files:

  • update services/db/create.sql: add CREATE DATABASE app_prod;
  • add services/backend/Dockerfile.prod
  • add services/frontend/Dockerfile.prod
  • add services/frontend/nginx/aws/default.conf: this file is used to overwrite the default nginx configuration
  • add docker-compose.prod.yml

Then, test out the production images locally:

$ docker-compose down -v
$ docker-compose -f docker-compose.prod.yml up -d --build
$ docker-compose exec backend python manage.py reset_db
$ docker-compose exec backend python manage.py load_data

Test it out at http://localhost:3007/

Build the production images with the prod tag:

$ docker build \
    -f services/backend/Dockerfile.prod \
    -t <ECR-fred-backend-repo-URI>:prod \
    ./services/backend

$ docker build \
    -f services/frontend/Dockerfile.prod \
    -t <ECR-fred-frontend-repo-URI>:prod \
    --build-arg NODE_ENV=production \
    --build-arg REACT_APP_USERS_SERVICE_URL=${REACT_APP_USERS_SERVICE_URL} \
    ./services/frontend

You should see the new production images using docker image ls (you can see the frontend production image size is much smaller than the dev image):

Screen Shot 2020-04-15 at 7 12 27 PM

Now, push the production images to ECR:

$ docker push <ECR-fred-backend-repo-URI>:prod
$ docker push <ECR-fred-frontend-repo-URI>:prod

You can see the production images on ECR:

Screen Shot 2020-04-15 at 7 21 01 PM

Configure CodeBuild

Go to the CodeBuild dashboard and click "Create project":

Screen Shot 2020-04-15 at 7 27 27 PM

Follow the screenshots below:

Screen Shot 2020-04-15 at 7 30 47 PM

Screen Shot 2020-04-15 at 7 29 04 PM

Screen Shot 2020-04-15 at 7 31 30 PM

Screen Shot 2020-04-15 at 7 32 28 PM

Screen Shot 2020-04-15 at 7 34 40 PM

Screen Shot 2020-04-15 at 7 36 07 PM

Screen Shot 2020-04-15 at 7 36 40 PM

NOTE: add the AmazonEC2ContainerRegistryPowerUser policy to the codebuild-my-fra-service-role role using IAM dashboard. Screen Shot 2020-04-15 at 7 47 54 PM

Then, add buildspec.yml, push the code to Github and build in CodeBuild. Make sure it succeeded: Screen Shot 2020-04-15 at 10 42 33 PM

EC2-Classic vs. EC2-VPC

My AWS is quite old and was using EC2-Class. The new accounts are created only for EC2-VPC. I have to contact AWS to switch to the new EC2-VPC.

Each AWS has a default VPC for each region. If the default VPC is deleted. You can use the following command to re-create one: aws ec2 create-default-vpc

Configure Load Balancer

Screen Shot 2020-04-16 at 10 52 32 AM

Create "Application Load Balancer" (ALB):

Screen Shot 2020-04-16 at 10 53 18 AM

Screen Shot 2020-04-17 at 1 47 50 PM

Screen Shot 2020-04-17 at 1 49 33 PM

Screen Shot 2020-04-17 at 1 52 06 PM

Don't forget to change the value of REACT_APP_USERS_SERVICE_URL in buildspec.yml to the DNS name of the ALB.

Essentially, one ALB is created with one listener at port 80 and then have two rules to forward traffic:

  • if path is /, forward to the frontend task group
  • if other paths (/users /auth /etc.), forward to the backend task group at port 5000. NOTE only five paths can be specified in the rule.

Configure RDS

Screen Shot 2020-04-17 at 2 28 05 PM

Screen Shot 2020-04-17 at 2 32 23 PM

Screen Shot 2020-04-17 at 2 34 17 PM

Screen Shot 2020-04-17 at 2 35 25 PM

Get the password with master user name: fredapp: Screen Shot 2020-04-17 at 2 41 15 PM Screen Shot 2020-04-17 at 2 41 29 PM

Get the status of database:

$ aws --region us-east-1 rds describe-db-instances \
  --db-instance-identifier fred-db \
  --query 'DBInstances[].{DBInstanceStatus:DBInstanceStatus}'

$ aws --region us-east-1 rds describe-db-instances \
  --db-instance-identifier fred-db

Run the following command to get the address of the database:

aws --region us-east-1 rds describe-db-instances \
  --db-instance-identifier fred-db \
  --query 'DBInstances[].{Address:Endpoint.Address}'

  [
    {
        "Address": "fred-db.coaqhaja4wc9.us-east-1.rds.amazonaws.com"
    }
]

So, the production URI is:

postgres://fredapp:<YOUR_PASSWORD>@<YOUR_ADDRESS>:5432/fred_prod

Configure ECS

Screen Shot 2020-04-17 at 3 00 14 PM

Screen Shot 2020-04-17 at 3 02 09 PM

Screen Shot 2020-04-17 at 3 13 45 PM

Screen Shot 2020-04-17 at 3 14 45 PM

Screen Shot 2020-04-17 at 3 12 34 PM

Screen Shot 2020-04-17 at 3 13 32 PM

Screen Shot 2020-04-17 at 3 12 18 PM

Screen Shot 2020-04-17 at 3 18 42 PM

Screen Shot 2020-04-17 at 3 19 17 PM

Screen Shot 2020-04-17 at 3 22 41 PM

Screen Shot 2020-04-17 at 3 22 30 PM

Screen Shot 2020-04-17 at 3 23 04 PM

Screen Shot 2020-04-17 at 3 23 51 PM

Screen Shot 2020-04-17 at 3 24 11 PM

Screen Shot 2020-04-17 at 3 25 52 PM

Screen Shot 2020-04-17 at 3 28 36 PM

Screen Shot 2020-04-17 at 3 30 19 PM

Screen Shot 2020-04-17 at 3 31 27 PM

Screen Shot 2020-04-17 at 3 31 53 PM

Screen Shot 2020-04-17 at 3 32 16 PM

Screen Shot 2020-04-17 at 3 34 57 PM

update security group rule to make healthy check pass:

Screen Shot 2020-04-17 at 3 56 14 PM

Screen Shot 2020-04-17 at 3 56 31 PM

  • Task Definition:
  • Tasks
  • Services
  • Clusters

Cluster has services, service has tasks

get the EC2 instance of the backend to login to initialize the database:

Screen Shot 2020-04-17 at 3 58 18 PM

Screen Shot 2020-04-17 at 3 58 27 PM

Screen Shot 2020-04-17 at 3 58 43 PM

Screen Shot 2020-04-17 at 3 58 50 PM

Screen Shot 2020-04-17 at 3 59 05 PM

dami:fred harrywang$ chmod 400 ~/sandbox/keys/fred-aws.pem
dami:fred harrywang$ ssh -i ~/sandbox/keys/fred-aws.pem [email protected]
[ec2-user@ip-172-31-84-8 ~]$ docker ps
CONTAINER ID        IMAGE                                                            COMMAND                  CREATED             STATUS                    PORTS                     NAMES
017ff3d54c29        991046682610.dkr.ecr.us-east-1.amazonaws.com/fred-backend:prod   "/bin/sh -c 'gunicor…"   4 minutes ago       Up 4 minutes              0.0.0.0:32770->5000/tcp   ecs-fred-backend-td-1-backend-e09bb2fc80e288904f00
de0d72895173        amazon/amazon-ecs-agent:latest                                   "/agent"                 22 minutes ago      Up 22 minutes (healthy)                             ecs-agent
$ docker exec -it 017ff3d54c29 bash
root@017ff3d54c29:/usr/src/app# python manage.py reset_db
database reset done!
root@017ff3d54c29:/usr/src/app# python manage.py load_data
user table loaded
author and quote tables loaded

Now go to http://LOAD_BALANCER_DNS_NAME to test out!!

Configure CodeBuild

add the following files:

  • ecs/ecs_backend_task_definition.json
  • ecs/ecs_frontend_task_definition.json
  • deploy.sh

update buildspec.yml:

post_build:
  commands:
  - echo pushing prod images to ecr...
  - docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/fred-backend:prod
  - docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/fred-frontend:prod
  - chmod +x ./deploy.sh
  - bash deploy.sh

Then, go to CodeBuild to add more environment variables:

Screen Shot 2020-04-17 at 4 11 48 PM

Screen Shot 2020-04-17 at 4 12 56 PM

Then, add a security policy to the role: Screen Shot 2020-04-17 at 4 15 02 PM

Shutdown

4 EC2 instances were started - you may want to shutdown them to avoid charges.

Delete the clusters will terminate all related EC2 instances.