이번 게시글에서는 이전에 작성한 Terraform 문서에서 다루지 않은 내용만 다뤄볼 것이다.
일반적으로 VPC 작업을 할 때 기존 VPC를 삭제하는 것을 권장한다고 한다.
AWS 콘솔에서 VPC를 삭제한 후 Terraform을 이용해서 VPC와 보안그룹을 생성한다.
#aws new vpc
resource "aws_vpc" "default"{
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
instance_tenancy = "default"
tags = {
Name = "default"
}
}
#aws default 보안 그룹
data "aws_security_group" "default"{
name = "default"
depends_on = ["aws_vpc.default"]
}
#외부 - 22번 포트 보안 그룹 생성
resource "aws_security_group" "ssh"{
name = "allow_ssh_from_all"
description = "Allow SSH port from all"
vpc_id = aws_vpc.default.id
depends_on = ["aws_vpc.default"]
ingress{
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
이 때 주의해야 할 설정들이 있다. VPC를 새로 생성하면 자동으로 default 보안 그룹이 생성된다. 이 default 보안 그룹을 사용하기 위해 단순히 data로 보안 그룹을 불러온다면 VPC가 아직 생성이 되지 않았기 때문에 보안 그룹을 생성할 수 없다는 에러
가 뜰 수 있다.
이를 방지 하기 위한 옵션이 depends_on
이다. 어떠한 리소스가 생성된 후에 해당 리소스를 생성하라는 종속성을 위한 옵션이다.
default 보안 그룹은 VPC가 생성된 후에 만들어져야 하므로 depends_on = ["aws_vpc.default"]
옵션을 추가한다.
생성해야 하는 ami(Amazone Machine Image) 중 marketplace에는 존재하지만 ami id가 명시되어있지 않은 경우가 있다.
이런 경우..
이럴 때에는 aws cli를 활용해서 ami id를 찾을 수 있다.
# 1. aws cli 설치
$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
$ unzip awscliv2.zip
$ sudo ./aws/install
# 2. aws cli로 ami id 찾기
aws ec2 describe-images --owners aws-marketplace --filters "Name=name,Values=*15 SP2*" --query "reverse(sort_by(Images, &Name))[:100].ImageId" --output text
ami-039b8ca5919916521 ami-0d7d36a6e5712d9ac
EC2에 추가 스토리지를 구성하는 방식은 EBS를 사용하는 것이다. EBS의 종류에는 SSD, HDD, 마그네틱이 있는데 이번에는 HDD를 사용하고자 한다. (종류를 더 알고싶으면 aws-console에서 확인 가능)
순서는 EBS 생성 > EC2생성 > EC2와 EBS 연결 이다.
#ebs(web1)생성
resource "aws_ebs_volume" "web1"{
availability_zone = "ap-northeast-2a"
size = 150
type = "st1"
tags = {
Name = "web1"
}
}
...
#ec2(web1)생성
resource "aws_instance" "web1"{
ami = "ami-0e4214f08b51e23cc"
instance_type = "t3.large"
subnet_id = aws_subnet.public1.id
key_name = aws_key_pair.ec2_key_pair.key_name
vpc_security_group_ids = [
aws_security_group.ssh.id,
data.aws_security_group.default.id
]
tags = {
Name = "web1"
}
}
#ebs ec2(web1,web2) 연결
resource "aws_volume_attachment" "web1ebs"{
device_name = "/dev/sdb"
volume_id = "${aws_ebs_volume.web1.id}"
instance_id = "${aws_instance.web1.id}"
depends_on = ["aws_instance.web1"]
}
이 경우도 마찬가지로 종속 관계를 고려해서 생성해야 한다. 종속관계가 있는경우 depends_on
속성을 사용한다.
또 주의해야할 점은 aws_volume_attachment"
에 있어 instance_id를 작성할 때 "${ }"
형식을 따라야 하는 것이다.
이 후 ec2에 접속해서 lsblk
명령어를 통해 확인해보면 디스크가 잘 생성이 되어 붙은 것을 볼 수 있다.
private 서브넷을 생성한 후 was용 ec2를 생성한다. 퍼블릭 서브넷에 NAT 게이트웨이를 구성한 후 private 서브넷을 연결한다.
방식은 이전 게시글과 같으므로 아래에 코드로 첨부하겠다.
WAS에서 RDS에 접근할 수 있어야하고 RDS에서 외부로 빠져나갈 수 있어야하기 때문에 보안 그룹을 설정해주어야 한다.
인바운드로 프라이빗 서브넷 ip와 postgres 포트 5432를 뚫어주고 아웃바운드로 0.0.0.0/0을 설정해준다.
#was - postgres 포트 보안 그룹 생성
resource "aws_security_group" "was-db"{
name = "allow_postgres_from_was"
vpc_id = aws_vpc.default.id
description = "Allow postgres port from was"
ingress{
from_port = 5432
to_port = 5432
protocol = "tcp"
cidr_blocks = ["10.0.3.0/24","10.0.4.0/24"]
}
egress{
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
이 후 RDS설정을 해준다. RDS에는 설정할 수 있는 것이 굉장히 많은데 Terraform 공식문서에서 살펴보고 필요한 것만 선별하여 설정하면 된다.(나머지는 default로 자동 생성)
여기서도 주의해야 할 사항이 있다.
admin
을 사용할 수 없다.vpc_security_group_ids = ["${ }"]
형식을 사용해야 한다.접속 순서는 다음과 같다.
public ec2(web) > private ec2(was) > rds(postgresql db)
public ec2 접속
# sudo ssh -i "ec2_key_pair.pem" centos@ec2-3-36-53-190.ap-northeast-2.compute.amazonaws.com
sftp로 pem key 이동 (local > public ec2)
private was 접속
# ssh -i "ec2_key_pair.pem" {private was ip}
postgres rds 접속
# yum install -y postgres-server
local에서 rds endpoint 확인
# terraform console
> aws_db_instance.was-db.endpoint
나온 endpoint로 rds 접속
psql --host=terraform-20210604013021074800000002.cv3tugvyuy2b.ap-northeast-2.rds.amazonaws.com --port=5432
provider "aws" {
access_key = ""
secret_key = ""
region = "ap-northeast-2"
}
#키페어 사용
resource "aws_key_pair" "ec2_key_pair"{
key_name = "ec2_key_pair"
public_key = file("~/.ssh/ec2_key_pair.pub")
}
#aws new vpc
resource "aws_vpc" "default"{
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
instance_tenancy = "default"
tags = {
Name = "default"
}
}
#aws default 보안 그룹
data "aws_security_group" "default"{
name = "default"
depends_on = ["aws_vpc.default"]
}
#외부 - 22번 포트 보안 그룹 생성
resource "aws_security_group" "ssh"{
name = "allow_ssh_from_all"
description = "Allow SSH port from all"
vpc_id = aws_vpc.default.id
depends_on = ["aws_vpc.default"]
ingress{
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
#web용 public subnet 생성
resource "aws_subnet" "public1"{
vpc_id = aws_vpc.default.id
cidr_block = "10.0.1.0/24"
availability_zone = "ap-northeast-2a"
map_public_ip_on_launch = true
}
resource "aws_subnet" "public2"{
vpc_id = aws_vpc.default.id
cidr_block = "10.0.2.0/24"
availability_zone = "ap-northeast-2c"
map_public_ip_on_launch = true
}
#외부 접근을 위한 VPC IGW 생성
resource "aws_internet_gateway" "default-gw"{
vpc_id = aws_vpc.default.id
tags = {
Name = "default-gw"
}
}
#IGW, 외부 연결 라우팅 테이블 생성
resource "aws_route_table" "route-public-igw1"{
vpc_id = aws_vpc.default.id
route{
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.default-gw.id
}
tags = {
Name = "terra-public1"
}
}
#라우팅 테이블과subnet 연결
resource "aws_route_table_association" "route-public1"{
subnet_id = aws_subnet.public1.id
route_table_id = aws_route_table.route-public-igw1.id
}
resource "aws_route_table_association" "route-public2"{
subnet_id = aws_subnet.public2.id
route_table_id = aws_route_table.route-public-igw1.id
}
#ebs(web1, web2)생성
resource "aws_ebs_volume" "web1"{
availability_zone = "ap-northeast-2a"
size = 150
type = "st1"
tags = {
Name = "web1"
}
}
resource "aws_ebs_volume" "web2"{
availability_zone = "ap-northeast-2c"
size = 150
type = "st1"
tags = {
Name = "web2"
}
}
#ec2(web1, web2)생성
resource "aws_instance" "web1"{
ami = "ami-0e4214f08b51e23cc"
instance_type = "t3.large"
subnet_id = aws_subnet.public1.id
key_name = aws_key_pair.ec2_key_pair.key_name
vpc_security_group_ids = [
aws_security_group.ssh.id,
data.aws_security_group.default.id
]
tags = {
Name = "web1"
}
}
resource "aws_instance" "web2"{
ami = "ami-0e4214f08b51e23cc"
instance_type = "t3.large"
subnet_id = aws_subnet.public2.id
key_name = aws_key_pair.ec2_key_pair.key_name
vpc_security_group_ids = [
aws_security_group.ssh.id,
data.aws_security_group.default.id
]
tags = {
Name = "web2"
}
}
#ebs ec2(web1,web2) 연결
resource "aws_volume_attachment" "web1ebs"{
device_name = "/dev/sdb"
volume_id = "${aws_ebs_volume.web1.id}"
instance_id = "${aws_instance.web1.id}"
depends_on = ["aws_instance.web1"]
}
resource "aws_volume_attachment" "web2ebs"{
device_name = "/dev/sdb"
volume_id = "${aws_ebs_volume.web2.id}"
instance_id = "${aws_instance.web2.id}"
depends_on = ["aws_instance.web2"]
}
#ebs(suse)생성
resource "aws_ebs_volume" "suse"{
availability_zone = "ap-northeast-2a"
size = 1000
type = "st1"
tags = {
Name = "suse"
}
}
#suse linux ec2생성
resource "aws_instance" "suse"{
ami = "ami-097fc5cd098dd20d5"
instance_type = "t2.micro"
subnet_id = aws_subnet.public1.id
key_name = aws_key_pair.ec2_key_pair.key_name
vpc_security_group_ids = [
aws_security_group.ssh.id,
data.aws_security_group.default.id
]
tags = {
Name = "suse"
}
}
#ebs ec2(suse) 연결
resource "aws_volume_attachment" "suseebs"{
device_name = "/dev/sdb"
volume_id = "${aws_ebs_volume.suse.id}"
instance_id = "${aws_instance.suse.id}"
depends_on = ["aws_instance.suse"]
}
#was용private subnet 생성
resource "aws_subnet" "private1"{
vpc_id = aws_vpc.default.id
cidr_block = "10.0.3.0/24"
availability_zone = "ap-northeast-2a"
}
resource "aws_subnet" "private2"{
vpc_id = aws_vpc.default.id
cidr_block = "10.0.4.0/24"
availability_zone = "ap-northeast-2c"
}
#NAT Gateway에 할당하기위한 탄력적 IP생성[eip]
resource "aws_eip" "nat"{
vpc = true
}
#public subnet과 연결을 위한 NAT Gateway 생성
resource "aws_nat_gateway" "natgw1"{
allocation_id = aws_eip.nat.id
subnet_id = aws_subnet.public1.id
tags = {
Name = "natgw1"
}
}
#NAT Gateway, 외부 연결 라우팅 테이블 생성
resource "aws_route_table" "route-private-nat1"{
vpc_id = aws_vpc.default.id
route{
cidr_block = "0.0.0.0/0"
gateway_id = aws_nat_gateway.natgw1.id
}
tags = {
Name = "route-private-nat1"
}
}
#라우팅 테이블과 private subnet 연결
resource "aws_route_table_association" "terra-private1-route"{
subnet_id = aws_subnet.private1.id
route_table_id = aws_route_table.route-private-nat1.id
}
resource "aws_route_table_association" "terra-private2-route"{
subnet_id = aws_subnet.private2.id
route_table_id = aws_route_table.route-private-nat1.id
}
#ebs(web1, web2)생성
resource "aws_ebs_volume" "was1"{
availability_zone = "ap-northeast-2a"
size = 150
type = "st1"
tags = {
Name = "was1"
}
}
resource "aws_ebs_volume" "was2"{
availability_zone = "ap-northeast-2c"
size = 150
type = "st1"
tags = {
Name = "was2"
}
}
#ec2(was1, was2)생성
resource "aws_instance" "was1"{
ami = "ami-0e4214f08b51e23cc"
instance_type = "t3.large"
subnet_id = aws_subnet.private1.id
key_name = aws_key_pair.ec2_key_pair.key_name
vpc_security_group_ids = [
data.aws_security_group.default.id
]
tags = {
Name = "was1"
}
}
resource "aws_instance" "was2"{
ami = "ami-0e4214f08b51e23cc"
instance_type = "t3.large"
subnet_id = aws_subnet.private2.id
key_name = aws_key_pair.ec2_key_pair.key_name
vpc_security_group_ids = [
data.aws_security_group.default.id
]
tags = {
Name = "was2"
}
}
#ebs ec2(was1,was2) 연결
resource "aws_volume_attachment" "was1ebs"{
device_name = "/dev/sdb"
volume_id = "${aws_ebs_volume.was1.id}"
instance_id = "${aws_instance.was1.id}"
depends_on = ["aws_instance.was1"]
}
resource "aws_volume_attachment" "was2ebs"{
device_name = "/dev/sdb"
volume_id = "${aws_ebs_volume.was2.id}"
instance_id = "${aws_instance.was2.id}"
depends_on = ["aws_instance.was2"]
}
#rds용 private subnet 생성
resource "aws_subnet" "private3"{
vpc_id = aws_vpc.default.id
cidr_block = "10.0.5.0/24"
availability_zone = "ap-northeast-2a"
}
resource "aws_subnet" "private4"{
vpc_id = aws_vpc.default.id
cidr_block = "10.0.6.0/24"
availability_zone = "ap-northeast-2c"
}
#rds private subnet group 생성
resource "aws_db_subnet_group" "db_subnet_group"{
name = "db_subnet_group"
subnet_ids = [aws_subnet.private1.id,aws_subnet.private2.id]
tags = {
Name = "db_subnet_group"
}
}
#was - postgres 포트 보안 그룹 생성
resource "aws_security_group" "was-db"{
name = "allow_postgres_from_was"
vpc_id = aws_vpc.default.id
description = "Allow postgres port from was"
ingress{
from_port = 5432
to_port = 5432
protocol = "tcp"
cidr_blocks = ["10.0.3.0/24","10.0.4.0/24"]
}
egress{
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
#rds 생성
resource "aws_db_instance" "was1-db1"{
engine = "postgres"
engine_version = "13.2"
instance_class = "db.t3.large"
allocated_storage = 100
storage_type = "gp2"
username = "postgres"
password = "<DB_PASSWORD>"
skip_final_snapshot = true
vpc_security_group_ids = ["${aws_security_group.was-db.id}"]
db_subnet_group_name = aws_db_subnet_group.db_subnet_group.id
multi_az = true
}
resource "aws_db_instance" "was2-db2"{
engine = "postgres"
engine_version = "13.2"
instance_class = "db.t3.large"
allocated_storage = 100
storage_type = "gp2"
username = "postgres"
password = "<DB_PASSWORD>"
skip_final_snapshot = true
vpc_security_group_ids = ["${aws_security_group.was-db.id}"]
db_subnet_group_name = aws_db_subnet_group.db_subnet_group.id
multi_az = true
}