Skip to content

vitingr/aetherion-infra

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

aetherion-infra

Terraform infrastructure for the deployment platform. Provisions the AWS foundation that all application workloads run on top of — networking, Kubernetes cluster, container registry, and IAM roles.

Repository structure

platform-infra/
├── modules/
│   ├── vpc/        # Network layer — VPC, subnets, NAT gateways
│   ├── eks/        # Kubernetes cluster — EKS, node groups, OIDC, addons
│   ├── ecr/        # Container registries — one repo per service
│   └── iam/        # IAM roles — GitHub Actions, ALB controller
└── environments/
    ├── dev/        # Dev cluster configuration
    │   ├── main.tf
    │   ├── backend.tf
    │   ├── variables.tf
    │   ├── outputs.tf
    │   └── terraform.tfvars
    └── prod/       # Prod cluster configuration (same structure)

Modules contain the infrastructure logic and are never environment-specific. Environments call modules with different variable values — dev gets smaller nodes and a single NAT gateway, prod gets larger nodes and one NAT gateway per AZ for high availability.

Dependency order

Each module depends on outputs from the previous one. Terraform resolves this automatically — you never need to apply modules in a specific order manually.

vpc  →  eks  →  iam
              ↘
               ecr  (independent, no deps)

Prerequisites

These steps are done once per AWS account before running Terraform.

1. Install required tools

brew install terraform awscli kubectl helm
terraform -v   # should be >= 1.6
aws --version

2. Configure AWS credentials

aws configure
# AWS Access Key ID:     from IAM → Users → your user → Security credentials
# AWS Secret Access Key: same
# Default region:        us-east-2
# Default output format: json

# verify
aws sts get-caller-identity

3. Create the Terraform state backend (S3 + DynamoDB)

Terraform stores its state in S3. This bucket must exist before terraform init can run. Create it once manually:

# state bucket
aws s3api create-bucket \
  --bucket aetherion-terraform-state \
  --region us-east-2 \
  --create-bucket-configuration LocationConstraint=us-east-2

aws s3api put-bucket-versioning \
  --bucket aetherion-terraform-state \
  --versioning-configuration Status=Enabled

aws s3api put-bucket-encryption \
  --bucket aetherion-terraform-state \
  --server-side-encryption-configuration '{
    "Rules": [{"ApplyServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}]
  }'

# state lock table (prevents concurrent applies from corrupting state)
aws dynamodb create-table \
  --table-name terraform-locks \
  --attribute-definitions AttributeName=LockID,AttributeType=S \
  --key-schema AttributeName=LockID,KeyType=HASH \
  --billing-mode PAY_PER_REQUEST \
  --region us-east-2

4. Create the ALB controller IAM policy

This policy does not exist in a fresh AWS account. Create it once:

curl -o alb-policy.json \
  https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/main/docs/install/iam_policy.json

aws iam create-policy \
  --policy-name AWSLoadBalancerControllerIAMPolicy \
  --policy-document file://alb-policy.json

Deploying

All commands are run from inside the environment directory, never from a module directory.

cd environments/dev

# first time only — downloads providers and modules
terraform init

# preview what will be created
terraform plan

# create the infrastructure
terraform apply

After apply completes, configure kubectl:

aws eks update-kubeconfig \
  --name aetherion-dev \
  --region us-east-2

kubectl get nodes   # should show your nodes as Ready

Install the ALB Ingress Controller via Helm (once per cluster):

helm repo add eks https://aws.github.io/eks-charts
helm repo update

helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
  --namespace kube-system \
  --set clusterName=aetherion-dev \
  --set serviceAccount.annotations."eks\.amazonaws\.com/role-arn"=$(terraform output -raw alb_controller_role_arn)

Populate GitHub Actions variables

After terraform apply, copy these outputs into your GitHub organisation or repository variables:

terraform output github_actions_role_arn   # → GHA_ROLE_ARN
terraform output ecr_registry              # → ECR_REGISTRY
terraform output cluster_name              # → EKS_CLUSTER_NAME

These are the values your reusable deploy workflow reads at runtime. You only need to update them when infrastructure changes (rare).

Adding a new service

  1. Add the service name to module "ecr" { service_names = [...] } in environments/dev/main.tf and environments/prod/main.tf
  2. Add the repo name to module "iam" { github_repos = [...] } if it has its own app repo
  3. Run terraform apply in both environments
  4. The new ECR URL appears in terraform output ecr_urls

Module documentation

Each module has its own README with full input/output reference:

Environment differences

Setting Dev Prod
Cluster name aetherion-dev aetherion-prod
Node instance t3.medium t3.xlarge
Node count 2 desired 4 desired
NAT Gateways 1 (single AZ) 3 (one per AZ)
State key platform/dev/terraform.tfstate platform/prod/terraform.tfstate

State files

Each environment has its own isolated state file in S3:

aetherion-terraform-state/
├── platform/dev/terraform.tfstate
└── platform/prod/terraform.tfstate

This means a terraform apply in environments/dev cannot affect prod resources under any circumstances.

About

Terraform infrastructure for the deployment platform. Provisions the AWS foundation that all application workloads run on top of, networking, Kubernetes cluster, container registry, and IAM roles.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages