Skip to content

coderabbit-demo/rabbits-playground-aws-cf

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AWS CloudFormation Infrastructure

This repository contains AWS CloudFormation templates for deploying a complete AWS infrastructure including VPC, EKS cluster, Bastion host, S3 buckets, CloudFront CDN, and Route53 DNS configuration.

Architecture Overview

The infrastructure consists of the following components:

  • VPC: Multi-AZ VPC with public and private subnets across 3 availability zones
  • EKS: Kubernetes cluster with managed node groups (ARM64 Graviton instances)
  • Bastion: Jump host with SSM Session Manager support
  • S3: Static content and user content buckets with encryption
  • CloudFront: CDN distribution for static content delivery
  • Route53: DNS configuration with hosted zone and records

Prerequisites

  • AWS CLI configured with appropriate credentials
  • Sufficient AWS permissions to create all resources
  • (Optional) A registered domain name for Route53
  • (Optional) ACM certificate in us-east-1 for CloudFront custom domain

Project Structure

.
├── vpc.yaml                      # VPC CloudFormation template
├── eks.yaml                      # EKS CloudFormation template
├── bastion.yaml                  # Bastion host template
├── s3.yaml                       # S3 buckets template
├── cloudfront.yaml               # CloudFront distribution template
├── route53.yaml                  # Route53 DNS template
├── parameters/
│   ├── dev/                      # Dev environment parameters
│   │   ├── vpc-params.json
│   │   ├── eks-params.json
│   │   ├── bastion-params.json
│   │   ├── s3-params.json
│   │   ├── cloudfront-params.json
│   │   └── route53-params.json
│   └── prod/                     # Prod environment parameters
│       ├── vpc-params.json
│       ├── eks-params.json
│       ├── bastion-params.json
│       ├── s3-params.json
│       ├── cloudfront-params.json
│       └── route53-params.json
└── README.md

Deployment Order

The stacks must be deployed in the following order due to dependencies:

  1. VPC (no dependencies)
  2. EKS (depends on VPC)
  3. Bastion (depends on VPC)
  4. S3 (no dependencies)
  5. CloudFront (depends on S3)
  6. Route53 (depends on CloudFront and Bastion)

Deployment Instructions

Development Environment

1. Deploy VPC

aws cloudformation create-stack \
  --stack-name myproject-dev-vpc \
  --template-body file://vpc.yaml \
  --parameters file://parameters/dev/vpc-params.json \
  --capabilities CAPABILITY_NAMED_IAM \
  --region us-west-2

# Wait for stack creation to complete
aws cloudformation wait stack-create-complete \
  --stack-name myproject-dev-vpc \
  --region us-west-2

2. Deploy EKS

aws cloudformation create-stack \
  --stack-name myproject-dev-eks \
  --template-body file://eks.yaml \
  --parameters file://parameters/dev/eks-params.json \
  --capabilities CAPABILITY_NAMED_IAM \
  --region us-west-2

# Wait for stack creation (this takes 15-20 minutes)
aws cloudformation wait stack-create-complete \
  --stack-name myproject-dev-eks \
  --region us-west-2

3. Deploy Bastion

aws cloudformation create-stack \
  --stack-name myproject-dev-bastion \
  --template-body file://bastion.yaml \
  --parameters file://parameters/dev/bastion-params.json \
  --capabilities CAPABILITY_NAMED_IAM \
  --region us-west-2

# Wait for stack creation
aws cloudformation wait stack-create-complete \
  --stack-name myproject-dev-bastion \
  --region us-west-2

4. Deploy S3

aws cloudformation create-stack \
  --stack-name myproject-dev-s3 \
  --template-body file://s3.yaml \
  --parameters file://parameters/dev/s3-params.json \
  --region us-west-2

# Wait for stack creation
aws cloudformation wait stack-create-complete \
  --stack-name myproject-dev-s3 \
  --region us-west-2

5. Deploy CloudFront

aws cloudformation create-stack \
  --stack-name myproject-dev-cloudfront \
  --template-body file://cloudfront.yaml \
  --parameters file://parameters/dev/cloudfront-params.json \
  --region us-west-2

# Wait for stack creation (this takes 10-15 minutes)
aws cloudformation wait stack-create-complete \
  --stack-name myproject-dev-cloudfront \
  --region us-west-2

6. Deploy Route53

Before deploying Route53, update the domain name in parameters/dev/route53-params.json if needed.

aws cloudformation create-stack \
  --stack-name myproject-dev-route53 \
  --template-body file://route53.yaml \
  --parameters file://parameters/dev/route53-params.json \
  --region us-west-2

# Wait for stack creation
aws cloudformation wait stack-create-complete \
  --stack-name myproject-dev-route53 \
  --region us-west-2

Production Environment

For production, use the same deployment order but replace dev with prod in the stack names and parameter files:

# Example for production VPC
aws cloudformation create-stack \
  --stack-name myproject-prod-vpc \
  --template-body file://vpc.yaml \
  --parameters file://parameters/prod/vpc-params.json \
  --capabilities CAPABILITY_NAMED_IAM \
  --region us-west-2

Quick Deploy Script

You can create a deployment script to automate the process:

#!/bin/bash

ENV=$1  # dev or prod
REGION="us-west-2"
PROJECT="myproject"

if [ -z "$ENV" ]; then
  echo "Usage: ./deploy.sh <dev|prod>"
  exit 1
fi

echo "Deploying $ENV environment..."

# Deploy VPC
echo "1. Deploying VPC..."
aws cloudformation create-stack \
  --stack-name ${PROJECT}-${ENV}-vpc \
  --template-body file://vpc.yaml \
  --parameters file://parameters/${ENV}/vpc-params.json \
  --capabilities CAPABILITY_NAMED_IAM \
  --region $REGION

aws cloudformation wait stack-create-complete \
  --stack-name ${PROJECT}-${ENV}-vpc \
  --region $REGION

# Deploy EKS
echo "2. Deploying EKS (this takes 15-20 minutes)..."
aws cloudformation create-stack \
  --stack-name ${PROJECT}-${ENV}-eks \
  --template-body file://eks.yaml \
  --parameters file://parameters/${ENV}/eks-params.json \
  --capabilities CAPABILITY_NAMED_IAM \
  --region $REGION

aws cloudformation wait stack-create-complete \
  --stack-name ${PROJECT}-${ENV}-eks \
  --region $REGION

# Deploy Bastion
echo "3. Deploying Bastion..."
aws cloudformation create-stack \
  --stack-name ${PROJECT}-${ENV}-bastion \
  --template-body file://bastion.yaml \
  --parameters file://parameters/${ENV}/bastion-params.json \
  --capabilities CAPABILITY_NAMED_IAM \
  --region $REGION

aws cloudformation wait stack-create-complete \
  --stack-name ${PROJECT}-${ENV}-bastion \
  --region $REGION

# Deploy S3
echo "4. Deploying S3..."
aws cloudformation create-stack \
  --stack-name ${PROJECT}-${ENV}-s3 \
  --template-body file://s3.yaml \
  --parameters file://parameters/${ENV}/s3-params.json \
  --region $REGION

aws cloudformation wait stack-create-complete \
  --stack-name ${PROJECT}-${ENV}-s3 \
  --region $REGION

# Deploy CloudFront
echo "5. Deploying CloudFront (this takes 10-15 minutes)..."
aws cloudformation create-stack \
  --stack-name ${PROJECT}-${ENV}-cloudfront \
  --template-body file://cloudfront.yaml \
  --parameters file://parameters/${ENV}/cloudfront-params.json \
  --region $REGION

aws cloudformation wait stack-create-complete \
  --stack-name ${PROJECT}-${ENV}-cloudfront \
  --region $REGION

# Deploy Route53
echo "6. Deploying Route53..."
aws cloudformation create-stack \
  --stack-name ${PROJECT}-${ENV}-route53 \
  --template-body file://route53.yaml \
  --parameters file://parameters/${ENV}/route53-params.json \
  --region $REGION

aws cloudformation wait stack-create-complete \
  --stack-name ${PROJECT}-${ENV}-route53 \
  --region $REGION

echo "Deployment complete!"

Save this as deploy.sh and run:

chmod +x deploy.sh
./deploy.sh dev  # or prod

Accessing Your Resources

EKS Cluster

Configure kubectl to access your EKS cluster:

aws eks update-kubeconfig \
  --name dev-eks-cluster \
  --region us-west-2

Bastion Host

Connect using SSM Session Manager (no SSH key required):

# Get instance ID
INSTANCE_ID=$(aws cloudformation describe-stacks \
  --stack-name myproject-dev-bastion \
  --query 'Stacks[0].Outputs[?OutputKey==`BastionInstanceId`].OutputValue' \
  --output text \
  --region us-west-2)

# Connect
aws ssm start-session --target $INSTANCE_ID --region us-west-2

Or via SSH (if you configured a key pair):

BASTION_IP=$(aws cloudformation describe-stacks \
  --stack-name myproject-dev-bastion \
  --query 'Stacks[0].Outputs[?OutputKey==`BastionPublicIP`].OutputValue' \
  --output text \
  --region us-west-2)

ssh -i your-key.pem ec2-user@$BASTION_IP

CloudFront Distribution

Get your CloudFront URL:

aws cloudformation describe-stacks \
  --stack-name myproject-dev-cloudfront \
  --query 'Stacks[0].Outputs[?OutputKey==`DistributionDomainName`].OutputValue' \
  --output text \
  --region us-west-2

Route53

If you created a new hosted zone, get the name servers:

aws cloudformation describe-stacks \
  --stack-name myproject-dev-route53 \
  --query 'Stacks[0].Outputs[?OutputKey==`HostedZoneNameServers`].OutputValue' \
  --output text \
  --region us-west-2

Update your domain registrar to use these name servers.

Updating Stacks

To update an existing stack:

aws cloudformation update-stack \
  --stack-name myproject-dev-vpc \
  --template-body file://vpc.yaml \
  --parameters file://parameters/dev/vpc-params.json \
  --capabilities CAPABILITY_NAMED_IAM \
  --region us-west-2

Deleting Stacks

Delete stacks in reverse order:

# Delete in reverse order
aws cloudformation delete-stack --stack-name myproject-dev-route53 --region us-west-2
aws cloudformation delete-stack --stack-name myproject-dev-cloudfront --region us-west-2
aws cloudformation delete-stack --stack-name myproject-dev-s3 --region us-west-2
aws cloudformation delete-stack --stack-name myproject-dev-bastion --region us-west-2
aws cloudformation delete-stack --stack-name myproject-dev-eks --region us-west-2
aws cloudformation delete-stack --stack-name myproject-dev-vpc --region us-west-2

Note: Before deleting the S3 stack, ensure buckets are empty:

# Empty static content bucket
aws s3 rm s3://myproject-dev-static-content --recursive

# Empty user content bucket
aws s3 rm s3://myproject-dev-user-content --recursive

Environment Differences

Feature Dev Prod
VPC CIDR 10.0.0.0/16 10.1.0.0/16
NAT Gateways 1 (single AZ) 3 (multi-AZ)
EKS API Endpoint Public Private
Node Capacity SPOT instances ON_DEMAND instances
Instance Types t4g.medium t4g.large
Node Scaling 1-3 nodes 3-10 nodes
S3 Versioning Disabled Enabled
S3 Lifecycle Rules Disabled Enabled (Glacier at 180d)
Log Retention 7 days 30 days

Customization

Changing Project Name

Update the ProjectName parameter in all parameter files:

# Find and replace in all parameter files
find parameters -name "*.json" -exec sed -i '' 's/"myproject"/"your-project-name"/g' {} \;

Changing Region

Update the region in all deployment commands and the RegionMap in bastion.yaml if using a different region.

Adding Custom Domain

  1. Request an ACM certificate in us-east-1 for your domain
  2. Update cloudfront-params.json:
    {
      "ParameterKey": "CustomDomainName",
      "ParameterValue": "cdn.yourdomain.com"
    },
    {
      "ParameterKey": "ACMCertificateArn",
      "ParameterValue": "arn:aws:acm:us-east-1:123456789012:certificate/xxx"
    }

Enabling SSH Key for Bastion

Update bastion-params.json:

{
  "ParameterKey": "KeyName",
  "ParameterValue": "your-ec2-keypair-name"
}

Cost Considerations

Development Environment (Approximate Monthly Costs)

  • VPC: ~$32 (1 NAT Gateway)
  • EKS: ~$73 (control plane) + ~$15 (2 t4g.medium SPOT nodes)
  • Bastion: ~$3 (t4g.micro)
  • S3: Variable (storage + requests)
  • CloudFront: Variable (data transfer)
  • Route53: ~$0.50 per hosted zone + query charges
  • Total: ~$125/month + variable costs

Production Environment (Approximate Monthly Costs)

  • VPC: ~$96 (3 NAT Gateways)
  • EKS: ~$73 (control plane) + ~$110 (3 t4g.large ON_DEMAND nodes)
  • Bastion: ~$3 (t4g.micro)
  • S3: Variable (storage + requests + lifecycle transitions)
  • CloudFront: Variable (data transfer)
  • Route53: ~$0.50 per hosted zone + query charges
  • Total: ~$285/month + variable costs

Security Best Practices

  1. Restrict SSH Access: Update AllowedSSHCIDR in bastion parameters to limit SSH access
  2. Use Private EKS Endpoint: Enable in production (already configured)
  3. Enable MFA: For AWS accounts with CloudFormation permissions
  4. Rotate Credentials: Regularly rotate IAM credentials and SSH keys
  5. Review IAM Policies: Audit IAM roles for least privilege
  6. Enable CloudTrail: For audit logging of all API calls
  7. Enable GuardDuty: For threat detection
  8. Enable Config: For compliance monitoring

Troubleshooting

Stack Creation Fails

Check stack events:

aws cloudformation describe-stack-events \
  --stack-name myproject-dev-vpc \
  --region us-west-2

EKS Nodes Not Joining

Check node group status:

aws eks describe-nodegroup \
  --cluster-name dev-eks-cluster \
  --nodegroup-name dev-eks-cluster-node-group \
  --region us-west-2

CloudFront Not Serving Content

Verify S3 bucket policy allows CloudFront OAI access.

Route53 Not Resolving

Ensure name servers at domain registrar match Route53 hosted zone name servers.

Migrating from Terragrunt/Terraform

This CloudFormation port maintains functional parity with the original Terragrunt/Terraform implementation. Key differences:

  1. State Management: CloudFormation manages state automatically (no S3 backend needed)
  2. Dependencies: Uses stack exports/imports instead of Terragrunt dependencies
  3. Syntax: YAML-based instead of HCL
  4. Modules: Templates are standalone (no module reuse)

To migrate existing infrastructure:

  1. Export Terraform state
  2. Import resources into CloudFormation (where supported)
  3. Or deploy new CloudFormation stacks alongside Terraform, migrate applications, then destroy Terraform resources

Support

For issues or questions:

License

This infrastructure code is provided as-is for educational and production use.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published