deployment documentation. Here's a summary of what was created: 📁 AWS Managed Services Documentation Structure Main Documentation Files: 1. README.md - Comprehensive overview and decision guide 2. 00-prerequisites-managed.md - AWS setup, VPC, security, and managed services 3. 01-ecs-managed-deployment.md - Amazon ECS with Fargate deployment 4. 02-eks-managed-deployment.md - Amazon EKS deployment 5. 03-production-managed-setup.md - Production hardening and advanced features Kubernetes Manifests (kubernetes-manifests/): - namespace.yaml - Namespace with resource quotas and network policies - storage.yaml - EFS and EBS storage classes and PVCs - configmap.yaml - Application configuration and Nginx config - secrets.yaml - External Secrets Operator integration with AWS Secrets Manager - erpnext-backend.yaml - Backend deployment with RDS connectivity - erpnext-frontend.yaml - Frontend deployment with load balancing - erpnext-workers.yaml - Worker deployments for different queues - ingress.yaml - AWS Load Balancer Controller ingress configuration - jobs.yaml - Site creation and backup automation jobs Deployment Scripts (scripts/): - deploy-ecs.sh - Automated ECS deployment script - deploy-eks.sh - Automated EKS deployment script 🔄 Key AWS Managed Services Used: Instead of GCP → AWS Equivalent: - Cloud SQL → Amazon RDS for MySQL - Memorystore → Amazon MemoryDB for Redis - Cloud Run → Amazon ECS with Fargate - GKE → Amazon EKS - Cloud Storage → Amazon S3 - Secret Manager → AWS Secrets Manager - VPC Access Connector → VPC Endpoints/NAT Gateway 🎯 Key Features Included: Production-Ready Features: - ✅ High Availability - Multi-AZ RDS and MemoryDB deployment - ✅ Auto-scaling - ECS Service Auto Scaling and EKS HPA - ✅ Security - VPC isolation, IAM roles, WAF, encryption - ✅ Monitoring - CloudWatch, X-Ray, custom metrics - ✅ Backup & DR - Automated backups, cross-region replication - ✅ Cost Optimization - Reserved instances, spot instances, right-sizing Deployment Options: - 🚀 Amazon ECS with Fargate - Serverless containers, minimal ops - ⚙️ Amazon EKS - Full Kubernetes with advanced features - 🛡️ Production Hardening - WAF, enhanced monitoring, security Automation Scripts: - 📜 One-click deployment scripts for both ECS and EKS - 🔧 Infrastructure as Code approach - 📊 Cost estimation and optimization guidance The documentation provides a complete migration path from GCP to AWS with equivalent managed services, maintaining the same level of reliability and operational efficiency while leveraging AWS-native services and best practices.
21 KiB
21 KiB
AWS Prerequisites for ERPNext with Managed Services
Overview
This guide covers the prerequisites and initial setup required for deploying ERPNext on Amazon Web Services (AWS) using managed database services: Amazon RDS for MySQL and Amazon MemoryDB for Redis. This approach provides better reliability, security, and operational efficiency compared to self-hosted databases.
🔧 Required Tools
1. AWS CLI
# Install AWS CLI v2
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
# Configure AWS CLI
aws configure
# Enter your Access Key ID, Secret Access Key, Default region, and output format
2. kubectl (Kubernetes CLI) - For EKS Option
# Install kubectl
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
# Verify installation
kubectl version --client
3. eksctl (EKS CLI) - For EKS Option
# Install eksctl
curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
sudo mv /tmp/eksctl /usr/local/bin
# Verify installation
eksctl version
4. Docker (for local testing and ECS)
# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh && sh get-docker.sh
# Enable Docker BuildKit
export DOCKER_BUILDKIT=1
5. AWS ECS CLI - For ECS Option
# Install ECS CLI
sudo curl -Lo /usr/local/bin/ecs-cli https://amazon-ecs-cli.s3.amazonaws.com/ecs-cli-linux-amd64-latest
sudo chmod +x /usr/local/bin/ecs-cli
# Verify installation
ecs-cli --version
6. Helm (for EKS Kubernetes package management)
# Install Helm
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
# Verify installation
helm version
🏗️ AWS Account Setup
1. Create or Configure AWS Account
# Verify AWS account and permissions
aws sts get-caller-identity
# Set default region
export AWS_DEFAULT_REGION=us-east-1
aws configure set default.region us-east-1
# Verify configuration
aws configure list
2. Enable Required AWS Services
# Verify access to required services
aws ec2 describe-regions --output table
aws rds describe-db-instances --output table
aws elasticache describe-cache-clusters --output table
aws ecs list-clusters --output table
aws eks list-clusters --output table
3. Create IAM Policies and Roles
# Create IAM policy for ERPNext managed services
cat > erpnext-managed-policy.json <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"rds:*",
"elasticache:*",
"ecs:*",
"eks:*",
"ec2:*",
"iam:PassRole",
"logs:*",
"cloudwatch:*",
"secretsmanager:*",
"ssm:*"
],
"Resource": "*"
}
]
}
EOF
# Create the policy
aws iam create-policy \
--policy-name ERPNextManagedPolicy \
--policy-document file://erpnext-managed-policy.json
# Create service role for ECS tasks
cat > ecs-task-role-trust.json <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ecs-tasks.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
aws iam create-role \
--role-name ERPNextECSTaskRole \
--assume-role-policy-document file://ecs-task-role-trust.json
# Attach policies to ECS task role
aws iam attach-role-policy \
--role-name ERPNextECSTaskRole \
--policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
aws iam attach-role-policy \
--role-name ERPNextECSTaskRole \
--policy-arn $(aws iam list-policies --query "Policies[?PolicyName=='ERPNextManagedPolicy'].Arn" --output text)
🔐 Security Setup
1. VPC and Networking Configuration
# Create VPC for ERPNext deployment
aws ec2 create-vpc \
--cidr-block 10.0.0.0/16 \
--tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=erpnext-vpc}]'
# Get VPC ID
VPC_ID=$(aws ec2 describe-vpcs \
--filters "Name=tag:Name,Values=erpnext-vpc" \
--query "Vpcs[0].VpcId" --output text)
# Create Internet Gateway
aws ec2 create-internet-gateway \
--tag-specifications 'ResourceType=internet-gateway,Tags=[{Key=Name,Value=erpnext-igw}]'
IGW_ID=$(aws ec2 describe-internet-gateways \
--filters "Name=tag:Name,Values=erpnext-igw" \
--query "InternetGateways[0].InternetGatewayId" --output text)
# Attach Internet Gateway to VPC
aws ec2 attach-internet-gateway \
--vpc-id $VPC_ID \
--internet-gateway-id $IGW_ID
# Create subnets
# Public subnet for load balancers
aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block 10.0.1.0/24 \
--availability-zone us-east-1a \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=erpnext-public-subnet-1a}]'
aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block 10.0.2.0/24 \
--availability-zone us-east-1b \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=erpnext-public-subnet-1b}]'
# Private subnets for application
aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block 10.0.10.0/24 \
--availability-zone us-east-1a \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=erpnext-private-subnet-1a}]'
aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block 10.0.11.0/24 \
--availability-zone us-east-1b \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=erpnext-private-subnet-1b}]'
# Database subnets
aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block 10.0.20.0/24 \
--availability-zone us-east-1a \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=erpnext-db-subnet-1a}]'
aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block 10.0.21.0/24 \
--availability-zone us-east-1b \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=erpnext-db-subnet-1b}]'
2. Route Tables and NAT Gateway
# Get subnet IDs
PUBLIC_SUBNET_1A=$(aws ec2 describe-subnets \
--filters "Name=tag:Name,Values=erpnext-public-subnet-1a" \
--query "Subnets[0].SubnetId" --output text)
PUBLIC_SUBNET_1B=$(aws ec2 describe-subnets \
--filters "Name=tag:Name,Values=erpnext-public-subnet-1b" \
--query "Subnets[0].SubnetId" --output text)
PRIVATE_SUBNET_1A=$(aws ec2 describe-subnets \
--filters "Name=tag:Name,Values=erpnext-private-subnet-1a" \
--query "Subnets[0].SubnetId" --output text)
PRIVATE_SUBNET_1B=$(aws ec2 describe-subnets \
--filters "Name=tag:Name,Values=erpnext-private-subnet-1b" \
--query "Subnets[0].SubnetId" --output text)
# Create NAT Gateway
aws ec2 allocate-address \
--domain vpc \
--tag-specifications 'ResourceType=elastic-ip,Tags=[{Key=Name,Value=erpnext-nat-eip}]'
NAT_EIP=$(aws ec2 describe-addresses \
--filters "Name=tag:Name,Values=erpnext-nat-eip" \
--query "Addresses[0].AllocationId" --output text)
aws ec2 create-nat-gateway \
--subnet-id $PUBLIC_SUBNET_1A \
--allocation-id $NAT_EIP \
--tag-specifications 'ResourceType=nat-gateway,Tags=[{Key=Name,Value=erpnext-nat}]'
NAT_ID=$(aws ec2 describe-nat-gateways \
--filter "Name=tag:Name,Values=erpnext-nat" \
--query "NatGateways[0].NatGatewayId" --output text)
# Create route tables
# Public route table
aws ec2 create-route-table \
--vpc-id $VPC_ID \
--tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value=erpnext-public-rt}]'
PUBLIC_RT=$(aws ec2 describe-route-tables \
--filters "Name=tag:Name,Values=erpnext-public-rt" \
--query "RouteTables[0].RouteTableId" --output text)
# Private route table
aws ec2 create-route-table \
--vpc-id $VPC_ID \
--tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value=erpnext-private-rt}]'
PRIVATE_RT=$(aws ec2 describe-route-tables \
--filters "Name=tag:Name,Values=erpnext-private-rt" \
--query "RouteTables[0].RouteTableId" --output text)
# Add routes
aws ec2 create-route \
--route-table-id $PUBLIC_RT \
--destination-cidr-block 0.0.0.0/0 \
--gateway-id $IGW_ID
aws ec2 create-route \
--route-table-id $PRIVATE_RT \
--destination-cidr-block 0.0.0.0/0 \
--nat-gateway-id $NAT_ID
# Associate subnets with route tables
aws ec2 associate-route-table \
--subnet-id $PUBLIC_SUBNET_1A \
--route-table-id $PUBLIC_RT
aws ec2 associate-route-table \
--subnet-id $PUBLIC_SUBNET_1B \
--route-table-id $PUBLIC_RT
aws ec2 associate-route-table \
--subnet-id $PRIVATE_SUBNET_1A \
--route-table-id $PRIVATE_RT
aws ec2 associate-route-table \
--subnet-id $PRIVATE_SUBNET_1B \
--route-table-id $PRIVATE_RT
3. Security Groups
# Create security group for ALB
aws ec2 create-security-group \
--group-name erpnext-alb-sg \
--description "Security group for ERPNext Application Load Balancer" \
--vpc-id $VPC_ID \
--tag-specifications 'ResourceType=security-group,Tags=[{Key=Name,Value=erpnext-alb-sg}]'
ALB_SG=$(aws ec2 describe-security-groups \
--filters "Name=tag:Name,Values=erpnext-alb-sg" \
--query "SecurityGroups[0].GroupId" --output text)
# Create security group for application
aws ec2 create-security-group \
--group-name erpnext-app-sg \
--description "Security group for ERPNext Application" \
--vpc-id $VPC_ID \
--tag-specifications 'ResourceType=security-group,Tags=[{Key=Name,Value=erpnext-app-sg}]'
APP_SG=$(aws ec2 describe-security-groups \
--filters "Name=tag:Name,Values=erpnext-app-sg" \
--query "SecurityGroups[0].GroupId" --output text)
# Create security group for database
aws ec2 create-security-group \
--group-name erpnext-db-sg \
--description "Security group for ERPNext Database" \
--vpc-id $VPC_ID \
--tag-specifications 'ResourceType=security-group,Tags=[{Key=Name,Value=erpnext-db-sg}]'
DB_SG=$(aws ec2 describe-security-groups \
--filters "Name=tag:Name,Values=erpnext-db-sg" \
--query "SecurityGroups[0].GroupId" --output text)
# Configure security group rules
# ALB security group
aws ec2 authorize-security-group-ingress \
--group-id $ALB_SG \
--protocol tcp \
--port 80 \
--cidr 0.0.0.0/0
aws ec2 authorize-security-group-ingress \
--group-id $ALB_SG \
--protocol tcp \
--port 443 \
--cidr 0.0.0.0/0
# Application security group
aws ec2 authorize-security-group-ingress \
--group-id $APP_SG \
--protocol tcp \
--port 8000 \
--source-group $ALB_SG
aws ec2 authorize-security-group-ingress \
--group-id $APP_SG \
--protocol tcp \
--port 9000 \
--source-group $ALB_SG
# Database security group
aws ec2 authorize-security-group-ingress \
--group-id $DB_SG \
--protocol tcp \
--port 3306 \
--source-group $APP_SG
aws ec2 authorize-security-group-ingress \
--group-id $DB_SG \
--protocol tcp \
--port 6379 \
--source-group $APP_SG
💾 Managed Database Services Setup
1. RDS MySQL Instance
# Create DB subnet group
DB_SUBNET_1A=$(aws ec2 describe-subnets \
--filters "Name=tag:Name,Values=erpnext-db-subnet-1a" \
--query "Subnets[0].SubnetId" --output text)
DB_SUBNET_1B=$(aws ec2 describe-subnets \
--filters "Name=tag:Name,Values=erpnext-db-subnet-1b" \
--query "Subnets[0].SubnetId" --output text)
aws rds create-db-subnet-group \
--db-subnet-group-name erpnext-db-subnet-group \
--db-subnet-group-description "Subnet group for ERPNext database" \
--subnet-ids $DB_SUBNET_1A $DB_SUBNET_1B \
--tags Key=Name,Value=erpnext-db-subnet-group
# Create RDS MySQL instance
aws rds create-db-instance \
--db-instance-identifier erpnext-db \
--db-instance-class db.t3.medium \
--engine mysql \
--engine-version 8.0.35 \
--master-username admin \
--master-user-password YourSecureDBPassword123! \
--allocated-storage 100 \
--storage-type gp3 \
--storage-encrypted \
--vpc-security-group-ids $DB_SG \
--db-subnet-group-name erpnext-db-subnet-group \
--backup-retention-period 7 \
--backup-window 03:00-04:00 \
--maintenance-window sun:04:00-sun:05:00 \
--auto-minor-version-upgrade \
--deletion-protection \
--enable-performance-insights \
--performance-insights-retention-period 7 \
--tags Key=Name,Value=erpnext-db
# Wait for instance to be available
aws rds wait db-instance-available --db-instance-identifier erpnext-db
# Create ERPNext database
aws rds create-db-instance \
--db-instance-identifier erpnext-db \
--allocated-storage 100 \
--db-instance-class db.t3.medium \
--engine mysql \
--master-username admin \
--master-user-password YourSecureDBPassword123! \
--vpc-security-group-ids $DB_SG \
--db-subnet-group-name erpnext-db-subnet-group
2. MemoryDB for Redis Instance
# Create MemoryDB subnet group
aws memorydb create-subnet-group \
--subnet-group-name erpnext-redis-subnet-group \
--description "Subnet group for ERPNext Redis" \
--subnet-ids $DB_SUBNET_1A $DB_SUBNET_1B \
--tags Key=Name,Value=erpnext-redis-subnet-group
# Create MemoryDB user
aws memorydb create-user \
--user-name erpnext-redis-user \
--authentication-mode Type=password,Passwords=YourSecureRedisPassword123! \
--access-string "on ~* &* +@all" \
--tags Key=Name,Value=erpnext-redis-user
# Create MemoryDB ACL
aws memorydb create-acl \
--acl-name erpnext-redis-acl \
--user-names erpnext-redis-user \
--tags Key=Name,Value=erpnext-redis-acl
# Create MemoryDB cluster
aws memorydb create-cluster \
--cluster-name erpnext-redis \
--node-type db.t4g.small \
--engine-version 6.2 \
--num-shards 1 \
--num-replicas-per-shard 1 \
--acl-name erpnext-redis-acl \
--subnet-group-name erpnext-redis-subnet-group \
--security-group-ids $DB_SG \
--maintenance-window sun:05:00-sun:06:00 \
--sns-topic-arn arn:aws:sns:us-east-1:$(aws sts get-caller-identity --query Account --output text):erpnext-notifications \
--tls-enabled \
--tags Key=Name,Value=erpnext-redis
# Wait for cluster to be available
aws memorydb describe-clusters \
--cluster-name erpnext-redis \
--query "Clusters[0].Status" --output text
3. AWS Systems Manager Parameter Store for Configuration
# Store database configuration
aws ssm put-parameter \
--name "/erpnext/database/host" \
--value $(aws rds describe-db-instances \
--db-instance-identifier erpnext-db \
--query "DBInstances[0].Endpoint.Address" --output text) \
--type "String" \
--description "ERPNext Database Host"
aws ssm put-parameter \
--name "/erpnext/database/port" \
--value "3306" \
--type "String" \
--description "ERPNext Database Port"
aws ssm put-parameter \
--name "/erpnext/database/name" \
--value "erpnext" \
--type "String" \
--description "ERPNext Database Name"
aws ssm put-parameter \
--name "/erpnext/database/username" \
--value "admin" \
--type "String" \
--description "ERPNext Database Username"
# Store Redis configuration
aws ssm put-parameter \
--name "/erpnext/redis/host" \
--value $(aws memorydb describe-clusters \
--cluster-name erpnext-redis \
--query "Clusters[0].ClusterEndpoint.Address" --output text) \
--type "String" \
--description "ERPNext Redis Host"
aws ssm put-parameter \
--name "/erpnext/redis/port" \
--value "6379" \
--type "String" \
--description "ERPNext Redis Port"
🔑 AWS Secrets Manager for Sensitive Data
# Store database password
aws secretsmanager create-secret \
--name "erpnext/database/password" \
--description "ERPNext Database Password" \
--secret-string "YourSecureDBPassword123!" \
--tags '[{"Key":"Application","Value":"ERPNext"},{"Key":"Environment","Value":"Production"}]'
# Store Redis password
aws secretsmanager create-secret \
--name "erpnext/redis/password" \
--description "ERPNext Redis Password" \
--secret-string "YourSecureRedisPassword123!" \
--tags '[{"Key":"Application","Value":"ERPNext"},{"Key":"Environment","Value":"Production"}]'
# Store ERPNext admin password
aws secretsmanager create-secret \
--name "erpnext/admin/password" \
--description "ERPNext Admin Password" \
--secret-string "YourSecureAdminPassword123!" \
--tags '[{"Key":"Application","Value":"ERPNext"},{"Key":"Environment","Value":"Production"}]'
# Store API credentials
aws secretsmanager create-secret \
--name "erpnext/api/credentials" \
--description "ERPNext API Credentials" \
--secret-string '{"api_key":"your-api-key-here","api_secret":"your-api-secret-here"}' \
--tags '[{"Key":"Application","Value":"ERPNext"},{"Key":"Environment","Value":"Production"}]'
📊 CloudWatch and Monitoring Setup
# Create CloudWatch log groups
aws logs create-log-group \
--log-group-name /aws/ecs/erpnext-backend \
--retention-in-days 7
aws logs create-log-group \
--log-group-name /aws/ecs/erpnext-frontend \
--retention-in-days 7
aws logs create-log-group \
--log-group-name /aws/ecs/erpnext-worker \
--retention-in-days 7
# Create SNS topic for alerts
aws sns create-topic \
--name erpnext-alerts \
--tags Key=Application,Value=ERPNext
# Subscribe email to alerts (replace with your email)
aws sns subscribe \
--topic-arn arn:aws:sns:us-east-1:$(aws sts get-caller-identity --query Account --output text):erpnext-alerts \
--protocol email \
--notification-endpoint your-email@yourdomain.com
🔍 Verification Checklist
Before proceeding to deployment, verify:
# Check AWS credentials and region
aws sts get-caller-identity
aws configure get region
# Verify VPC and subnets
aws ec2 describe-vpcs --filters "Name=tag:Name,Values=erpnext-vpc"
aws ec2 describe-subnets --filters "Name=vpc-id,Values=$VPC_ID"
# Check security groups
aws ec2 describe-security-groups --filters "Name=vpc-id,Values=$VPC_ID"
# Verify RDS instance
aws rds describe-db-instances --db-instance-identifier erpnext-db
# Check MemoryDB cluster
aws memorydb describe-clusters --cluster-name erpnext-redis
# Verify secrets
aws secretsmanager list-secrets --filters Key=tag-key,Values=Application Key=tag-value,Values=ERPNext
# Check IAM roles
aws iam get-role --role-name ERPNextECSTaskRole
# Verify CloudWatch log groups
aws logs describe-log-groups --log-group-name-prefix /aws/ecs/erpnext
💡 Cost Optimization for Managed Services
1. RDS Optimization
# Use appropriate instance types
# Development: db.t3.micro or db.t3.small
# Production: db.t3.medium or larger
# Enable storage autoscaling
aws rds modify-db-instance \
--db-instance-identifier erpnext-db \
--max-allocated-storage 1000 \
--apply-immediately
# Use Reserved Instances for production (1-3 year terms)
aws rds describe-reserved-db-instances-offerings \
--db-instance-class db.t3.medium \
--engine mysql
2. MemoryDB Optimization
# Right-size cluster based on memory usage
# Start with db.t4g.small and scale based on usage
# Monitor memory utilization and adjust
# Use Multi-AZ only for production
# Single-AZ for development/testing environments
3. Network Cost Optimization
# Use same AZ for services to minimize data transfer costs
# Monitor VPC Flow Logs for inter-AZ traffic
# Consider VPC endpoints for AWS services if needed
🚨 Security Best Practices for Managed Services
1. Network Security
- VPC isolation: All managed services use private subnets
- Security groups: Restrictive access between tiers
- No public access: Database and Redis not accessible from internet
2. Access Control
# Enable RDS IAM database authentication
aws rds modify-db-instance \
--db-instance-identifier erpnext-db \
--enable-iam-database-authentication \
--apply-immediately
# Create IAM database user
aws rds create-db-instance-read-replica \
--db-instance-identifier erpnext-db-read-replica \
--source-db-instance-identifier erpnext-db \
--db-instance-class db.t3.small
3. Encryption
- Encryption at rest: Enabled by default for both services
- Encryption in transit: SSL/TLS enforced
- Secrets management: AWS Secrets Manager for credentials
📚 Additional Resources
- Amazon RDS Documentation
- Amazon MemoryDB Documentation
- Amazon ECS Documentation
- Amazon EKS Documentation
- AWS VPC Documentation
➡️ Next Steps
After completing prerequisites:
- ECS with Managed Services: Follow
01-ecs-managed-deployment.md - EKS with Managed Services: Follow
02-eks-managed-deployment.md - Production Hardening: See
03-production-managed-setup.md
⚠️ Important Notes:
- Managed services incur continuous costs even when not in use
- Plan your backup and disaster recovery strategy
- Monitor costs regularly using AWS Cost Explorer
- Keep track of all resources created for billing purposes
- Use AWS Config for compliance and governance