Skip to content

Commit

Permalink
Merge pull request #7 from Altonhe/feature/paas
Browse files Browse the repository at this point in the history
PaaS: add deployment on ACI, AWS ECS and Google Cloud Run
  • Loading branch information
aaronbrethorst committed Jul 27, 2024
2 parents 4e4b06b + a3f9e59 commit ef9c8b5
Show file tree
Hide file tree
Showing 18 changed files with 1,101 additions and 9 deletions.
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ This repo is using [Opentofu](https://opentofu.org/) and other tools to create c

## Platform Support Status

| | VM | Docker | K8s |
|-----------------------|-------------|-----------------|--------------|
| Microsoft Azure | VM ✅ | ACI 🚧 | AKS 🔲 |
| Amazon Web Services | EC2 ✅ | ECS 🚧 | EKS 🔲 |
| Google Cloud Platform | GCE ✅ | GAE 🚧 | GKE 🔲 |
| Render || DOCKER ✅(See 1) ||
| Heroku || HCR 🔲 ||
| DigitalOcean | Droplets 🔲 | CR 🔲 | DOKS 🔲 |
| Native K8s ||| K8S ✅(See 2) |
| | VM | Docker | K8s |
|-----------------------|-------------|-------------------|--------------|
| Microsoft Azure | VM ✅ | ACI | AKS 🔲 |
| Amazon Web Services | EC2 ✅ | ECS(Fargate) ✅ | EKS 🔲 |
| Google Cloud Platform | GCE ✅ | Cloud Run ✅ | GKE 🔲 |
| Render || DOCKER ✅🚧(See 1) ||
| Heroku || HCR 🚧 ||
| DigitalOcean | Droplets 🚧 | CR 🚧 | DOKS 🔲 |
| Native K8s || | K8S ✅(See 2) |

The following icons are used to represent the status of support for each platform:
- ✅: completed
Expand Down
19 changes: 19 additions & 0 deletions modules/aws-ecs/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

199 changes: 199 additions & 0 deletions modules/aws-ecs/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
provider "aws" {
region = var.region
}

locals {
liveness_probe_path = "/onebusaway-api-webapp/api/where/current-time.json?key=org.onebusaway.iphone"
liveness_probe_initial_delay_seconds = 120
liveness_probe_period_seconds = 30
}

resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
}

resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
}

resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id

route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
}

resource "aws_route_table_association" "public" {
subnet_id = aws_subnet.main.id
route_table_id = aws_route_table.public.id
}

resource "aws_subnet" "main" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = "${var.region}a"
map_public_ip_on_launch = true
}

resource "aws_security_group" "main" {
vpc_id = aws_vpc.main.id

ingress {
from_port = 8080
to_port = 8080
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}

ingress {
from_port = 2049
to_port = 2049
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}

egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}

resource "aws_efs_file_system" "main" {
creation_token = "ecs-efs-oba"
}

resource "aws_efs_mount_target" "main" {
file_system_id = aws_efs_file_system.main.id
subnet_id = aws_subnet.main.id
security_groups = [aws_security_group.main.id]
}

resource "aws_ecs_cluster" "main" {
name = var.cluster_name
}

resource "aws_cloudwatch_log_group" "main" {
name = "/ecs/${var.container_name}"
retention_in_days = 7
}

resource "aws_iam_role" "ecs_task_execution_role" {
name = "ecsTaskExecutionRole"

assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "ecs-tasks.amazonaws.com"
}
}]
})
}

resource "aws_iam_role_policy_attachment" "ecs_task_execution_role_policy" {
role = aws_iam_role.ecs_task_execution_role.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
}

resource "aws_ecs_task_definition" "main" {
family = var.container_name
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
cpu = var.container_cpu
memory = var.container_memory
execution_role_arn = aws_iam_role.ecs_task_execution_role.arn

container_definitions = jsonencode([{
name = var.container_name
image = var.container_image
cpu = var.container_cpu
memory = var.container_memory
memoryReservation = var.container_memory
essential = true

environment = [
{ name = "TZ", value = var.env_var_tz },
{ name = "GTFS_URL", value = var.env_var_gtfs_url },
{ name = "VEHICLE_POSITIONS_URL", value = var.env_var_vehicle_positions_url },
{ name = "TRIP_UPDATES_URL", value = var.env_var_trip_updates_url },
{ name = "ALERTS_URL", value = var.env_var_alerts_url },
{ name = "REFRESH_INTERVAL", value = var.env_var_refresh_interval },
{ name = "AGENCY_ID", value = var.env_var_agency_id },
{ name = "FEED_API_KEY", value = var.env_var_feed_api_key },
{ name = "FEED_API_VALUE", value = var.env_var_feed_api_value },
{ name = "JDBC_USER", value = var.env_var_jdbc_user },
{ name = "JDBC_PASSWORD", value = var.env_var_jdbc_password },
{ name = "JDBC_URL", value = var.env_var_jdbc_url },
{ name = "GOOGLE_MAPS_API_KEY", value = var.env_var_google_maps_api_key },
{ name = "GOOGLE_MAPS_CHANNEL_ID", value = var.env_var_google_maps_channel_id },
{ name = "GOOGLE_MAPS_CLIENT_ID", value = var.env_var_google_maps_client_id },
]

portMappings = [
{
containerPort = 8080
hostPort = 8080
protocol = "tcp"
}
]

mountPoints = [
{
sourceVolume = "bundle"
containerPath = "/bundle"
readOnly = false
}
]

healthCheck = {
command = ["CMD-SHELL", "curl -f http://localhost:8080${local.liveness_probe_path} || exit 1"]
interval = local.liveness_probe_period_seconds
timeout = 5
retries = 3
startPeriod = local.liveness_probe_initial_delay_seconds
}

logConfiguration = {
logDriver = "awslogs"
options = {
"awslogs-group" = "/ecs/${var.container_name}"
"awslogs-region" = var.region
"awslogs-stream-prefix" = "ecs"
}
}
}])

volume {
name = "bundle"

efs_volume_configuration {
file_system_id = aws_efs_file_system.main.id
root_directory = "/"
}
}

depends_on = [
aws_efs_file_system.main, aws_efs_mount_target.main
]
}

resource "aws_ecs_service" "main" {
name = var.service_name
cluster = aws_ecs_cluster.main.id
task_definition = aws_ecs_task_definition.main.arn
desired_count = 1
launch_type = "FARGATE"

network_configuration {
subnets = [aws_subnet.main.id]
security_groups = [aws_security_group.main.id]
assign_public_ip = true
}
}
68 changes: 68 additions & 0 deletions modules/aws-ecs/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Deployment Guide for AWS ECS(Fargate)

AWS ECS is a robust choice for deploying the OneBusAway server, providing a managed container orchestration service that simplifies running and scaling containerized applications. This guide will walk you through deploying the OneBusAway server on AWS ECS using Opentofu.

## Prerequisites

1. An AWS account. If you don't have one, you can create a free account [here](https://aws.amazon.com/free/).

2. AWS CLI. You can install it by following the instructions [here](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html).

3. Opentofu, an open-source Terraform alternative, you can install it by following the instructions [here](https://opentofu.org/docs/intro/install/).

4. Ensure you have *ALL* the prerequisites installed before starting the deployment.

## Steps

1. Clone this repository to your local machine. You can run:

```bash
git clone https://github.com/OneBusAway/onebusaway-deployment.git
cd onebusaway-deployment/modules/aws-ecs
```

2. Initialize the project. This will download the necessary plugins and providers for the project:

```bash
tofu init
```

3. Create a `terraform.tfvars` file by copying the example variables file, and then modify it according to your needs:

```bash
cp terraform.tfvars.example terraform.tfvars
```

4. Edit the `terraform.tfvars` file and update the variable values to match your specific requirements, such as AWS region, cluster name, container details, and environment variables.

5. Run Tofu plan to preview the infrastructure changes:

```bash
tofu plan
```

6. Apply the Tofu configuration to create the actual resources:

```bash
tofu apply
```

Type `yes` when prompted to confirm the resource creation.

7. After the deployment is complete, verify the created resources in the AWS Management Console. Ensure the ECS cluster, tasks, service, and other related resources are created and running correctly.

8. Access the OneBusAway server by visiting the public IP of the ECS service. You can find the server IP in the AWS Management Console under the ECS service details.

## Clean up

If you want to shut down the server and clean up the resources, you can run the following command:

```bash
tofu destroy
```

Opentofu will destroy all resources created by this project, including the ECS cluster, task definition, security groups, and other resources.

## Conclusion

This guide shows you how to deploy the OneBusAway server on AWS ECS using Opentofu. If you have any questions or suggestions, feel free to open an issue in this repository.
23 changes: 23 additions & 0 deletions modules/aws-ecs/terraform.tfvars.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
region = "us-east-1"
cluster_name = "oba-cluster"
container_name = "onebusaway-api-server"
container_image = "ghcr.io/onebusaway/onebusaway-api-webapp:latest"
container_cpu = 2048
container_memory = 4096
service_name = "oba-service"

env_var_tz = "America/Toronto"
env_var_gtfs_url = "https://api.cityofkingston.ca/gtfs/gtfs.zip"
env_var_vehicle_positions_url = "https://api.cityofkingston.ca/gtfs-realtime/vehicleupdates.pb"
env_var_trip_updates_url = "https://api.cityofkingston.ca/gtfs-realtime/tripupdates.pb"
env_var_alerts_url = "https://api.cityofkingston.ca/gtfs-realtime/alerts.pb"
env_var_feed_api_key = ""
env_var_feed_api_value = ""
env_var_refresh_interval = "30"
env_var_agency_id = "0"
env_var_jdbc_user = "oba_user"
env_var_jdbc_password = "oba_password"
env_var_jdbc_url = "jdbc:mysql://<DATABASE_HOST>:<PORT>/oba_database"
env_var_google_maps_api_key = ""
env_var_google_maps_channel_id = ""
env_var_google_maps_client_id = ""
Loading

0 comments on commit ef9c8b5

Please sign in to comment.