Code Patterns & References
Study each pattern before starting the activity. The official references are at the end of each section.
What to Deliver
| Deliverable | Requirement |
|---|---|
| CloudFormation template | Valid YAML template that defines at least: VPC, subnet, security group, and EC2 instance. Uses Parameters for configurable values. Has Outputs section. |
| Successful deployment | aws cloudformation deploy or create-stack completes without errors. Resources visible in AWS Console. |
| Resource cleanup | All resources deleted after the activity. Stack deleted with delete-stack. Verified in Console. |
| Presentation | Walk through your template structure, explain what each resource does, show the deployed resources, demonstrate cleanup. |
| Check | How It's Verified | Blocking? |
|---|---|---|
| CloudFormation template is valid YAML with no syntax errors | aws cloudformation validate-template passes | Yes |
| All required resources are defined | Instructor reviews the template | Yes |
| Stack deploys successfully | aws cloudformation describe-stacks shows CREATE_COMPLETE | Yes |
| Resources cleaned up after activity | Console shows no orphaned EC2, VPC, or SG | Yes |
| You can explain each resource in the template | Live Q&A during presentation | Yes |
Deliverable Checklist
- Send to your instructor before the presentation:
- [ ] GitLab repo link with your CloudFormation template committed
- [ ] Screenshot of a successful stack deployment in the AWS Console
- [ ] Screenshot showing stack DELETE_COMPLETE after cleanup
5.1 CloudFormation Template Structure
# template.yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: "Activity 1 - Basic AWS infrastructure"
Parameters:
Environment:
Type: String
Default: dev
AllowedValues: [dev, staging, prod]
VpcCidr:
Type: String
Default: "10.0.0.0/16"
Resources:
MyVpc:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VpcCidr
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: !Sub "${Environment}-vpc"
PublicSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MyVpc
CidrBlock: "10.0.1.0/24"
AvailabilityZone: !Select [0, !GetAZs ""]
MapPublicIpOnLaunch: true
WebSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: "Allow HTTP and SSH"
VpcId: !Ref MyVpc
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: "0.0.0.0/0" # Restrict to your IP in production
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: "0.0.0.0/0"
Outputs:
VpcId:
Description: "VPC ID"
Value: !Ref MyVpc
SubnetId:
Description: "Public Subnet ID"
Value: !Ref PublicSubnet
5.2 CloudFormation CLI Commands
# Validate template aws cloudformation validate-template --template-body file://template.yaml # Create stack aws cloudformation create-stack \ --stack-name activity1-stack \ --template-body file://template.yaml \ --parameters ParameterKey=Environment,ParameterValue=dev # Check stack status aws cloudformation describe-stacks --stack-name activity1-stack \ --query "Stacks[0].StackStatus" # Delete stack (always run this after the activity) aws cloudformation delete-stack --stack-name activity1-stack # Confirm deletion aws cloudformation describe-stacks --stack-name activity1-stack # Should return "Stack with id ... does not exist"
Week 1 Official References
| Category | Resource | What You'll Learn | URL |
|---|---|---|---|
| CloudFormation | CloudFormation Docs | Template anatomy, resource types, intrinsic functions | docs.aws.amazon.com/cloudformation/ |
| CloudFormation | AWS::EC2::VPC Resource | VPC resource type reference | docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html |
| AWS | AWS VPC User Guide | Subnets, route tables, gateways explained | docs.aws.amazon.com/vpc/latest/userguide/ |
| AWS | IAM Best Practices | Least-privilege access, roles, policies | docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html |
| AWS CLI | AWS CLI Reference | All CLI commands and options | docs.aws.amazon.com/cli/latest/reference/ |
| AWS | EC2 Instance Types | Choosing the right instance for cost and performance | aws.amazon.com/ec2/instance-types/ |
Deliverables per Activity
| Activity | Deliverable | Acceptance |
|---|---|---|
| 2a: My First Terraform | Working Terraform config that provisions at least one AWS resource (e.g. S3 bucket or VPC). init, fmt, validate, plan, apply, destroy all run successfully. | All 6 commands run without error. Resource visible in AWS Console. Destroyed after activity. |
| 2b: Variables | Refactor Activity 2a to use input variables and outputs. terraform.tfvars file used. No hardcoded values. | Variables used for all configurable values. Outputs defined and visible after apply. Clean destroy. |
| 2c: Modules | Extract at least one reusable module (e.g. a VPC module). Module called from root. Module has its own variables.tf and outputs.tf. | Module lives in its own folder. Root calls it via module block. State clean after destroy. |
Deliverable Checklist
- For each activity, send to your instructor:
- [ ] GitLab repo commit link for the activity
- [ ] Screenshot of terraform apply output (resources created)
- [ ] Screenshot of terraform destroy output (all resources destroyed)
- [ ] Ready to present: explain your config, the workflow, and what each block does
5.3 Terraform File Structure
my-terraform-project/
main.tf # resource definitions
variables.tf # input variable declarations
outputs.tf # output value declarations
terraform.tfvars # variable values (do NOT commit if it has secrets)
providers.tf # provider configuration
versions.tf # required_providers and terraform version constraint
# Module structure:
modules/
vpc/
main.tf
variables.tf
outputs.tf
README.md
5.4 providers.tf and versions.tf
# versions.tf
terraform {
required_version = ">= 1.6"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
# providers.tf
provider "aws" {
region = var.aws_region
# Credentials come from environment or ~/.aws/config — NEVER hardcoded
}
5.5 variables.tf and terraform.tfvars
# variables.tf
variable "aws_region" {
description = "AWS region to deploy into"
type = string
default = "ap-southeast-1"
}
variable "environment" {
description = "Deployment environment (dev, staging, prod)"
type = string
validation {
condition = contains(["dev","staging","prod"], var.environment)
error_message = "environment must be dev, staging, or prod."
}
}
variable "vpc_cidr" {
description = "CIDR block for the VPC"
type = string
default = "10.0.0.0/16"
}
# terraform.tfvars (values for the above)
aws_region = "ap-southeast-1"
environment = "dev"
vpc_cidr = "10.1.0.0/16"
5.6 Module Pattern
# modules/vpc/main.tf
resource "aws_vpc" "this" {
cidr_block = var.vpc_cidr
enable_dns_support = true
enable_dns_hostnames = true
tags = { Name = "${var.environment}-vpc" }
}
resource "aws_subnet" "public" {
count = length(var.public_subnet_cidrs)
vpc_id = aws_vpc.this.id
cidr_block = var.public_subnet_cidrs[count.index]
availability_zone = var.availability_zones[count.index]
map_public_ip_on_launch = true
tags = { Name = "${var.environment}-public-${count.index + 1}" }
}
# modules/vpc/outputs.tf
output "vpc_id" { value = aws_vpc.this.id }
output "public_subnet_ids" { value = aws_subnet.public[*].id }
# root main.tf — calling the module
module "vpc" {
source = "./modules/vpc"
environment = var.environment
vpc_cidr = var.vpc_cidr
public_subnet_cidrs = ["10.0.1.0/24","10.0.2.0/24"]
availability_zones = ["ap-southeast-1a","ap-southeast-1b"]
}
5.7 The Terraform Workflow — Every Time
| Command | What it does | When to run |
|---|---|---|
| terraform init | Downloads provider plugins, initialises backend | Once per new project, and after adding new providers |
| terraform fmt | Auto-formats all .tf files to canonical style | Before every commit |
| terraform validate | Checks syntax and configuration validity | Before every plan |
| terraform plan | Shows what will be created, changed, or destroyed | Before every apply — ALWAYS review the output |
| terraform apply | Provisions the resources | After reviewing plan output |
| terraform destroy | Removes all managed resources | After every activity — do not leave resources running |
| terraform state list | Lists all resources in the state file | Debugging, verifying what Terraform manages |
| terraform output | Shows output values after apply | After apply to see IPs, IDs, etc. |
Watch Out
Always run terraform plan before terraform apply. Read the output carefully.
Never run terraform destroy without checking what will be destroyed first.
If state is corrupted or you manually deleted resources in the Console: tell your instructor before trying to fix it yourself.
Weeks 2–3 Official References
| Category | Resource | What You'll Learn | URL |
|---|---|---|---|
| Terraform | Terraform Docs | Language reference, CLI commands, providers | developer.hashicorp.com/terraform/docs |
| Terraform | Terraform AWS Provider | All aws_* resource types and data sources | registry.terraform.io/providers/hashicorp/aws/latest/docs |
| Terraform | Input Variables | variable blocks, types, validation, defaults | developer.hashicorp.com/terraform/language/values/variables |
| Terraform | Output Values | output blocks and how to use them | developer.hashicorp.com/terraform/language/values/outputs |
| Terraform | Modules | Creating and calling reusable modules | developer.hashicorp.com/terraform/language/modules |
| Terraform | Terraform State | How state works, what tfstate files contain | developer.hashicorp.com/terraform/language/state |
| AWS | AWS Terraform Tutorials | Official step-by-step Terraform + AWS guides | developer.hashicorp.com/terraform/tutorials/aws |
Minimum Infrastructure Requirements
| Component | Requirement | Terraform Resource |
|---|---|---|
| VPC | Multi-AZ, CIDR /16 | aws_vpc |
| Subnets | Public subnets in 2 AZs, private subnets in 2 AZs | aws_subnet |
| Internet Gateway | Attached to VPC, route in public route table | aws_internet_gateway, aws_route_table |
| Security Groups | Least-privilege rules. Jump host, web tier, RDS each have separate SGs. | aws_security_group |
| Jump Host | Single EC2 in public subnet. SSH access restricted to your IP. | aws_instance |
| Launch Template | AMI, instance type, user data script, SG attached | aws_launch_template |
| Auto Scaling Group | Uses launch template. Min/Max/Desired defined. Spans 2 AZs. | aws_autoscaling_group |
| Application Load Balancer | Internet-facing. Listener on port 80. Target group pointing to ASG. | aws_lb, aws_lb_listener, aws_lb_target_group |
| RDS | MySQL or PostgreSQL. Multi-AZ enabled. In private subnets. Not publicly accessible. | aws_db_instance, aws_db_subnet_group |
| S3 Bucket | Private, no public access. Lifecycle rule to move objects to Glacier after 90 days. | aws_s3_bucket, aws_s3_bucket_lifecycle_configuration |
| Resource Tagging | All resources tagged with Environment, Project, Owner at minimum. | tags = {} on every resource |
Milestone Breakdown
| Week | Milestone | What to Have Done |
|---|---|---|
| 4 | Kickoff | Architecture diagram drafted. GitLab repo created. Folder structure and modules planned. Initial main.tf with provider config committed. |
| 5 | Milestone 1: Networking | VPC, all subnets, Internet Gateway, route tables, and all security groups provisioned and tested. terraform plan is clean. |
| 6 | Milestone 2: Compute | Jump host, launch template, Auto Scaling Group, and ALB provisioned. Can reach the ALB DNS name from a browser. |
| 7 | Milestone 3: Data | RDS Multi-AZ provisioned in private subnets. S3 bucket with lifecycle policy. Jump host can connect to RDS. |
| 8 | Finalization | All terraform test and connectivity checks done. Architecture diagram final. README complete. Resources destroyed. Presentation delivered. |
Capstone Terraform Structure
capstone/
main.tf # calls all modules
variables.tf
outputs.tf
terraform.tfvars # do not commit secrets
versions.tf
providers.tf
README.md
docs/
architecture.png # architecture diagram
testing-notes.md
modules/
networking/ # VPC, subnets, IGW, route tables
main.tf
variables.tf
outputs.tf
security-groups/ # all security group definitions
compute/ # launch template, ASG, jump host
load-balancer/ # ALB, listener, target group
database/ # RDS, subnet group
storage/ # S3 bucket and lifecycle
Key Terraform Patterns for the Capstone
Security Group with Least-Privilege Rules
resource "aws_security_group" "web" {
name = "${var.environment}-web-sg"
description = "Web tier — allow HTTP from ALB only"
vpc_id = var.vpc_id
ingress {
description = "HTTP from ALB"
from_port = 80
to_port = 80
protocol = "tcp"
security_groups = [var.alb_sg_id] # NOT 0.0.0.0/0
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = { Name = "${var.environment}-web-sg" }
}
Auto Scaling Group with ALB Integration
resource "aws_autoscaling_group" "web" {
name = "${var.environment}-web-asg"
min_size = 1
max_size = 3
desired_capacity = 2
vpc_zone_identifier = var.private_subnet_ids # private subnets
target_group_arns = [aws_lb_target_group.web.arn]
health_check_type = "ELB"
launch_template {
id = aws_launch_template.web.id
version = "$Latest"
}
tag {
key = "Name"
value = "${var.environment}-web"
propagate_at_launch = true
}
}
RDS Multi-AZ
resource "aws_db_instance" "main" {
identifier = "${var.environment}-db"
engine = "mysql"
engine_version = "8.0"
instance_class = "db.t3.micro"
allocated_storage = 20
db_name = "appdb"
username = var.db_username
password = var.db_password # use secrets manager in production
db_subnet_group_name = aws_db_subnet_group.main.name
vpc_security_group_ids = [var.rds_sg_id]
multi_az = true
publicly_accessible = false
skip_final_snapshot = true # set to false in production
tags = { Name = "${var.environment}-rds" }
}
Capstone Deliverables
Deliverable Checklist
- Submit or present all of the following in Week 8:
- [ ] Terraform code in the assigned GitLab repository (clean commit history)
- [ ] Architecture diagram (draw.io or Lucidchart export — PNG committed to docs/)
- [ ] README with: architecture overview, how to deploy, how to destroy, known issues
- [ ] Testing notes: connectivity test (browser to ALB), jump host SSH, RDS reachability
- [ ] terraform destroy confirmed — all resources cleaned up after presentation
- [ ] Individual capstone presentation delivered
Capstone Evaluation (3-point scale per area)
| Area | Rating 2 — Implemented and working | Rating 1 — Incomplete or with errors | Rating 0 |
|---|---|---|---|
| Infrastructure provisioning | All resources deploy with terraform apply and no errors | Partial deployment or errors during apply | Not attempted |
| AWS architecture and network design | VPC, subnets, IGW, route tables all correct and functional | Present but misconfigured | Not present |
| Security and access control | Least-privilege SGs, no public RDS, SSH restricted, no secrets in code | Some security issues present | Critical issues or secrets in repo |
| Terraform best practices | Modules, variables, outputs, clean file structure | Partial — some hardcoding or missing outputs | Single flat file, no modules |
| Variables, outputs, and modules | All three used correctly and meaningfully | Present but incomplete | Not used |
| Cost-efficient resource usage | Appropriate instance types, resources destroyed after use | Minor cost inefficiencies | Expensive or orphaned resources |
| Testing and troubleshooting | Testing notes document checks and any issues found | Minimal testing documented | Not documented |
| Documentation | README, architecture diagram, and deploy/destroy instructions clear | Present but incomplete | Missing |
| GitLab repository quality | Regular commits, clear messages, clean .gitignore | Infrequent commits or poor messages | No commits or secrets in repo |
| Capstone presentation | Architecture, code, blockers, and learnings all covered clearly | Presentation incomplete | Not presented |
Weeks 4–8 Official References
| Category | Resource | What You'll Learn | URL |
|---|---|---|---|
| AWS | VPC User Guide | Subnets, route tables, NACLs, IGW | docs.aws.amazon.com/vpc/latest/userguide/ |
| AWS | ALB User Guide | Load balancer, listeners, target groups | docs.aws.amazon.com/elasticloadbalancing/latest/application/ |
| AWS | EC2 Auto Scaling | Launch templates, ASG, scaling policies | docs.aws.amazon.com/autoscaling/ec2/userguide/ |
| AWS | RDS User Guide | Multi-AZ, subnet groups, security | docs.aws.amazon.com/AmazonRDS/latest/UserGuide/ |
| AWS | S3 User Guide | Bucket policies, lifecycle, access control | docs.aws.amazon.com/AmazonS3/latest/userguide/ |
| Terraform | AWS Provider — Full Index | Every aws_* resource with examples | registry.terraform.io/providers/hashicorp/aws/latest/docs |
| Diagrams | draw.io | Free architecture diagram tool | app.diagrams.net |
| AWS | AWS Architecture Icons | Official icons for architecture diagrams | aws.amazon.com/architecture/icons/ |
Project Immersion Expectations
| Activity | What is Expected |
|---|---|
| Observation | Attend assigned project meetings or ceremonies. Listen and take notes. Do not interrupt unless invited. |
| Documentation | Write structured notes after each observation session — tools used, workflows observed, questions that came up. |
| Questions | Bring questions to your instructor, not directly to the project team (unless explicitly invited). |
| Professional conduct | Treat the project team as clients. Be on time, be quiet, be respectful. |
Watch Out
Project observation is a privilege. The project team is working on real deliverables.
Never share client information, project details, or repository contents outside the internship.
You will NOT be given production access or asked to make changes to live systems.
5.8 Docker Fundamentals
# Dockerfile — basic Node.js web app example FROM node:20-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --only=production COPY . . EXPOSE 3000 CMD ["node", "server.js"]
# Build an image docker build -t my-app:latest . # Run a container docker run -p 3000:3000 my-app:latest # List running containers docker ps # Stop a container docker stop <container-id> # Remove all stopped containers and unused images docker system prune -f
5.9 Kubernetes Fundamentals
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
labels:
app: my-app
spec:
replicas: 2
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: my-app:latest
ports:
- containerPort: 3000
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "250m"
memory: "256Mi"
---
apiVersion: v1
kind: Service
metadata:
name: my-app-service
spec:
selector:
app: my-app
ports:
- port: 80
targetPort: 3000
type: LoadBalancer
5.10 GitLab CI/CD Pipeline
# .gitlab-ci.yml
stages:
- validate
- build
- deploy
variables:
TF_ROOT: ${CI_PROJECT_DIR}/terraform
terraform:validate:
stage: validate
image:
name: hashicorp/terraform:1.6
entrypoint: [""]
script:
- cd $TF_ROOT
- terraform init -backend=false
- terraform validate
docker:build:
stage: build
image: docker:24
services:
- docker:dind
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
only:
- main
Weeks 9–11 Deliverables
Deliverable Checklist
- By the end of Week 11:
- [ ] Observation notes from at least 3 project sessions (structured: tools, workflows, learnings)
- [ ] Cloud Native DevOps learning activities completed in StratU Classroom
- [ ] Working Dockerfile for a sample application (run locally)
- [ ] Basic Kubernetes manifest reviewed and understood (Deployment + Service)
- [ ] GitLab CI/CD pipeline reviewed and at least one stage understood
- [ ] Summary document: what you observed, what surprised you, what you want to learn more about
Weeks 9–11 Official References
| Category | Resource | What You'll Learn | URL |
|---|---|---|---|
| Docker | Docker Docs | Dockerfile, images, containers, volumes | docs.docker.com |
| Docker | Dockerfile reference | Every Dockerfile instruction explained | docs.docker.com/engine/reference/builder/ |
| Kubernetes | Kubernetes Concepts | Pods, Deployments, Services, ConfigMaps | kubernetes.io/docs/concepts/ |
| Kubernetes | kubectl Cheat Sheet | All kubectl commands | kubernetes.io/docs/reference/kubectl/cheatsheet/ |
| GitLab | GitLab CI/CD Docs | Pipelines, stages, jobs, variables | docs.gitlab.com/ee/ci/ |
| GitLab | GitLab CI YAML reference | All .gitlab-ci.yml keywords | docs.gitlab.com/ee/ci/yaml/ |