본문 바로가기
[AWS]/AWS 기타

[AWS] Terraform 사용해서 VPC 구성하기

by METAVERSE STORY 2022. 8. 30.
반응형
728x170

 

 

IaC란 무엇인가?

IaC는 코드형 인프라스트럭처(Infrastructure as code)의 약어로 물리적 하드웨어 구성이나 인터페이스 구성 도구가 아닌 기계가 읽을 수 있는 정의 파일들을 통한 컴퓨터 데이터 센터의 관리 및 프로비저닝 과정이다. 

 

 

IaC 종류

Iac에는 이러한 툴들이 존재한다. 

  • Chef
  • Puppet
  • Ansible
  • AWS Cloudformation
  • Terraform

 

 

Terraform이란 무엇인가?

테라폼(Terraform)은 HashiCorp가 개발한 오픈 소스 코드형 인프라스트럭처(Infrastructure as Code, IaC)이다. 사용자는 HCL(HashiCorp Configuration Language)이라는 선언형 구성 언어나 선택적으로 JSON을 사용하여 데이터 센터 인프라스트럭처를 정의하고 제공한다.

 

 

 

1. IAM 사용자 만들기 및 CLI 등록하기

Terraform을 이용하기 위해서는 AWS CLI 명령어를 사용해야 한다. 그러기 위해서는 액세스키와 시크릿 액세스 키가 있는 사용자가 필요하다. 

 

[AWS] AWS CLI 구성하기 (tistory.com)

 

[AWS] AWS CLI 구성하기

오늘은 AWS 서비스를 Command Line Interface로 구동하는 AWS CLI에 대해서 포스팅을 하도록 하겠다. 우선 AWS Command Line으로 검색하면 AWS 사이트가 확인된다. 해당 사이트로 접속을해서 왼쪽 메뉴중에 Insta

cloud-allstudy.tistory.com

AWS CLI 구성하는 방법에 대해서는 위 글을 읽은 후 따라하면 된다. 

 

 

 

 

2.  테라폼 설치하기

 

https://www.terraform.io/downloads

 

Downloads | Terraform by HashiCorp

Terraform is an open-source infrastructure as code software tool that enables you to safely and predictably create, change, and improve infrastructure.

www.terraform.io

먼저 테라폼을 다운로드 해야 한다. 

위 사이트로 들어간 이후 386 버전을 다운로드 해 준다. 

 

 

그 이후 다운로드 한 압축파일을 풀어준 이후 terraform.exe을 C드라이브에 옮겨준다. 

 

 

 

윈도우 키를 누른 후 시스템 환경 변수 편집을 클릭한다.

그 이후 환경 변수를 클릭한다. 

 

 

그 다음 시스템 변수에서 Path를 클릭한 이후 편집을 클릭한다. 

 

 

 

그 후 새로 만들기를 클릭해서 terraform.exe가 위치한 폴더를 지정해주면 된다. 

 

 

 

 

 

지정한 이후 CMD와 VSCODE Powershell 터미널에서 모두 Terraform의 버전이 뜨는 모습을 확인할 수 있다.

이는 테라폼이 잘 깔렸다는 뜻이다.

 

 

 

3. provider.tf 작성하기

 

나는 VSCode를 사용해서 파일을 만들어 주었다.

terraform은 .tf 파일로 정의한다. 

apply를 하면 해당 디렉토리의 tf 파일을 읽어서 적용한다. 

먼저 provider를 aws로 지정한 후 자신이 사용할 지역 및 IAM 유저 생성 당시 만들었던 accesskey와 secret_accesskey를 입력해 준다. 

물론 코드 안에 입력해 주어도 되지만 보안상 권장되지 않으므로 따로 환경변수로 빼서 사용하는 것을 권장한다. 

 

 

 

환경 변수를 사용하여 AWS CLI 구성 - AWS Command Line Interface (amazon.com)

환경변수를 설정하는 방법은 위 아마존 공식 사이트에 나와있다. 

자신의 OS에 맞는 방법으로 AccessKey와 SecretAccessKey를 환경변수로 설정하자. 

 

 

 

그 후 terraform init이라고 입력해준다. 

이 명령어는 Terraform 구성 파일이 들어있는 작업 디렉토리를 초기화하는 데 사용됩니다. 새 Terraform 구성을 작성하거나 기존 버전 구성을 버전 제어에서 복제 한 후에 실행해야하는 첫 번째 명령입니다. 이 명령을 여러 번 실행하는 것이 안전합니다.

 

 

 

4.  vpc.tf 작성하기

 

AWS 계정을 생성하면 Default VPC와 서브넷 등이 존재한다. 그러나 서비스를 구현할 때는 Default를 사용하지 않고 주로 VPC 부터 서브넷, 라우팅테이블, IGW 등 모든 구성을 직접 생성한다. 

그러한 구성들을 vpc.tf 파일을 통해서 코드로 작성한 후 생성 시키는 것이 목표이다. 

 

 

## VPC 생성

먼저 VPC에 대한 이름 및 IP 대역과 tags를 달아준다. 

resource "aws_vpc" "VPC 이름 지정" {
    cidr_block = "자신이 할당할 IP 대역"

    tags = {
        Name = "VPC 이름 지정"
    }
}

 

 

## 서브넷 생성

두번째로 자신이 사용할 서브넷을 작성해 준다. 

서브넷에는 VPC의 아이디와 IP 대역 그리고 서브넷을 생성할 AZ에 대한 정보를 입력해야 한다. 

나는 이런식으로 PUBLIC 서브넷 2개, PRIVATE 서브넷 2개 총 4개의 서브넷을 생성 해 주었다. 

resource "aws_subnet" "서브넷 이름" {
    vpc_id = aws_vpc.위에서 설정한 VPC 이름.id
    cidr_block = "내가 할당할 IP대역 선택"

    availability_zone = "할당할 가용영역 선택"

    tags = {
        Name = "서브넷 이름태그 작성"
}

 

 

 

## NACL 생성

그 다음 Network ACL을 생성해 주었다. 나는 Nacl에서는 인바운드, 아웃바운드 모두 허용해 줄 생각이므로 인바운드와 아웃바운드 모두 허용하는 형태로 코드를 작성하였다. 여기서 -1은 "allow"와 같은 의미를 지닌다. 

resource "aws_network_acl" "nacl 이름"{
    vpc_id = aws_vpc.terraform_vpc.id

    egress {
        protocol = 프로토콜 설정(ex: tcp udp)
        rule_no = 규칙 우선순위
        action = 허용 혹은 거부
        cidr_block = 허용하거나 거부할 IP
        from_port = (선택 사항) 일치시킬 시작 포트입니다.
        to_port =  (선택 사항) 일치시킬 포트입니다.
    }

    ingress {
        protocol = 프로토콜 설정(ex: tcp udp)
        rule_no = 규칙 우선 순위
        action = 허용 혹은 거부
        cidr_block = 허용하거나 거부할 IP
        from_port = (선택 사항) 일치시킬 시작 포트입니다.
        to_port =  (선택 사항) 일치시킬 포트입니다.
    }

    tags {
        Name = "nacl 이름"
    }
}

 

 

 

## NACL 서브넷과 연결

Network ACL을 생성한 후 서브넷과 연결시켜 줘야 한다.

https://github.com/hashicorp/terraform/issues/1717

위 문서를 보고 한가지 문제점을 찾아냈다.

AWS 콘솔에서는 한 NACL에 여러 서브넷을 연결하는 것이 가능하지만 내가 현재까지 찾아본 결과 Terraform에서는 아직 그 기능을 지원하지 않는다. Terraform을 이용해서 하려면 서브넷 개수만큼 Nacl을 만들어 줘야 한다. 

나는 하나만 우선 하나 연결을 한 후 콘솔로 들어가서 마지막에 수정해 주겠다. 

 

resource "aws_network_acl_association" "이름 작성"{
    network_acl_id = aws_network_acl.nacl 이름.id
    subnet_id = aws_subnet.연결하려는 서브넷 이름.id

}

 

 

 

## 인터넷 게이트웨이 생성

그 다음 퍼블릭 라우팅 테이블에 연결할 인터넷게이트웨이를 생성해 주었다. 

resource "aws_internet_gateway" "IGW 이름"{
    vpc_id = aws_vpc.VPC 이름.id

    tags = {
        Name = "IGW 이름"
    }
}

 

 

 

## 라우팅테이블 생성

그 다음 라우팅 테이블을 생성해 주었다. 라우팅 테이블은 서브넷과 연결한다.

위에서 보는것처럼 public 라우팅 테이블에는 igw을 연결해 주고 private 라우팅 테이블에는 연결을 하지 않는다. 이런 식으로 Public 라우팅 테이블 2개, Private 라우팅 테이블 2개를 생성 해 주었다. 

resource "aws_route_table" "라우팅테이블 이름"{
    vpc_id = aws_vpc.vpc 이름.id

    route{
        cidr_block = "0.0.0.0/0"
        gateway_id = aws_internet_gateway.인터넷게이트웨이 이름.id
    }

    tags = {
        Name = "라우팅테이블 이름"
    }
}

resource "aws_route_table" "라우팅테이블 이름"{
    vpc_id = aws_vpc.vpc 이름.id

    tags = {
        Name = "라우팅테이블 이름"
    }
}

 

 

 

## NAT Gateway 생성

그 다음은 Nat Gateway를 생성해 주었다. Nat Gateway는 Private Subnet에서 외부로 연결하기 위해서 사용하는 것이다. 또한 NatGateway를 사용하려면 EIP가 필요하므로 먼저 EIP를 만들어 준 후 NatGateway와 연결해 주었다.

여기서 subnet 아이디를 Private 서브넷이 아닌 Public 서브넷과 연결해줘야 Private 서브넷 안에 위치한 인스턴스들이 인터넷과 연결이 가능하다.

resource "aws_eip" "eip 이름"{
    vpc = true

    lifecycle{
        create_before_destroy = true
    }
}

resource "aws_nat_gateway" "natgateway 이름"{
    allocation_id = aws_eip.eip 이름.id

    subnet_id = aws_subnet.연결할 서브넷 이름.id

    tags = {
        Name = "natgateway 이름"
    }

    depends_on = [aws_internet_gateway.연결할 igw 이름]
}

resource "aws_eip" "eip 이름"{
    vpc = true

    lifecycle{
        create_before_destroy = true
    }
}

resource "aws_nat_gateway" "natgateway 이름"{
    allocation_id = aws_eip.eip 이름.id

    subnet_id = aws_subnet.연결할 서브넷 이름.id

    tags = {
        Name = "natgateway 이름"
    }
    depends_on = [aws_internet_gateway.연결할 igw 이름]
}

 

 

## 라우팅테이블 연결

마지막으로는 라우팅 테이블을 각각 서브넷과 연결해 주는 작업을 했다. 

마지막 두 줄은 Nat Gateway와 라우팅 테이블을 연결해 주는 코드이다. 

 

resource "aws_route_table_association" "table_asso 이름 작성"{
    subnet_id = aws_subnet.연결할 서브넷 이름.id
    route_table_id = aws_route_table.연결할 라우팅테이블 이름.id
}

resource "aws_route_table_association" "table_asso 이름 작성"{
    subnet_id = aws_subnet.연결할 서브넷 이름.id
    route_table_id = aws_route_table.연결할 라우팅테이블 이름.id
}

resource "aws_route_table_association" "table_asso 이름 작성"{
    subnet_id = aws_subnet.연결할 서브넷 이름.id
    route_table_id = aws_route_table.연결할 라우팅테이블 이름.id
}

resource "aws_route_table_association" "table_asso 이름 작성"{
    subnet_id = aws_subnet.연결할 서브넷 이름.id
    route_table_id = aws_route_table.연결할 라우팅테이블 이름.id
}

resource "aws_route" "nat_asso 이름 작성"{
    route_table_id = aws_route_table.연결할 라우팅테이블 이름.id
    destination_cidr_block = "0.0.0.0/0"
    nat_gateway_id = aws_nat_gateway.연결할 natgateway 이름.id
}

resource "aws_route" "nat_asso 이름 작성"{
    route_table_id = aws_route_table.연결할 라우팅테이블 이름.id
    destination_cidr_block = "0.0.0.0/0"
    nat_gateway_id = aws_nat_gateway.연결할 natgateway 이름.id
}

 

 

 

 

 

5. 적용하기

 

작성을 완료한 후 terraform plan을 입력한다.

만약 코드가 잘못된 부분이 있다면 오류를 찝어 줄 것이다.

그게 아니라면 

아래와 같은 명령어가 나온다. 

 

 

 

그 후 terraform apply를 입력한다. 

 

 

그럼 중간에 이 행동을 허용할 것인지에 대해 묻는다.

yes라고 입력한 후 엔터를 눌러준다. 

 

 

6. 결과 확인

 

# VPC

 

# 서브넷

 

# 라우팅테이블

 

# IGW

 

# Nat Gateway용 EIP

 

# Nat Gateway

 

#Network ACL

 

# Network ACL Inbound, Outbound 

 

 

다음에는 테라폼으로 Ec2와 RDS를 생성하는 단계를 진행 해 볼 것이다. 

 

 

 

 

참조 문서

https://runebook.dev/ko/docs/terraform/-index-#VPC%20Resources

 

Terraform 0.11 한국어

 

runebook.dev

https://terraform101.inflearn.devopsart.dev/cont/vpc-practice/vpc-practice-with-nat/

 

Private Subnet 및 NAT 구성 :: Terraform & AWS 101

Private Subnet 및 NAT 구성 본 페이지에서 생성하는 리소스 중 Nat Gateway는 비용이 많이 발생하는 서비스입니다. 잠깐 생성하고 지우면 문제되지 않지만, 시간단위로 과금되기 때문에 실습이 끝나시

terraform101.inflearn.devopsart.dev

https://dev.classmethod.jp/articles/build-multiple-services-with-terraform-03/

 

테라폼으로 AWS 서비스 구축하기 2장. EC2 RDS S3 구축하기 – 1 | DevelopersIO

테라폼으로 EC2 RDS S3의 구성을 구현해봅시다

dev.classmethod.jp

https://registry.terraform.io/providers/hashicorp/aws/latest/docs

 

Terraform Registry

 

registry.terraform.io

 

반응형
그리드형

댓글