IT STUDY LOG

[Infrastructure as Code] 02. Terraform 본문

devops bootcamp 4/DevOps 인프라 관리

[Infrastructure as Code] 02. Terraform

roheerumi 2023. 5. 12. 16:51

# 학습 목표

  • Infrastructure as Code(이하 IaC)의 의미와 필요성을 이해할 수 있다.
    • 수동으로 인프라를 설정하는 것의 장/단점을 파악할 수 있다.
    • IaC의 장점을 파악할 수 있다.
  • IaC의 종류를 파악할 수 있다.
    • 선언형 IaC와 절차형 IaC의 차이를 이해할 수 있다.
  • 테라폼의 특징 및 장점을 통해 테라폼의 주 사용 목적을 이해할 수 있다.
  • 예상치 못한 인프라 변경을 어떻게 대비하는지 이해할 수 있다.
    • 불변(Immutable)한 인프라를 구성한다는 것의 의미를 이해할 수 있다.
  • 테라폼의 작동 원리를 이해할 수 있다.
    • 테라폼 공식 문서를 통해, HCL 언어로 인프라를 구성할 수 있다.
    • 주요 명령어를 이해할 수 있다.
    • 테라폼 상태 파일의 의미를 이해할 수 있다.
    • 테라폼 상태 파일을 이용한 운영의 모범 사례를 이해할 수 있다.
  • AWS VPC 구성을 더욱 잘 이해할 수 있다.
    • VPC 및 public/private 서브넷에 대한 개념을 보다 더 확실하게 이해할 수 있다.
 

# 학습 내용

1.  IaC 종류와 Terraform의 장점

IaC의 종류

절차형 IaC

- 프로그래밍 언어를 이용해 직접 순차적으로 인프라를 생성하도록 코드를 작성하는 방법

- 선언형에 비해 더 강력한 일들을 할 수 있으나 실제 적용된 결과를 가늠하기 어렵고, 코드도 직관적이지 않음

절차형 IaC의 종류

  • AWS CDK
  • Pulumi

선언형 IaC

- 선언형 언어 JSON, YAML 등을 사용

- 실제 인프라가 적용된 결과(기대하는 상태)와 적용할 내용(YAML 등)이 직관적으로 매핑됨

선언형 IaC의 종류

  • CloudFormation (AWS에서만 사용가능)
  • Azure Blueprint (Azure에서만 사용가능)
  • Cloud Deployment Manager (GCP에서만 사용가능)
  • Terraform: 어떤 클라우드 서비스에도 적용되는 범용 IaC 도구

 

2. Terraform 기초 Hands On

Step 1 : What is Infrastructure as Code with Terraform?

What is Infrastructure as Code with Terraform? | Terraform | HashiCorp Developer

코드형 인프라(IaC) 도구 : Terraform

- Terraform은 HashiCorp의 인프라 코드 도구

- 그래픽 사용자 인터페이스가 아닌 구성 파일로 인프라를 관리 가능

- 버전화, 재사용 및 공유할 수 있는 리소스 구성을 정의하여 안전하고 일관되며 반복 가능한 방식으로 인프라를 구축, 변경 및 관리 가능

- 사람이 읽을 수 있는 선언적 구성 파일에서 리소스와 인프라를 정의하고 인프라의 수명 주기를 관리 가능

수동 설정이 아닌 Terraform을 사용할 때 이점

  • Terraform은 여러 클라우드 플랫폼에서 인프라를 관리 가능
  • 사람이 읽을 수 있는 구성 언어로 인프라 코드를 빠르게 작성하는 데 도움
  • Terraform의 상태를 사용하면 배포 전체에서 리소스 변경 사항을 추적 가능
  • 버전 제어에 대한 구성을 커밋하여 인프라에서 안전하게 협업 가능
  • 배포 워크 플로를 표준화
    • scope : 프로젝트의 인프라를 식별
    • author : 인프라에 대한 구성을 작성
    • initialize : Terraform이 인프라를 관리하는 데 필요한 플러그인을 설치
    • plan : 구성과 일치하도록 Terraform이 수행할 변경 사항을 미리 확인
    • apply : 계획된 변경 사항을 적용

 

Step 2 : Install Terraform

1. Terraform 설치

# 시스템이 최신 상태이고 gnupg, software-properties-common및 curl패키지가 설치되어 있는지 확인
$ sudo apt-get update && sudo apt-get install -y gnupg software-properties-common

# HashiCorp GPG 키를 설치
$ wget -O- https://apt.releases.hashicorp.com/gpg | \
gpg --dearmor | \
sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg

# 키 핑거프린트 확인
$ gpg --no-default-keyring \
--keyring /usr/share/keyrings/hashicorp-archive-keyring.gpg \
--fingerprint

# 공식 HashiCorp 저장소를 시스템에 추가
# lsb_release -cs 명령은 현재 시스템의 배포판 코드명(ex. buster: groovy,sid)을 찾음
$ echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] \
https://apt.releases.hashicorp.com $(lsb_release -cs) main" | \
sudo tee /etc/apt/sources.list.d/hashicorp.list

# HashiCorp에서 패키지 정보를 다운로드 후 새 리포지토리에서 Terraform을 설치
$ sudo apt update
$ sudo apt-get install terraform

2. Terraform 설치 확인

$ terraform -help
Usage: terraform [global options] <subcommand> [args]

The available commands for execution are listed below.
The primary workflow commands are given first, followed by
less common or more advanced commands.

3. 탭 완성 활성화

# shell에서 테라폼 탭 완성 추가
$ touch ~/.bashrc
$ terraform -install-autocomplete

4. terraform으로 docker nginx 실행해보기

4-1. 프로젝트 디렉터리에서 main.tf 파일 작성

4-2. 터미널에서 terraform init 명령어를 사용해 프로젝트를 초기화해 플러그인 다운로드하고 terraform apply 명령어를 이용해 구성 실행

4-3. docker ps 명령어로 테라폼을 통해 정상적으로 nginx 컨테이너가 도커로 동작하는지 확인

4-4. 컨테이너 기동을 멈추고 리소스를 제거하기 위해 terraform destroy 명령어 사용

 

Step 3 : Build Infrastructure

0. 사전 조건

1. 프로젝트 디렉터리에 terraform 구성 파일 작성

# main.tf

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

  required_version = ">= 1.2.0"
}

provider "aws" {
  region = "us-west-2" # 지역에 따라 리소스 ami id가 다름
}

resource "aws_instance" "app_server" {
  ami           = "ami-830c94e3"
  instance_type = "t2.micro"

  tags = {
    Name = "ExampleAppServerInstance"
  }
}
  1. terraform 블럭
    • 블록 terraform {}에는 Terraform이 인프라를 프로비저닝하는 데 사용할 필수 공급자를 포함하여 Terraform 설정이 포함
      • required_providers의 source 속성: 선택적 호스트 이름, 네임스페이스 및 제공자 유형을 정의(Terraform은 기본적으로 Terraform 레지스트리 에서 공급자를 설치)
      • equired_providers의 version 속성 : 선택적으로 버전 제약 조건 설정 가능. 단, Terraform이 사용자의 구성과 작동하지 않는 공급자 버전을 설치하지 않도록 공급자 버전을 제한하도록 이 속성을 사용하기를 권장하며, 공급자 버전을 지정하지 않으면 Terraform은 초기화 중에 최신 버전을 자동으로 다운로드
    • 자세히 알아보려면 제공자 소스 문서를 참조
  2. provider 블럭
    • 공급자(이 경우 aws)를 구성하는 블럭으로 공급자는 Terraform이 리소스를 만들고 관리하는 데 사용하는 플러그인
    • Terraform 구성에서 여러 공급자 블록을 사용하여 다른 공급자의 리소스를 관리 가능하며 다른 공급자를 함께 사용할 수도 있음 (ex. AWS EC2 인스턴스의 IP 주소를 DataDog의 모니터링 리소스에 전달)
  3. resource 블럭
    • 블록을 사용하여 resource인프라의 구성 요소를 정의
    • 리소스는 EC2 인스턴스와 같은 물리적 또는 가상 구성 요소이거나 Heroku 애플리케이션과 같은 논리적 리소스도 가능
    • 리소스 블록에는 블록 앞에 리소스 유형리소스 이름이라는 두 개의 문자열 존재
      • 리소스 유형 : 리소스 유형의 접두사는 공급자 이름과 매핑 (ex. aws_instance이고 Terraform은 aws_instance리소스를 aws 공급자를 사용해 관리)
      • 리소스 이름 : 이 경우 app_server
      • 고유 ID는 리소스 유형과 리소스 이름으로 생성 (ex. EC2 인스턴스의 ID는 aws_instance.app_server) 
    • 리소스 블록에는 리소스를 구성하는 데 사용하는 인수가 포함 (머신 크기, 디스크 이미지 이름, VPC  ID등)
      • 공급자 레퍼런스 통해 각 리소스에 대한 필수 및 선택적 인수 확인 가능
      • 이 예시의 경우 EC2 인스턴스를 AMI ID를 Ubuntu 이미지로 설정하고 인스턴스 유형을 t2.microAWS의 프리 티어에 적합한 로 설정하며 인스턴스에 이름을 지정하는 태그를 설정

2. 디렉터리 초기화

- Terraform은 aws공 급자를 다운로드하여 현재 작업 디렉토리의 숨겨진 하위 디렉토리인 .terraform. 에 설치

- terraform init 명령은 설치된 공급자 버전을 출력

- Terraform은 사용된 정확한 공급자 버전을 지정하는 .terraform.lock.hcl이라는 이름의 잠금 파일을 생성하므로 프로젝트에 사용되는 공급자를 업데이트하려는 시기 제어 가능

$  terraform init

Initializing the backend...

Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 4.16"...
- Installing hashicorp/aws v4.67.0...
- Installed hashicorp/aws v4.67.0 (signed by HashiCorp)

Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

3. 구성 형식 지정 및 유효성 검사

- 모든 구성 파일에서 일관된 형식을 사용하는 것을 권장하며 terraform fmt명령은 가독성과 일관성을 위해 현재 디렉터리의 구성을 자동으로 업데이트

$ terraform fmt

- terraform validate명령을 사용하여 구성이 구문적으로 유효하고 내부적으로 일관성이 있는지 확인 가능 

$ terraform validate
Success! The configuration is valid.

4. 인프라 만들기

4-1. terraform apply 명령을 사용하여 구성 적용

$ terraform apply

Terraform used the selected providers to generate the following execution plan.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_instance.app_server will be created
  + resource "aws_instance" "app_server" {
      + ami                                  = "ami-830c94e3"
# ... 중략 ... #
      + get_password_data                    = false
# ... 중략 ... #
      + instance_type                        = "t2.micro"
# ... 중략 ... #
      + source_dest_check                    = true
# ... 중략 ... #
      + tags                                 = {
          + "Name" = "ExampleAppServerInstance"
        }
      + tags_all                             = {
          + "Name" = "ExampleAppServerInstance"
        }
# ... 중략 ... #
      + user_data_replace_on_change          = false
# ... 중략 ... #
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

- 변경 사항을 적용하기 전에 Terraform은 구성과 일치하도록 인프라를 변경하기 위해 Terraform이 수행할 작업을 설명하는 실행 계획을 출력

  •  + :  Terraform이 이 리소스를 생성함을 의미 그 아래에는 설정할 속성이 표시
  • known after apply : 리소스가 생성될 때까지 값을 알 수 없음을 의미 

4-2. 진행하기 전에 승인을 요구하므로 계획의 어떤 것이 잘못되었거나 위험해 보이는 경우 Terraform이 인프라를 수정하기 전에 여기에서 중단하는 것이 안전

aws_instance.app_server: Creating...
aws_instance.app_server: Still creating... [10s elapsed]
aws_instance.app_server: Still creating... [20s elapsed]
aws_instance.app_server: Still creating... [30s elapsed]
aws_instance.app_server: Creation complete after 34s [id=i-08a3c15caca1d7236]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

4-3. 콘솔에 접속해 EC2 인스턴스가 정상적으로 생성되었는지 확인

5. 상태 검사

- terraform apply 명령어를 실행하면 Terraform이 데이터를 terraform.tfstate 파일에 작성함

- Terraform은 관리하는 리소스의 ID와 속성을 이 파일에 저장하므로 앞으로 해당 리소스를 업데이트하거나 삭제 가능

- Terraform 상태 파일은 Terraform이 관리하는 리소스를 추적할 수 있는 유일한 방법이며 종종 민감한 정보를 포함하므로 상태 파일을 안전하게 저장하고 인프라를 관리해야 하는 신뢰할 수 있는 팀 구성원으로만 액세스를 제한해야 함

※ 프로덕션에서는 Terraform Cloud 또는 Terraform Enterprise를 사용하여 상태를 원격으로 저장하는 것을 권장하며 Terraform은 상태를 저장하고 관리하는 데 사용할 수 있는 다른 여러 원격 백엔드도 지원

5-1.  terraform show를 사용하여 현재 상태를 검사

$ terraform show
# aws_instance.app_server:
resource "aws_instance" "app_server" {
    ami                                  = "ami-830c94e3"
    arn                                  = "arn:aws:ec2:us-west-2:644329934495:instance/i-08a3c15caca1d7236"
    associate_public_ip_address          = true
    availability_zone                    = "us-west-2a"
    cpu_core_count                       = 1
    cpu_threads_per_core                 = 1
    disable_api_stop                     = false
    disable_api_termination              = false
    ebs_optimized                        = false
    get_password_data                    = false
    hibernation                          = false
    id                                   = "i-08a3c15caca1d7236"
    instance_initiated_shutdown_behavior = "stop"
    instance_state                       = "running"
    instance_type                        = "t2.micro"
    ipv6_address_count                   = 0
    ipv6_addresses                       = []
    monitoring                           = false
    placement_partition_number           = 0
    primary_network_interface_id         = "eni-020b5469f09447bb9"
    private_dns                          = "ip-172-31-28-153.us-west-2.compute.internal"
    private_ip                           = "172.31.28.153"
    public_dns                           = "ec2-54-245-191-139.us-west-2.compute.amazonaws.com"
    public_ip                            = "54.245.191.139"
# ... 중략 ... #
    private_dns_name_options {
        enable_resource_name_dns_a_record    = false
        enable_resource_name_dns_aaaa_record = false
        hostname_type                        = "ip-name"
    }

    root_block_device {
        delete_on_termination = true
        device_name           = "/dev/sda1"
        encrypted             = false
        iops                  = 0
        tags                  = {}
        throughput            = 0
        volume_id             = "vol-03b8df68fc548487e"
        volume_size           = 8
        volume_type           = "standard"
    }
}

6. 수동으로 상태 관리

6-1. terraform state  list 명령을 사용하여 프로젝트 상태의 리소스를 나열

$ terraform state list
aws_instance.app_server

(optional) 서울에 만들기 

- AMI ID는 리전별로 다르므로 변경해야 함 

- 다음 지침 에 따라 지역에 맞는 AMI ID를 찾아 main.tf을 해당 ID로 수정하고 terraform apply를 다시 실행

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

  required_version = ">= 1.2.0"
}

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

resource "aws_instance" "app_server" {
  ami           = "ami-0970cc54a3aa77466"
  instance_type = "t2.micro"

  tags = {
    Name = "ExampleAppServerInstance"
  }
}

 

Step 4 : Change Infrastructure

1. main.tf 파일의 Ubuntu 버전을 20.04에서 22.04로 변경해 구성 변경하기

resource "aws_instance" "app_server" {
  - ami           = "ami-0970cc54a3aa77466"
  + ami           = "ami-0f5cdcb15c8e06197"
  instance_type = "t2.micro"

  tags = {
    Name = "ExampleAppServerInstance"
  }
}

2. terraform apply 명령어로 변경 승인

- 구성을 변경한 후 다시 실행하여 Terraform이 이 변경 사항을 기존 리소스에 어떻게 적용하는지 확인

$ terraform apply
aws_instance.app_server: Refreshing state... [id=i-03a9b2556c6650754]

Terraform used the selected providers to generate the following execution plan.
Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement

Terraform will perform the following actions:

  # aws_instance.app_server must be replaced
-/+ resource "aws_instance" "app_server" {
      ~ ami                                  = "ami-0970cc54a3aa77466" -> "ami-0f5cdcb15c8e06197" # forces replacement
      ~ arn                                  = "arn:aws:ec2:ap-northeast-2:644329934495:instance/i-03a9b2556c6650754" -> (known after apply)
      ~ associate_public_ip_address          = true -> (known after apply)
      ~ availability_zone                    = "ap-northeast-2c" -> (known after apply)
      ~ cpu_core_count                       = 1 -> (known after apply)
      ~ cpu_threads_per_core                 = 1 -> (known after apply)
      ~ disable_api_stop                     = false -> (known after apply)
      ~ disable_api_termination              = false -> (known after apply)
      ~ ebs_optimized                        = false -> (known after apply)
      - hibernation                          = false -> null
      + host_id                              = (known after apply)
      + host_resource_group_arn              = (known after apply)
      + iam_instance_profile                 = (known after apply)
      ~ id                                   = "i-03a9b2556c6650754" -> (known after apply)
      ~ instance_initiated_shutdown_behavior = "stop" -> (known after apply)
      ~ instance_state                       = "running" -> (known after apply)
      ~ ipv6_address_count                   = 0 -> (known after apply)
      ~ ipv6_addresses                       = [] -> (known after apply)
      + key_name                             = (known after apply)
      ~ monitoring                           = false -> (known after apply)
      + outpost_arn                          = (known after apply)
      + password_data                        = (known after apply)
      + placement_group                      = (known after apply)
      ~ placement_partition_number           = 0 -> (known after apply)
      ~ primary_network_interface_id         = "eni-00478e13c35933532" -> (known after apply)
      ~ private_dns                          = "ip-172-31-42-185.ap-northeast-2.compute.internal" -> (known after apply)
      ~ private_ip                           = "172.31.42.185" -> (known after apply)
      ~ public_dns                           = "ec2-3-37-55-250.ap-northeast-2.compute.amazonaws.com" -> (known after apply)
      ~ public_ip                            = "3.37.55.250" -> (known after apply)
      ~ secondary_private_ips                = [] -> (known after apply)
      ~ security_groups                      = [
          - "default",
        ] -> (known after apply)
      ~ subnet_id                            = "subnet-0a5fd3671a4190e0f" -> (known after apply)
        tags                                 = {
            "Name" = "ExampleAppServerInstance"
        }
      ~ tenancy                              = "default" -> (known after apply)
      + user_data                            = (known after apply)
      + user_data_base64                     = (known after apply)
      ~ vpc_security_group_ids               = [
          - "sg-0dd97094921425464",
        ] -> (known after apply)
        # (5 unchanged attributes hidden)

      - capacity_reservation_specification {
          - capacity_reservation_preference = "open" -> null
        }

      - cpu_options {
          - core_count       = 1 -> null
          - threads_per_core = 1 -> null
        }

      - credit_specification {
          - cpu_credits = "standard" -> null
        }

      - enclave_options {
          - enabled = false -> null
        }

      - maintenance_options {
          - auto_recovery = "default" -> null
        }

      - metadata_options {
          - http_endpoint               = "enabled" -> null
          - http_put_response_hop_limit = 1 -> null
          - http_tokens                 = "optional" -> null
          - instance_metadata_tags      = "disabled" -> null
        }

      - private_dns_name_options {
          - enable_resource_name_dns_a_record    = false -> null
          - enable_resource_name_dns_aaaa_record = false -> null
          - hostname_type                        = "ip-name" -> null
        }

      - root_block_device {
          - delete_on_termination = true -> null
          - device_name           = "/dev/sda1" -> null
          - encrypted             = false -> null
          - iops                  = 100 -> null
          - tags                  = {} -> null
          - throughput            = 0 -> null
          - volume_id             = "vol-0bfd7bc70170f4d3b" -> null
          - volume_size           = 8 -> null
          - volume_type           = "gp2" -> null
        }
    }

Plan: 1 to add, 0 to change, 1 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.
  
    Enter a value: yes
  • -/+ : Terraform이 리소스를 내부에서 업데이트하는 대신 리소스를 삭제하고 다시 생성함을 의미
  • ~ : Terraform이 일부 속성을 내부에서 업데이트하나 EC2 인스턴스에 대한 AMI를 변경하려면 다시 생성해야 함
  • Plan :  Terraform이 수행할 작업을 표시
  Enter a value: yes

aws_instance.app_server: Destroying... [id=i-01e03375ba238b384]
aws_instance.app_server: Still destroying... [id=i-01e03375ba238b384, 10s elapsed]
aws_instance.app_server: Still destroying... [id=i-01e03375ba238b384, 20s elapsed]
aws_instance.app_server: Still destroying... [id=i-01e03375ba238b384, 30s elapsed]
aws_instance.app_server: Still destroying... [id=i-01e03375ba238b384, 40s elapsed]
aws_instance.app_server: Destruction complete after 42s
aws_instance.app_server: Creating...
aws_instance.app_server: Still creating... [10s elapsed]
aws_instance.app_server: Still creating... [20s elapsed]
aws_instance.app_server: Still creating... [30s elapsed]
aws_instance.app_server: Still creating... [40s elapsed]
aws_instance.app_server: Creation complete after 50s [id=i-0fd4a35969bd21710]

Apply complete! Resources: 1 added, 0 changed, 1 destroyed.

3. EC2 콘솔에서 정상적으로 삭제되고 새로운 버전의 인스턴스가 생성되었는지 확인

 

Step 5 : Destroy Infrastructure

1. terraform destroy명령어로 생성한 인스턴스 파괴 (프로젝트 관리하는 리소스 종료)

$ terraform destroy
# ... 중략 ... #
aws_instance.app_server: Destroying... [id=i-026ada30ab37b3ea2]
aws_instance.app_server: Still destroying... [id=i-026ada30ab37b3ea2, 10s elapsed]
aws_instance.app_server: Still destroying... [id=i-026ada30ab37b3ea2, 20s elapsed]
aws_instance.app_server: Still destroying... [id=i-026ada30ab37b3ea2, 30s elapsed]
aws_instance.app_server: Still destroying... [id=i-026ada30ab37b3ea2, 40s elapsed]
aws_instance.app_server: Destruction complete after 40s

 

Step 6 : Define Input Variables

1. variables.tf 파일을 생성해 변수로 인스턴스 이름 설정 후 main.tf 파일에 적용

-Terraform은 .tf로 끝나는 현재 디렉터리의 모든 파일을 로드하므로 원하는 대로 구성 파일의 이름을 지정 가능

# variables.tf

variable "instance_name" {
  description = "EC2 인스턴스 네임태그 값"
  type        = string
  default     = "EC2 서버 인스턴스 예제"
}
# main.tf

resource "aws_instance" "app_server" {
  ami           = "ami-0f5cdcb15c8e06197"
  instance_type = "t2.micro"

  tags = {
    Name = var.instance_name
  }
}

2. terraform apply 명령어로 구성 적용

$ terraform apply

Terraform used the selected providers to generate the following execution plan.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_instance.app_server will be created
  + resource "aws_instance" "app_server" {
      + ami                                  = "ami-0970cc54a3aa77466"
 # ... 중략 ... #
      + tags                                 = {
          + "Name" = "EC2 서버 인스턴스 예제"
        }
      + tags_all                             = {
          + "Name" = "EC2 서버 인스턴스 예제"
        }
 # ... 중략 ... #
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.
  
  
  Enter a value: yes

aws_instance.app_server: Creating...
aws_instance.app_server: Still creating... [10s elapsed]
aws_instance.app_server: Still creating... [20s elapsed]
aws_instance.app_server: Still creating... [30s elapsed]
aws_instance.app_server: Creation complete after 32s [id=i-088dce28da4765eb4]

3. 플래그를 사용하여 변수를 전달하여 기본 인스턴스 이름을 재정의

-  terraform apply -var 옵션을 사용해 Terraform은 인스턴스의 Name 태그를 새 이름으로 업데이트 

- 단, 명령어 통해 변수를 설정하면 해당 값이 저장되지 않음(변수를 사용하여 Terraform 구성 사용자 지정 참고)

$ terraform apply -var "instance_name=EC2 이름 설정"
aws_instance.app_server: Refreshing state... [id=i-088dce28da4765eb4]

Terraform used the selected providers to generate the following execution plan.
Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # aws_instance.app_server will be updated in-place
  ~ resource "aws_instance" "app_server" {
        id                                   = "i-088dce28da4765eb4"
      ~ tags                                 = {
          ~ "Name" = "EC2 서버 인스턴스 예제" -> "EC2 이름 설정"
        }
      ~ tags_all                             = {
          ~ "Name" = "EC2 서버 인스턴스 예제" -> "EC2 이름 설정"
        }
        # (30 unchanged attributes hidden)

        # (8 unchanged blocks hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_instance.app_server: Modifying... [id=i-088dce28da4765eb4]
aws_instance.app_server: Modifications complete after 1s [id=i-088dce28da4765eb4]

Apply complete! Resources: 0 added, 1 changed, 0 destroyed.

 

Step 7 : Query Data with Outputs

1. EC2 인스턴스 구성 출력을 위해 learn-terraform-aws-instance디렉토리에서 outputs.tf 파일 작성

- outputs.tf에 EC2 인스턴스의 ID 및 IP 주소에 대한 출력을 정의하려면 아래 구성을 추가

# output.tf

output "instance_id" {
  description = "EC2 인스턴스 아이디"
  value       = aws_instance.app_server.id
}

output "instance_public_ip" {
  description = "EC2 인스턴스의 공인 IP 주소"
  value       = aws_instance.app_server.public_ip
}
 

2. terraform apply 명령어로 구성 적용 후 정상적으로 출력되는지 확인

- Terraform은 구성을 적용할 때 출력 값을 화면에 출력하

$ terraform apply
aws_instance.app_server: Refreshing state... [id=i-088dce28da4765eb4]

Terraform used the selected providers to generate the following execution plan.
Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # aws_instance.app_server will be updated in-place
  ~ resource "aws_instance" "app_server" {
        id                                   = "i-088dce28da4765eb4"
      ~ tags                                 = {
          ~ "Name" = "EC2 이름 설정" -> "EC2 서버 인스턴스 예제"
        }
      ~ tags_all                             = {
          ~ "Name" = "EC2 이름 설정" -> "EC2 서버 인스턴스 예제"
        }
        # (30 unchanged attributes hidden)

        # (8 unchanged blocks hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.

Changes to Outputs:
  + instance_id        = "i-088dce28da4765eb4"
  + instance_public_ip = "43.200.175.93"

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_instance.app_server: Modifying... [id=i-088dce28da4765eb4]
aws_instance.app_server: Modifications complete after 1s [id=i-088dce28da4765eb4]

Apply complete! Resources: 0 added, 1 changed, 0 destroyed.

Outputs:

instance_id = "i-088dce28da4765eb4"
instance_public_ip = "43.200.175.93"

3. terraform output 명령어를 통해 명령으로 출력 가능

$ terraform output
instance_id = "i-088dce28da4765eb4"
instance_public_ip = "43.200.175.93"

- Terraform 출력을 사용하여 Terraform 프로젝트를 인프라의 다른 부분 또는 다른 Terraform 프로젝트와 연결 가능(참고:Terraform의 데이터 출력)

4. 인프라 종료

$ terraform destroy
 

Step 8 : Store Remote State

0.Terraform 클라우드란?

- Terraform Cloud는 로컬 시스템에서 Terraform 실행을 지원하기 위해 상태를 저장할 수 있지만 원격 실행 환경에서 훨씬 더 잘 작동 

- Terraform 실행을 수행하기 위한 두 가지 주요 워크플로우를 지원

  • VCS 기반 워크플로우: 구성의 VCS 저장소에 변경 사항이 커밋될 때마다 계획을 자동으로 대기열에 추가 
  • API 기반 워크플로우: CI 파이프라인 또는 기타 자동화 도구가 구성을 직접 업로드

- Terraform Cloud는 로컬 시스템이 아닌 일관되고 안정적인 환경에서 Terraform 실행을 관리하여 이러한 기능을 기반으로  상태 및 비밀 데이터를 안전하게 저장하고 버전 제어 시스템에 연결할 수 있으므로 애플리케이션 개발과 유사한 워크플로를 사용하여 인프라를 개발 가능

- Terraform Cloud UI는 Terraform 프로젝트에서 관리하는 리소스에 대한 자세한 보기를 제공하고 각 Terraform 작업에 대한 향상된 가시성을 제공

- Terraform Cloud는 인프라 개발 프로세스의 각 단계에서 협업할 수 있도록 지원(ex. 새 변경을 계획할 때마다 팀에서 계획을 적용하기 전에 검토하고 승인 가능 또한 상태 파일을 손상시킬 수 있는 동시 수정을 방지하기 위해 작업 중에 상태를 자동으로 잠금)

Terraform Cloud의 워크플로우

- Terraform Cloud에서 리소스는 리소스 정의, 환경 및 입력 변수, 상태 파일을 포함하는 작업 공간으로 구성되며 Terraform 작업은 작업 공간 내에서 발생하고 Terraform은 해당 작업 공간의 구성 및 상태를 사용하여 인프라를 수정

Terraform Cloud이 Terraform 실행을 위해 지원하는 세 가지 워크플로

  • Terraform의 표준 CLI 도구를 사용하여 Terraform Cloud에서 실행하는 CLI 기반 워크플로우
    • CLI 기반 워크플로에서는 터미널에서 Terraform 작업을 시작하고 작업에 Terraform Cloud의 임시 원격 실행 환경을 사용 
    • Terraform Cloud는 현재 및 이전 상태 파일뿐만 아니라 구성에 필요한 모든 입력 및 환경 변수를 안전하게 저장 
    • CLI 기반 워크플로우는 협업을 가능하게 하며 최소한의 추가 구성으로 익숙하고 동일한 Terraform 워크플로우를 계속 사용하면서 Terraform Cloud의 안정성, 보안 및 향상된 가시성을 활용 가능
  • 버전 제어 리포지토리에 푸시된 변경 사항이 연결된 작업 공간에서 실행되는 UI/Version Control System(VCS) 기반 워크플로우
    • VCS 기반 워크플로우의 경우 VCS 액세스를 구성하고 작업공간을 생성한 다음 이를 Terraform 구성이 포함된 저장소와 연결해야 함
    • 이후 풀 리퀘스트에 대한 예측 계획을 생성하도록 작업 영역을 구성 가능
    • 이를 통해 팀은 변경 사항이 인프라를 수정하는 방법을 검토 가능
    • 기본 브랜치에 대한 모든 병합은 Terraform 실행을 트리거하여 변경 사항을 구현
  • 프로그래밍 방식으로 Terraform Cloud API와 상호 작용하는 도구를 만들 수 있는 API 기반 워크플로

1. Terraform 클라우드 설정

1-1. https://app.terraform.io/signup/account 에서 무료 Terraform Cloud 계정 생성

1-2. 이메일에 계정 승인 후, 조직을 생성하고 Terraform Cloud UI에서 사용할 설정 워크플로에서 처음부터 시작을 선택 

1-3.  main.tf 파일의 Terraform 구성에 cloud 블록을 추가하도록 수정하고 설정한 조직 이름을 지정

# main.tf 

terraform {
  cloud {
    organization = "roheerumi"
      workspaces {
        name = "learn-tfc-aws"
      }
  }
  
  # .. 하략 .. #
}

 

※ 참고 : 1.1.0 이전 버전의 Terraform은 블록을 지원하지 않으므로 이전 버전에서는 백엔드 블록을 사용하여 CLI 워크플로를 구성하고 상태를 마이그레이션 가능

2. Terraform 클라우드에 로그인

2-1. 터미널에서 Terraform CLI를 사용하여 Terraform Cloud 계정에 로그인

$ terraform login
Terraform will request an API token for app.terraform.io using your browser.

If login is successful, Terraform will store the token in plain text in
the following file for use by subsequent commands:
    /Users/<USER>/.terraform.d/credentials.tfrc.json

Do you want to proceed?
  Only 'yes' will be accepted to confirm.

  Enter a value: yes
 

2-2.  자동으로 열리는 브라우저 창의 워크플로를 따라생성된 API 키를 터미널에 붙여 로그인(자세한 내용: Terraform Cloud 자습서로 CLI 인증)

$ terraform login
Terraform will request an API token for app.terraform.io using your browser.

If login is successful, Terraform will store the token in plain text in
the following file for use by subsequent commands:
    /home/roheerumi/.terraform.d/credentials.tfrc.json

Do you want to proceed?
  Only 'yes' will be accepted to confirm.

  Enter a value: yes


---------------------------------------------------------------------------------

Terraform must now open a web browser to the tokens page for app.terraform.io.

If a browser does not open this automatically, open the following URL to proceed:
    https://app.terraform.io/app/settings/tokens?source=terraform-login


---------------------------------------------------------------------------------

Generate a token using your browser, and copy-paste it into this prompt.

Terraform will store the token in plain text in the following file
for use by subsequent commands:
    /home/roheerumi/.terraform.d/credentials.tfrc.json

Token for app.terraform.io:
  Enter a value: 기존 브라우저 세션에서 여는 중



Retrieved token for user roheerumi


---------------------------------------------------------------------------------

                                          -                                
                                          -----                           -
                                          ---------                      --
                                          ---------  -                -----
                                           ---------  ------        -------
                                             -------  ---------  ----------
                                                ----  ---------- ----------
                                                  --  ---------- ----------
   Welcome to Terraform Cloud!                     -  ---------- -------
                                                      ---  ----- ---
   Documentation: terraform.io/docs/cloud             --------   -
                                                      ----------
                                                      ----------
                                                       ---------
                                                           -----
                                                               -


   New to TFC? Follow these steps to instantly apply an example configuration:

   $ git clone https://github.com/hashicorp/tfc-getting-started.git
   $ cd tfc-getting-started
   $ scripts/setup.sh

3. Terraform 초기화

3-1. Terraform Cloud 통합을 구성했으므로  terraform init을 실행해 구성을 다시 초기화하고 상태 파일을 Terraform Cloud로 마이그레이션

- terraform init으로 Terraform Cloud 조직에 learn-tfc-aws 작업공간을 생성

$ terraform init

Initializing Terraform Cloud...
Do you wish to proceed?
  As part of migrating to Terraform Cloud, Terraform can optionally copy your
  current workspace state to the configured Terraform Cloud workspace.
  
  Answer "yes" to copy the latest state snapshot to the configured
  Terraform Cloud workspace.
  
  Answer "no" to ignore the existing state and just activate the configured
  Terraform Cloud workspace with its existing state, if any.
  
  Should Terraform migrate your existing state?

  Enter a value: yes


Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Using previously-installed hashicorp/aws v4.67.0

Terraform Cloud has been successfully initialized!

You may now begin working with Terraform Cloud. Try running "terraform plan" to
see any changes that are required for your infrastructure.

If you ever set or change modules or Terraform Settings, run "terraform init"
again to reinitialize your working directory.
3-2. Terraform이 상태 파일을 Terraform Cloud로 마이그레이션했으므로 로컬 상태 파일을 삭제
 $ rm terraform.tfstate

※ 참고 : CLI 기반 워크플로와 함께 Terraform Cloud를 사용하는 경우 Terraform을 원격으로 실행하거나 로컬 시스템에서 실행하도록 선택 가능 로컬 실행을 사용하는 경우 Terraform Cloud는 로컬 시스템에서 Terraform을 실행하고 원격으로 Terraform Cloud에 상태 파일을 저장 이 자습서에서는 원격 실행 모드를 사용

4. 작업 공간 변수 설정

AWS 공급자를 인증하려면 AWS 자격 증명으로 작업 공간을 구성해야 함

4-1. Terraform Cloud에서 작업 공간 으로 이동  변수 페이지로 이동 후  Add variable 선택

4-2.  AWS_ACCESS_KEY_ID 및 AWS_SECRET_ACCESS_KEY를 "environment variable" 추가하고 "sensitive" 설정

5. terraform apply 명령어로 구성 적용하여 Terraform Cloud에서 실행

- 원격 상태 스토리지를 사용하면 협업이 쉬워지고 상태 및 비밀 정보가 로컬 디스크에 저장되지 않으며 원격 상태는 사용될 때만 메모리에 로드됨

5-1. terraform apply 명령어 실행

$ terraform apply

5-2. terraform cloud에서 진행 상황 확인

 5-3. 실제 EC2 인스턴스가 생성되었는지 확인

6. 인프라 종료

6-1. terraform destroy 명령어 실행

$ terraform destroy

6-2. terraform cloud에서 진행 상황 확인

 6-3. 실제 EC2 인스턴스가 종료되었는지 확인

 

# References

https://developer.hashicorp.com/terraform/tutorials/aws-get-started

 

AWS | Terraform | HashiCorp Developer

Build, change, and destroy AWS infrastructure using Terraform. Step-by-step, command-line tutorials will walk you through the Terraform basics for the first time.

developer.hashicorp.com

 

Terraform 구성 언어

 

Configuration Language | Terraform | HashiCorp Developer

Learn Terraform configuration language by example. Write configurations to manage multiple pieces of infrastructure and iterate over structured data. Deploy and manage related infrastructure by referring to resources in other configurations.

developer.hashicorp.com

Terraform 모듈

 

Modules Overview | Terraform | HashiCorp Developer

Read about how Terraform modules make configuration easier to organize, understand, reuse, and share. Learn about the directory structure of a module, and how to call them.

developer.hashicorp.com

Terraform 프로비저닝

 

Provision | Terraform | HashiCorp Developer

Install software, edit files, and provision machines created with Terraform. Use Packer or Cloud-Init to automatically provision SSH keys and a web server onto a Linux VM created by Terraform in AWS.

developer.hashicorp.com

Terraform 가져오기 

 

Import Terraform Configuration | Terraform | HashiCorp Developer

Import existing infrastructure into Terraform. Review important considerations to keep in mind when bring infrastructure under Terraform management.

developer.hashicorp.com

 Terraform 설명서

 

Documentation | Terraform | HashiCorp Developer

Documentation for Terraform, including Terraform CLI, Terraform Cloud, and Terraform Enterprise.

developer.hashicorp.com

 Terraform Cloud 시작하기 자습서

 

Terraform Cloud | Terraform | HashiCorp Developer

Collaborate on version-controlled configuration using Terraform Cloud. Follow this track to build, change, and destroy infrastructure using remote runs and state.

developer.hashicorp.com

Terraform 팀 권한 관리, 정책 시행, 에이전트 등을 포함하는 상용 솔루션

 

HashiCorp Terraform: Enterprise Pricing, Packages & Features

HashiCorp offers three editions of Terraform: Open Source, Terraform Cloud, and Terraform Enterprise.

www.hashicorp.com

 

Comments