테라폼/T101[3기]

T101 - 1주차

시스템 엔지니어 2023. 9. 2. 08:39

1주차 목표

  • IaC와 테라폼을 이해하고 스터디에 필요한 실습 환경을 구성합니다.
  • 테라폼 기본 명령 사용법을 알아봅니다.
  • HCL을 이해하고 기본 활용 방법을 학습합니다.
  • 샘플코드 작성 및 배포를 실습합니다.

 

목표1) 실습 환경 구성

윈도우11 WSL2 설치

WSL2란? https://learn.microsoft.com/ko-kr/windows/wsl/about

WSL2 설치 완료

 

IDE 구성 및 확장 설치

  • HashiCorp HCL
  • HashiCorp Terraform
  • WSL

WSL2 Ubuntu에 테라폼설치 https://developer.hashicorp.com/terraform/downloads

[스터디 전용/실습1] AWS CLI 설치 및 자격증명

[스터디 전용/실습2] EC2 1대 배포

mkdir t101-1week-ec2
cd t101-1week-ec2

cat <<EOT > main.tf
provider "aws" {
  region = "ap-northeast-2"
}

resource "aws_instance" "example" {
  ami           = "ami-084e92d3e117f7692"
  instance_type = "t2.micro"
}
EOT

# 초기화
terraform init
ls -al
tree .terraform

# plan 확인
terraform plan

# apply 실행
terraform apply
 Enter a value: yes 입력

tags를 추가하여 인스턴스 이름 변경

cat <<EOT > main.tf
provider "aws" {
  region = "ap-northeast-2"
}

resource "aws_instance" "example" {
  ami           = "ami-084e92d3e117f7692"
  instance_type = "t2.micro"

  tags = {
    Name = "t101-study"
  }

}
EOT

[스터디 전용/실습3] EC2 1대 배포 & 웹 서버 설정

cat <<EOT > main.tf
provider "aws" {
  region = "ap-northeast-2"
}

resource "aws_instance" "example" {
  ami                    = "ami-0c9c942bd7bf113a2"
  instance_type          = "t2.micro"

  user_data = <<-EOF
              #!/bin/bash
              echo "Hello, T101 Study" > index.html
              nohup busybox httpd -f -p 8080 &
              EOF

  tags = {
    Name = "terraform-Study-101"
  }
}
EOT

접속 불가

Security Group 문제로 인한 접속 불가

Security Group 추가

cat <<EOT > main.tf
provider "aws" {
  region = "ap-northeast-2"
}

resource "aws_instance" "example" {
  ami                    = "ami-0c9c942bd7bf113a2"
  instance_type          = "t2.micro"
  vpc_security_group_ids = [aws_security_group.instance.id]

  user_data = <<-EOF
              #!/bin/bash
              echo "Hello, T101 Study" > index.html
              nohup busybox httpd -f -p 8080 &
              EOF

  tags = {
    Name = "Single-WebSrv"
  }
}

resource "aws_security_group" "instance" {
  name = var.security_group_name

  ingress {
    from_port   = 8080
    to_port     = 8080
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

variable "security_group_name" {
  description = "The name of the security group"
  type        = string
  default     = "terraform-example-instance"
}

output "public_ip" {
  value       = aws_instance.example.public_ip
  description = "The public IP of the Instance"
}
EOT

웹 접근 확인

[도전과제1] EC2 웹 서버 배포

목표

EC2 웹 서버 배포 : Ubuntu 에 apache(httpd) 를 설치하고 index.html 생성(닉네임 출력)하는 user_data 를 작성해서 설정 배포, 포트는 TCP 80 후 curl 접속 → 해당 테라폼 코드(파일)를 작성

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

resource "aws_instance" "example" {
  ami                    = "ami-0c9c942bd7bf113a2"
  instance_type          = "t2.micro"
  vpc_security_group_ids = [aws_security_group.instance.id]

  user_data = <<-EOF
              #!/bin/bash
              echo "Hello, T101 Study Thumbup" > index.html
              nohup busybox httpd -f -p 80 &
              EOF

  tags = {
    Name = "Single-WebSrv"
  }
}

resource "aws_security_group" "instance" {
  name = var.security_group_name

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

variable "security_group_name" {
  description = "The name of the security group"
  type        = string
  default     = "terraform-example-instance"
}

output "public_ip" {
  value       = aws_instance.example.public_ip
  description = "The public IP of the Instance"
}

HCL 특징 (HashiCorp Configuration Language)

  • HCL은 가장 빠르게 성장한 언어중 하나이다.
  • Json을 기반으로 만든 언어이지만, json이랑 다르고 사람이 사용하기 친숙하게 만든 언어이다.
  • 일반적인 프로그래밍 언어의 조건문 반복문 같은 동작이 가능하다.
딱 봐도 HCL이 보기편하다

주석이 가능하다
// 한줄 주석 방법1
# 한줄 주석 방법2

/*
라인
주석
*/​

 

'=' 를 기준으로 키와 값이 구분되며
UTF-8 문자를 지원한다.
locals {
  key1     = "value1"     # = 를 기준으로 키와 값이 구분되며
  myStr    = "TF ♡ UTF-8" # UTF-8 문자를 지원한다.
boolean 을 지원하고
기본적으로 숫자는 10진수
0으로 시작하는 숫자는 8진수
0x 값을 포함하는 스트링은 16진수
과학표기 법도 지원한다.
boolean1    = true   # boolean true
boolean2    = false  # boolean false를 지원한다.
deciaml     = 123    # 기본적으로 숫자는 10진수,
octal       = 0123   # 0으로 시작하는 숫자는 8진수,
hexadecimal = "0xD5" # 0x 값을 포함하는 스트링은 16진수,
scientific  = 1e10   # 과학표기 법도 지원한다.​

 

function 호출
3항 연산자 조건문을 지원한다.
  # function 호출 예
  myprojectname = format("%s is myproject name", var.project)

  # 3항 연산자 조건문을 지원한다.
  credentials = var.credentials == "" ? file(var.credentials_file) : var.credentials

 

테라폼 블록

테라폼 구성을 명시하는 데 사용한다.

오늘 실행하던, 3년 후에 실행하던 동일한 결과를 얻을 수 있어야 한다! (Desired State + Immutable)

  • 버전을 명시하지 않으면 최신 버전으로 사용 된다.
  • 버전을 명시하지 않으면, 과거에 작업 했던 결과물이 동일하게 배포되지 않는 이슈가 생길 수 있다.
  • Best Practice는 없지만 Badder Practice는 있다.
    • 운영상 버전을 명시하지 않는 것은 Badder Practice라고 본다.
terraform {
  required_version = "~> 1.3.0" # 테라폼 버전

  required_providers { # 프로바이더 버전을 나열
    random = {
      version = ">= 3.0.0, < 3.1.0"
    }
    aws = {
      version = "4.2.0"
    }
  }

  cloud { # Cloud/Enterprise 같은 원격 실행을 위한 정보 [참고: Docs]
    organization = "<MY_ORG_NAME>"
    workspaces {
      name = "my-first-workspace"
    }
  }

  backend "local" { # state를 보관하는 위치를 지정 [참고: Docs, local, remote, s3]
    path = "relative/path/to/terraform.tfstate"
  }
}
  • 시맨틱 버전 관리 방식
    • Major 버전 : 내부 동작의 API가 변경 또는 삭제되거나 하위 호환이 되지 않는 버전
    • Minor 버전 : 신규 기능이 추가되거나 개선되고 하위 호환이 가능한 버전
    • Patch 버전 : 버그 및 일부 기능이 개선된 하위 호환이 가능한 버전
  • 버전 제약 구문은 다른 프로그램 언어에서의 종속성 관리 시스템과 흡사하다.
    • = 또는 연산자 없음 : 지정된 버전만을 허용하고 다른 조건과 병기할 수 없다.
    • != : 지정된 버전을 제외한다.
    • >, >=, <, <= : 지정된 버전과 비교해 조건(부등호)에 맞는 경우 허용한다.
      • ~> : 지정된 버전에서 가장 자리수가 낮은 구성요소만 증가하는 것을 허용한다.
        • ~> x.y 인 경우 y 버전에 대해서만, ~> x.y.z인 경우 z 버전에 대해서만 보다 큰 버전을 허용한다

  • 프로바이더 버전
    • 우측 상단의 [USE PROVIDER]를 클릭하면 테라폼 코드에 해당 버전을 사용하는 샘플 코드가 표기된다. - 링크

백엔드 블록

  • 주의할점
  • state 잠금 동작
    • 기본적으로 활성화되는 백엔드local이다.
    • 상태를 작업자의 로컬 환경저장하고 관리하는 방식이다.
    • 이 밖의 다른 백엔드 구성은 동시에 여러 작업자가 접근해 사용할 수 있도록 공유 스토리지 같은 개념을 갖는다.
    • 공유되는 백엔드에 State가 관리되면 테라폼이 실행되는 동안 .terraform.tfstate.lock.info 파일이 생성되면서 해당 State를 동시에 사용하지 못하도록 잠금 처리를 한다.
ID:        30773305-a78d-49f1-8f3f-5604d742b66f
Operation: OperationTypeApply                      # 어떤 동작으로 인해 해당 잠금 파일이 생성되었는지 명기
Info:
Who:       gasida@seojonghoui-MacBookPro.local     # 작업자 정보
Version:   1.5.1                                   # 실행한 테라폼 버전
Created:   2023-06-28 12:23:59.113608 +0000 UTC
Path:      state/terraform.tfstate                 # 잠긴 state 파일의 위치

리소스 

리소스 블록은 resource로 시작한다. 이후 리소스 블록이 생성할 ‘리소스 유형’을 정의한다.

  • 리소스 동작 보조 추가 메타인수를 정의 할 수 있다
    • depends_on : 종속성을 선언하며, 선언된 구성요소와의 생성 시점에 대해 정의
    • count : 선언된 개수에 따라 여러 리소스를 생성
    • for_each : map 또는 set 타입의 데이터 배열의 값을 기준으로 여러 리소스를 생성
    • provider : 동일한 프로바이더가 다수 정의되어 있는 경우 지정
    • lifecycle : 리소스의 수명주기 관리
    • provisioner : 리소스 생성 후 추가 작업 정의
    • timeouts : 프로바이더에서 정의한 일부 리소스 유형에서는 create, update, delete에 대한 허용 시간 정의 가능

종속성

File "abc"와 File "def"를 생성후 종속성 테스트를 진행해 본다.

resource "local_file" "abc" {
  content  = "123!"
  filename = "${path.module}/abc.txt"
}

resource "local_file" "def" {
  content  = "456!"
  filename = "${path.module}/def.txt"
}

File "def" 가 File "abc"를 바라보게 한다.

resource "local_file" "abc" {
  content  = "123!"
  filename = "${path.module}/abc.txt"
}

resource "local_file" "def" {
  content  = local_file.abc.content    # 123! 
  filename = "${path.module}/def.txt"
}

depends_on 메타인수로 명시적으로 종속성을 부여한다.

resource "local_file" "abc" {
  content  = "123!"
  filename = "${path.module}/abc.txt"
}

resource "local_file" "def" {
  depends_on = [
    local_file.abc
  ]

  content  = "456!"
  filename = "${path.module}/def.txt"
}

 

느낀점

기본환경 구축해 보면서, 사용해보지 못했던 환경이었는데,
당장 업무하는데 사용해도 도움이 많이 될 것이라고 느꼈습니다.
테라폼에 기본 사용방법은 해당 교육으로 알게 되었네요.
의존성 파악할때 그래프를 그려 파악도 해볼수 있을 것 같습니다.
교육이 많은 도움이 되었습니다.