https://github.com/willis0826/ecs-flask-openresty
This is a demo of using AWS ECS, Flask and Openresty with CI/CD
https://github.com/willis0826/ecs-flask-openresty
aws ecs flask openresty semaphore-ci
Last synced: about 1 month ago
JSON representation
This is a demo of using AWS ECS, Flask and Openresty with CI/CD
- Host: GitHub
- URL: https://github.com/willis0826/ecs-flask-openresty
- Owner: Willis0826
- License: mit
- Created: 2020-01-06T09:28:44.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2023-05-29T12:14:11.000Z (about 3 years ago)
- Last Synced: 2025-02-28T10:09:04.870Z (over 1 year ago)
- Topics: aws, ecs, flask, openresty, semaphore-ci
- Language: HCL
- Homepage:
- Size: 2.46 MB
- Stars: 2
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# ecs-flask-openresty
[](https://willis.semaphoreci.com/projects/ecs-flask-openresty)
This is a demo of using AWS ECS, Flask and Openresty with CI/CD pipeline. The project uses a Openresty as reverse proxy to a backend Flask application. The Openresty and Flask are all run on AWS ECS.
## Manually create env for CI/CD
We use Semaphore CI to run our CI/CD pipeline which use Terraform. Therefore, the environment variables below are needed:
```yaml
AWS_ACCESS_KEY_ID: ___
AWS_SECRET_ACCESS_KEY: ___
AWS_DEFAULT_REGION: us-east-2
```
We also need a fallback ssl cert for Openresty using `lua-resty-auto-ssl`. The Semaphore CI secrets with file type is needed:
```yaml
~/resty-auto-ssl-fallback.crt
~/resty-auto-ssl-fallback.key
```

## Manually create resource
There are resources needed to be manually create before running CI/CD.
Pleaes be awared the S3 bucket name is global unique, you may need to create it with your specific name.
1. ECR `ecs-flask-openresty/flask` and `ecs-flask-openresty/openresty`

2. S3 `ecs-flask-openresty-tf-states` and `willis-lambda-assets`

3. EC2 Key Pairs `ecs-flask-cluster` `ecs-openresty-cluster`

4. IAM User with programmatic access

(This is for demo propuse, restrict your CI/CD user permission is recommanded)
There are resources needed to be manually create after ran CI/CD.
1. DNS domain `willischou.com` and setup DNS Server to created Route53
## Architecture
The diagram is generated with [PlantUML](https://plantuml.com/) and [C4 Model Extension](https://github.com/RicardoNiepel/C4-PlantUML)

```plantuml
@startuml architecture-component
!includeurl https://raw.githubusercontent.com/RicardoNiepel/C4-PlantUML/release/1-0/C4_Container.puml
LAYOUT_LEFT_RIGHT
Person(person, "User", "Access flask app")
System(lets_encrypt, "Let's Encrypt(CA)")
Container(route53, "Route 53", "Service")
Boundary(ecs_openresty, "ECS Openresty") {
Container(openresty_elb, "ELB Openresty", "Service")
Boundary(asg_openresty, "ASG Openresty") {
Container(openresty_instance_1, "EC2 Openresty", "Instance")
Container(openresty_instance_2, "EC2 Openresty", "Instance")
}
Rel(openresty_elb, openresty_instance_1, "Route to", "HTTP:80/HTTP:443")
Rel(openresty_elb, openresty_instance_2, "Route to", "HTTP:80/HTTP:443")
}
Boundary(ecs_flask, "ECS Flask") {
Container(flask_alb, "ALB Flask", "Service")
Boundary(asg_flask, "ASG Flask") {
Container(flask_instance_1, "EC2 Flask", "Instance")
}
Rel(flask_alb, flask_instance_1, "Route to", "HTTP:32768-61000")
}
Rel(person, openresty_elb, "Access", "HTTP:443/HTTP:80")
Rel(person, route53, "DNS resolve", "TCP:53/UDP:53")
Rel(openresty_instance_1, flask_alb, "Route to", "HTTP:5000")
Rel(openresty_instance_1, lets_encrypt, "Ask certificate", "HTTP:443")
Rel(openresty_instance_2, flask_alb, "Route to", "HTTP:5000")
Rel(openresty_instance_2, lets_encrypt, "Ask certificate", "HTTP:443")
@enduml
```
## CI/CD Implement
1. Create a sempahore 2.0 account and project
2. Create secrets at user(or organization or project) level, please refers "Manually create env for CI/CD" section
3. Create ECR, S3 and EC2 key pairs, please refers "Manually create resource" section
4. Replace the value of `ECR_REGISTRY`, `LAMBDA_ASSETS_S3` and `TERRAFORM_REMOTE_STATE_S3` in `.semaphore/semaphore.yml`
5. Replace the value of `AWS_VPC_ID`, `AWS_SUBNET_A_ID`, `AWS_SUBNET_B_ID` and `ALLOW_SSH_IP` with your own in `.semaphore/semaphore.yml`
6. Replace domain `willischou.com` with your own in `deploy/aws/template/route53.tf` and `nginx/default.conf`
7. Commit your changes and let the pipeline build it for you.
## Fedora CoreOs with ECS
You will need to transpile YAML formatted Butance config (`deploy/aws/template/cloud-config.yaml`) into JSON Ignition file (`deploy/aws/template/transpiled_config.ign`) via the following command:
```bash
docker run -it --rm --volume ${PWD}:/pwd --workdir /pwd quay.io/coreos/butane:release --pretty --strict deploy/aws/template/cloud-config.yaml > deploy/aws/template/transpiled_config.ign
```
Please read the fedora docs for more detail:
https://docs.fedoraproject.org/en-US/fedora-coreos/producing-ign/#_configuration_process
## Try it!
After deployed all the resources and point your domain name DNS server to Route53, you can test the application by the `curl`.
```bash
curl https://www.willischou.com -v
```
## Teardown
You can destroy all the resources created by terraform by running the following commands in local.
requirements:
1. gomplate https://github.com/hairyhenderson/gomplate
2. terraform 0.12.18 https://releases.hashicorp.com/terraform/
```bash
cd deploy/aws
ALLOW_SSH_IP="" AWS_SUBNET_B_ID="subnet-e9ec6492" AWS_SUBNET_A_ID="subnet-5664293f" AWS_VPC_ID="vpc-2a324d43" ECR_REGISTRY="" TERRAFORM_REMOTE_STATE_S3="ecs-flask-openresty-tf-states" AWS_DEFAULT_REGION="us-east-2" SLACK_INCOMING_WEBHOOK="" DEPLOY_ENV="dev" VERSION="" gomplate --input-dir=template --output-dir=dist -V
```
```
cd dist
AWS_PROFILE="__Your profile name goes here__" terraform init
AWS_PROFILE="__Your profile name goes here__" terraform destroy
```