TL;DR Konfigurasi Amazon VPC private subnet dengan menggunakan Terraform
Melanjut dari bagian 1 dari topik Konfigurasi Dasar Amazon VPC Menggunakan Terraform, pada bagian ke 2 ini saya akan mencoba menjelaskan cara konfigurasi Amazon VPC private subnet menggunakan Terraform.
Seperti yang sudah dijelaskan pada bagian 1, salah satu penggunaan public dan private subnet di Amazon VPC adalah jika kita ingin membuat multi-tier website. Jika pada bagian 1 kita sudah mencoba mensimulasikan menjalankan sebuah ec2 instance yang bertindak sebagai web server di public subnet, pada bagian ke 2 ini kita akan mencoba menjalankan sebuah ec2 instance yang akan bertindak sebagai database server yang berada di private subnet.
Keuntungan dari penggunaan private subnet ini adalah, database yang kita gunakan tidak mudah ter-expose dari public dan hanya instance/resource tertentu saja yang dapat mengakses misalkan resource yang ada di public subnet dalam VPC kita.
Skenario yang saya gunakan pada artikel ini merupakan lanjutan dari bagian 1. Jika pada bagian 1 saya sudah mensimulasikan membuat nondefault VPC di region ap-southeast-1 dengan membuat public subnet dan segala komponennya. Pada bagian 2 ini saya akan membuat sebuah private subnet di dalam VPC tersebut. Untuk akses ke internet dari private subnet akan dibuat sebuah route table yang berisi route ke internet dengan target/next hop NAT Gateway. Karena NAT Gateway perlu berinteraksi dengan public internet dan memerlukan public IP, maka NAT Gateway akan berada di dalam public subnet. Selain itu juga akan dibuat sebuah Security Group yang akan digunakan oleh EC2 yang berada di private subnet, dimana EC2 tersebut akan bertindak seolah-olah sebagai database server. Jika digambarkan topologinya seperti berikut:
Konfigurasi resource VPC dan komponen terkait lainnya pada artikel ini menggunakan IaC tool Terraform. Terraform yang digunakan adalah Terraform Cloud.
Konfigurasi
Pada artikel ini, struktur file yang digunakan oleh terraform code sebagai berikut:
vpc/
├─ vpc-apse1/
├─ main.tf
├─ sec-groups.tf
├─ variables.tf
├─ vpc.tf
-
Sebagai langkah awal, saya mulai dengan membuat satu file dengan nama main.tf. Di file ini saya akan mendeklarasikan konfigurasi terraform yang akan mengacu ke terraform cloud (app.terraform.io) sebagai backend. Dan mereferensikan nama organisasi dan workspace yang digunakan. Kemudian saya juga deklarasikan terraform provider yang digunakan yaitu hashisorp/aws dengan versi terkait. Di akhir saya deklarasikan region aws yang digunakan, mengacu ke variable aws_region yang ada di file variable.tf yang berikutnya akan saya jelaskan.
# Setup terraform cloud and workspace
terraform {
backend "remote" {
hostname = "app.terraform.io"
organization = "lanandra"
workspaces {
name = "vpc-ap-southeast-1"
}
}
}
# Setup terraform providers
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.57.0"
}
}
required_version = ">= 1.0.6"
}
# Setup AWS provider
provider "aws" {
region = var.aws_region
}
-
Langkah berikutnya yaitu dengan membuat variable di file variable.tf. Di file ini saya deklarasikan variable aws_region, availability_zone dan default_route. Variable aws_region digunakan untuk menentukan default AWS region yang digunakan yaitu ap-southeast-1. Variable availability_zone digunakan untuk mendeklarasikan seluruh availability zone yang ada di region ap-southeast-1 ke dalam sebuah list string. Terakhir variable default_route digunakan untuk mendeklarasikan default route (0.0.0.0/0).
# Setup AWS Region
variable "aws_region" {
type = string
description = "AWS Region"
default = "ap-southeast-1"
}
# Setup Availability Zone
variable "availability_zone" {
type = list(string)
description = "Availability Zone used by subnet"
default = ["ap-southeast-1a", "ap-southeast-1b", "ap-southeast-1c"]
}
# Setup Default Route
variable "default_route" {
type = string
description = "Default Route from and to internet"
default = "0.0.0.0/0"
}
-
Selanjutnya adalah konfigurasi VPC dan komponen terkait seperti Internet Gateway, NAT Gateway dan Subnet. Konfigurasi saya lakukan di file vpc.tf. Di artikel ini saya akan membuat sebuah vpc dengan nama apse1-0 dengan CIDR block 10.0.0.0/16. Kemudian akan di attach sebuah Internet Gateway ke VPC tersebut.
Berikutnya saya definisikan sebuah Elastic IP (eip) dengan nama nat-apse1-0. EIP ini nantinya akan di asosiasikan ke sebuah NAT Gateway dengan nama apse1-0 yang mana resource nya juga didefinisikan di dalam file ini. Karena NAT Gateway memerlukan akses langsung ke public/internet, maka penempatannya adalah di dalam public subnet dan diasosiasikan dengan public IP.
Terakhir adalah saya definisikan dua buah subnet. Yang pertama adalah public subnet dengan nama public-apse1-0 dengan CIDR block 10.0.0.0/22. Yang kedua adalah private subnet dengan nama private-apse1-0 dengan CIDR block 10.0.128.0/22. Kedua subnet menggunakan availability zone yang di-definisikan menggunakan variable availability_zone dengan mengambil index 0 (ap-southeast-1a).
# Configuration section for vpc
resource "aws_vpc" "apse1_0" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "apse1-0"
}
}
# Configuration section for internet gateway
resource "aws_internet_gateway" "apse1_0" {
vpc_id = aws_vpc.apse1_0.id
tags = {
Name = "apse1-0"
}
}
# Configuration section for elastic ip
resource "aws_eip" "nat_apse1_0" {
vpc = true
tags = {
Name = "nat-apse1-0"
}
}
# Configuration section for nat gateway
resource "aws_nat_gateway" "apse1_0" {
allocation_id = aws_eip.nat_apse1_0.id
subnet_id = aws_subnet.public_apse1_0.id
tags = {
Name = "apse1-0"
}
}*/
# Configuration section for public subnet
resource "aws_subnet" "public_apse1_0" {
cidr_block = "10.0.0.0/22"
vpc_id = aws_vpc.apse1_0.id
availability_zone = var.availability_zone[0]
tags = {
Name = "public-apse1-0"
}
}
# Configuration section for private subnet
resource "aws_subnet" "private_apse1_0" {
cidr_block = "10.0.128.0/22"
vpc_id = aws_vpc.apse1_0.id
availability_zone = var.availability_zone[0]
tags = {
Name = "private-apse1-0"
}
}
-
Berikutnya masih di file yang sama, vpc.tf. Saya definisikan Route Table, Route dan Route Table Association untuk public dan private subnet. Pada route table public-apse1-0, saya akan membuat default route(0.0.0.0/0) ke internet via Internet Gateway dan subnet yang di-asosiasikan adalah public-apse1-0. Dan pada route table private-apse1-0, default route (0.0.0.0/0) akan dilewatkan via NAT gateway dan subnet yang di-asosiasikan adalah private-apse1-0. Hal ini adalah salah satu konsep dasar dari Amazon VPC. Jika public subnet perlu akses ke internet maka jalur nya melalui Internet Gateway, sedangkan untuk private subnet melalui NAT Gateway.
# Configuration section for route table public_apse1_0
resource "aws_route_table" "public_apse1_0" {
vpc_id = aws_vpc.apse1_0.id
tags = {
Name = "public-apse1-0"
}
}
resource "aws_route" "default_public_apse1_0" {
route_table_id = aws_route_table.public_apse1_0.id
destination_cidr_block = var.default_route
gateway_id = aws_internet_gateway.apse1_0.id
}
resource "aws_route_table_association" "public_apse1_0" {
subnet_id = aws_subnet.public_apse1_0.id
route_table_id = aws_route_table.public_apse1_0.id
# Configuration section for route table private_apse1_0
resource "aws_route_table" "private_apse1_0" {
vpc_id = aws_vpc.apse1_0.id
tags = {
Name = "private-apse1-0"
}
}
# Route to internet from private_apse1_0 via nat gateway
resource "aws_route" "default_private_apse1_0" {
route_table_id = aws_route_table.private_apse1_0.id
destination_cidr_block = var.default_route
nat_gateway_id = aws_nat_gateway.apse1_0.id
}
resource "aws_route_table_association" "private_apse1_0" {
subnet_id = aws_subnet.private_apse1_0.id
route_table_id = aws_route_table.private_apse1_0.id
}
-
Selanjutnya adalah konfigurasi security group di dalam file sec-groups.tf. Pada artikel ini saya akan bahas lebih detail hanya konfigurasi security group yang digunakan oleh private instance. Untuk security group di public instance dapat melihat referensi di bagian 1. Security group akan saya beri nama demo-private-apse1-0 dan saya buat di dalam VPC apse1-0. Untuk Ingress/Inbound rule, akan saya izinkan port 22, 80, 443, 5432 dengan sumber IP 10.0.0.0/20 (CIDR block ini sedikit lebih lebar subnet nya dari CIDR yang digunakan public subnet yaitu /22, karena tujuannya saya summarize untuk subnet lain yang nantinya akan dibuat di public subnet. Kemudian untuk Egress/Outbound rule akan saya izinkan semua port, protocol dan IP.
# Configuration related to security groups
resource "aws_security_group" "demo_private_apse1_0" {
name = "demo-private-apse1-0"
description = "Security Group for demo purposes"
vpc_id = aws_vpc.apse1_0.id
ingress {
description = "from public apse1"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["10.0.0.0/20"]
}
ingress {
description = "from public apse1"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["10.0.0.0/20"]
}
ingress {
description = "from public apse1"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["10.0.0.0/20"]
}
ingress {
description = "from public apse1"
from_port = 5432
to_port = 5432
protocol = "tcp"
cidr_blocks = ["10.0.0.0/20"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = [var.default_route]
}
tags = {
Name = "demo-private-apse1-0"
}
}
-
Selanjutnya adalah melakukan terraform plan dan terraform apply di Terraform Cloud. Namun bagian ini saya hanya gambarkan ilustarsinya saja. Pastikan di production, plan dan apply berhasil/success.
-
Setelah infrastructure/service berhasil dibuat oleh Terraform, selanjutnya kita dapat melakukan verifikasi via AWS Web Console. Resource seperti VPC, Internet Gateway, Subnet, Route Table, Route Table Association dan hal lain yang berhubungan dengan public subnet tidak saya jelaskan lebih detail di artikel ini, silahkan lihat lebih detail di bagian 1.
-
Pada artikel ini, hal pertama yang saya akan pastikan adalah sudah berhasil terbentuk Elastic IP (EIP). Masuk ke halaman service VPC dan masuk ke menu Elastic IPs. Pastikan sudah ada 1 IP Public yang dialokasikan dengan nama nat-apse1-0.
-
Selanjutnya masuk ke menu NAT Gateways. Pastikan sudah terbentuk NAT Gateway dengan nama apse1-0 dan diasosiakan dengan Public IP yang sama dengan IP yang ada di halaman Elastic IP.
-
Selanjutnya masuk ke menu Subnets. Pastikan subnet private-apse1-0 sudah berhasil terbentuk dengan CIDR block yang sesuai.
-
Selanjutnya masuk ke menu Route Tables. Pastikan route table private-apse1-0 sudah berhasil terbentuk.
-
Pastikan Route yang ter-associate dengan Route Table private-apse1-0. Secara otomatis, Route Table akan menambahkan route ke local CIDR block yang ada dalam vpc tersebut, dalam contoh disini adalah 10.0.0.0/16. Setelah itu akan ada 1 Route tujuan 0.0.0.0/0 (default route) via NAT Gateway, seperti yang sudah di deklarasikan di Terraform code.
-
Selanjutnya pastikan Subnet associations yang ada pada Route Table tersebut. Pada artikel ini, Subnet private-apse1-0 di associate secara explicit ke dalam Route Table private-apse1-0.
-
Selanjutnya masuk ke menu Security Groups. Pastikan Security Group demo-private-apse1-0 sudah berhasil terbentuk.
-
Pastikan Inbound Rule di Security Group tersebut sudah mengizinkan port 22, 80, 443 dan 5432.
-
Selanjutnya pastikan Outbound Rule di Security Group sudah mengizinkan semua traffic.
-
Selanjutnya adalah simulasi menjalankan EC2 di atas VPC dan Subnet yang baru dibentuk di atas. Konfigurasi EC2 tidak saya jelaskan secara detail di artikel ini. Namun saya akan mensimulasikan dua buah demo EC2 dengan nama demo-ubuntu-public-0 dan demo-ubuntu-private-0.
-
EC2 yang pertama akan dijalankan di atas VPC apse1-0 dan menggunakan subnet public-apse1-0. Karena Subnet public-apse1-0 di deklarasikan menggunakan Availability Zone (AZ) ap-southeast-1a, maka EC2 juga akan berjalan di AZ tersebut.
Karena EC2 berjalan di atas public subnet, saya coba asosiasikan juga public IP address ke EC2 tersebut. Sehingga EC2 memiliki IP address private yg berada di range CIDR public-apse1-0 dan juga memiliki 1 IP public.
-
EC2 yang kedua akan dijalankan di atas VPC apse1-0 dan menggunakan subnet private-apse1-0. EC2 juga akan berjalan di atas Availability Zone (AZ) ap-southeast-1a mengikuti konfigurasi yang dideklarasikan untuk private subnet private-apse1-0.
-
Kemudian EC2 demo-ubuntu-private-0 akan dijalankan menggunakan Security Group demo-private-apse1-0.
-
Selanjutnya verifikasi koneksi dari EC2 demo-ubuntu-private-0 tersebut. Saya verifikasi koneksi via ping ke nama domain ludesdeveloper.wordpress.com. Dari hasil tes ini, dapat disimpulkan koneksi outbound dari EC2 sudah berhasil. Kemudian saya juga coba jalankan command untuk meng-install postgresql. Dari hasil tes ini, dapat disimpulkan inbound ke EC2 sudah berhasil karena untuk download package menggunakan protocol http.
-
Terakhir saya coba pastikan komunikasi dari public subnet ke private subnet sudah berjalan. Dari EC2 public subnet dengan IP 10.0.3.240 melakukan psql command untuk login ke Database postgres di EC2 private subnet dengan IP 10.0.129.19. Hasilnya sudah berhasil login ke Database postgres.
Kesimpulan
Akhirnya kita sampai di penghujung artikel ini. Pada artikel ini kita sudah membahas konsep dasar dari Amazon VPC, khususnya private subnet. Setelah itu kita juga telah melakukan bagaimana cara konfigurasi Amazon VPC, Private Subnet, NAT Gateway dan beberapa komponen lain menggunakan Terraform. Kita juga telah melakukan demo menjalankan EC2 di atas VPC dan Private Subnet yang baru dibuat di artikel ini.
Silahkan kunjungi GitHub repo saya untuk melihat source code yang saya gunakan pada artikel ini.
Sekian artikel kali ini. Jika ada saran, kritik, atau masukan silahkan tinggalkan di kolom komentar.
Tinggalkan Balasan