Terraform 기본

KH55S·2025년 12월 1일
  • 데브옵스는 소프트웨어의 개발(Development)과 운영(Operations)의 합성어로, 현재의 데브옵스는 단순히 개발과 운영의 통합을 의미하는 것은 아니다.
    • 즉, 데브옵스란 어떤 요구사항을 효율적으로 만족시키기 위해 일을 자동화하며 변경사항 지표들을 측정하고, 공유하고, 이 모든 결과물들을 지속적으로 축적해 나아가는 문화를 만들어가는 방법론이자 기술을 의미한다.
  • DevOps 엔지니어 : 올바른 DevOps 문화를 위해 서비스 혹은 S/W LifeCycle 에서 반복적인 일들을 자동화하고, 기술적 문제 혹은 팀의 차이를 기술적으로 예방하고, 해소시키는 사람
    • 문화(Culture) - 사람, 서비스, S/W 라이프 싸이클
    • 자동화(Automation) - 프로그래밍, 자동화 툴, 네트워크 등
    • 측정(Measurement) - 테스트 및 데이터를 통한 추론
    • 공유(Sharing) - 어떤 문제를 최단 시간의 해결하는 방법.
    • 축적(File up and Pile up) - 재반복할 수 있는 이 문제에서 정확하게 회고하고, 축적해 나가는 것.
  • DevOps 로드맵 : https://roadmap.sh/devops

IaC (Infrastructure as Code, 코드로써의 인프라)

  • 인프라를 이루는 서버, 미들웨어, 서비스 등 인프라 구성요소들을 코드를 통해 구축하는 것. IaC는 코드로써의 장점, 작성용이성, 재사용성, 유지보수 등의 장점을 가진다

Terrafrom

  • 간단 설명 : 인프라를 만들고, 변경하고, 기록하는 IaC를 위해 만들어진 도구로써, 문법이 쉬워 비교적 다뤽 쉽고 사용자가 매우 많아 참고할 수 있는 예제가 많다. .tf 라는 파일 형식을 가진다. AWs, GCP, Azue 같은 퍼블릭 클라우드뿐만이 아니라 다양한 서비스들 역시 지원한다.
  • 구성요소
    • provider : 테라폼으로 생성할 인프라의 종류
    • resource : 테라폼으로 실제로 생성할 인프라 자원
    • state : 테라폼을 통해 생성한 자원의 상태
    • output : 테라폼으로 만든 자원을 변수 형태로 state에 저장하는 것
    • module : 공통적으로 활용할 수 있는 코드를 문자 그대로 모듈 형태로 정의하는 것
    • remote : 다른 경로의 state를 참조하는 것. output 변수를 불러올 때 주로 사용한다.
  • 테라폼 작동 원리
    • 테라폼에는 3가지의 형상이 존재한다.
      • Local 코드 : 현재 개발자가 작성/수정하고 있는 코드
      • AWS 실제 인프라 : 실제로 AWS에 배포되어 있는 인프라
      • Backend에 저장된 상태 : 가장 최근에 배포한 테라폼 코드 형
    • AWS 실제 인프라와 Backend에 저장된 상태가 100% 일치하도록 만드는 것이 중요하다.
  • Terraform init
    • 지정한 backend에 상태 저장을 위한 .tfstate 파일을 생성한다. 여기에는 가장 마지막에 적용한 테라폼 내역이 저장된다.
    • init 작업을 완료하면, local에는 .tfstate에 정의된 내용을 담은 .terraform 파일이 생성된다.
    • 기존에 다른 개발자가 이미 .tfstate에 인프라를 정의해 놓은 것이 있다면, 다른 개발자는 init작업을 통해서 local에 sync를 맞출 수 있다.
  • Terraform plan
    • 정의한 코드가 어떤 인프라를 만들게 되는지 미리 예측 결과를 보여준다. 단, plan을 한 내용에 에러가 없다고 하더라도, 실제 적용되었을 때는 에러가 발생할 수 있다.
    • Plan 명령어는 어떠한 형상에도 변화를 주지 않는다.
  • Terraform apply
    • 실제로 인프라를 배포하기 위한 명령어. apply를 완료하면, AWS 상에 실제로 해당 인프라가 생성되고 작업 결과가 backend의 .tfstate 파일에 저장된다.
    • 해당 결과는 local의 .terraform 파일에도 저장된다.
  • Terraform import
    • AWS 인프라에 배포된 리소스를 terraform state로 옮겨주는 작업.
    • 이는 local의 .terraform에 해당 리소스의 상태 정보를 저장해주는 역할을 한다. (절대 코드를 생성해주지 않는다.)
      • Apply 전까지는 backend에 저장되지 않는다.
      • Import 이후에 plan을 하면 로컬에 해당 코드가 없기 때문에 리소스가 삭제 또는 변경된다는 결과를 보여준다. 이 결과를 바탕으로 코드를 작성할 수 있다.
  • 기본 명령어
    • init : 테라폼 명령어 사용을 위해 각종 설정을 진행
    • plan : 테라폼으로 작성한 코드가 실제로 어떻게 만들어질지에 대한 예측 결과를 보여준다.
    • apply : 테라폼 코드로 실제 인프라를 생성하는 명령어
    • import : 이미 만들어진 자원을 테라폼 state 파일로 옮겨주는 명령어
    • state : 테라폼 state를 다루는 명령어. 하위 명령어로 mv, push 와 같은 명령어가 있다.
    • destroy : 생성된 자원들을 state 파일을 기준으로 모두 삭제하는 명령어

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


# VPC ##############################
resource "aws_vpc" "main" {
  cidr_block       = "10.0.0.0/24"

  tags = {
    Name = "my-vpc"
  }
}


# subnet (Public / Private Subnet) ##############################
resource "aws_subnet" "first_subnet" {
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.1.0.0/16"

  availability_zone = "ap-northeast-2a"

  tags = {
    Name = "my-public-subnet"
  }
}

resource "aws_subnet" "second_subnet" {
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.2.0.0/16"

  availability_zone = "ap-northeast-2b"

  tags = {
    Name = "my-private-subnet"
  }
}


# Internet Gateway ##############################
resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "my-igw"
  }
}


# Route Table (Route Table 생성은 aws_route_table, 서브넷과 연결은 aws_route_table_association)
# 퍼블릭 서브넷인 first_subnet과 IGW와 연결된 라우팅 테이블을 연결 ##############################
resource "aws_route_table" "route_table_public" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "public-subnet-rtb"
  }
}

resource "aws_route_table_association" "route_table_association_1" {
  subnet_id      = aws_subnet.first_subnet.id
  route_table_id = aws_route_table.route_table_public.id
}


# Priavet Subent
# Elastic IP, Nat Gateway (+ 라우팅 테이블 연결) ##############################
resource "aws_eip" "my-ip" {
  vpc   = true

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_nat_gateway" "nat_gateway_1" {
  allocation_id = aws_eip.my-ip.id

  # NAT Gateway는 퍼블릭 서브넷에 위치
  subnet_id = aws_subnet.first_subnet.id

  tags = {
    Name = "my-nat"
  }
}

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

  tags = {
    Name = "private-subent-rtb"
  }
}

resource "aws_route_table_association" "route_table_association_private_2" {
  subnet_id      = aws_subnet.second_private_subnet.id
  route_table_id = aws_route_table.route_table_private.id
}

resource "aws_route" "private_nat_1" {
  route_table_id              = aws_route_table.route_table_private.id
  destination_cidr_block      = "0.0.0.0/0"
  nat_gateway_id              = aws_nat_gateway.nat_gateway_1.id
}


# S3 Bucket 생성 ##############################
resource "aws_s3_bucket" "main" {
  bucket = "my-s3-bucket-123"

  tags = {
    Name        = "my-bucket"
  }
}


# IAM User 생성 ##############################
resource "aws_iam_user" "gildong_hong" {
  name = "gildong.hong"
}


# IAM group 생성 
resource "aws_iam_group" "devops_group" {
  name = "devops"
}


# 생성한 IAM User를 IAM group에 등록 
resource "aws_iam_group_membership" "devops" {
  name = aws_iam_group.devops_group.name

  users = [
    aws_iam_user.gildong_hong.name
  ]

  group = aws_iam_group.devops_group.name
}

0개의 댓글