diff --git a/.github/workflows/terraform.yaml b/.github/workflows/ecs_terraform.yaml
similarity index 91%
rename from .github/workflows/terraform.yaml
rename to .github/workflows/ecs_terraform.yaml
index ae78e9d..f5e20bf 100644
--- a/.github/workflows/terraform.yaml
+++ b/.github/workflows/ecs_terraform.yaml
@@ -2,11 +2,17 @@ name: "Terraform CICD - AWS ECS Instance"
on:
pull_request:
- branches:
- - main
+ branches: [main]
+ paths:
+ - 'infra/ecs/**'
+ - 'infra/envs/**'
+ - '.github/workflows/ecs_terraform.yaml'
push:
- branches:
- - main
+ branches: [main]
+ paths:
+ - 'infra/ecs/**'
+ - 'infra/envs/**'
+ - '.github/workflows/ecs_terraform.yaml'
permissions:
contents: read
@@ -30,7 +36,7 @@ jobs:
defaults:
run:
shell: bash
- working-directory: infra
+ working-directory: infra/ecs
environment: dev
steps:
@@ -60,7 +66,7 @@ jobs:
- name: Terraform plan - dev
id: plan-dev
if: github.event_name == 'pull_request'
- run: terraform plan -var-file=envs/dev.tfvars -no-color -input=false
+ run: terraform plan -var-file=../envs/dev.tfvars -no-color -input=false
continue-on-error: true
- uses: actions/github-script@v7
@@ -96,7 +102,7 @@ jobs:
- name: Terraform Apply
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
- run: terraform apply -var-file=envs/dev.tfvars -no-color -auto-approve -input=false # TODO: use tf plan file
+ run: terraform apply -var-file=../envs/dev.tfvars -no-color -auto-approve -input=false # TODO: use tf plan file
# # Terraform Prod CI
# terraform-prod-ci:
@@ -134,7 +140,7 @@ jobs:
# - name: Terraform plan - prod
# id: plan-prod
# if: github.event_name == 'pull_request'
-# run: terraform plan -var-file=envs/prod.tfvars -no-color -input=false
+# run: terraform plan -var-file=../envs/prod.tfvars -no-color -input=false
# continue-on-error: true
# - uses: actions/github-script@v6
diff --git a/.github/workflows/eks_terraform.yaml b/.github/workflows/eks_terraform.yaml
new file mode 100644
index 0000000..be42703
--- /dev/null
+++ b/.github/workflows/eks_terraform.yaml
@@ -0,0 +1,202 @@
+name: "Terraform CICD - AWS EKS Cluster"
+
+on:
+ pull_request:
+ branches: [main]
+ paths:
+ - 'infra/eks/**'
+ - 'infra/envs/**'
+ - '.github/workflows/eks_terraform.yaml'
+ push:
+ branches: [main]
+ paths:
+ - 'infra/eks/**'
+ - 'infra/envs/**'
+ - '.github/workflows/eks_terraform.yaml'
+
+permissions:
+ contents: read
+ issues: write
+ pull-requests: write
+
+env:
+ # Verbosity setting for Terraform logs
+ TF_LOG: ERROR
+ # Credentials for deployment to AWS
+ AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+ # S3 bucket for the Terraform state
+ BUCKET_TF_STATE: ${{ secrets.EKS_BUCKET_TF_STATE}}
+
+jobs:
+# Terraform Dev CICD
+ terraform-dev:
+ name: "Terraform Infra CICD Dev"
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ shell: bash
+ working-directory: infra/ecs
+ environment: dev
+
+ steps:
+ - name: Checkout the repository to the runner
+ uses: actions/checkout@v4
+
+ - name: Setup Terraform with specified version on the runner
+ uses: hashicorp/setup-terraform@v3
+ with:
+ terraform_version: 1.11.3
+
+ - name: Terraform init dev
+ id: init-dev
+ run: terraform init -reconfigure -backend-config=bucket=$BUCKET_TF_STATE
+
+ # Quality checks DEV
+ - name: Terraform format
+ id: fmt-dev
+ if: github.event_name == 'pull_request'
+ run: terraform fmt -check
+
+ - name: Terraform validate
+ id: validate-dev
+ if: github.event_name == 'pull_request'
+ run: terraform validate
+
+ - name: Terraform plan - dev
+ id: plan-dev
+ if: github.event_name == 'pull_request'
+ run: terraform plan -var-file=../envs/dev.tfvars -no-color -input=false
+ continue-on-error: true
+
+ - uses: actions/github-script@v7
+ if: github.event_name == 'pull_request'
+ env:
+ PLAN: "terraform\n${{ steps.plan-dev.outputs.stdout }}"
+ with:
+ script: |
+ const output = `#### Terraform Format and Style - DEV 🖌\`${{ steps.fmt-dev.outcome }}\`
+ #### Terraform Initialization - DEV ⚙️\`${{ steps.init-dev.outcome }}\`
+ #### Terraform Validation - DEV 🤖\`${{ steps.validate-dev.outcome }}\`
+ #### Terraform Plan - DEV 📖\`${{ steps.plan-dev.outcome }}\`
+
+ Show Plan
+
+ \`\`\`\n
+ ${process.env.PLAN}
+ \`\`\`
+
+
+ *Pushed by: @${{ github.actor }}, Action: \`${{ github.event_name }}\`*`;
+
+ github.rest.issues.createComment({
+ issue_number: context.issue.number,
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ body: output
+ })
+
+ - name: Terraform Plan Status
+ if: steps.plan-dev.outcome == 'failure'
+ run: exit 1
+
+ - name: Terraform Apply
+ if: github.ref == 'refs/heads/main' && github.event_name == 'push'
+ run: terraform apply -var-file=../envs/dev.tfvars -no-color -auto-approve -input=false # TODO: use tf plan file
+
+# # Terraform Prod CI
+# terraform-prod-ci:
+# name: "Terraform Infra CI Prod"
+# runs-on: ubuntu-latest
+# defaults:
+# run:
+# shell: bash
+# environment: prod
+
+# steps:
+# - name: Checkout the repository to the runner
+# uses: actions/checkout@v4
+
+# - name: Setup Terraform with specified version on the runner
+# uses: hashicorp/setup-terraform@v3
+# with:
+# terraform_version: 1.11.3
+
+# - name: Terraform init prod
+# id: init-prod
+# run: terraform init -reconfigure -backend-config=bucket=$BUCKET_TF_STATE #Create new bucket for prod
+
+# # Quality checks PROD
+# - name: Terraform format
+# id: fmt-prod
+# if: github.event_name == 'pull_request'
+# run: terraform fmt -check
+
+# - name: Terraform validate
+# id: validate-prod
+# if: github.event_name == 'pull_request'
+# run: terraform validate
+
+# - name: Terraform plan - prod
+# id: plan-prod
+# if: github.event_name == 'pull_request'
+# run: terraform plan -var-file=../envs/prod.tfvars -no-color -input=false
+# continue-on-error: true
+
+# - uses: actions/github-script@v6
+# if: github.event_name == 'pull_request'
+# env:
+# PLAN: "terraform\n${{ steps.plan-prod.outputs.stdout }}"
+# with:
+# script: |
+# const output = `#### Terraform Format and Style - PROD 🖌\`${{ steps.fmt-prod.outcome }}\`
+# #### Terraform Initialization - PROD ⚙️\`${{ steps.init-prod.outcome }}\`
+# #### Terraform Validation - PROD 🤖\`${{ steps.validate-prod.outcome }}\`
+# #### Terraform Plan - PROD 📖\`${{ steps.plan-prod.outcome }}\`
+
+# Show Plan
+
+# \`\`\`\n
+# ${process.env.PLAN}
+# \`\`\`
+
+#
+# *Pushed by: @${{ github.actor }}, Action: \`${{ github.event_name }}\`*`;
+
+# github.rest.issues.createComment({
+# issue_number: context.issue.number,
+# owner: context.repo.owner,
+# repo: context.repo.repo,
+# body: output
+# })
+
+# - name: Terraform Plan Status
+# if: steps.plan-prod.outcome == 'failure'
+# run: exit 1
+
+# # Terraform PROD CD
+# terraform-prod-cd:
+# name: "Terraform Infra CD Prod"
+# needs: [terraform-dev, terraform-prod-ci]
+# runs-on: ubuntu-latest
+# defaults:
+# run:
+# shell: bash
+# environment: prod
+
+# steps:
+# - name: Checkout the repository to the runner
+# uses: actions/checkout@v3
+
+# - name: Setup Terraform with specified version on the runner
+# uses: hashicorp/setup-terraform@v2
+# with:
+# terraform_version: 1.3.9
+
+# - name: Terraform init prod
+# id: init-prod
+# run: terraform init -reconfigure -backend-config=bucket=$BUCKET_TF_STATE
+
+# - name: Terraform Apply
+# if: github.ref == 'refs/heads/main' && github.event_name == 'push' # only on push/merge to main
+# run: terraform apply -auto-approve -input=false
\ No newline at end of file
diff --git a/README.md b/README.md
index 8af4761..b99f2e8 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,30 @@
# TypeScript Node.js API → Docker → Amazon ECS
-*(local build & Terraform deploy – GitHub Actions pipeline coming soon)*
+*(local build & Terraform deploy – GitHub Actions EKS Infra CICD pipeline)*
+
+This repo walks you through containerising a simple Node.js API, pushing the image to Docker Hub, and provisioning the infrastructure on **Amazon EKS (EC2 capacity)** with **Terraform**.
+The VPC, Public Subnets, Internet Gateway, Route Table and Terraform remote-state bucket (S3 + DynamoDB) are assumed to exist already.
+
+Remote backend: S3 bucket `node-app-eks-tfstate-`
+
+## 1 · Initialise Terraform (one‑time per env)
+
+```bash
+cd infra/eks
+terraform init -reconfigure -backend-config=bucket=node-app-eks-tfstate-dev -backend-config=profile=node-app-terraform-dev
+```
+
+## 3 · Deploy with Terraform from directory infra/eks/
+
+```bash
+AWS_PROFILE=node-app-terraform-dev terraform plan -var-file=../envs/dev.tfvars
+
+AWS_PROFILE=node-app-terraform-dev terraform apply -var-file=../envs/dev.tfvars
+```
+
+
+
+# TypeScript Node.js API → Docker → Amazon ECS
+*(local build & Terraform deploy – GitHub Actions ECS Infra CICD pipeline)*
This repo walks you through containerising a simple Node.js API, pushing the image to Docker Hub, and provisioning the infrastructure on **Amazon ECS (EC2 capacity)** with **Terraform**.
The VPC, Public Subnets, Internet Gateway, Route Table and Terraform remote-state bucket (S3 + DynamoDB) are assumed to exist already.
@@ -20,19 +45,21 @@ The VPC, Public Subnets, Internet Gateway, Route Table and Terraform remote-stat
## 1 · Initialise Terraform (one‑time per env)
```bash
-cd infra
+cd infra/ecs
terraform init -reconfigure -backend-config=bucket=node-app-infra-tfstate-dev -backend-config=profile=node-app-terraform-dev
```
---
-## 2 · Build & push the container image (Apply new version tag where appropriate)
+## 2 · Local Build & push the container image (Apply new version tag)
```bash
docker buildx build --platform linux/amd64,linux/arm64 -t nrampling/demo-node-app:1.0.2 --push .
```
-
-Update the image tag in `infra/envs/dev.tfvars`:
+For ECS workload
+Update the image tag in `infra/ecs/envs/dev.tfvars`:
+For EKS workload
+Update the image tag in `infra/eks/envs/dev.tfvars`:
```hcl
node_app_image = "nrampling/demo-node-app:1.0.2"
@@ -40,12 +67,12 @@ node_app_image = "nrampling/demo-node-app:1.0.2"
---
-## 3 · Deploy with Terraform
+## 3 · Deploy with Terraform from directory infra/ecs/
```bash
-AWS_PROFILE=node-app-terraform-dev terraform plan -var-file=envs/dev.tfvars
+AWS_PROFILE=node-app-terraform-dev terraform plan -var-file=../envs/dev.tfvars
-AWS_PROFILE=node-app-terraform-dev terraform apply -var-file=envs/dev.tfvars
+AWS_PROFILE=node-app-terraform-dev terraform apply -var-file=../envs/dev.tfvars
```
### Outputs (example only - plug in aws account)
diff --git a/infra/.terraform.lock.hcl b/infra/ecs/.terraform.lock.hcl
similarity index 100%
rename from infra/.terraform.lock.hcl
rename to infra/ecs/.terraform.lock.hcl
diff --git a/infra/_backend.tf b/infra/ecs/_backend.tf
similarity index 100%
rename from infra/_backend.tf
rename to infra/ecs/_backend.tf
diff --git a/infra/_outputs.tf b/infra/ecs/_outputs.tf
similarity index 100%
rename from infra/_outputs.tf
rename to infra/ecs/_outputs.tf
diff --git a/infra/_providers.tf b/infra/ecs/_providers.tf
similarity index 100%
rename from infra/_providers.tf
rename to infra/ecs/_providers.tf
diff --git a/infra/_variables.tf b/infra/ecs/_variables.tf
similarity index 100%
rename from infra/_variables.tf
rename to infra/ecs/_variables.tf
diff --git a/infra/_versions.tf b/infra/ecs/_versions.tf
similarity index 100%
rename from infra/_versions.tf
rename to infra/ecs/_versions.tf
diff --git a/infra/alb.tf b/infra/ecs/alb.tf
similarity index 100%
rename from infra/alb.tf
rename to infra/ecs/alb.tf
diff --git a/infra/alb_sg.tf b/infra/ecs/alb_sg.tf
similarity index 100%
rename from infra/alb_sg.tf
rename to infra/ecs/alb_sg.tf
diff --git a/infra/ecs_asg_capacity.tf b/infra/ecs/ecs_asg_capacity.tf
similarity index 100%
rename from infra/ecs_asg_capacity.tf
rename to infra/ecs/ecs_asg_capacity.tf
diff --git a/infra/ecs_cluster.tf b/infra/ecs/ecs_cluster.tf
similarity index 100%
rename from infra/ecs_cluster.tf
rename to infra/ecs/ecs_cluster.tf
diff --git a/infra/ecs_instance_sg.tf b/infra/ecs/ecs_instance_sg.tf
similarity index 100%
rename from infra/ecs_instance_sg.tf
rename to infra/ecs/ecs_instance_sg.tf
diff --git a/infra/ecs_service.tf b/infra/ecs/ecs_service.tf
similarity index 100%
rename from infra/ecs_service.tf
rename to infra/ecs/ecs_service.tf
diff --git a/infra/iam_ecs_instance_assume_role.tf b/infra/ecs/iam_ecs_instance_assume_role.tf
similarity index 100%
rename from infra/iam_ecs_instance_assume_role.tf
rename to infra/ecs/iam_ecs_instance_assume_role.tf
diff --git a/infra/iam_task_execution_role.tf b/infra/ecs/iam_task_execution_role.tf
similarity index 100%
rename from infra/iam_task_execution_role.tf
rename to infra/ecs/iam_task_execution_role.tf
diff --git a/infra/launch_template_ecs.tf b/infra/ecs/launch_template_ecs.tf
similarity index 100%
rename from infra/launch_template_ecs.tf
rename to infra/ecs/launch_template_ecs.tf
diff --git a/infra/target_group_ecs.tf b/infra/ecs/target_group_ecs.tf
similarity index 100%
rename from infra/target_group_ecs.tf
rename to infra/ecs/target_group_ecs.tf
diff --git a/infra/task_definition.tf b/infra/ecs/task_definition.tf
similarity index 100%
rename from infra/task_definition.tf
rename to infra/ecs/task_definition.tf
diff --git a/infra/task_sg.tf b/infra/ecs/task_sg.tf
similarity index 100%
rename from infra/task_sg.tf
rename to infra/ecs/task_sg.tf
diff --git a/infra/eks/.terraform.lock.hcl b/infra/eks/.terraform.lock.hcl
new file mode 100644
index 0000000..964d099
--- /dev/null
+++ b/infra/eks/.terraform.lock.hcl
@@ -0,0 +1,105 @@
+# This file is maintained automatically by "terraform init".
+# Manual edits may be lost in future updates.
+
+provider "registry.terraform.io/hashicorp/aws" {
+ version = "5.98.0"
+ constraints = ">= 4.33.0, >= 5.95.0"
+ hashes = [
+ "h1:neMFK/kP1KT6cTGID+Tkkt8L7PsN9XqwrPDGXVw3WVY=",
+ "zh:23377bd90204b6203b904f48f53edcae3294eb072d8fc18a4531c0cde531a3a1",
+ "zh:2e55a6ea14cc43b08cf82d43063e96c5c2f58ee953c2628523d0ee918fe3b609",
+ "zh:4885a817c16fdaaeddc5031edc9594c1f300db0e5b23be7cd76a473e7dcc7b4f",
+ "zh:6ca7177ad4e5c9d93dee4be1ac0792b37107df04657fddfe0c976f36abdd18b5",
+ "zh:78bf8eb0a67bae5dede09666676c7a38c9fb8d1b80a90ba06cf36ae268257d6f",
+ "zh:874b5a99457a3f88e2915df8773120846b63d820868a8f43082193f3dc84adcb",
+ "zh:95e1e4cf587cde4537ac9dfee9e94270652c812ab31fce3a431778c053abf354",
+ "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425",
+ "zh:a75145b58b241d64570803e6565c72467cd664633df32678755b51871f553e50",
+ "zh:aa31b13d0b0e8432940d6892a48b6268721fa54a02ed62ee42745186ee32f58d",
+ "zh:ae4565770f76672ce8e96528cbb66afdade1f91383123c079c7fdeafcb3d2877",
+ "zh:b99f042c45bf6aa69dd73f3f6d9cbe0b495b30442c526e0b3810089c059ba724",
+ "zh:bbb38e86d926ef101cefafe8fe090c57f2b1356eac9fc5ec81af310c50375897",
+ "zh:d03c89988ba4a0bd3cfc8659f951183ae7027aa8018a7ca1e53a300944af59cb",
+ "zh:d179ef28843fe663fc63169291a211898199009f0d3f63f0a6f65349e77727ec",
+ ]
+}
+
+provider "registry.terraform.io/hashicorp/cloudinit" {
+ version = "2.3.7"
+ constraints = ">= 2.0.0"
+ hashes = [
+ "h1:M9TpQxKAE/hyOwytdX9MUNZw30HoD/OXqYIug5fkqH8=",
+ "zh:06f1c54e919425c3139f8aeb8fcf9bceca7e560d48c9f0c1e3bb0a8ad9d9da1e",
+ "zh:0e1e4cf6fd98b019e764c28586a386dc136129fef50af8c7165a067e7e4a31d5",
+ "zh:1871f4337c7c57287d4d67396f633d224b8938708b772abfc664d1f80bd67edd",
+ "zh:2b9269d91b742a71b2248439d5e9824f0447e6d261bfb86a8a88528609b136d1",
+ "zh:3d8ae039af21426072c66d6a59a467d51f2d9189b8198616888c1b7fc42addc7",
+ "zh:3ef4e2db5bcf3e2d915921adced43929214e0946a6fb11793085d9a48995ae01",
+ "zh:42ae54381147437c83cbb8790cc68935d71b6357728a154109d3220b1beb4dc9",
+ "zh:4496b362605ae4cbc9ef7995d102351e2fe311897586ffc7a4a262ccca0c782a",
+ "zh:652a2401257a12706d32842f66dac05a735693abcb3e6517d6b5e2573729ba13",
+ "zh:7406c30806f5979eaed5f50c548eced2ea18ea121e01801d2f0d4d87a04f6a14",
+ "zh:7848429fd5a5bcf35f6fee8487df0fb64b09ec071330f3ff240c0343fe2a5224",
+ "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
+ ]
+}
+
+provider "registry.terraform.io/hashicorp/null" {
+ version = "3.2.4"
+ constraints = ">= 3.0.0"
+ hashes = [
+ "h1:L5V05xwp/Gto1leRryuesxjMfgZwjb7oool4WS1UEFQ=",
+ "zh:59f6b52ab4ff35739647f9509ee6d93d7c032985d9f8c6237d1f8a59471bbbe2",
+ "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
+ "zh:795c897119ff082133150121d39ff26cb5f89a730a2c8c26f3a9c1abf81a9c43",
+ "zh:7b9c7b16f118fbc2b05a983817b8ce2f86df125857966ad356353baf4bff5c0a",
+ "zh:85e33ab43e0e1726e5f97a874b8e24820b6565ff8076523cc2922ba671492991",
+ "zh:9d32ac3619cfc93eb3c4f423492a8e0f79db05fec58e449dee9b2d5873d5f69f",
+ "zh:9e15c3c9dd8e0d1e3731841d44c34571b6c97f5b95e8296a45318b94e5287a6e",
+ "zh:b4c2ab35d1b7696c30b64bf2c0f3a62329107bd1a9121ce70683dec58af19615",
+ "zh:c43723e8cc65bcdf5e0c92581dcbbdcbdcf18b8d2037406a5f2033b1e22de442",
+ "zh:ceb5495d9c31bfb299d246ab333f08c7fb0d67a4f82681fbf47f2a21c3e11ab5",
+ "zh:e171026b3659305c558d9804062762d168f50ba02b88b231d20ec99578a6233f",
+ "zh:ed0fe2acdb61330b01841fa790be00ec6beaac91d41f311fb8254f74eb6a711f",
+ ]
+}
+
+provider "registry.terraform.io/hashicorp/time" {
+ version = "0.13.1"
+ constraints = ">= 0.9.0"
+ hashes = [
+ "h1:ZT5ppCNIModqk3iOkVt5my8b8yBHmDpl663JtXAIRqM=",
+ "zh:02cb9aab1002f0f2a94a4f85acec8893297dc75915f7404c165983f720a54b74",
+ "zh:04429b2b31a492d19e5ecf999b116d396dac0b24bba0d0fb19ecaefe193fdb8f",
+ "zh:26f8e51bb7c275c404ba6028c1b530312066009194db721a8427a7bc5cdbc83a",
+ "zh:772ff8dbdbef968651ab3ae76d04afd355c32f8a868d03244db3f8496e462690",
+ "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
+ "zh:898db5d2b6bd6ca5457dccb52eedbc7c5b1a71e4a4658381bcbb38cedbbda328",
+ "zh:8de913bf09a3fa7bedc29fec18c47c571d0c7a3d0644322c46f3aa648cf30cd8",
+ "zh:9402102c86a87bdfe7e501ffbb9c685c32bbcefcfcf897fd7d53df414c36877b",
+ "zh:b18b9bb1726bb8cfbefc0a29cf3657c82578001f514bcf4c079839b6776c47f0",
+ "zh:b9d31fdc4faecb909d7c5ce41d2479dd0536862a963df434be4b16e8e4edc94d",
+ "zh:c951e9f39cca3446c060bd63933ebb89cedde9523904813973fbc3d11863ba75",
+ "zh:e5b773c0d07e962291be0e9b413c7a22c044b8c7b58c76e8aa91d1659990dfb5",
+ ]
+}
+
+provider "registry.terraform.io/hashicorp/tls" {
+ version = "4.1.0"
+ constraints = ">= 3.0.0"
+ hashes = [
+ "h1:zEv9tY1KR5vaLSyp2lkrucNJ+Vq3c+sTFK9GyQGLtFs=",
+ "zh:14c35d89307988c835a7f8e26f1b83ce771e5f9b41e407f86a644c0152089ac2",
+ "zh:2fb9fe7a8b5afdbd3e903acb6776ef1be3f2e587fb236a8c60f11a9fa165faa8",
+ "zh:35808142ef850c0c60dd93dc06b95c747720ed2c40c89031781165f0c2baa2fc",
+ "zh:35b5dc95bc75f0b3b9c5ce54d4d7600c1ebc96fbb8dfca174536e8bf103c8cdc",
+ "zh:38aa27c6a6c98f1712aa5cc30011884dc4b128b4073a4a27883374bfa3ec9fac",
+ "zh:51fb247e3a2e88f0047cb97bb9df7c228254a3b3021c5534e4563b4007e6f882",
+ "zh:62b981ce491e38d892ba6364d1d0cdaadcee37cc218590e07b310b1dfa34be2d",
+ "zh:bc8e47efc611924a79f947ce072a9ad698f311d4a60d0b4dfff6758c912b7298",
+ "zh:c149508bd131765d1bc085c75a870abb314ff5a6d7f5ac1035a8892d686b6297",
+ "zh:d38d40783503d278b63858978d40e07ac48123a2925e1a6b47e62179c046f87a",
+ "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
+ "zh:fb07f708e3316615f6d218cec198504984c0ce7000b9f1eebff7516e384f4b54",
+ ]
+}
diff --git a/infra/eks/_backend.tf b/infra/eks/_backend.tf
new file mode 100644
index 0000000..c625800
--- /dev/null
+++ b/infra/eks/_backend.tf
@@ -0,0 +1,8 @@
+terraform {
+ backend "s3" {
+ key = "eks/terraform.tfstate"
+ region = "ap-southeast-2"
+ dynamodb_table = "terraform-locks"
+ encrypt = true
+ }
+}
diff --git a/infra/eks/_providers.tf b/infra/eks/_providers.tf
new file mode 100644
index 0000000..f101193
--- /dev/null
+++ b/infra/eks/_providers.tf
@@ -0,0 +1,4 @@
+provider "aws" {
+ region = var.aws_region
+ # Optionally pick credentials/profile via CLI flags or ENV vars
+}
diff --git a/infra/eks/_variables.tf b/infra/eks/_variables.tf
new file mode 100644
index 0000000..b2a35e7
--- /dev/null
+++ b/infra/eks/_variables.tf
@@ -0,0 +1,86 @@
+variable "environment" {
+ description = "Environment to deploy into"
+ type = string
+}
+
+variable "aws_region" {
+ description = "AWS Region to deploy into"
+ type = string
+ default = "ap-southeast-2"
+}
+
+variable "vpc_id" {
+ type = string
+ description = "VPC ID where the ECS cluster will be created"
+}
+
+variable "app_public_subnet_ids" {
+ type = list(string)
+}
+
+variable "alb_public_subnet_ids" {
+ type = list(string)
+}
+
+# variable "instance_type" {
+# type = string
+# default = "t2.micro"
+# }
+
+# variable "desired_capacity" {
+# type = number
+# default = 1
+# }
+
+# variable "min_size" {
+# type = number
+# default = 1
+# }
+
+# variable "max_size" {
+# type = number
+# default = 2
+# }
+
+# variable "key_name" {
+# type = string
+# default = ""
+# description = "Name of the key pair to use for SSH access to the EC2 instances."
+# }
+
+# variable "container_port" {
+# type = number
+# default = 3000
+# description = "Listening port for the container"
+# }
+
+# variable "node_app_health_check_path" {
+# type = string
+# default = "/ping"
+# description = "Health check path for the target group"
+# }
+
+# Public docker image for the application
+variable "node_app_image" {
+ type = string
+}
+
+# variable "desired_service_count" {
+# type = number
+# default = 1
+# }
+
+# variable "node_app_container_name" {
+# type = string
+# default = "node-app"
+# }
+
+# variable "log_group_name" {
+# type = string
+# default = "/ecs/node-app"
+# }
+
+# variable "log_stream_prefix" {
+# type = string
+# default = "ecs"
+# }
diff --git a/infra/eks/_versions.tf b/infra/eks/_versions.tf
new file mode 100644
index 0000000..4a7c24d
--- /dev/null
+++ b/infra/eks/_versions.tf
@@ -0,0 +1,9 @@
+terraform {
+ required_version = ">= 1.7.0"
+ required_providers {
+ aws = {
+ source = "hashicorp/aws"
+ version = "~> 5.0"
+ }
+ }
+}
diff --git a/infra/eks/cluster.tf b/infra/eks/cluster.tf
new file mode 100644
index 0000000..a575d0d
--- /dev/null
+++ b/infra/eks/cluster.tf
@@ -0,0 +1,20 @@
+module "eks" {
+ source = "terraform-aws-modules/eks/aws"
+ version = "~> 20.0"
+
+ cluster_name = "${var.environment}-eks"
+ cluster_version = "1.29"
+
+ vpc_id = var.vpc_id
+ subnet_ids = var.app_public_subnet_ids
+
+ # This config maps to an Auto Scaling Group under the hood
+ eks_managed_node_groups = {
+ default = {
+ instance_types = ["var.instance_type"]
+ desired_size = 1
+ min_size = 1
+ max_size = 2
+ }
+ }
+}