|
Size: 6282
Comment:
|
Size: 6779
Comment:
|
| Deletions are marked like this. | Additions are marked like this. |
| Line 232: | Line 232: |
{{{#!highlight sh sudo apk add aws-cli --repository=https://alpinelinux.org aws --version aws configure sudo apk add terraform --repository=https://alpinelinux.org terraform --version terraform init terraform validate terraform plan terraform applu aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin ://amazonaws.com docker build -t cherrypy-app . docker tag cherrypy-app:latest ://amazonaws.com docker push ://amazonaws.com }}} |
terraform
Terraform is as open source tool to create, change and manage infrastructure through code (IaC infrastructure as code).
It acts as a infrastructure blueprint.
main.tf for ECS with cherrypy and postgres
1 # Provider definition
2 terraform {
3 required_providers {
4 aws = {
5 source = "hashicorp/aws"
6 version = "~> 5.0"
7 }
8 }
9 }
10
11 provider "aws" {
12 region = var.aws_region
13 }
14
15 # Variables
16 variable "aws_region" {
17 type = string
18 default = "us-east-1"
19 }
20
21 variable "db_password" {
22 type = string
23 description = "PostgreSQL database master password"
24 sensitive = true
25 default = "SuperSecurePassword123!"
26 }
27
28 # --- NETWORKING (VPC) ---
29 data "aws_availability_zones" "available" {
30 state = "available"
31 }
32
33 resource "aws_vpc" "main" {
34 cidr_block = "10.0.0.0/16"
35 enable_dns_hostnames = true
36 enable_dns_support = true
37 tags = { Name = "cherrypy-ecs-vpc" }
38 }
39
40 resource "aws_subnet" "public_1" {
41 vpc_id = aws_vpc.main.id
42 cidr_block = "10.0.1.0/24"
43 availability_zone = data.aws_availability_zones.available.names[0]
44 map_public_ip_on_launch = true
45 tags = { Name = "cherrypy-public-1" }
46 }
47
48 resource "aws_subnet" "public_2" {
49 vpc_id = aws_vpc.main.id
50 cidr_block = "10.0.2.0/24"
51 availability_zone = data.aws_availability_zones.available.names[1]
52 map_public_ip_on_launch = true
53 tags = { Name = "cherrypy-public-2" }
54 }
55
56 resource "aws_internet_gateway" "gw" {
57 vpc_id = aws_vpc.main.id
58 tags = { Name = "cherrypy-igw" }
59 }
60
61 resource "aws_route_table" "public" {
62 vpc_id = aws_vpc.main.id
63 route {
64 cidr_block = "0.0.0.0/0"
65 gateway_id = aws_internet_gateway.gw.id
66 }
67 tags = { Name = "cherrypy-public-rt" }
68 }
69
70 resource "aws_route_table_association" "public_1" {
71 subnet_id = aws_subnet.public_1.id
72 route_table_id = aws_route_table.public.id
73 }
74
75 resource "aws_route_table_association" "public_2" {
76 subnet_id = aws_subnet.public_2.id
77 route_table_id = aws_route_table.public.id
78 }
79
80 # --- SECURITY GROUPS ---
81 resource "aws_security_group" "ecs_tasks" {
82 name = "cherrypy-ecs-tasks-sg"
83 description = "Allow inbound traffic on port 8080"
84 vpc_id = aws_vpc.main.id
85
86 ingress {
87 protocol = "tcp"
88 from_port = 8080
89 to_port = 8080
90 cidr_blocks = ["0.0.0.0/0"] # For testing. In production, restrict via a Load Balancer.
91 }
92
93 egress {
94 protocol = "-1"
95 from_port = 0
96 to_port = 0
97 cidr_blocks = ["0.0.0.0/0"]
98 }
99 }
100
101 resource "aws_security_group" "db" {
102 name = "cherrypy-db-sg"
103 description = "Allow inbound traffic from ECS tasks only"
104 vpc_id = aws_vpc.main.id
105
106 ingress {
107 protocol = "tcp"
108 from_port = 5432
109 to_port = 5432
110 security_groups = [aws_security_group.ecs_tasks.id]
111 }
112
113 egress {
114 protocol = "-1"
115 from_port = 0
116 to_port = 0
117 cidr_blocks = ["0.0.0.0/0"]
118 }
119 }
120
121 # --- DATABASE (RDS PostgreSQL) ---
122 resource "aws_db_subnet_group" "main" {
123 name = "cherrypy-db-subnet-group"
124 subnet_ids = [aws_subnet.public_1.id, aws_subnet.public_2.id]
125 }
126
127 resource "aws_db_instance" "postgres" {
128 identifier = "cherrypy-postgres-db"
129 allocated_storage = 20
130 engine = "postgres"
131 engine_version = "15"
132 instance_class = "db.t4g.micro"
133 db_name = "cherrypy_db"
134 username = "cherrypy_user"
135 password = var.db_password
136 db_subnet_group_name = aws_db_subnet_group.main.name
137 vpc_security_group_ids = [aws_security_group.db.id]
138 skip_final_snapshot = true
139 }
140
141 # --- CONTAINER REGISTRY (ECR) ---
142 resource "aws_ecr_repository" "app" {
143 name = "cherrypy-app"
144 image_tag_mutability = "MUTABLE"
145 image_scanning_configuration {
146 scan_on_push = true
147 }
148 }
149
150 # --- IAM ROLES FOR ECS ---
151 resource "aws_iam_role" "ecs_execution_role" {
152 name = "cherrypy-ecs-execution-role"
153
154 assume_role_policy = jsonencode({
155 Version = "2012-10-17"
156 Statement = [{
157 Action = "sts:AssumeRole"
158 Effect = "Allow"
159 Principal = { Service = "ecs-tasks.amazonaws.com" }
160 }]
161 })
162 }
163
164 resource "aws_iam_role_policy_attachment" "ecs_execution" {
165 role = aws_iam_role.ecs_execution_role.name
166 policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
167 }
168
169 # --- CONTAINER ORCHESTRATION (ECS) ---
170 resource "aws_ecs_cluster" "main" {
171 name = "cherrypy-ecs-cluster"
172 }
173
174 resource "aws_ecs_task_definition" "app" {
175 family = "cherrypy-task"
176 network_mode = "awsvpc"
177 requires_compatibilities = ["FARGATE"]
178 cpu = "256"
179 memory = "512"
180 execution_role_arn = aws_iam_role.ecs_execution_role.arn
181
182 container_definitions = jsonencode([{
183 name = "cherrypy-container"
184 image = "${aws_ecr_repository.app.repository_url}:latest"
185 essential = true
186 portMappings = [{
187 containerPort = 8080
188 hostPort = 8080
189 }]
190 environment = [
191 { name = "DB_HOST", value = aws_db_instance.postgres.address },
192 { name = "DB_NAME", value = aws_db_instance.postgres.db_name },
193 { name = "DB_USER", value = aws_db_instance.postgres.username },
194 { name = "DB_PASS", value = var.db_password }
195 ]
196 }])
197 }
198
199 resource "aws_ecs_service" "main" {
200 name = "cherrypy-service"
201 cluster = aws_ecs_cluster.main.id
202 task_definition = aws_ecs_task_definition.app.arn
203 desired_count = 1
204 launch_type = "FARGATE"
205
206 network_configuration {
207 subnets = [aws_subnet.public_1.id, aws_subnet.public_2.id]
208 security_groups = [aws_security_group.ecs_tasks.id]
209 assign_public_ip = true
210 }
211 }
212
213 # --- OUTPUTS ---
214 output "ecr_repository_url" {
215 value = aws_ecr_repository.app.repository_url
216 description = "Use URL to push the CherryPy Docker image"
217 }
218
219 output "db_endpoint" {
220 value = aws_db_instance.postgres.endpoint
221 description = "PostgreSQL database endpoint"
222 }
1 sudo apk add aws-cli --repository=https://alpinelinux.org
2 aws --version
3 aws configure
4 sudo apk add terraform --repository=https://alpinelinux.org
5 terraform --version
6 terraform init
7 terraform validate
8 terraform plan
9 terraform applu
10 aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin ://amazonaws.com
11 docker build -t cherrypy-app .
12 docker tag cherrypy-app:latest ://amazonaws.com
13 docker push ://amazonaws.com
