Week 01 - Lab 02: Modular WordPress Architecture
Overview
Take your WordPress deployment to the next level! In this lab, you'll refactor the monolithic WordPress from Week-00/Lab-01 into a multi-tier, modular architecture using separate modules for networking, database, and compute resources.
Instead of one EC2 instance with a local database, you'll build:
- VPC Module: Custom networking with public/private subnets
- Database Module: Managed RDS MySQL instance
- Compute Module: EC2 instance connecting to external database
- WordPress Module: Composition module that orchestrates everything
Architecture Evolution
Before (Week-00/Lab-01): Monolithic
┌─────────────────────────┐
│ EC2 Instance │
│ ┌─────────────────────┐│
│ │ WordPress + Apache ││
│ │ Local MariaDB ││
│ └─────────────────────┘│
└─────────────────────────┘
After (Week-01/Lab-02): Modular
┌─────────────────────────────────────────────────────────┐
│ VPC Module │
│ ┌──────────────────┐ ┌───────────────────┐ │
│ │ Public Subnet │ │ Private Subnet │ │
│ │ ┌─────────────┐ │ │ ┌───────────────┐ │ │
│ │ │ EC2 │ │ │ │ RDS MySQL │ │ │
│ │ │ WordPress │◄┼───────────┼►│ Database │ │ │
│ │ └─────────────┘ │ │ └───────────────┘ │ │
│ └──────────────────┘ └───────────────────┘ │
└─────────────────────────────────────────────────────────┘
Learning Objectives
By completing this lab, you will:
- Design modular infrastructure using Terraform modules
- Implement module composition (modules calling other modules)
- Manage complex dependencies between infrastructure components
- Research AWS services using official documentation
- Debug module integration issues and dependency problems
- Understand real-world architecture patterns used in production
Prerequisites
- Completed Week-01/Lab-00 (S3 Module) and Lab-01 (Hugo + CloudFront)
- Understanding of Terraform modules from Lab-00
- AWS CLI configured with credentials
- Terraform >= 1.9.0
- SSH key pair for EC2 access
Learning Approach: Guided Discovery
This lab uses a guided discovery approach. Instead of copying complete code, you'll:
- Research AWS services and Terraform resources
- Solve specific implementation challenges
- Debug integration issues between modules
- Learn by doing, with hints and guidance
Phase 1: Research & Planning (60 minutes)
Before writing any code, understand what you're building.
Architecture Research Questions
📚 Use these resources to answer the questions:
VPC Research (20 minutes)
| Question | Your Answer |
|---|---|
| What is a VPC and why not use the default VPC? | |
| What's the difference between public and private subnets? | |
| Why do you need an Internet Gateway? | |
| What does a route table control? | |
| Why does RDS need subnets in multiple AZs? |
RDS Research (20 minutes)
| Question | Your Answer |
|---|---|
| What's the minimum storage for RDS MySQL? | |
| What instance classes are available? What's cheapest? | |
| What's a DB subnet group and why is it required? | |
| What ports does MySQL use by default? | |
| How do you secure RDS access? |
Module Architecture Research (20 minutes)
| Question | Your Answer |
|---|---|
| How do you pass data between modules? | |
| What happens if Module A needs output from Module B? | |
| How do you handle circular dependencies? | |
When should you use depends_on vs. implicit dependencies? |
💡 Hint: Save your answers! You'll reference them while coding.
Phase 2: Module Implementation (3-4 hours)
Now implement each module step by step. The starter files provide structure and TODOs, but you must research and fill in the details.
Step 1: Implement VPC Module (45 minutes)
Location: terraform-course/modules/vpc/
Your mission: Create a VPC with public and private subnets.
Documentation Hunt Checklist:
- Find
aws_vpcresource in Terraform docs - Find
aws_subnetresource arguments - Find
aws_internet_gatewayresource - Find
aws_route_tableandaws_routeresources - Find
aws_db_subnet_groupresource
Implementation Checklist:
- Complete all TODO items in
variables.tf - Complete all TODO items in
main.tf - Complete all TODO items in
outputs.tf - Test with
terraform validate
Key Challenges:
- CIDR Calculation: How do you split
10.0.0.0/16into 4 subnets? - Multiple Resources: How do you create 2 public + 2 private subnets?
- Route Tables: How do you make subnets "public" vs "private"?
Success Criteria:
cd terraform-course/modules/vpc
terraform init
terraform validate # Should passStep 2: Implement Database Module (45 minutes)
Location: terraform-course/modules/database/
Your mission: Create an RDS MySQL instance with proper security.
Documentation Hunt Checklist:
- Find
aws_db_instanceresource and all its arguments - Find
aws_security_groupingress/egress rules - Research RDS instance classes and engine versions
- Find backup and maintenance window formats
Implementation Checklist:
- Complete all TODO items in
variables.tf - Complete all TODO items in
main.tf - Complete all TODO items in
outputs.tf - Test with
terraform validate
Key Challenges:
- Security Groups: How do you allow MySQL access from EC2 but not internet?
- Subnet Groups: How do you configure RDS to use private subnets?
- Password Security: How do you handle sensitive database passwords?
Step 3: Implement Compute Module (60 minutes)
Location: terraform-course/modules/compute/
Your mission: Create EC2 instance that connects to external RDS database.
Documentation Hunt Checklist:
- Review
aws_instanceresource from Week-00/Lab-01 - Find
aws_security_group_ruleresource - Research how to template user data scripts
- Find instance metadata service configuration
Implementation Checklist:
- Complete all TODO items in
variables.tf - Complete all TODO items in
main.tf - Complete all TODO items in
outputs.tf - Adapt the
user_data.shscript for external database - Test with
terraform validate
Key Challenges:
- Database Connection: How does the user data script connect to RDS?
- Security Groups: How do you allow EC2 to access RDS MySQL?
- Script Adaptation: What changes from the Week-00 WordPress script?
- Site URL Discovery: How can the script determine the WordPress URL dynamically?
User Data Script Adaptation:
You need to modify the user data script to:
- ❌ Remove: Local MariaDB installation and configuration
- ✅ Add: Remote MySQL connection testing
- ✅ Add: IMDS queries to get the instance's public IP
- ✅ Change: wp-config.php to use RDS endpoint and dynamic site URL
- ✅ Add: Error handling for database connectivity
IMDS Research Challenge:
Research Question: How can a user_data script determine the instance's public IP without creating a circular dependency in Terraform?
Your Mission: Research the EC2 Instance Metadata Service (IMDS) and answer:
- What is IMDS? What information does it provide?
- IMDSv1 vs IMDSv2: What's the security difference?
- Dynamic Discovery: How can a script query its own public IP?
- WordPress Integration: How do you use the discovered IP in wp-config.php?
Key IMDS Endpoints to Research:
- Token endpoint:
http://169.254.169.254/latest/api/token - Metadata endpoint:
http://169.254.169.254/latest/meta-data/ - Public IP:
http://169.254.169.254/latest/meta-data/public-ipv4
Step 4: Implement WordPress Composition Module (60 minutes)
Location: terraform-course/modules/wordpress/
Your mission: Orchestrate VPC, Database, and Compute modules together.
Documentation Hunt Checklist:
- Review module composition patterns
- Research
cidrsubnets()function for subnet calculation - Find how to reference module outputs
- Research module dependency management
Implementation Checklist:
- Complete all TODO items in
variables.tf - Complete all TODO items in
main.tf - Complete all TODO items in
outputs.tf - Test with
terraform validate
Key Challenges:
- Module Dependencies: What order should modules be created?
- Data Flow: How do you pass VPC outputs to Database and Compute modules?
- CIDR Calculation: How do you split the VPC CIDR into subnet CIDRs?
- IMDS for Site URL: How do you use EC2 metadata to dynamically configure WordPress?
Phase 3: Integration & Testing (1-2 hours)
Step 5: Set Up Your Working Directory (5 minutes)
Location: week-01/lab-02/
Copy the starter files to your student-work directory:
Setup:
cd week-01/lab-02
cp -r starter/* student-work/
cd student-workImplementation Checklist:
- Complete all TODO items in
main.tf - Complete all TODO items in
variables.tf - Complete all TODO items in
outputs.tf - Create
terraform.tfvarsfrom the example - Configure backend for remote state storage
Key Configuration Decisions:
- Availability Zones: Which AZs will you use?
- Credentials: How will you securely provide database passwords?
- SSH Access: What's your current IP address for SSH access?
- Key Pair: Which AWS key pair will you use?
Step 6: Deploy and Troubleshoot (30-60 minutes)
Now for the moment of truth!
# Initialize and validate
terraform init
terraform validate
terraform plan
# Deploy (this will take 5-10 minutes)
terraform applyExpected Resources:
- 1 VPC with 4 subnets
- 1 Internet Gateway and 2 route tables
- 1 RDS MySQL instance
- 1 EC2 instance
- Multiple security groups
- 1 DB subnet group
Common Issues & Debugging:
Issue: "InvalidParameterValue: CIDR block is not valid"
# Check your CIDR calculations
terraform console
> cidrsubnets("10.0.0.0/16", 8, 8, 8, 8)Issue: "DB subnet group doesn't meet availability zone coverage requirement"
# Check your AZ configuration - RDS needs 2+ AZs
data.aws_availability_zones.available.namesIssue: "Error connecting to database"
# SSH to instance and check connectivity
ssh -i ~/.ssh/your-key ec2-user@<public-ip>
mysql -h <db-endpoint> -u admin -pIssue: "Module not found"
# Check your module source paths
terraform get -updatePhase 4: Validation & Testing (30 minutes)
Functional Testing
- Access WordPress: Visit the public IP in your browser
- Complete Setup: Follow the WordPress installation wizard
- Create Content: Create a test post to verify database connectivity
- SSH Access: Confirm you can SSH to troubleshoot
Infrastructure Validation
# Verify all resources exist
terraform show | grep "# aws_"
# Check costs
infracost breakdown --path .
# Test module outputs
terraform outputSuccess Criteria:
- WordPress loads in browser
- Database connection works (can create posts)
- SSH access works for troubleshooting
- All module outputs display correctly
- Infrastructure costs are reasonable (< $15/month)
Expected File Structure
After completion, you should have:
week-01/lab-02/student-work/ # Your working directory
├── modules/ # Your custom modules
│ ├── vpc/ # VPC module
│ │ ├── main.tf # VPC, subnets, routing
│ │ ├── variables.tf # VPC configuration
│ │ └── outputs.tf # VPC IDs and info
│ ├── database/ # Database module
│ │ ├── main.tf # RDS instance, security
│ │ ├── variables.tf # DB configuration
│ │ └── outputs.tf # DB connection info
│ ├── compute/ # Compute module
│ │ ├── main.tf # EC2, security groups
│ │ ├── variables.tf # Instance configuration
│ │ ├── outputs.tf # Instance info
│ │ └── user_data.sh # WordPress install script
│ └── wordpress/ # Composition module
│ ├── main.tf # Orchestrates all modules
│ ├── variables.tf # High-level config
│ └── outputs.tf # Aggregated outputs
├── main.tf # Uses WordPress module
├── variables.tf # Root variables
├── outputs.tf # Root outputs
├── providers.tf # Provider config
├── terraform.tfvars # Your specific values
└── .gitignore # Ignore sensitive files
After completing the lab: Copy your working modules to the project root for use in future labs:
cp -r student-work/modules/* ../../modules/Troubleshooting Guide
Module Issues
"Module not found"
- Check source path:
../../../modules/module-name - Run
terraform get -update - Verify module directory exists and has .tf files
"No configuration files"
- Ensure module directory has main.tf, variables.tf, outputs.tf
- Check file permissions and extensions (.tf not .txt)
Dependency Issues
"Resource not found"
- Check module output references:
module.vpc.output_name - Verify module outputs are defined correctly
- Use
terraform planto see dependency graph
"Cycle in dependency graph"
- Remove circular dependencies between modules
- Use data sources to query existing resources
- Restructure module interfaces to avoid cycles
AWS Resource Issues
RDS Issues:
- Verify 2+ AZs for subnet group
- Check security group rules allow MySQL (3306)
- Confirm instance class is supported
- Verify password meets AWS requirements
EC2 Issues:
- Check SSH key pair exists in AWS
- Verify security group allows SSH (22) and HTTP (80)
- Confirm user data script has correct database endpoint
- Check subnet is public (has Internet Gateway route)
Network Issues:
- Verify route tables have Internet Gateway route for public subnets
- Check CIDR blocks don't overlap
- Ensure security groups allow required traffic
Cost Management
Expected monthly costs (if running 24/7):
- t3.micro EC2: ~$7.59/month
- db.t3.micro RDS: ~$12.41/month
- EBS Storage: ~$2.40/month
- Total: ~$22.40/month
Cost Optimization Tips:
- Use
AutoTeardown = "8h"tags for automatic cleanup - Stop instances when not needed (RDS can't be stopped easily)
- Use smaller instance types for development
- Enable deletion protection only for production
Submission Checklist
Before Submitting:
- All modules validate successfully (
terraform validatein each module directory) - WordPress loads and works correctly in browser
- Database connectivity confirmed (can create/edit posts)
- SSH access works for troubleshooting
- All TODO comments removed or completed with working code
- Costs analyzed with infracost (should be < $25/month)
- No hardcoded values (everything parameterized)
Submission Process:
- Clean up your code: Remove or complete all TODO comments
- Copy modules to project root for future labs:
cd week-01/lab-02 cp -r student-work/modules/* ../../modules/
- Destroy infrastructure (save costs):
cd student-work terraform destroy - Commit your work:
git add . git commit -m "Week 01 Lab 02 - Modular WordPress Architecture - [Your Name]" git push origin your-branch-name
- Create Pull Request with title:
Week 01 Lab 02 - [Your Name] - Include in PR description:
- Screenshot of working WordPress site
- Brief description of your architecture
- Any challenges you overcame
- Infracost output
Grading Criteria (100 points)
| Category | Points | Criteria |
|---|---|---|
| VPC Module | 20 | Correct subnets, routing, DB subnet group |
| Database Module | 20 | RDS instance, security groups, outputs |
| Compute Module | 20 | EC2 instance, security, user data script |
| WordPress Module | 20 | Module composition, dependencies |
| Integration | 10 | Root module, working WordPress |
| Code Quality | 10 | Clean code, no hardcoded values, validation |
What's Next?
In Week 02, you'll learn advanced state management, including:
- State locking and remote backends
- Handling state drift and importing existing resources
- Using
movedandremovedblocks for refactoring - Team collaboration with Terraform Cloud
This modular foundation will serve you well as infrastructure grows in complexity!
Resources & References
AWS Documentation
Terraform Documentation
WordPress & MySQL
Need Help?
- Review the troubleshooting section above
- Check AWS CloudTrail for API errors
- Use
terraform planto understand dependencies - Post questions in the course discussion forum