Skip to content

Latest commit

 

History

History
456 lines (351 loc) · 13.7 KB

SAMPLE03-EC2-EBS-EFS.md

File metadata and controls

456 lines (351 loc) · 13.7 KB

SAMPLE-03: EBS (Elastic Block Storage: HDD, SDD) and EFS (Elastic File System: NFS) Configuration with EC2s (Ubuntu and Windows Instances)

This sample shows:

There are 3 main parts:

  • main.tf: It includes 2 EC2 (Ubuntu, Windows), VPC, subnet, IGW, route table, security group implementation.
  • efs.tf: It includes EFS configuration for Ubuntu EC2.
  • ebs.tf: It includes EBS configuration for both Ubuntu and Windows EC2s.

image

Code: https://github.com/omerbsezer/Fast-Terraform/tree/main/samples/ec2-ebs-efs

Table of Contents

Prerequisite

Steps

Key-Pair

SSH key-pairs (public and private key) are used to connect remote server. Public key (xx.pub) is on the remote server, with private key, user can connect using SSH.

  • There are 2 ways of creating key-pairs (public and private key):

    • Creating them on cloud (AWS)
      • EC2 > Key-pairs > Create Key-Pair
    • Creating them on on-premise
      • "ssh-keygen -t rsa -b 2048"
  • Creating key-pairs on AWS: Go to EC2 > Key-pairs

image

  • After creating key-pairs, public key is listed on AWS:

image

  • Private key (testkey.pem) is downloaded on your PC:

image

  • Copy this testkey.pem into your directory on which main.tf exists.

image

VPC, EC2, SG Implementation

  • Create main.tf:
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.16"
    }
  }
  required_version = ">= 1.2.0"
}

provider "aws" {
	region = "eu-central-1"
}

resource "aws_vpc" "my_vpc" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  tags = {
    Name = "My VPC"
  }
}

resource "aws_subnet" "public" {
  vpc_id            = aws_vpc.my_vpc.id
  cidr_block        = "10.0.0.0/24"
  availability_zone = "eu-central-1c"
  tags = {
    Name = "Public Subnet"
  }
}

resource "aws_internet_gateway" "my_vpc_igw" {
  vpc_id = aws_vpc.my_vpc.id
  tags = {
    Name = "My VPC - Internet Gateway"
  }
}

resource "aws_route_table" "my_vpc_eu_central_1c_public" {
    vpc_id = aws_vpc.my_vpc.id
    route {
        cidr_block = "0.0.0.0/0"
        gateway_id = aws_internet_gateway.my_vpc_igw.id
    }
    tags = {
        Name = "Public Subnet Route Table"
    }
}
resource "aws_route_table_association" "my_vpc_eu_central_1c_public" {
    subnet_id      = aws_subnet.public.id
    route_table_id = aws_route_table.my_vpc_eu_central_1c_public.id
}

resource "aws_security_group" "sg_config" {
  name        = "allow_ssh_sg"
  description = "Allow SSH inbound connections"
  vpc_id      = aws_vpc.my_vpc.id
  # for SSH
  ingress {
    from_port        = 22
    to_port          = 22
    protocol         = "tcp"
    cidr_blocks      = ["0.0.0.0/0"]
  }
  # for HTTP Apache Server
  ingress {
    from_port        = 80
    to_port          = 80
    protocol         = "tcp"
    cidr_blocks      = ["0.0.0.0/0"]
  }
  # for RDP
  ingress {
    from_port        = 3389
    to_port          = 3389
    protocol         = "tcp"
    cidr_blocks      = ["0.0.0.0/0"]
  }
  # for ping
  ingress {
    from_port        = -1
    to_port          = -1
    protocol         = "icmp"
    cidr_blocks      = ["10.0.0.0/16"]
  }
  # EFS mount target, important to connect with NFS file system, it must be added.
  ingress {
    from_port        = 2049
    to_port          = 2049
    protocol         = "tcp"
    cidr_blocks      = ["0.0.0.0/0"]
  }
  egress {
    from_port       = 0
    to_port         = 0
    protocol        = "-1"
    cidr_blocks     = ["0.0.0.0/0"]
  }
  tags = {
    Name = "allow_ssh_sg"
  }
}

resource "aws_instance" "ubuntu2004" {
  ami                         = "ami-0e067cc8a2b58de59" # Ubuntu 20.04 eu-central-1 Frankfurt
  instance_type               = "t2.nano"
  key_name                    = "testkey"
  vpc_security_group_ids      = [aws_security_group.sg_config.id]
  subnet_id                   = aws_subnet.public.id
  associate_public_ip_address = true
  tags = {
    Name = "Ubuntu 20.04"
  }
}

resource "aws_instance" "win2019" {
  ami                         = "ami-02c2da541ae36c6fc" # Windows 2019 Server eu-central-1 Frankfurt
  instance_type               = "t2.micro"
  key_name                    = "testkey"
  vpc_security_group_ids      = [aws_security_group.allow_ssh.id]
  subnet_id                   = aws_subnet.public.id  
  associate_public_ip_address = true
  tags = {
		Name = "Win 2019 Server"
	}
}

output "instance_ubuntu2004_public_ip" {
  value = "${aws_instance.ubuntu2004.public_ip}"
}

output "instance_win2019_public_ip" {
  value = "${aws_instance.win2019.public_ip}"
}

Code: https://github.com/omerbsezer/Fast-Terraform/blob/main/samples/ec2-ebs-efs/main.tf

image

EBS Implementation

  • Create ebs.tf:
# Creating EBS for Ubuntu
# details: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ebs_volume
resource "aws_ebs_volume" "ebs_ubuntu" {
  availability_zone = "eu-central-1c"
  size = 20   # The size of the drive in GiBs.
  type= "gp2" # default gp2. others: standard, gp2, gp3, io1, io2, sc1 or st1
}

# EBS-Ubuntu attachment
resource "aws_volume_attachment" "ubuntu2004_ebs_ubuntu" {
  device_name = "/dev/sdh"
  volume_id   = "${aws_ebs_volume.ebs_ubuntu.id}"
  instance_id = "${aws_instance.ubuntu2004.id}"
}

# Creating EBS for Windows
# details: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ebs_volume
resource "aws_ebs_volume" "ebs_windows" {
  availability_zone = "eu-central-1c"
  size = 15   # The size of the drive in GiBs.
  type= "gp2" # default gp2. others: standard, gp2, gp3, io1, io2, sc1 or st1
}

# EBS-Windows attachment
resource "aws_volume_attachment" "win2019_ebs_windows" {
  device_name = "/dev/sdg"
  volume_id   = "${aws_ebs_volume.ebs_windows.id}"
  instance_id = "${aws_instance.win2019.id}"
}

Code: https://github.com/omerbsezer/Fast-Terraform/blob/main/samples/ec2-ebs-efs/ebs.tf

image

EFS Implementation

  • Create efs.tf:
# Creating Amazon EFS File system
# Amazon EFS supports two lifecycle policies. Transition into IA and Transition out of IA
resource "aws_efs_file_system" "efs" {
  lifecycle_policy {
    transition_to_ia = "AFTER_30_DAYS"
  }
  tags = {
    Name = "efs-example"
  }
}

# Creating the EFS access point for AWS EFS File system
resource "aws_efs_access_point" "access_point" {
  file_system_id = aws_efs_file_system.efs.id
}

# Creating the AWS EFS System policy to transition files into and out of the file system.
# The EFS System Policy allows clients to mount, read and perform, write operations on File system 
# The communication of client and EFS is set using aws:secureTransport Option
resource "aws_efs_file_system_policy" "policy" {
  file_system_id = aws_efs_file_system.efs.id
  policy = <<POLICY
{
    "Version": "2012-10-17",
    "Id": "Policy01",
    "Statement": [
        {
            "Sid": "Statement",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Resource": "${aws_efs_file_system.efs.arn}",
            "Action": [
                "elasticfilesystem:ClientMount",
                "elasticfilesystem:ClientRootAccess",
                "elasticfilesystem:ClientWrite"
            ],
            "Condition": {
                "Bool": {
                    "aws:SecureTransport": "false"
                }
            }
        }
    ]
}
POLICY
}

# Creating the AWS EFS Mount point in a specified Subnet 
resource "aws_efs_mount_target" "mount" {
  file_system_id = aws_efs_file_system.efs.id
  subnet_id      = aws_subnet.public.id
  security_groups = [aws_security_group.sg_config.id]  # open ingress 2049 port for EFS
}

resource "null_resource" "configure_nfs" {
  depends_on = [aws_efs_mount_target.mount]
   
  connection {
    type     = "ssh"
    user     = "ubuntu"
    private_key = file("testkey.pem")
    host     = aws_instance.ubuntu2004.public_ip
  }

  provisioner "remote-exec" {
    inline = [
      "sudo apt install nfs-common -y",
      "mkdir ~/efs",
      "cd ~/efs",
      "df -kh"
    ]
  }
}

Code: https://github.com/omerbsezer/Fast-Terraform/blob/main/samples/ec2-ebs-efs/efs.tf

image

Terraform Run

  • Run init, validate, plan, apply commands:
terraform init
terraform validate
terraform plan
terraform apply

image

image

EBS Final Setup and Test on Ubuntu

  • On AWS EC2:

image

  • On AWS EC2 Volumes, EC2 have default root volumes (8GB, 30GB).
  • New addition volumes (15GB, 20GB) are added as a second volume of EC2s.

image

  • Connect to the Ubuntu via SSH:
ssh -i .\testkey.pem ubuntu@3.69.53.254
lsblk

image

  • Formatting disk, mounting EBS:
sudo file -s /dev/xvdh       # “/dev/xvdf: data“, it means your volume is empty.

#format, Format the volume to the ext4 or xfs
sudo mkfs -t ext4 /dev/xvdh  # prefer ext4  
# sudo mkfs -t xfs /dev/xvdh

# mounting EBS
sudo mkdir newvolume
sudo mount /dev/xvdh newvolume
cd newvolume
df -h .

image

EFS Final Setup and Test on Ubuntu

  • Go to EFS Service, new EFS filesystem:

image

  • Click "Attach" to attach EFS to EC2:

image

  • Copy the command:

image

  • Mount the EFS:
e.g. sudo mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport fs-0adf50bc47d99ff95.efs.eu-central-1.amazonaws.com:/ efs
  • After mounting EFS, EFS mounted directory can be seen in the list.
  • Although creating 2 x 200MB files, root part's size does not change. It shows that EFS is mounted successfully, files are created on EFS part.

image

EBS Final Setup and Test on Windows

  • Connect Windows with RDP, get password using pem key:

image

image

image

  • Make "Initialize" the disk, with MBR:

image

  • New Simple Volume:

image

  • Final configuration:

image

  • New EBS disk is mounted successfully:

image

  • Destroy infrastructure:
terraform destroy 
  • It is easy to manage 17 resources:

image

References: