[Terraform docs : AWS] 03. Build Infrastructure

박종배·2023년 1월 18일
0
post-thumbnail

서론

아래에 글은 공식문서를 공부하며 정리한 내용입니다.

참고


목표

앞서 테라폼 설치를 완료했으니 이제 테라폼으로 aws ec2를 배포해보자.

전제

  • terraform cli v1.2.0+
  • aws cli
  • aws account, associated credential

conf 파일 작성

테라폼에서 인프라를 설명하는 파일을 terraform configuration 이라고 함.

이제, conf 파일에 배포할 aws ec2 instance 1개에 대해 정의 해보자.

mkdir learn-terraform-aws-instance
cd learn-terraform-aws-instance
cat <<EOF > main.tf
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-0c76973fbe0ee100c"
  instance_type = "t2.micro"

  tags = {
    Name = "ExampleAppServerInstance"
  }
}
EOF

위에서 정의한 내용들을 각 블록 별로 검토해보자.

terraform block

terraform {} 블록은 테라폼의 설정을 포함하며 여기에는 실제 인프라를 배포하기 위해 사용하는 required_providers {} 블록이 포함됨.

각 required_providers 블록에 정의한 각 provider들에는 source 속성으로 optional한 hostname, namespace, provider type을 정의함.

기본적으로 테라폼은 terraform registry에서 provider를 설치함. 위 예제에서는 aws provider의 source가 hashicorp/aws로 정의되어 있음. 이는 registry.terraform.io/hashicorp/aws의 축약어임.

그리고 required_providers 블록에서 각 provider에 대한 버전을 제한할 수 있음. 이 version 속성은 옵셔널하지만 권고사항임. 만약, version을 명시하지 않으면 최신 버전을 다운로드함.

providers

provider {} 블록에서 각 provider들을 정의할 수 있음. 위 예제에서는 aws 라는 provider를 정의함.

이런 provider는 테라폼이 실제 리소스를 생성하고 관리하는데 사용하는 plugin 임.

테라폼 conf 파일에는 서로 다른 provider들을 사용해서 리소스를 관리하기 위해 여러 개의 provider 블록을 사용할 수 있음. 서로 다른 provider들을 같이 쓸 수도 있음. 예를 들어, AWS EC2 인스턴스의 IP 주소를 DataDog의 모니터링 리소스에 전달할 수 있음.

resources

resource {} 블록으로 배포할 인프라의 구성요소들을 정의할 수 있음.

예를 들어, EC2 instance 같은 physical or virtual component 또는 Heroku app 같은 logical resource 등이 있음.

resource 블록에는 {} 앞에 두 개의 string을 갖고 있음. 바로 resource typeresource name임. 위 예제에서는 aws_instance가 resource type이고 app_server가 resource name임. 여기서 type의 prefix는 provider 이름과 매핑됨. 그리고 resource type과 name이 합쳐져서 해당 리소스의 고유 ID를 만듦. 예를 들어, 위 예제에서 EC2 인스턴스의 ID는 aws_instance.app_server이 됨.

그리고 resource 블록에는 리소스를 구성하는 데 사용하는 인수(argument)가 포함되어 있음. 인수에는 machine size, disk image name, VPC ID 등이 포함될 수 있음. 위 예제 EC2 인스턴스의 경우, conf에 AMI ID를 Ubuntu image로, instance type을 t2.micro로 설정했고 인스턴스의 이름을 지정하기 위해 태그를 설정했음.

initialize directory

conf 파일(main.tf 등)이 있는 디렉토리에서 terraform init 명령어로 디렉토리를 초기화하면 conf에 정의된 provider들을 다운로드하고 설치하게 됨. 위 예제에서는 aws provider를 설치하게 됨.

$ terraform init

Initializing the backend...

Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 4.16"...
- Installing hashicorp/aws v4.50.0...
- Installed hashicorp/aws v4.50.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.
  • terraform init 명령어는 아웃풋으로 어떤 버전의 provider들을 설치할지 출력함. 그리고 위 예제의 경우, aws provider를 해당 워킹디렉토리 안에 숨겨진 폴더 .terraform 밑에 다운로드하고 설치하며 실제 사용된 provider와 버전이 명시된 .terraform.lock.hcl 이라는 lock 파일을 생성함. 즉, 이 파일들을 관리하면 원하는대로 provider를 업데이트할 수 있음.

terraform init으로 생성된 .terraform 폴더와 .terraform.lock.hcl 파일 확인

conf 파일을 format하고 validate 하기

conf 파일들에 대해 일관된 포멧팅을 권고함. terraform fmt 명령어는 가독성, 일관성을 위해 현재 디렉토리의 conf 파일을 자동으로 업데이트함. 명령어를 수행하고나면 수정된 파일 이름을 출력해줌.

conf 파일 format하기

$ terraform fmt -diff
main.tf
--- old/main.tf
+++ new/main.tf
@@ -14,7 +14,7 @@
 }
 
 resource "aws_instance" "app_server" {
-  ami      = "ami-0c76973fbe0ee100c"
+  ami           = "ami-0c76973fbe0ee100c"
   instance_type = "t2.micro"
 
   tags = {
  • -diff 옵션을 사용하면 무엇이 바꼈는지 출력됨.

그리고 terraform validate 명령어를 사용하여 conf 파일이 구문적으로 유효하고 내부적으로 일관성이 있는지 확인할 수도 있음. 검증이 성공하면 로그로 출력해줌.

conf 파일 validate하기

$ terraform validate
Success! The configuration is valid.

인프라 생성

conf 파일을 적용하기

$ 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-0c76973fbe0ee100c"
      + arn                          = (known after apply)
##...

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 36s [id=i-01e03375ba238b384]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
  • 변경 사항을 적용하기 전에 Terraform은 conf 파일과 일치하도록 인프라를 변경하기 위해 Terraform이 수행할 작업을 설명하는 실행 계획을 출력함. 출력 형식은 Git과 같은 툴에서 생성된 diff 형식과 유사함. 위 예제의 경우, 출력에는 + 옆에 aws_instance.app_server가 있으며 이는 Terraform이 이 리소스를 생성함을 의미함. 그 아래에는 설정할 속성이 표시됨. 표시된 값이 (known after apply)인 경우 리소스가 생성될 때까지 값을 알 수 없음을 의미함. 예를 들어, AWS는 생성 시 Amazon 리소스 이름(ARN)을 인스턴스에 할당하므로 Terraform은 변경 사항을 적용하고 AWS provider가 AWS API에서 해당 값을 반환할 때까지 arn 속성 값을 알 수 없음.
  • 그 다음 로그를 보면 Terraform이 일시 중지되고 진행하기 전에 승인을 기다리게 됨. plan의 어떤 것이 잘못되었거나 위험해 보이는 경우 Terraform이 인프라를 수정하기 전에 여기에서 중단하는 것이 안전함. 이 경우, plan이 acceptable하므로 계속 진행하기 위해 프롬프트에 yes를 입력하자. Terraform이 EC2 인스턴스를 사용할 수 있을 때까지 기다리기 때문에 계획을 실행하는 데 몇 분 정도 걸릴 수 있음.

state 검사

conf 파일을 적용하면 Terraform이 terraform.tfstate라는 파일에 데이터를 기록함. Terraform은 관리하는 리소스의 ID와 속성을 이 파일에 저장하므로 이를 통해 해당 리소스를 업데이트하거나 삭제할 수 있음.

Terraform state 파일은 Terraform이 관리하는 리소스를 추적할 수 있는 유일한 방법. 종종 민감한 정보를 포함하므로 state 파일을 안전하게 저장하고 인프라 관리자에게만 액세스를 제한해야 함. Terraform은 상태를 저장하고 관리하는 데 사용할 수 있는 다른 여러 원격 백엔드도 지원함.

state 조회하기

$ terraform show

# aws_instance.app_server:
resource "aws_instance" "app_server" {
    ami                                  = "ami-0c76973fbe0ee100c"
...
        volume_size           = 8
        volume_type           = "gp2"
    }
}

다시 말해, Terraform이 이 EC2 인스턴스를 생성할 때 AWS provider로부터 리소스의 메타데이터도 수집하고 메타데이터를 상태 파일에 기록하므로 이후에 이러한 값을 참조하여 다른 리소스 및 출력값을 설정하도록 conf 파일을 수정할 수 있음.

manual하게 state 관리하기

terraform state 명령어는 state 관리할 수 있는 명령어임. 예를 들어, list 하위 명령어는 state에 있는 리소스들의 목록을 보여줌.

profile
기록하는 엔지니어 되기 💪

0개의 댓글