Deployment Guide
Step-by-step guide to deploy the stage environment
Prerequisites
Software on local machine
- Terraform ≥ 1.5
- AWS CLI v2 (with
aws,aws sso loginworking) - PowerShell 5.1+ (Windows default OK)
AWS Permissions
- Account must have permissions to create: VPC, EC2, ELB (ALB/NLB), ECR, ACM, Route53, CloudWatch, IAM, S3, CloudFront
- IAM role
MILU2-AWS-ALLOWalready exists (or setexisting_iam = falsein shared to create) - Access to DNS zone
*.milu.jp(for ACM certificate validation)
AWS Login
aws sso login # open browser, login once per day
aws sts get-caller-identity # check if credentials are validInfo
Pre-deploy check (preflight)
cd d:\terraform_svn\terraform-resource\terraform
.\preflight-check.ps1Script checks 10 items: credential, S3 bucket, IAM, CloudFront, ECR, AMI, ACM, VPC peering, CIDR conflict, region. Auto-fixes existing_* flags and stage_index in terraform.tfvars if needed.
Quick Deploy (1 command)
Script runs 7 steps automatically, pausing for confirmation at key points:
cd d:\terraform_svn\terraform-resource\terraform
.\deploy.ps1| Step | Action | Interaction |
|---|---|---|
| 0 | AWS login (opens browser if expired) | Confirm on web |
| 1 | Confirm aws_region, az_*, ec2_ami_id, stage_index | Enter to keep, type new value to change |
| 2 | Sync shared region | Automatic |
| 3 | Preflight check | Enter to continue |
| 4 | Deploy Shared (only runs if existing = false) | Automatic |
| 5 | Deploy Stage: auto import → terraform plan → review → Enter → terraform apply | Review plan then Enter |
| 6 | Verify outputs | Automatic |
Manual Deploy (when you need more control)
cd d:\terraform_svn\terraform-resource\terraform
# (1) Preflight
.\preflight-check.ps1
# (2) Shared — run once per account, don't repeat unless shared changes
cd shared
terraform init
terraform plan # Expect: No changes (if existing = true)
terraform apply # Only run if plan shows changes
cd ..
# (3) Stage
terraform init
terraform plan # Review what will be created
terraform apply # Type 'yes' to confirmTarget Apply (single module)
Use when you only want to apply a small change (e.g., only change EC2 user_data, not touching VPC/ALB).
cd d:\terraform_svn\terraform-resource\terraform
# Apply only module 17-ec2-instances
terraform plan -target='module.ec2_instances'
terraform apply -target='module.ec2_instances'
# Apply only module 09-autoscaling (Launch Template + ASG API)
terraform plan -target='module.autoscaling'
terraform apply -target='module.autoscaling'
# Apply only module 06-alb
terraform plan -target='module.alb'
terraform apply -target='module.alb'
# Apply multiple modules at once
terraform apply -target='module.target_groups_listeners' -target='module.alb'Apply only 1 instance in module 17
When instance_counts.mysql = 1, the state key will be mysql-1:
# Replace EC2 mysql-1 (keep other EC2s)
terraform apply -replace='module.ec2_instances.aws_instance.this["mysql-1"]'
# Replace both mysql-1 and mysql_mirror-1
terraform apply `
-replace='module.ec2_instances.aws_instance.this["mysql-1"]' `
-replace='module.ec2_instances.aws_instance.this["mysql_mirror-1"]'
# Force refresh ASG (force immediate re-launch)
terraform apply -replace='module.autoscaling.aws_launch_template.api'Info
Module names for targeting
| Module | Target string |
|---|---|
| 01-vpc | module.vpc |
| 02-subnets | module.subnets |
| 03-internet-gateway | module.internet_gateway |
| 04-route-tables-peering | module.route_tables_peering |
| 05-security-groups | module.security_groups |
| 06-alb | module.alb |
| 07-nlb | module.nlb |
| 08-target-groups-listeners | module.target_groups_listeners |
| 09-autoscaling | module.autoscaling |
| 11-ecr | module.ecr |
| 12-acm | module.acm |
| 13-route53 | module.route53 |
| 15-iam | module.iam |
| 16-cloudwatch | module.cloudwatch |
| 17-ec2-instances | module.ec2_instances |
When resources already exist on AWS (import)
deploy.ps1 auto-detects and imports 31 resource types (ECR, ALB, NLB, TG, ASG, Launch Template, CloudWatch alarms…). For manual import:
# ECR
terraform import 'module.ecr.aws_ecr_repository.this["milu2/milu2-stage-api"]' milu2/milu2-stage-api
# ALB internal
terraform import 'module.alb.aws_lb.internal' arn:aws:elasticloadbalancing:...
# View current state
terraform state listMulti-region / Multi-stage
No need to copy folders. From the same terraform/ directory:
- Change aws_region, az_1, az_2, ec2_ami_id in terraform.tfvars
- Run preflight-check.ps1 → script reads Build VPC route table, suggests non-conflicting stage_index
- Run deploy.ps1 as usual
Tip
Destroy (tear down environment)
Danger
# Destroy stage, KEEP shared
.\deploy.ps1 -DestroyOnly
# When asked 'Destroy shared resources too?' → press Enter (don't type yes)
# Destroy BOTH shared + stage
.\deploy.ps1 -DestroyOnly
# When asked → type yes + Enter
# Or manually
terraform destroy
cd shared
terraform destroy
cd ..Important Note — read before changing EC2 user_data
Warning
Consequences:
- EBS root lost → data on /home/ec2-user, /var/log, … is lost
- EBS /home2 (mysql) also lost → MySQL must be re-imported from schema_only.sql + mysql_users.sql on S3
- ASG (module 09) does rolling refresh automatically, not destroyed suddenly
Before applying user_data changes to DB:
# 1. Backup MySQL
mysqldump --all-databases > schema_only.sql
aws s3 cp schema_only.sql s3://<bucket>/docker/milu2-mysql/
# 2. Apply to each instance separately to reduce risk
terraform apply -replace='module.ec2_instances.aws_instance.this["mysql-1"]'Tip