Skip to Content
ArchiveEKS IaC

EKS IaC

Infrastructure as Code 의 줄인말로, 구성할 인프라를 코드로 선언하는 방식입니다.

Hashicorp 사에서 공개한 도구인 Terraform 을 이용하여 AWS 자원을 프로비저닝 해볼 생각입니다.

실습은 Mac 에서 진행하기위해 brew로 설치를 진행합니다

# tfenv 설치 brew install tfenv # 설치 가능 버전 리스트 확인 tfenv list-remote # 테라폼 1.5.1 버전 설치 tfenv install 1.8.1 # 테라폼 1.5.1 버전 사용 설정 tfenv use 1.8.1 # tfenv로 설치한 버전 확인 tfenv list # 테라폼 버전 정보 확인 terraform version # 자동완성 terraform -install-autocomplete ## 참고 .zshrc 에 아래 추가됨 cat ~/.zshrc autoload -U +X bashcompinit && bashcompinit complete -o nospace -C /usr/local/bin/terraform terraform # AWS CLI 설치 brew install awscli # EKSCTL 설치 brew install eksctl # Kubectl 설치 brew install kubernetes-cli # Helm 설치 brew install helm # 추가 도구 설치 brew install tree jq watch

VS Code Extension 설치

Extension → HashiCorp HCL 설치

Untitled

기본 환경준비

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

사용하려는 최신 AL2 ami ID 검색

AL2ID=`aws ec2 describe-images --owners amazon --filters "Name=name,Values=amzn2-ami-hvm-2.0.*-x86_64-gp2" "Name=state,Values=available" --query 'Images|sort_by(@, &CreationDate)[-1].[ImageId]' --output text` echo $AL2ID

리소스 생성 Test

cat <<EOT > main.tf provider "aws" { region = "ap-northeast-2" } resource "aws_instance" "example" { ami = "$AL2ID" instance_type = "t2.micro" } EOT

배포하기

# plan 실행 시 아래와 같은 정보가 출력 terraform plan # apply 실행 terraform apply # Enter a value: yes 입력

삭제

# 리소스 삭제 terraform destroy -auto-approve

HCL

HCL(HashiCorp Configuration Language)은 Hashicorp사에서 IaC와 구성 정보를 명시하기 위해 개발된 오픈 소스 도구입니다.

HCL 특징

  • IaC는 코드를 통해 인프라를 관리하고 프로비저닝
  • HCL이 테라폼에서의 코드영역. 읽기쉽고 빠르게 배울 수 있게 설계
  • 선언적(declarative) 특성을 갖고 Turing-complete 언어적 특성

Untitled

json type으로 생성하는것보다 훨씬 간결하고 읽기 쉽다는 점이 제일 큰 장점입니다.

json type에 비해 약 50~70%정도 짧아진다고 하네요

HCL에서 사용하는 표현식은 다음과 같습니다

// 한줄 주석 방법1 # 한줄 주석 방법2 /* 라인 주석 */ locals { key1 = "value1" # = 를 기준으로 키와 값이 구분되며 myStr = "TF ♡ UTF-8" # UTF-8 문자를 지원한다. multiStr = <<EOF Multi Line String with anytext EOF boolean1 =true # boolean true boolean2 =false # boolean false를 지원한다. deciaml = 123 # 기본적으로 숫자는 10진수, octal = 0123 # 0으로 시작하는 숫자는 8진수, hexadecimal = "0xD5" # 0x 값을 포함하는 스트링은 16진수, scientific = 1e10 # 과학표기 법도 지원한다. # funtion 호출 예 myprojectname = format("%s is myproject name", var.project) # 3항 연산자 조건문을 지원한다. credentials = var.credentials == "" ? file(var.credentials_file) : var.credentials }

테라폼 블록

테라폼 버전이나 프로바이더 버전들은 명시적으로 선언해 실행 오류를 최소화하는것을 목표로 합니다.

멱등성을 보장하기 위해서죠

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" } }

버전 체계는 시맥틴 버전관리를 따라

# version = Major.Minor.Patch version = 1.3.4

일반적으로 MAJOR.MINOR.PATCH 형태로 표현됩니다.

  • MAJOR: 호환되지 않는 API 변경
  • MINOR: 기존 버전과 호환되는 새로운 기능 추가
  • PATCH: 기존 버전과 호환되는 버그 수정

테라폼에서의 버전 제약 구문은 다른 프로그래밍 언어의 종속성 관리와 매우 유사하게 동작합니다. 여기 몇 가지 주요 연산자와 그들이 어떻게 작동하는지에 대한 간단한 요약입니다:

  • = 또는 없음: 이 연산자는 오직 지정된 버전만을 허용합니다. 다른 조건과는 병합될 수 없습니다.
  • !=: 이 연산자는 지정된 버전을 제외하고 모든 것을 허용합니다.
  • >, >=, <, <=: 이 연산자들은 기본 수학적 비교를 수행하여 버전을 허용하거나 제외합니다.
  • ~>: 이 연산자는 “거의 동일한” 버전을 허용합니다. 지정된 버전의 마지막 숫자만이 증가할 수 있습니다. 예를 들어, **~> 1.2**는 1.3, 1.4 등을 허용하지만 2.0은 허용하지 않습니다.

리소스 구성

리소스 블록은 Terraform 코드에서 실제 클라우드 리소스를 선언하고 생성합니다.

  • 기본 구조resource 를 사용하여 리소스 블록을 시작합니다.
  • 리소스 유형resource 프로바이더에 종속적입니다.
  • 이름: 동일한 유형의 리소스를 구분하기 위해 사용합니다.
  • 구성 인수: 중괄호 &#123;&#125; 안에는 해당 리소스의 속성이나 설정을 정의합니다.

코드 예시

resource "local_file" "abc" { content = "123" filename = "${path.module}/abc.txt" } resource "aws_instance" "web" { ami = "ami-a1b2c3d4" instance_type = "t2.micro" }

주의사항

  • 프로바이더 블록 별도 선언 권장resource 블록에서 사용되는 리소스 유형은 특정 프로바이더에 종속되기 떄문에 별도로 프로바이더를 선언하는 것이 권장됩니다.

종속성

resource, module의 선언으로 프로비저닝 되는 요소의 순서를 정의할수있습니다.

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

이런식으로 def는 abc를 참조해야만 생성이 가능하지만, 명시적인 depend_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" }

리소스 속성

  • 리소스 구성에서 참조 가능한 값은 인수속성이다
    • 인수 : 리소스 생성 시 사용자가 선언하는 값
    • 속성 : 사용자가 설정하는 것은 불가능하지만 리소스 생성 이후 획득 가능한 리소스 고유 값
# Terraform Code resource "<리소스 유형>" "<이름>" { <인수> = <값> } # 리소스 참조 <리소스 유형>.<이름>.<인수> <리소스 유형>.<이름>.<속성> resource "kubernetes_namespace" "example" { metadata { annotations = { name = "example-annotation" } name = "terraform-example-namespace" } } resource "kubernetes_secret" "example" { metadata { namespace = kubernetes_namespace.example.metadata.0.name # namespace 리소스 인수 참조 name = "terraform-example" } data = { password = "P4ssw0rd" } }

쿠버네티스 프로바이더의 Namespace를 리소스로 생성해,

Secret을 해당 Namespace에 생성하는 종속성을 갖는 예시입니다.

Namespace 가 바뀌어도 참조중인 모든 리소스가 업데이트되죠.

데이터 소스 구성

**데이터 소스**는 외부 리소스나 저장된 정보를 참조할 때 사용합니다.

데이터 소스를 설정하는 방법은 리소스 블록을 정의하는 것과 비슷합니다.

데이터 소스 유형은 프로바이더 이름과 리소스 유형으로 구성되며, 이후에는 고유한 이름과 구성 인수를 선언합니다.

cat <<'EOT' > main.tf data "local_file" "abc" { filename = "${path.module}/abc.txt" } EOT

메타인수로는 depends_oncountfor_eachlifecycle 등이 사용 가능합니다.

  • depends_on : 종속성을 선언하며, 선언된 구성요소와의 생성 시점에 대해 정의
  • count : 선언된 개수에 따라 여러 리소스를 생성
  • for_each : map 또는 set 타입의 데이터 배열의 값을 기준으로 여러 리소스를 생성
  • lifecycle : 리소스의 수명주기 관리