HumanGov: Model Automated Multi-Tenant Architecture (MAMA) Part 1 of 3: MAMA in the Cloud (AWS EC2, AWS S3 and Amazon DynamoDB) using Terraform and AWS CLI on AWSCloud9
Background
This project is about establishing cloud infrastructure for a Model Automated Multi-Tenant Architecture (MAMA), HumanGov. Each tenant (state = tenant in this case) will have their own EC2 instance, their own S3 bucket, and their own DynamoDB. (For example, Missouri and Kansas will have separate infrastructures.) The states wanted a Reusable, Multi-Tenant Software as a Service (SaaS) Application Infrastructure for dinner, and MAMA will feed it to them. This is a three part project:
HumanGov: Model Automated Multi-Tenant Architecture (MAMA), A Three-Part Series
There will not be lengthy explanations here. This post assumes that you already reviewed the ten (10)-part series on Terraform. If you want more in-depth explanation/background/information about what is going on, you can check out this 10-part series: Terraform: 10-Part Series for Familiarization
1 of 8. Open the AWS Cloud9 environment
2 of 8. Setup folders and files for the project
Start from your "environment" folder in AWS Cloud9. The "terraform" folder will be the main project folder. The other folder "modules/aws_humangov_infrastructure" is for modules.
pwd
cd human-gov-infrastructure
mkdir terraform
cd terraform
touch variables.tf main.tf outputs.tf
mkdir -p modules/aws_humangov_infrastructure
cd modules/aws_humangov_infrastructure
touch variables.tf main.tf outputs.tf
3 of 8. In "modules/aws_humangov_infrastructure", modify "variables.tf", "main.tf" and "outputs.tf"
"variables.tf"
variable "state_name" {
description = "The name of the US State"
}
"main.tf"
resource "aws_security_group" "state_ec2_sg" {
name = "humangov-${var.state_name}-ec2-sg"
description = "Allow traffic on ports 22 and 80"
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "humangov-${var.state_name}"
}
}
resource "aws_instance" "state_ec2" {
ami = "ami-007855ac798b5175e"
instance_type = "t2.micro"
key_name = "humangov-ec2-key"
vpc_security_group_ids = [aws_security_group.state_ec2_sg.id]
tags = {
Name = "humangov-${var.state_name}"
}
}
resource "aws_dynamodb_table" "state_dynamodb" {
name = "humangov-${var.state_name}-dynamodb"
billing_mode = "PAY_PER_REQUEST"
hash_key = "id"
attribute {
name = "id"
type = "S"
}
tags = {
Name = "humangov-${var.state_name}"
}
}
resource "random_string" "bucket_suffix" {
length = 7
special = false
upper = false
}
resource "aws_s3_bucket" "state_s3" {
bucket = "humangov-${var.state_name}-s3-${random_string.bucket_suffix.result}"
tags = {
Name = "humangov-${var.state_name}"
}
}
resource "aws_s3_bucket_ownership_controls" "state_s3" {
bucket = aws_s3_bucket.state_s3.id
rule {
object_ownership = "BucketOwnerPreferred"
}
}
resource "aws_s3_bucket_acl" "state_s3" {
depends_on = [aws_s3_bucket_ownership_controls.state_s3]
bucket = aws_s3_bucket.state_s3.id
acl = "private"
}
"outputs.tf"
output "state_ec2_public_dns" {
value = aws_instance.state_ec2.public_dns
}
output "state_dynamodb_table" {
value = aws_dynamodb_table.state_dynamodb.name
}
output "state_s3_bucket" {
value = aws_s3_bucket.state_s3.bucket
}
4 of 8. In the root project directory "terraform", modify "variables.tf", "main.tf" and "outputs.tf".
The most important thing here is navigation. Make sure that you're editing in the correct folder, else the logic will not flow per design.
"variables.tf" is for states. "main.tf" will feed off the modules/aws_humangov_infrastructure. "outputs.tf" will show the status of the created infrastructures.
"variables.tf"
variable "states" {
description = "A list of state names"
default = ["california","florida","texas"]
}
"main.tf"
provider "aws" {
region = "us-east-1"
}
module "aws_humangov_infrastructure" {
source = "./modules/aws_humangov_infrastructure"
for_each = toset(var.states)
state_name = each.value
}
"outputs.tf"
output "state_infrastructure_outputs" {
value = {
for state, infrastructure in module.aws_humangov_infrastructure :
state => {
ec2_public_dns = infrastructure.state_ec2_public_dns
dynamodb_table = infrastructure.state_dynamodb_table
s3_bucket = infrastructure.state_s3_bucket
}
}
}
5 of 8. Create SSH key.
The EC2 configuration refers to an SSH key by the name of "humangov-ec2-key". Make sure it exists. You can create the key pair however you want to, but the CLI is convenient for this case.
mkdir ~/environment/human-gov-infrastructure/terraform/keys
cd ~/environment/human-gov-infrastructure/terraform/keys
aws ec2 create-key-pair --key-name humangov-ec2-key --query 'KeyMaterial' --output text > humangov-ec2-key.pem
6 of 8. Initialize and apply
Make sure that you navigate to the main project folder, to avoid unexpected results.
21 resources? Yes, because there are 3 states, and each state gets 7 resources created:
1. DynamoDB
2. EC2
3. S3 bucket
4. S3 bucket ACL
5. S3 bucket ownership controls
6. security group for EC2
7. random string for the S3 bucket suffix
The most interesting part is probably the S3 bucket ACL and S3 bucket ownership controls. The documentation for that is included in the Reference section below.
cd ~/environment/human-gov-infrastructure/terraform
pwd
terraform fmt
terraform init
terraform validate
terraform plan
terraform apply
7 of 8. Validate you can see the resources in cloud
You should see instances, S3 buckets, DynamoDB tables.
8 of 8. Cleanup.
Remove the resources
terraform destroy
Reference
Comments
Post a Comment