Dev./Terraform

Terraform: AWS 서버구축

Ivan'show 2023. 9. 8.
728x90
반응형

Using Terraform for AWS

NCP 로 staging 과 productions 을 구축하고 써봤다. 이제 AWS 에서 staging 환경까지 구축해보자. 사실 클라우드 서비스를 제공하는 회사에 따라 적용해야될 부분이 크게 다르지 않기 때문에 어렵지않게 적용시킬 수 있다. 단지 어떻게 공식문서를 확인해가면서 필요한 부분들을 찾아가는지 고민해야하는 부분이다.

netwrok → db server → be server → loadbalancer 순서로 구현해보자.

Modules

구조나 필요한 리소스는 NCP 와 다를게 없다. 공식문서를 잘 확인해서 필요한 부분들을 구현하자.

network

variables.tf

# staing 에서 network 모듈로 전달하는 변수들 정리
env
region

main.tf

# provider
<https://registry.terraform.io/providers/hashicorp/aws/latest/docs>

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

# Configure the AWS Provider
provider "aws" {
  region = var.region
}
# aws_vpc
<https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc>

resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"

  tags = {
    Name = "main-${var.env}"
  }
}
# aws_subnet
<https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet>

resource "aws_subnet" "main" {
  vpc_id     = aws_vpc.main.id
  cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 8, 1)
  map_public_ip_on_launch = true
  availability_zone = "ap-northeast-2a"

  tags = {
    Name = "Main"
    Env = var.env
  }
}
# aws_internet_gateway
<https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/internet_gateway>
# aws 는 ncp 와 다르게 vpc 와 subnet 설정만으로 인터넷연결이 되지 않는다. 게이트웨이 설정을 통해 인터넷 연결을 진행할 수 있다.
# 또한, ingress, egress 구성이 inbound 와 outbound 구성인데 egress 를 설정하지 않는다면 밖으로 내보내는 요청을 허가하지 않기 때문에 인터넷 연결이 불가능하니 꼭 설정해 둘 것

resource "aws_internet_gateway" "gw" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "main-${var.env}"
  }
}
# aws_route_table
<https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route>
# subnet 내의 instance 가 트래픽을 전달할 때 목적지 IP 주소에 따라 어떤 경로를 따라야 하는지 결정한다.

resource "aws_route_table" "main" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "main-${var.env}"
  }
}
# aws_rotue
<https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route>
# 라우팅 설정으로 aws_route_table 과 aws_internet_gateway 설정을 해준다. vpc 내의 라우트 테이블에 대한 라우팅 규칙을 생성하고 관리한다.

resource "aws_route" "main" {
  route_table_id = aws_route_table.main.id
  destination_cidr_block = "0.0.0.0/0"
  gateway_id = aws_internet_gateway.gw.id
  depends_on = [ aws_route_table.main ]
}

# aws_route_table_association
<https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table_association>
# subnet 설정을 담고 있다.

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

output.tf

# network 에서 나온 정보로 staging 에서 가져다 쓸 정보들
vpc_id
subnet_main_id

server

variables.tf

# server, 인스턴스 생성하는 과정에서 필요한 변수들
region
env
name
vpc_id
subnet_main_id
port_range
init_script_path
init_script_vars

main.tf

# provider

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

# Configure the AWS Provider
provider "aws" {
  region = var.region
}
# vpc 와 subnet 정보는 data 를 사용하여 가져온다.
data "aws_vpc" "main" {
  id = var.vpc_id
}

data "aws_subnet" "main" {
  id = var.subnet_main_id
}
# aws_instance, data aws_ami
<https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance>
# Ubuntu AMI 를 가져오기 위한 데이터 소스 = 이미지 파일

data "aws_ami" "ubuntu" {
  most_recent = true
  owners = ["099720109477"] # Canonical

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
}
# owners 는 canonical 의 공식 AWS 계정 ID로 해당 계정에서 제공하는 Ubuntu AMI 를 가져오게 된다.

resource "aws_instance" "main" {
  ami           = data.aws_ami.ubuntu.id
  instance_type = "t2.micro"
  subnet_id = var.subnet_main_id
  vpc_security_group_ids = [
    aws_security_group.main.id
  ]
  
  user_data = templatefile("${path.module}/${var.init_script_path}", var.init_script_vars)
  associate_public_ip_address = true
  user_data_replace_on_change = true
  
  tags = {
    Name = "${var.name}-server-${var.env}"
  }
}
# instance type 으로 프리티어가 가능한 t2.micro 를 가져오며, subnet_id 를 전달받고 vpc_security_group 으로 NCP 의 ACG 설정을 대신한다.
# user_data 로 init_script 를 만들고 진행하게 된다.

# associate_public_ip_address 로 public ip 자동 할당 설정
# user_data_replace_on_change 를 user_data 와 사용하면서 사용자 데이터가 변경될 때마다 데체 하게끔 true
# security group: access control group
<https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group>

resource "aws_security_group" "main" {
  name        = "lion-${var.name}-${var.env}"
  description = "Allow SSH, ${var.port_range} inbound traffic"
  vpc_id      = data.aws_vpc.main.id

  # inbound
  ingress {
    description      = "${var.port_range} from VPC"
    from_port        = var.port_range
    to_port          = var.port_range
    protocol         = "tcp"
    cidr_blocks      = ["0.0.0.0/0"]
  }
  
  # inbound
  ingress {
    description      = "SSH"
    from_port        = 22
    to_port          = 22
    protocol         = "tcp"
    cidr_blocks      = ["0.0.0.0/0"]
  }

  # outbound
  egress {
    from_port        = 0
    to_port          = 0
    protocol         = "-1"
    cidr_blocks      = ["0.0.0.0/0"]
    ipv6_cidr_blocks = ["::/0"]
  }

  tags = {
    Name = "allow_ssh_${var.name}_${var.env}"
  }
}
# SSH 접속을 위한 inbound 설정과 인스턴스의 성격에 맞는 port_range 를 설정해준다.

outputs.tf

# 생성한 인스턴스의 id 를 loadbalancer 에서 가져다 쓰고 public_ip 의 경우 제너럴하게 사용되나 출력
public_ip
instance_id

Staging: DB

terraform.tfvars (hidden file)

# staging 환경의 인프라를 구축하는데 사용할 숨겨진 변수

# cloud
region="ap-northeast-2"

# init script
username=""
password=""

# postgres DB
db = ""
db_user = ""
db_password = ""
db_port = ""

variables.tf

# 사실상 terraform.tfvars 에 선언한 내용 가져오기
region
username
password
db
db_user
db_password
db_port

main.tf

# provider
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

# Configure the AWS Provider
provider "aws" {
  region = var.region
}
# locals
locals {
  env = "staging"
  db_port = "5432"
  be_port = "8000"
}
# network module
module "network" {
  source = "../modules/network"

  env = local.env
  region = var.region
}
module "db" {
  source = "../modules/server"

  env  = local.env
  name = "db"
  region = var.region

  vpc_id = module.network.vpc_id
  subnet_main_id = module.network.subnet_main_id
  port_range = local.db_port

  init_script_path = "db_init_script.tftpl"
  init_script_vars = {
    username = var.username
    password = var.password
    db = "lionforum"
    db_port = local.db_port
    db_user = var.db_user
    db_password = var.db_password
  }
}

outputs.tf

# db 관련 정보 출력

output "db_public_ip" {
  value = module.db.public_ip
}

output "db_instance_id" {
  value = module.db.instance_id
}

result

 

728x90
반응형

'Dev. > Terraform' 카테고리의 다른 글

Terraform: AWS 서버구축2  (0) 2023.09.10
Terraform: AWS ssh connection  (0) 2023.09.09
Terraform: Status 가 꼬이는 현상  (0) 2023.09.07
Terraform: Separating  (0) 2023.09.06
Terraform: Modules  (0) 2023.09.05

댓글