Terraform으로 AWS EC2 생성하고 삭제하기

기운찬곰·2023년 6월 15일
0

AWS

목록 보기
5/5
post-thumbnail

Overview

요근래 프론트엔드 블로그 글만 작성했었는데, 최근에 뭔가 시도해보고 있는 작업이 있습니다. 그건 뭐... 나중에 잘 되면 작성해보도록 하고, 아무튼 이를 위해 간단한 서버가 필요한데 역시 만만하게 AWS EC2이죠.

근데 그냥 생성하면 재미가 없는거 같아서 요즘 자주보이는 Terraform(테라폼)을 사용해보기로 했습니다. 테라폼을 사용해서 코드 단에서 제어할 수 있다는게 가장 큰 메리트인거 같습니다. 반복적인 작업도 코드만 작성해놨다면 여러번 할 수 있고요. 공유하기도 편하겠죠?

이번 시간에는 Terraform이 무엇이고 어떻게 AWS EC2를 생성하고 삭제했는지 실습 내용을 정리해보도록 하겠습니다.


Terraform이란?

개발 문서 : https://developer.hashicorp.com/terraform

테라폼 홈페이지보다 개발 문서를 보는게 Terraform이 무엇인지에 대해 더 자세한 설명을 얻을 수 있었습니다.

Intro

Terraform은 인프라를 안전하고 효율적으로 구축, 변경 및 버전 관리할 수 있는 코드 도구로서의 infrastructure 입니다. 여기에는 컴퓨팅 인스턴스, 스토리지 및 네트워킹과 같은 낮은 수준의 구성 요소와 DNS 항목 및 SaaS 기능과 같은 높은 수준의 구성 요소가 포함됩니다.

How does Terraform work?

테라폼은 애플리케이션 프로그래밍 인터페이스(API)를 통해 클라우드 플랫폼 및 기타 서비스에서 리소스를 생성하고 관리합니다. Providers(AWS, GCP 등)는 테라폼이 접근 가능한 API로 사실상 모든 플랫폼이나 서비스와 함께 작동할 수 있도록 합니다.

AWS(Amazon Web Services), Azure, GCP(Google Cloud Platform), Kubernetes, Helm, GitHub, Splunk, DataDog 등을 포함하여 공개적으로 사용 가능한 모든 Providers를 테라폼 레지스트리에서 찾을 수 있습니다.

핵심 Terraform 워크플로우는 세 단계로 구성됩니다:

  • Write : 여러 클라우드 공급자 및 서비스에 걸쳐 있을 수 있는 리소스를 정의합니다. 예를 들어 Security Group 및 로드 밸런서가 있는 VPC(Virtual Private Cloud) 네트워크의 가상 시스템에 애플리케이션을 배포하는 configuration을 생성할 수 있습니다.
  • Plan : Terraform은 기존 인프라와 사용자 configuration을 기반으로 생성, 업데이트 또는 제거할 인프라를 설명하는 실행 계획을 생성합니다.
  • Apply : Terraform은 리소스 종속성을 고려하여 제안된 작업을 올바른 순서로 수행합니다. 예를 들어 VPC의 속성을 업데이트하고 해당 VPC의 가상 시스템 수를 변경하면 Terraform이 가상 시스템을 확장하기 전에 VPC를 다시 생성합니다.


Terraform Get Started - AWS EC2

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

테라폼을 사용하여 AWS 인프라를 구축, 변경 및 제거하도록 실습해봅니다.

Install Terraform

참고로 저의 실습 환경은 MacOS M1 silicon 입니다.

설치 : https://developer.hashicorp.com/terraform/downloads

brew tap hashicorp/tap
brew install hashicorp/tap/terraform

설치가 잘 되었는지 확인

terraform -help

Build Infrastructure

테라폼 설치가 끝나면 AWS CLI를 설치해야 합니다.

AWS CLI 설치 : https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html

pkg를 다운받고 설치하면 됩니다. 설치가 잘 되면 아래 명령어가 실행되는지 확인합니다.

❯ which aws
/usr/local/bin/aws
❯ aws --version
aws-cli/2.11.27 Python/3.11.3 Darwin/22.5.0 exe/x86_64 prompt/off

마지막으로 AWS 계정과 관련 자격 리소스를 생성해야 합니다.

IAM 자격 증명을 사용하여 Terraform AWS 제공자를 인증하려면 AWS_ACCESS_KEY_ID 환경 변수를 설정합니다. 또한, secret key도 필요합니다.

export AWS_ACCESS_KEY_ID=
export AWS_SECRET_ACCESS_KEY=

이제 본격적인 실습을 위해 폴더를 생성하고 main.tf 파일을 생성해줍니다.

mkdir learn-terraform-aws-instance
cd learn-terraform-aws-instance
touch main.tf

공식문서 사이트에 나온 코드대로 사용하면 되는데, 다만 us-west-2 리전 대신 서울(ap-northeast-2) 리전을 사용하려면 AMI ID도 바뀌어야 합니다. 왜냐면 리전마다 AMI ID도 달라지기 때문이라고 합니다.

참고 : https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/finding-an-ami.html#finding-quick-start-ami

그래서 AMI는 AWS 콘솔에서 직접 찾아야 할 듯 합니다... 귀찮...😂😢

저는 가장 위에 있는 AMI 사용하겠습니다.

최종 작성 코드입니다. 일단, 가장 기본적인 설정(리전, AMI, 인스턴스 타입)만 했습니다.

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

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

resource "aws_instance" "app_server" {
  ami           = "ami-0462a914135d20297"
  instance_type = "t2.micro"

  tags = {
    Name = "ExampleAppServerInstance"
  }
}

새 구성을 만들거나 기존 구성을 체크아웃할 때 버전 제어에서 테라폼을 사용하여 디렉터리를 초기화해야 합니다. 디렉터리를 초기화하면 공급자가 다운로드되고 설치됩니다. configuration에 정의되어 있으며, 저의 경우 AWS 공급자입니다.

> 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.

  • Terraform은 AWS 공급자를 다운로드하여 .terraform 에 설치합니다
  • Terraform은 정확한 공급자 버전을 지정하는 .terraform.lock.hcl이라는 잠금 파일을 생성합니다

모든 구성 파일에서 일관된 형식을 사용하는 것이 좋습니다. 그 terraform fmt 명령은 현재 구성을 자동으로 업데이트합니다. (음... 아무 변화가 없는데... 🤔)

> terraform fmt

또한 구성이 구문적으로 유효하고 내부적으로 유효한지 확인할 수 있습니다. terraform validate 명령을 사용하여 일관성을 유지합니다. 성공하면 아래처럼 메시지가 뜹니다.

❯ terraform validate
Success! The configuration is valid.

마지막으로 terraform apply 명령을 사용하여 구성을 적용합니다. 근데 저는 여기서 실행이 안되더군요... 몇분을 기다려도 아무 반응이 없었습니다.

❯ terraform apply

그래서 찾아본 결과 Apple M1 silicon에서는 이런 문제가 있을 수 있다고 하더군요. 해결 방법으로는 아래와 같은 환경변수를 설정해주면 된다고 합니다. 아마 내부적으로는 Go를 사용하나봅니다...?

export GODEBUG=asyncpreemptoff=1

그래도 안되길래, 찾아보니 뭐 여러번 해야 작동한다, 혹은 20분 기다려야 작동한다는 글도 있네요...😢

근데 막상 terraform apply 중간에 plan이라는 명령이 있긴 하더군요. 아마 apply하면서 같이 실행되는거 같아서 실행하지는 않았는데, 지금은 apply가 안되니까 plan을 실행시켜봤습니다. 잘 되던군요.

❯ terraform plan

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-0462a914135d20297"
      + arn                                  = (known after apply)
      + associate_public_ip_address          = (known after apply)
      + availability_zone                    = (known after apply)
      + cpu_core_count                       = (known after apply)
      + cpu_threads_per_core                 = (known after apply)
      + disable_api_stop                     = (known after apply)
      + disable_api_termination              = (known after apply)
      + ebs_optimized                        = (known after apply)
      + get_password_data                    = false
      + host_id                              = (known after apply)
      + host_resource_group_arn              = (known after apply)
      + iam_instance_profile                 = (known after apply)
      + id                                   = (known after apply)
      + instance_initiated_shutdown_behavior = (known after apply)
      + instance_state                       = (known after apply)
      + instance_type                        = "t2.micro"
      + ipv6_address_count                   = (known after apply)
      + ipv6_addresses                       = (known after apply)
      + key_name                             = (known after apply)
      + monitoring                           = (known after apply)
      + outpost_arn                          = (known after apply)
      + password_data                        = (known after apply)
      + placement_group                      = (known after apply)
      + placement_partition_number           = (known after apply)
      + primary_network_interface_id         = (known after apply)
      + private_dns                          = (known after apply)
      + private_ip                           = (known after apply)
      + public_dns                           = (known after apply)
      + public_ip                            = (known after apply)
      + secondary_private_ips                = (known after apply)
      + security_groups                      = (known after apply)
      + source_dest_check                    = true
      + subnet_id                            = (known after apply)
      + tags                                 = {
          + "Name" = "ExampleAppServerInstance"
        }
      + tags_all                             = {
          + "Name" = "ExampleAppServerInstance"
        }
      + tenancy                              = (known after apply)
      + user_data                            = (known after apply)
      + user_data_base64                     = (known after apply)
      + user_data_replace_on_change          = false
      + vpc_security_group_ids               = (known after apply)
    }

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

그리고 나서 apply를 실행시켜보니까 잘 됩니다.

❯ terraform apply
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: Still creating... [40s elapsed]
aws_instance.app_server: Creation complete after 42s [id=i-0abf0c194ace11c2c]

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

오. AWS 사이트에도 잘 보입니다. EBS도 생성이 되었습니다.

Destroy Infrastructure

계속 놔두면 돈 나가니까 이제 삭제하고 마무리하도록 하겠습니다. 삭제는 간단합니다.

❯ terraform destroy
aws_instance.app_server: Refreshing state... [id=i-0abf0c194ace11c2c]

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

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value:  yes

aws_instance.app_server: Destroying... [id=i-0abf0c194ace11c2c]
aws_instance.app_server: Still destroying... [id=i-0abf0c194ace11c2c, 10s elapsed]
aws_instance.app_server: Still destroying... [id=i-0abf0c194ace11c2c, 20s elapsed]
aws_instance.app_server: Destruction complete after 30s

Destroy complete! Resources: 1 destroyed.

참고. Git에 Terraform 올릴때 gitIgnore는 어떻게 할까

gitIgnore 참고. 뭔가 내부 설정은 올리면 안될거 같긴해서... 다른 terraform aws modules를 찾아봤습니다.

참고 : https://github.com/terraform-aws-modules/terraform-aws-vpc/blob/master/.gitignore

# Local .terraform directories
**/.terraform/*

# Terraform lockfile
.terraform.lock.hcl

# .tfstate files
*.tfstate
*.tfstate.*

마치면서

이번 시간에는 간단하게 테라폼을 알아보고 테라폼을 사용하기 위한 사전 설치와 EC2를 올렸다가 내려보는 간단한 실습을 진행해봤습니다.

저는 개인적으로 프론트엔드 개발자라서 백엔드는 몰라도 된다고 생각하지는 않습니다. 그러기에는 너무 아쉽기 때문이죠. 좀 더 넓은 사고를 갖기 위해서라도 백엔드도 어느 정도 알아두면 도움이 됩니다. 그래서 그런지 콴다 개발 블로그 를 보면 참 많은 생각이 드는거 같습니다. 참고해보시면 좋을거 같습니다.

물론, 프론트엔드 공부도 소홀히 할 수 없겠죠? ㅎㅎ


참고 자료

profile
배움을 좋아합니다. 새로운 것을 좋아합니다.

0개의 댓글