본문 바로가기
공부/IaC

[Terraform on AWS] 간단한 VPC 구성 & 웹서버용 EC2 생성하기

by haejang 2021. 3. 23.
728x90
728x90

 

테라폼으로 간단한 네트워크 구성을 해보겠다

 

 

생성할 것

  • VPC : 10.0.0.0/16
  • Subnet
    • Public : 10.0.1.0/24, igw와 연결
    • Private : 10.0.10.0/24, NAT gw와 연결
  • EC2
    • Public(WebServer용) : httpd 실행, 22/80 포트 오픈
    • Private(DB용) : WebServer에서의 22 포트 오픈 (DB 설치는 pass...)

 


1. init.tf

provider "aws" {
  region = "ap-northeast-2"
}

data "aws_availability_zones" "available" {
  state = "available"
}

기본 프로바이더와 가용 영역을 설정해주었다

프로바이더 구문에서 AWS ACCESS KEY와 SECRET KEY를 설정해도 된다

(난 내 컴퓨터에 시스템 변수로 설정해놔서 안해도 됨)

가용 영역은 사용 가능한 모든 영역을 사용한다

aws provider

data source : aws_availability_zones

 

2. vpc.tf

// vpc
resource "aws_vpc" "vpc" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true

  tags = {
    "Name" = "vpc"
  }
}

// internet gateway
resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.vpc.id

  tags = {
    Name = "IGW"
  }
}

// EIP for NAT gw
resource "aws_eip" "nat" {
  vpc = true
}

// NAT gateway
resource "aws_nat_gateway" "nat_gw" {
  allocation_id = aws_eip.nat.id
  subnet_id     = aws_subnet.public_subnet.id
}

resource : aws_vpc

  • cidr_block (필수) : VPC의 CIDR 블록
  • enable_dns_hostnames : 기본값이 false라 true로 해줬다
  • enable_dns_support : 기본값이 true라 건드리지 않았다

resource : aws_internet_gateway

  • vpc_id (필수) : 연결될 VPC ID

resource : aws_eip

  • vpc : EIP를 VPC 안에 존재시킬건지 여부
  • instancenetwork_interface 를 사용하면 직접 EIP를 어딘가에 붙일 수 있다

resource : aws_nat_gateway

  • allocation_id (필수) : 할당받은 EIP ID
  • subnet_id (필수) : 존재시킬 서브넷 ID - NAT gateway는 무조건 퍼블릭 서브넷에 있어야 한다 (코드 안의 퍼블릭 서브넷 리소스는 뒤에 나올 예정

 

3. public_subnet.tf

// public subnet
resource "aws_subnet" "public_subnet" {
  vpc_id                  = aws_vpc.vpc.id
  cidr_block              = "10.0.1.0/24"
  availability_zone       = data.aws_availability_zones.available.names[0]
  map_public_ip_on_launch = true

  tags = {
    Name = "Public Subnet"
  }
}

// public route table
resource "aws_route_table" "public_rtb" {
  vpc_id = aws_vpc.vpc.id

  tags = {
    Name = "Public rtb"
  }
}

resource "aws_route" "public_rtb" {
  route_table_id         = aws_route_table.public_rtb.id
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = aws_internet_gateway.igw.id
}

resource "aws_route_table_association" "public_rtb" {
  subnet_id      = aws_subnet.public_subnet.id
  route_table_id = aws_route_table.public_rtb.id
}

resoucce : aws_subnet

  • vpc_id (필수) : VPC ID
  • cidr_block (필수) : 사용할 사설 IP 대역
  • availability_zone : 가용 영역 - init.tf에서 정의한 aws_availability_zones 데이터 available의 첫번째 값을 가져오겠다(a)
  • map_public_ip_on_launch : 이 서브넷에서 시작하는 인스턴스들이 public ip를 가질지 아닐지 여부 -> Public Subnet이니까 true로 해줬다 (기본값은 false)

resource : aws_route_table

  • vpc_id (필수) : VPC ID
  • route 인수를 사용하면 여기서 직접 라우팅 설정 가능

resource : aws_route

  • route_table_id (필수) : 라우팅 설정할 route table 지정
  • destination_cidr_block (필수) : 목적지 CIDR 블록 - IPv6을 쓰면 destination_ipv6_cidr_block 사용
  • internet gateway를 붙일거라 gateway_id 를 사용했다 - 불일 리소스에 따라 인수 이름 달라짐

resource : aws_table_association

  • route table에 subnet(또는 gateway) 붙이는거임
  • route_table_id필수, subnet_idgateway_id 는 둘 중 하나만 필수

 

4. private_subnet.tf

// private subnets
resource "aws_subnet" "private_subnet" {
  vpc_id            = aws_vpc.vpc.id
  cidr_block        = "10.0.10.0/24"
  availability_zone = data.aws_availability_zones.available.names[0]
  tags = {
    Name = "Private Subnet"
  }
}

// private route table
resource "aws_route_table" "private_rtb" {
  vpc_id = aws_vpc.vpc.id

  tags = {
    Name = "Private rtb"
  }
}

resource "aws_route" "private_rtb" {
  route_table_id         = aws_route_table.private_rtb.id
  destination_cidr_block = "0.0.0.0/0"
  nat_gateway_id         = aws_nat_gateway.nat_gw.id
}

resource "aws_route_table_association" "private_rtb" {
  subnet_id      = aws_subnet.private_subnet.id
  route_table_id = aws_route_table.private_rtb.id
}

Public Subnet 설정할 때와 똑같다

다른점이 하나 있다면 route table에 internet gateway 대신 NAT gateway를 붙였다

 

5. webserver_ec2.tf

resource "aws_instance" "webserver" {
  ami                    = "ami-081511b9e3af53902"
  instance_type          = "t3.micro"
  key_name               = "seoul"
  subnet_id              = aws_subnet.public_subnet.id
  vpc_security_group_ids = ["${aws_security_group.webserversg.id}"]
  user_data              = <<-EOF
                           #!/bin/bash
                           sudo yum install -y httpd
                           echo "Honglab WebServer" > /var/www/html/index.html
                           sudo systemctl start httpd
                           sudo systemctl enable httpd
                           EOF

  tags = {
    Name = "webserver"
  }

  depends_on = ["aws_internet_gateway.igw"]
}

resource "aws_security_group" "webserversg" {
  name        = "webserversg"
  description = "allow 22, 80"
  vpc_id      = aws_vpc.vpc.id
}

resource "aws_security_group_rule" "websg_ssh" {
  type              = "ingress"
  from_port         = 22
  to_port           = 22
  protocol          = "tcp"
  cidr_blocks       = ["0.0.0.0/0"]
  security_group_id = aws_security_group.webserversg.id
  description       = "ssh"
}

resource "aws_security_group_rule" "websg_http" {
  type              = "ingress"
  from_port         = 80
  to_port           = 80
  protocol          = "tcp"
  cidr_blocks       = ["0.0.0.0/0"]
  security_group_id = aws_security_group.webserversg.id
  description       = "http"
}

resource "aws_security_group_rule" "websg_outbound" {
  type              = "egress"
  from_port         = 0
  to_port           = 0
  protocol          = "-1"
  cidr_blocks       = ["0.0.0.0/0"]
  security_group_id = aws_security_group.webserversg.id
  description       = "outbound"
}

resource : aws_instance

  • ami (필수) : EC2의 ami
  • instance_type (필수) : EC2의 타입
  • key_name : 해당 계정, 리전에 존재하는 key 이름을 적으면 된다 - 테라폼으로 만들려고 하면 public key밖에 안만들어지기 때문에 이것저것 할게 많아서 골치아프니 AWS에서 만든 후 사용하자
  • vpc_security_group_ids : 연결할 보안그룹 리스트 - default vpc면 security_groups 를 사용해도 되는듯하다
  • user_data : EC2에 넣을 user data이다. 테라폼의 히어닥 문법(EOF)를 사용했다
  • depends_on은 aws_instance의 인수는 아니지만 igw를 먼저 생성한 후에 생성하라는 뜻으로 넣어놓았다. 안써도 된다

resource : aws_security_group

  • name, description, vpc_id 모두 새로 생성하는 경우엔 필수
  • ingress, egress 인자를 사용해 바로 룰을 만들 수 있다

resource : aws_security_group_rule

  • type (필수) : ingress(인바운드) 인지 egress(아웃바운드)인지 정해줘야 한다
  • from_port, to_port (필수) : 포트 번호 지정 - 모두 열고 싶을 땐 0 사용
  • protocol (필수) : 프로토콜 지정 - 모두 열고 싶을 땐 -1 사용
  • cidr_blocks 또는 source_security_group_id (필수) : 허용할 소스를 지정해준다
  • security_group_id (필수) : 룰을 연결할 보안 그룹 ID

 

6. db_ec2.tf

resource "aws_instance" "db" {
  ami                    = "ami-081511b9e3af53902"
  instance_type          = "t3.micro"
  key_name               = "seoul"
  subnet_id              = aws_subnet.private_subnet.id
  vpc_security_group_ids = ["${aws_security_group.dbsg.id}"]

  tags = {
    Name = "DB"
  }
}

resource "aws_security_group" "dbsg" {
  name        = "dbsg"
  description = "allow 22 from web"
  vpc_id      = aws_vpc.vpc.id
}

resource "aws_security_group_rule" "dbssh" {
  type                     = "ingress"
  from_port                = 22
  to_port                  = 22
  protocol                 = "tcp"
  source_security_group_id = aws_security_group.webserversg.id
  security_group_id        = aws_security_group.dbsg.id
  description              = "ssh"
}

resource "aws_security_group_rule" "dboutbound" {
  type              = "egress"
  from_port         = 0
  to_port           = 0
  protocol          = "-1"
  cidr_blocks       = ["0.0.0.0/0"]
  security_group_id = aws_security_group.dbsg.id
  description       = "outbound"
}

webserver ec2에서만 22 포트를 허용하게 해줬다

 


코드 작성이 끝났으니 terraform init > plan > apply를 실행해보자

 

 

VPC의 리소스들과 EC2가 잘 만들어진걸 확인할 수 있다

 

웹으로 webserver EC2에 접속해보자

 

원하는 대로 웹이 떴다

 

SSH로 webserver EC2에 접속해보면

 

 

DB 서버로도 접속되는걸 확인했다

 

DB 서버라곤 하지만 DB랑 연동하는건 귀찮아서 안했다

 

다음엔 오늘 만든 것들을 모듈화 해 볼 예정이다

 

728x90
728x90

댓글