This is the continuation of an AWS Terraform demo to create a VPC in AWS with an EC2 instance connected to the MariaDB database running in RDS using a single Terraform plan.
AWS with Terraform: The Essential Guide: Sections
Our new tutorial series delves into cloud infrastructure deployment using Terraform or OpenTofu on AWS. In this series, the fundamentals are shown, guiding you through minimizing resource usage and simplifying the deployment complexities associated with cloud infrastructure. This tutorial series is a work in progress and will have these sections:
EC2 instances are defined using the terraform.tfvars, some values (ami, vpc_security_group_ids, and subnet_id) are derived from modules output so the definition is in the aws_ec2_pro_wp.tf file as terraform.tfvars doesn't allow interpolation.
#------------------------ # WP PRO #------------------------ aws_ec2_pro_pub_wp_01 = { name = "ditwl-ec2-pro-pub-wp01" ami = "" #Uses data.aws_ami.ubuntu1604.id instance_type = "t2.micro" #AWS Free Tier: 750 hours per month of Linux, RHEL, or SLES t2.micro instance usage availability_zone = "us-east-1a" key_name = "ditwl_kp_infradmin" # vpc_security_group_ids = SEE TF file # subnet_id = SEE TF file associate_public_ip_address = true root_block_device_size = 8 # See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSVolumeTypes.html root_block_device_volume_type = "gp2" tag_private_name = "ditwl-ec2-pro-pub-wp-01" tag_public_name = "www" tag_app = "wp" tag_app_id = "wp-01" tag_os = "ubuntu" tag_os_id = "ubuntu-16" tags_environment = "pro" tag_cost_center = "ditwl-permanent" tags_volume = "ditwl-ec2-pro-pub-wp-01-root" } #------------------------ # WP PRO Security Group #------------------------ aws_sg_ec2_pro_pub_wp_01 = { sec_name = "ditwl-sg-ec2-pro-pub-01" sec_description = "ditwl - WP server access rules - Pub, Env: PRO" allow_all_outbound = false } aws_sr_ec2_pro_pub_wp_01_internet_to_80 = { type = "ingress" from_port = 80 to_port = 80 protocol = "tcp" cidr_blocks = "0.0.0.0/0" description = "Access from Internet to port 80" } aws_sr_ec2_pro_pub_wp_01_internet_to_443 = { type = "ingress" from_port = 443 to_port = 443 protocol = "tcp" cidr_blocks = "0.0.0.0/0" description = "Access from Internet to port 443" }
All EC2 instance names and their Security Rules and Groups follow a standardized naming pattern.
To access the created Linux instances in AWS you will need an SSH client. Authentication will use a private key and in the case of Ubuntu a username named "ubuntu".
The private key needs to be registered in the AWS EC2 console, it can be uploaded to the console or created using a wizard.
Having configured most of the values for the instance in the terraform.tfvars, now the file aws_ec2_pro_wp.tf makes use of Terraform modules to create the resources.
The Terraform module /modules/aws/ec2/instance/add is used to create the EC2 instance. Most of the variables come from the aws_ec2_pro_pub_wp_01 variable definition from terraform.tfvars and the rest are interpolations to other resources:
# Create WP instance module "aws_ec2_pro_pub_wp_01" { source = "./modules/aws/ec2/instance/add" name = var.aws_ec2_pro_pub_wp_01["name"] ami = data.aws_ami.ubuntu1604.id instance_type = var.aws_ec2_pro_pub_wp_01["instance_type"] availability_zone = var.aws_ec2_pro_pub_wp_01["availability_zone"] key_name = var.aws_ec2_pro_pub_wp_01["key_name"] disable_api_termination = var.is_production ? true : false vpc_security_group_ids = [module.aws_sg_ec2_default.id,module.aws_sg_ec2_pro_pub_wp_01.id] subnet_id = module.aws_sn_za_pro_pub_32.id associate_public_ip_address = var.aws_ec2_pro_pub_wp_01["associate_public_ip_address"] instance_tags = {} tag_private_name = var.aws_ec2_pro_pub_wp_01["tag_private_name"] tag_public_name = var.aws_ec2_pro_pub_wp_01["tag_public_name"] tag_app = var.aws_ec2_pro_pub_wp_01["tag_app"] tag_app_id = var.aws_ec2_pro_pub_wp_01["tag_app_id"] tag_os = var.aws_ec2_pro_pub_wp_01["tag_os"] tag_os_id = var.aws_ec2_pro_pub_wp_01["tag_os_id"] tags_environment = var.aws_ec2_pro_pub_wp_01["tags_environment"] tag_cost_center = var.aws_ec2_pro_pub_wp_01["tag_cost_center"] register_dns_private = true route53_private_zone_id = module.aws_route53_public.id register_dns_public = true route53_public_zone_id = module.aws_route53_public.id root_block_device = { volume_size = var.aws_ec2_pro_pub_wp_01["root_block_device_size"] volume_type = var.aws_ec2_pro_pub_wp_01["root_block_device_volume_type"] delete_on_termination = var.is_production ? false : true #If production, Do not delete! } volume_tags = { Name = var.aws_ec2_pro_pub_wp_01["name"] } ignore_changes = ["ami"] }
Securing AWS VPC resources with Terraform makes use of 3 modules:
See AWS Security Groups' Best Practices.
The following illustration shows the security groups and rules applied to each AWS resource.
Continue the Terraform and Ansible demo, see:
IT Wonder Lab tutorials are based on the diverse experience of Javier Ruiz, who founded and bootstrapped a SaaS company in the energy sector. His company, later acquired by a NASDAQ traded company, managed over €2 billion per year of electricity for prominent energy producers across Europe and America. Javier has over 25 years of experience in building and managing IT companies, developing cloud infrastructure, leading cross-functional teams, and transitioning his own company from on-premises, consulting, and custom software development to a successful SaaS model that scaled globally.