Terraform is a simple and reliable way to manage infrastructure in AWS, Google Cloud, Azure, Digital Ocean and more IaaS (providers, in terms of Terraform). The main idea of such tools is to create reproducible infrastructure and Terraform provides DSL to describe infrastructure and then apply to different environments. Previously we used a set of Python and bash scripts to describe what create in AWS, described different conditions which checks if some resource exists in AWS and create if it's not. Actually, Terraform is doing the same underhood. This is an introduction which covers simple use case to create Alluxio cluster I used in the previous post.
Terraform supports a number of different providers, but Terraform script must be written every time for new provider.
For beginning, let's define AWS provider:
provider "aws" { region = "us-west-1" profile = "xxx-federated" # this is source of credentials; without profile use access keys}Then create security group and open/close required ports:
# As simplification, it opens wide range of ports from 20 to 65530, use more grained controlresource "aws_security_group" "my_test" { description = "Used in the terraform" vpc_id = "vpc-XXXXX" # VPC in which we want to have this subnet # input ingress { from_port = 20 to_port = 65530 protocol = "tcp" cidr_blocks = ["10.0.0.0/8","172.0.0.0/8"] } # outbound egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] }}AWS very actively relies on roles so our Alluxio instances are supposed to have IAM roles:
# this is profile for our instance, used for IAM purposesresource "aws_iam_instance_profile" "my_profile" { name = "my_profile" role = "BEST_EVER_Role" # yeah, role we're gonna use}# EC2 to host Alluxio masterresource "aws_instance" "emr2-master" { instance_type = "m4.2xlarge" count=1 # ami based on Amazon linux with docker and git ami="ami-YYYY" # our instance is based on this role # The name of our SSH keypair we created above. key_name = "key" # EC2 key pair name which is known to AWS iam_instance_profile = "${aws_iam_instance_profile.my_profile.id}" # sweet part: reference to instance profile ID vpc_security_group_ids = ["${aws_security_group.my_test.id}"] # another sweet part: reference to security group declared above subnet_id = "subnet-123ce1da" # subnet, just hardcode for now tags { Name = "Alluxio-master" # here we can describe several tags we need } provisioner "remote-exec" { # provisioner, what we want to run on master after it created inline = [ "cd alluxio/integration/docker", "docker build -t alluxio .", "cd ~", "mkdir underStorage", "sudo mkdir /mnt/ramdisk", "sudo mount -t ramfs -o size=12G ramfs /mnt/ramdisk", "sudo chmod a+w /mnt/ramdisk", "sudo service docker restart", "docker run -d --net=host -v $PWD/underStorage:/underStorage -e ALLUXIO_MASTER_HOSTNAME=127.0.0.1 -e ALLUXIO_UNDERFS_ADDRESS=/underStorage alluxio master" ] } connection { timeout = "15m" user = "ec2-user" private_key = "${file("/Users/kostia/.ssh/key.pem")}" }}Last step is to describe Alluxio slaves and connect them to Master
resource "aws_instance" "emr2-slaves" { instance_type = "r4.xlarge" count=3 # ami based on Amazon linux with docker and git ami="ami-ZZZ" # The name of our SSH keypair we created above. key_name = "key" vpc_security_group_ids = ["${aws_security_group.my_test.id}"] iam_instance_profile = "${aws_iam_instance_profile.my_profile.id}" subnet_id = "subnet-123c1a0b" tags { Name = "Alluxio-slaves" } provisioner "remote-exec" { inline = [ "cd alluxio/integration/docker", "docker build -t alluxio .", "cd ~", "mkdir underStorage", "sudo mkdir /mnt/ramdisk", "sudo mount -t ramfs -o size=28G ramfs /mnt/ramdisk", "sudo chmod a+w /mnt/ramdisk", "sudo service docker restart", "docker run -d --net=host -v /mnt/ramdisk:/opt/ramdisk -v $PWD/underStorage:/underStorage -e ALLUXIO_MASTER_HOSTNAME=${aws_instance.emr2-master.private_ip} -e ALLUXIO_RAM_FOLDER=/opt/ramdisk -e ALLUXIO_WORKER_MEMORY_SIZE=28GB -e ALLUXIO_UNDERFS_ADDRESS=/underStorage alluxio worker" ] } connection { timeout = "15m" # wait 15 minutes for connection to be established user = "ec2-user" private_key = "${file("/Users/kostia/.ssh/key.pem")}" }
}
Last step is apply changes from Terraform json script to AWS infrastructure. The main commands to know:
terraform apply applies changes to AWS account (i.e. create, update or delete instances)
terraform plan will show plan (list of commands to be executed) before applying
terraform destroy destroys created previously infrastructure
# Einführung in Terraform (in English)
# Introduksjon i Terraform (in English)
Find Whatsapp Number
ВідповістиВидалитиI’ve always struggled with combining security groups and instance profiles, but your example makes it easy to see how they work together. I’m wondering, do you usually manage the private keys locally or use AWS Systems Manager for this kind of deployment with Terraform?
ВідповістиВидалити