"Everything about infra" 2026. 3. 13. 02:02

안녕하세요,

좋은 기회를 얻어 CloudNet@ 팀 'Gasida' 님이 진행하시는

스터디 모임 4기에 참여하게 되었습니다.

모임에서 진행되는 스터디 내용들을 포스팅 해보도록 하겠습니다 !

 

EKS를 알아보기에 앞서, Terraform으로 구축을 하기 때문에

기초적인 선수지식을 알아본 후에 진행하도록 하겠습니다.

 

 

포스팅에 앞서, 해당 내용들은 '테라폼으로 시작하는 IaC' 책을 기준하여
정리하였음을 사전에 알려드리며 시작하도록 하겠습니다.

 

01. Terraform 이란?

  • Hashicorp에서 오픈소스로 개발중인 클라우드 인프라스트럭쳐 자동화를 지향하는 laC 도구
  • HCL (Hashicorp Configuration Language) 언어를 사용하여 리소스를 선언
  • CloudFormation과 달리 AWS, Azure, GCP와 같은 클라우드 서비스에 대해서 provider 방식으로 제공
  • 인스턴스, 네트워크와 같은 low-level 뿐 아니라 DNS, SaaS와 같은 high-level의 요소도 관리 가능.

 

📌 특징

  1. 말 그대로, IaC (Infrastructure as Code)
    • 인프라를 코드로 정의하여 생산성과 투명성을 높임
    • 정의한 코드를 쉽게 공유할 수 있어 효율적으로 협엽 가능합니다.
  2. Execution Plan
    • 변경 계획과 변경 적용을 분리하여 변경 내용을 적용할 때 발생할 수 있는 실수를 줄일 수 있음
  3. Resource Graph
    • 사소한 변경이 인프라 전체에 어떤 영향을 미칠지 미리 확인 가능
    • 종속성 그래프를 작성하여 이 그래프를 바탕으로 계획을 세우고, 적용했을 때 변경되는 인프라 상태 확인 가능.
  4. Change Automation
    • 여러 장소에 같은 구성의 인프라를 구축하고 변경할 수 있도록 자동화 가능
    • 인프라를 구축하는 데 드는 시간을 절약, Human Error 감소

 

📌 Deploy Workflow

  1. Write : Terraform으로 구성하고자 하는 Code를 .tf 파일로 작성
  2. Plan :  인프라를 원하는 방향으로 구성한 후, 위 명령을 통해 예상되는 변경점을 미리 확인해보는 단계
  3. Apply : 작성한 코드를 실제로 배포하는 단계이며, 선후관계를 명시하지 않아도 자동으로 병렬적으로 실행됨.
  4. Destory : 위 그림에는 없지만, 제로의 상태로 돌아오는 과정 (=삭제)이라고 생각해주시면 됩니다.

 

📌 장단점은?

  1. 장점
    • 콘솔에 로그인할 필요없이 서버 운영 및 관리가 모두 자동화
    • 사람이 수동으로 작업하는 것보다 빠르게 배포 가능.
    • 유효성 검증을 통해 문제가 발생하는것을 어느 정도 예방 가능함.
    • 일관성 있다!
  2. 단점
    • AWS 설정을 terraform 으로 한번에 migration 하기 어려움
    • 배포 전략이 제한적이다. (Blue/Green 배포를 구현할 수 없음)
    • 러닝 커브(Learning Curve)가 많이 존재한다. (HCL 문법이 보다 어려움)
    • plan과 apply 명령어의 차이 (plan에선 성공하지만 현재 state에 따라서 apply는 실패할 수 있음)
    • 프로젝트 규모가 커질수록 배포시 점점 더 느려진다.

 


1-1. HCL 문법 vs JSON 문법

먼저 Terraform의 기본 문법은 HCL이며, JSON 문법과 비교하였을 때 확연히 뛰어나보인다!

 

📌 기본 문법 (HCL)

.tf 파일 형태로 이루어져 있으며, 문법 정의를 보다 쉽게 할 수 있습니다.

resource "aws_s3_bucket" "example" {
  bucket = "my-bucket"
  acl    = "private"
}
  • 위 예시와 같이 구조가 간결하고 Convention 규칙(indent = 2 space)을 사용하여 가독성이 뛰어남.
  • 블록 기반, key/value 기반 구조.
  • 인프라가 코드로 표현되고, 이 코드는 곧 인프라를 나타내기 때문에 선언적 특성을 갖게 된다.
    • 이를 '튜링 완전한 Turing-complete 언어적 특성' 이라고 부른다.

 

📌 JSON 문법

주로 CloudFormation에서 사용되며 HCL 문법과 다르게 JSON 문법은 확실히 복잡해 보인다!

{
  "resource": {
    "aws_s3_bucket": {
      "example": {
        "bucket": "my-bucket",
        "acl": "private"
      }
    }
  }
}
  • 확실히 HCL 문법보다 가독성이 떨어지는 것을 확연하게 실감할 수 있다.
  • 긴 구조를 반복적으로 사용해야 하는 특징이 있으며 매핑/템플릿 함수 구조가 복잡합니다.
  • 자동화 스크립트나 외부 시스템이 Terraform 코드를 생성할 때 사용된다. (기계 친화적)

 


1-2. Terraform 내부 구조 (Core Architecture)

📌 Terraform core

  • .tf 파일 파싱 (HCL parser)
  • State 파일 로딩 및 비교
  • Plan 단계에서 diff 생성
  • Graph builder: Dependency Graph 생성
  • Apply에서 CRUD 실행
뭔가 직관적으로 와닿지가 않을 수도 있으므로, 아래와 같이 예시를 한번 들어보겠습니다.
Terraform core : 요리사 '두뇌' 라고 가정해봅시다.

.tf 파일(레시피)을 읽고, 현재 냄비 및 조리 도구 상태 확인 (State file) 후, 필요한 재료를 비교합니다(Plan diff)
비교를 마친 후 어떤 순서로 조리를 해야할 지 그래프로 분석한 후 마지막에 실제로 조리합니다(apply)

 

📌 Provider Plugin

실제 클라우드 API 호출은 Provider가 담당합니다.

공식 Provider는 AWS, Azure, GCP등이 있으며, Hashicorp가 직접 유지 관리합니다.

  • Provider 특성 : 독립 바이너리, gRPC기반 통신
    • 각 Provider는 자체 Schema 정의 (Resource, Data Source etc..)
Provider : 요리사의 '팔'이라고 생각하시면 되겠습니다.

Core는 두뇌 이기 때문에 직접 요리에 물리적으로 가담하지 못합니다.
Core는 AWS에게 어떠한 요리를 만들어라! 라고 제시할 뿐, 직접 요리를 하는 녀석이 Provider라고 보시면 될 것 같습니다.
(AWS Provier : AWS API만 다루는 요리사의 팔)

 

📌 Modules

재사용 가능한 코드를 구성하거나 리소스 설정을 패키징할 때 사용된다.

  • 내부 모듈 (로컬)
  • 외부 모듈 (Terraform Registry)
Module : 반찬 세트라고 가정해봅시다.

저희가 요리를 할 때 매번 양념장을 처음부터 만들지 않고, 사전에 준비를 해둔다고 생각하시면 될 것 같습니다.
"모듈"이라는 반찬 세트(양념장들)를 가져다 쓰는 것.

ex: VPC module, ALB module etc..

 

또한, 모든 terraform 설정은 적어도 하나의 module로 구성된다 (=root module)

  • child module : root module 내의 다른 module (ex: main.tf 파일 외 다른 .tf 파일)
  • 즉, 함께 사용되는 여러개의 리소스에 대한 컨테이너

 


02. Terraform Block

terraform {} 블록은 Terraform 자체 설정을 정의하는 최상위 블록이며, 아래 항목들을 선언하여 사용

  • terraform version
  • provider version
  • cloud block
  • backend block
terraform {
  required_version = "~> 1.3.0" # 테라폼 버전

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

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

  backend "local" { # state를 보관하는 위치를 지정
    path = "relative/path/to/terraform.tfstate"
  }
}

 

테라폼 내에서 버전이 명시되는 terraform, module에서 사용 가능하며 버전에 대한 제약을 둠으로써

테라폼, 프로바이더, 모듈이 항상 의도한 정의대로 실행되는 것을 목적으로 한다.

 

위 코드에서 버전 연산자가 각각 다른데, "Semantic Versioning" 방식을 따릅니다.

 

📌 버전 제약 구문

  • Major : 내부 동작의 API가 변경 또는 삭제되거나 하위 호환이 되지 않는 버전
  • Minor : 신규 기능이 추가되거나 개선되고 하위 호환이 가능한 버전
  • Patch : 버그 및 일부 기능이 개선된 하위 호환이 가능한 버전
구문 의미 고려 사항
= 1.3.0 해당 버전만 사용 테라폼을 업그레이드 하기 위해선 선언된 버전을 변경해야 함.
>= 1.3.0 이상 모든 버전 허용 v1.3.0 버전을 포함해 그 이상의 모든 버전을 허용해 실행된다
~> 1.3.0 1.3.x만 허용 (1.4 이상 불가) 부 버전에 대한 업데이트는 무중단으로 이루어진다.
>= 1.0, < 2.0 1.x 계열만 허용 주 버전에 대한 업데이트를 방지한다.

 

 

📌 Cloud block

 

cloud 블록은 Terraform 실행 환경을 Terraform Cloud / Enterprise에 위임할 때 사용한다.

  • provider 블록 → "어디에 인프라를 만들 거냐" (AWS, GCP 등)
  • cloud 블록 → "terraform plan/apply를 어디서 실행할 거냐"

그래서 cloud 블록이 있어도 provider "aws"는 여전히 따로 선언해야 합니다!

(실행은 Terraform Cloud가 하더라도, AWS에 리소스를 만드는 건 별개의 설정이니까요)

 

즉, 로컬에서 직접 실행하지 않고 Terraform Cloud에 실행을 위임하고 싶을 때 선언한다.

(반대로, 로컬에서 'terraform apply'를 직접 치면 cloud 블록이 필요 없어요)

terraform {
  cloud {
    hostname     = "app.terraform.io"  # 기본값, Terraform Cloud URL
    organization = "my-org"

    workspaces {
      name = "my-app-prod"
    }
  }
}

 

 

📌 Backend block

 

backend 란? 상태 저장소를 나타내며, Terraform은 영구적인 state data 파일을 계속 관리해야 함

즉, backend = state data file 저장 위치.

 

⚠️ 주의할 점

  • backend block은 하나의 백엔드만 사용된다.
  • 현업 특성 상 상태 저장 파일을 공유할 수 있는 외부 백엔드 저장소가 필요한데, 외부로 노출되면 안되는 패스워드나 인증서 같은 민감정보 및 데이터들이 포함될 수 있으므로 "접근 제어"가 반드시 필요하다.
  • backend 설정 변경 시 반드시 'terraform init' 재실행.

 

백엔드의 특징 'State 잠금 동작'

  • 백엔드 구성은 동시에 여러 작업자가 접근해 사용할 수 있도록 공유 스토리지 같은 개념을 갖는다.
  • 공유되는 백엔드에 State가 관리되면 테라폼이 실행되는 동안 .terraform.tfstate.lock.info 파일이 생성되면서 해당 State를 동시에 사용하지 못하도록 잠금 처리를 한다.

예를들어, 팀원 A가 terraform apply 실행 중인데, 팀원 B도 동시에 terraform apply를 실행하면

같은 state 파일을 동시에 수정하게 돼서 state가 망가질 수 있다.

A: terraform apply 실행 중 → 🔒 lock 생성
B: terraform apply 시도   → ❌ "이미 lock 걸려있음, 대기"
A: apply 완료             → 🔓 lock 해제
B: terraform apply 실행 가능 ✅

 

⚠️ 만약, State 파일을 강제로 삭제하게 된다면?

 

Terraform 입장에서는 "인프라가 아무것도 없다"라고 인식된다.

실제로 AWS에 VPC, EC2 등이 멀쩡히 떠 있어도, state 파일이 없으면 Terraform은 그 리소스들의 존재를 모름.

 

terraform plan 실행 시

실제론 있는데 state가 없으니 "새로 만들어야 함"으로 인식
+ aws_vpc.main        (새로 생성 예정)
+ aws_subnet.public   (새로 생성 예정)

 

terraform apply 실행 시

  • AWS API를 호출해서 리소스를 생성 시도
  • AWS 입장에서는 이미 동일한 이름/설정의 리소스가 존재하면 "이미 있어" 라고 에러를 반환

결론적으로 state를 날리면 실제 인프라는 그대로인데 Terraform만 모르는 상태가 되는 거고,

이걸 복구하려면 terraform import로 기존 리소스를 state에 다시 등록해야 한다.

 


 

긴 글을 읽어주셔서 감사합니다.

 

다음 챕터에서는, 실제로 도전과제를 수행하는 포스팅으로 찾아 뵙도록 하겠습니다.