8000 Setup CI for real app by VGLoic · Pull Request #2 · VGLoic/aws-exploration · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Setup CI for real app #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 23 additions & 24 deletions .github/workflows/aws.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ on:
env:
AWS_REGION: eu-west-3 # set this to your preferred AWS region, e.g. us-west-1
ECR_REPOSITORY: aws-guide-repo # set this to your Amazon ECR repository name
ECS_SERVICE: sample-fargate-service # set this to your Amazon ECS service name
ECS_SERVICE: app-fargate-service # set this to your Amazon ECS service name
ECS_CLUSTER: AwsFargateGuideCluster # set this to your Amazon ECS cluster name
ECS_TASK_DEFINITION: aws/task-def.json # set this to the path to your Amazon ECS task definition
ECS_TASK_DEFINITION: aws/app-task-def.json # set this to the path to your Amazon ECS task definition
# file, e.g. .aws/task-definition.json
CONTAINER_NAME: fargate-app # set this to the name of the container in the
CONTAINER_NAME: fargate-ci-guide-app # set this to the name of the container in the
# containerDefinitions section of your task definition

permissions:
Expand All @@ -63,32 +63,31 @@ jobs:
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1

# - name: Build, tag, and push image to Amazon ECR
# id: build-image
# env:
# ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
# IMAGE_TAG: ${{ github.sha }}
# 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: Build, tag, and push image to Amazon ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
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: ${{ env.ECS_TASK_DEFINITION }}
# container-name: ${{ env.CONTAINER_NAME }}
# image: ${{ steps.build-image.outputs.image }}
- 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: ${{ env.ECS_TASK_DEFINITION }}
container-name: ${{ env.CONTAINER_NAME }}
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 }}
task-definition: ${{ env.ECS_TASK_DEFINITION }}
task-definition: ${{ steps.task-def.outputs.task-definition }}
service: ${{ env.ECS_SERVICE }}
cluster: ${{ env.ECS_CLUSTER }}
10000 wait-for-service-stability: true
49 changes: 47 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,8 @@ The list of steps will be updated below.
2. [Creating a new task definition](#2-creating-a-new-task-definition),
3. [Running as as task](#3-running-as-a-task),
4. [Creating a service](#4-creating-a-service),
5. [Creating a Service in default security group and Load Balancer in another security group](#5-creating-a-service-in-default-security-group-and-load-balancer-in-another-security-group).
5. [Creating a Service in default security group and Load Balancer in another security group](#5-creating-a-service-in-default-security-group-and-load-balancer-in-another-security-group),
6. [Integrating a CI/CD with a dummy app](#6-integrating-a-ci/cd-with-a-dummy-app).


### 1. Modifying my cluster, actually creating a new one
Expand Down Expand Up @@ -665,7 +666,7 @@ So I go to the security group part in AWS and I go for modifying my default secu

I save this and try to hit on my load balancer DNS (with `/health`) and it works!

### 6. Integrating a CI/CD - following the blog post
### 6. Integrating a CI/CD with a dummy app

I would now like to have some automation and try to automatically deploy my new code when I push it on the `main` branch. I found this [blog post](https://aws.amazon.com/blogs/opensource/github-actions-aws-fargate/) of AWS that introduce the main AWS Github Actions, let's dig a bit.

Expand Down Expand Up @@ -764,6 +765,50 @@ I will try to re-modify my HTML just to see what happens. Not working again.

I will try to delete the html file before creating it.

Okay actually it was working all along but I was only updating the `head` part of the HTML... But at least it works fine!

I will delete this service and I'll try to update this for our codebase now!


### 7. Integrating a CI/CD with our app

I'll try to start very simple, I want a minimal task definition and a minimal service, so no load balancer or logs or else.

For this I'll start from the task definition that I used in the step 5 above, get its JSON, and try to simplify it as much as possible when taking a look at my previous task definition for the blog post app.

I rename my `task-def.json` to `sample-app-task-def.json` and create the new `app-task-def.json`.

So I first try to register my new task definition but it fails with `An error occurred (ClientException) when calling the RegisterTaskDefinition operation: Fargate requires task definition to have execution role ARN to support ECR images`.

So originally, my imported task definition had a line `"executionRoleArn": "arn:aws:iam::<ID>:role/ecsTaskExecutionRole"`, I removed it. Now I take a better look at this task execution role on [AWS documentation](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_execution_IAM_role.html). So my tasks need this role in order to pull the image from my ECR repository, looks fair.

I add back the line `executionRoleArn` and try again. Now it fails because it says that I don't have the `iam:PassRole` policy for the `role/ecsTaskExecutionRole`. Taking a look at what [it is](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_passrole.html), it is a role that is allowing me as user to give the designated role to a service. In my case, my user is not allowed to give this famous `ecsTaskExecutionRole` to my task definition. I'll try to add it directly in my user group using an inline policy. The policy is in `IAM` service and I needed to specify that it acted on the `role` `ecsTaskExecutionRole`. Now let's try again.

Amazing it worked fine, I can now see my new task definition in my console.

Let's create a service with it now.
```console
aws ecs create-service --region eu-west-3 --cluster AwsFargateGuideCluster --service-name app-fargate-service --task-definition fargate-ci-guide:1 --desired-count 2 --launch-type "FARGATE" --network-configuration "awsvpcConfiguration={subnets=[<my three subnets>],securityGroups=[<my default security group>],assignPublicIp=ENABLED}" --assignPublicIp ENABLED --profile aws-guide
```

Again, no load balancer or more complex settings. Let's see if it works.

I also modify my inbound rules of security group in order to allow incoming traffic to PORT 3000.

And it actually works, that's great news!

#### Let's setup the CI for this now!

I'll modify my workflow:
- the env variables need to be changed with new service name and app name,
- I enabled the steps in order to build and push my docker image, and update my local definition.


I'll update my healtcheck route to add an hardcoded `version` integer, just to be able to see the results.

I create a new PR for that.


## De 10000 velopment

This repository uses the [rust language](https://www.rust-lang.org/), make sure to have it installed before going further. Installation instructions can be found [here](https://www.rust-lang.org/tools/install).
Expand Down
39 changes: 39 additions & 0 deletions aws/app-task-def.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"family": "fargate-ci-guide",
"networkMode": "awsvpc",
"executionRoleArn": "arn:aws:iam::159541855776:role/ecsTaskExecutionRole",
"containerDefinitions": [
{
"name": "fargate-ci-guide-app",
"image": "159541855776.dkr.ecr.eu-west-3.amazonaws.com/aws-guide-repo:simple",
"cpu": 256,
"memory": 512,
"memoryReservation": 512,
"portMappings": [
{
"name": "fargateciguideapp-3000-tcp",
"containerPort": 3000,
"hostPort": 3000,
"protocol": "tcp",
"appProtocol": "http"
}
],
"essential": true,
"healthCheck": {
"command": [
"CMD-SHELL",
"curl -f http://localhost:3000/health || exit 1"
],
"interval": 30,
"timeout": 5,
"retries": 3
}
}
],
"volumes": [],
"requiresCompatibilities": [
"FARGATE"
],
"cpu": "256",
"memory": "512"
}
File renamed without changes.
4 changes: 3 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ async fn main() {

async fn healthcheck() -> (StatusCode, Json<HealthcheckResponse>) {
println!("Healthcheck has been called");
(StatusCode::OK, Json(HealthcheckResponse { ok: true }))
let version = 1;
(StatusCode::OK, Json(HealthcheckResponse { ok: true, version }))
}
// async fn healthcheck(State(db): State<Pool<Postgres>>) -> (StatusCode, Json<HealthcheckResponse>) {
// println!("Healthcheck has been called");
Expand All @@ -77,6 +78,7 @@ async fn healthcheck() -> (StatusCode, Json<HealthcheckResponse>) {
struct HealthcheckResponse {
// db_ok: bool,
ok: bool,
version: u8,
}

struct Config {
Expand Down
0