사전 상태 파일
개념

상태 파일

gabury1고친 사람 github-actions[bot]

상태 파일은 인프라를 코드로 관리하는 도구에게 자기가 무엇을 만들었는지 알려 줍니다. 코드에 적힌 이름과 클라우드에 생긴 자원을 하나씩 짝지어 적어 둡니다. 도구는 다음에 돌 때 이 짝을 보고 무엇을 새로 만들고 무엇을 고칠지 정합니다. 이 파일을 잃으면 도구는 자기가 만든 자원을 알아보지 못합니다.

쉽고 빠른 이해

무슨 일을 하나 — 코드 속 이름과 클라우드의 실물을 잇는 기록입니다. 코드에서 web 이라고 부르는 서버가 클라우드에서는 i-0a1b2c3d 라는 번호로 있다고 적어 둡니다.

왜 필요한가 — 상태 파일이 없으면 도구는 이미 만든 서버를 모릅니다. 다음 실행 때 같은 것을 또 만들려 합니다. 코드에서 지운 자원도 찾아서 지우지 못합니다.

어떻게 도나

  1. 자원을 만든 뒤 짝을 상태 파일에 적습니다
  2. 다음 실행 때 상태 파일에 적힌 자원의 지금 모습을 클라우드에서 읽어 옵니다
  3. 코드와 견줘 다른 것만 바꾸고 상태 파일을 새로 적습니다

대가 — 상태 파일에 비밀번호까지 그대로 적힙니다. 잃거나 두 사람이 동시에 고치면 인프라가 꼬입니다. 그래서 팀은 상태 파일을 한곳에 모아 둡니다. 그리고 한 번에 한 사람만 고치게 막습니다.

상세

이 절은 상태 파일이 무엇과 무엇을 잇는지부터 정합니다. 이어서 한 번의 실행에서 이 파일이 어떻게 읽히고 다시 적히는지 따라갑니다. 뒤쪽에서는 도구 하나의 상태 파일을 열어 안에 무엇이 드는지 봅니다. 마지막으로 여럿이 함께 쓸 때 생기는 문제를 봅니다.

발렛 주차를 떠올려 보면 쉽습니다. 직원은 차 키를 받을 때마다 번호표를 건네고 장부에 「7번 표는 지하 2층 14번 칸」이라고 적습니다. 장부가 사라져도 차는 주차장에 그대로 있습니다. 다만 어느 칸의 차가 몇 번 표의 것인지 아무도 모릅니다.

코드의 이름과 실물의 식별자

코드형 인프라는 서버·네트워크·저장소 같은 인프라를 손 대신 코드로 만들고 관리하는 방식입니다. 설정 파일에 「있어야 할 모습」을 적으면 도구가 클라우드에 요청을 보내 그 모습을 만듭니다. 이렇게 적어 둔 모습을 원하는 상태라 하고, 클라우드에 지금 있는 모습을 실제 상태라 합니다.

도구가 만드는 서버 한 대, 저장소 하나를 자원이라 부릅니다. 설정 파일은 자원마다 사람이 붙인 이름을 씁니다. 예를 들어 웹 서버 한 대를 web 이라고 부릅니다. 이 이름은 설정 파일 안에서만 쓰입니다. 클라우드는 이 이름을 모릅니다.

클라우드는 자원을 만들 때 자기 쪽 식별자를 붙입니다. 식별자는 그 자원 하나를 가리키는 고유한 값입니다. 서버라면 i-0a1b2c3d 같은 문자열을 클라우드가 정해 돌려줍니다. 사람은 이 값을 미리 알 수 없습니다. 자원이 만들어진 뒤에야 받습니다.

상태 파일은 이 둘을 짝지어 적습니다. 「설정 파일의 web 은 클라우드의 i-0a1b2c3d 다」 같은 줄이 자원마다 하나씩 들어갑니다. 짝과 함께 자원을 만들 때 받은 속성 값도 적어 둡니다.

flowchart TD
    C["설정 파일 · 사람이 붙인 이름 web"] --> S["상태 파일 · web 은 i-0a1b2c3d"]
    S --> R["클라우드 · 식별자 i-0a1b2c3d 인 서버"]

그림처럼 설정 파일과 클라우드는 서로를 직접 알지 못합니다. 가운데 상태 파일이 있어야 web 이 어느 서버인지 이어집니다.

상태 파일이 없으면 곤란한 것

도구가 실행될 때마다 받는 것은 설정 파일뿐입니다. 설정 파일에는 원하는 상태만 있고 이미 만든 것의 기록은 없습니다. 그래서 상태 파일이 없으면 세 가지가 곤란해집니다.

첫째는 중복입니다. 도구는 web 서버를 지난번에 만들었는지 모릅니다. 다시 만들려 들면 똑같은 서버가 한 대 더 생깁니다. 이름이 겹치면 안 되는 자원이라면 만들기가 실패합니다.

둘째는 삭제입니다. 설정 파일에서 자원을 적은 부분을 지우면 도구는 그 자원을 클라우드에서도 지워야 합니다. 그런데 설정 파일에서 사라진 자원은 도구가 이름조차 모릅니다. 상태 파일에 남은 줄만이 「이것도 내가 만들었다」를 알려 줍니다. 상태 파일이 없으면 그 자원은 아무도 관리하지 않는 채로 클라우드에 남아 요금만 냅니다.

셋째는 순서입니다. 자원끼리는 서로 기댑니다. 서버는 네트워크 안에 만들어지므로 네트워크에 기댑니다. 이런 관계를 의존 관계라 합니다. 지울 때는 기대는 쪽부터 지웁니다. 네트워크보다 그 안의 서버를 먼저 지워야 합니다. 설정 파일에서 이미 사라진 자원은 이 의존 관계를 알려 줄 코드도 없습니다. 상태 파일이 의존 관계까지 함께 적어 두어 지우는 순서를 정합니다.

한 번의 실행

도구는 상태 파일만 믿고 움직이지 않습니다. 실행할 때마다 상태 파일에 적힌 자원의 지금 모습을 클라우드에서 읽어 옵니다. 그 모습으로 상태 파일을 먼저 맞춥니다. 그다음 설정 파일과 견줍니다. 견준 결과가 계획입니다. 사람이 승인하면 계획대로 바꿉니다.

flowchart TD
    S["상태 파일 · 지난번 기록"] --> R["클라우드에서 지금 모습 읽기"]
    R --> N["지금 모습으로 맞춘 상태 파일"]
    C["설정 파일 · 원하는 상태"] --> P["견줘서 계획 세우기"]
    N --> P
    P --> A["계획대로 만들기 · 고치기 · 지우기"]
    A --> W["상태 파일을 새로 적기"]

「클라우드에서 지금 모습 읽기」를 거치는 까닭은 지난번 기록과 지금 모습이 다를 수 있어서입니다. 누군가 관리 화면에서 손으로 설정을 바꿨을 수 있습니다. 이렇게 코드와 실물이 어긋나는 일이 구성 드리프트입니다.

상태 파일의 줄마다 도구가 내는 계획은 세 갈래로 나뉩니다. 실물의 값이 설정 파일과 같으면 계획에 아무것도 오르지 않습니다. 값이 다르면 설정 파일 쪽으로 되돌리는 계획을 냅니다. 도구에게 정본은 설정 파일이기 때문입니다. 손으로 자원을 아예 지웠다면 읽어 올 것이 없습니다. 도구는 상태 파일에서 그 줄을 빼고 자원을 새로 만드는 계획을 냅니다.

flowchart TD
    L["상태 파일의 한 줄"] --> Q1{"클라우드에 실물이 있나"}
    Q1 -->|없다| X["줄을 빼고 새로 만드는 계획"]
    Q1 -->|있다| Q2{"값이 설정 파일과 같나"}
    Q2 -->|같다| K["계획에 오르지 않음"]
    Q2 -->|다르다| F["설정 파일 값으로 되돌리는 계획"]

손으로 고친 값을 남기려면 그 값을 설정 파일에도 적어야 합니다.

테라폼의 상태 파일

테라폼은 대표적인 코드형 인프라 도구입니다. 상태 파일을 따로 설정하지 않으면 작업 폴더의 terraform.tfstate 에 적습니다. 새로 적기 직전의 판은 terraform.tfstate.backup 으로 하나 남겨 둡니다.

형식은 JSON(JavaScript Object Notation)입니다. JSON 은 중괄호와 따옴표로 값을 적는 글자 형식입니다. 아래는 AWS(Amazon Web Services)에 서버 한 대를 만든 뒤의 상태 파일을 줄여 보인 것입니다. AWS 는 아마존이 운영하는 클라우드입니다. 설정 파일에는 이 서버가 resource "aws_instance" "web" 으로 적혀 있습니다. aws_instance 는 AWS 서버라는 자원 종류입니다. web 은 사람이 붙인 이름입니다.

JSON
{
  "version": 4,
  "serial": 7,
  "lineage": "3f2a9c1e-...",
  "resources": [
    {
      "mode": "managed",
      "type": "aws_instance",
      "name": "web",
      "instances": [
        { "attributes": { "id": "i-0a1b2c3d", "instance_type": "t3.micro" } }
      ]
    }
  ]
}

type 과 name 이 설정 파일 쪽 이름입니다. attributes 안의 id 가 클라우드가 붙인 식별자입니다. 이 둘이 한 항목 안에 같이 있어 짝이 됩니다. serial 은 상태 파일을 새로 적을 때마다 하나씩 오르는 번호입니다. 낡은 판이 새 판을 덮으려 하면 이 번호로 알아챕니다. lineage 는 상태 파일이 처음 생길 때 붙는 고유값입니다. 전혀 다른 인프라의 상태 파일을 잘못 가져다 쓰는 일을 막습니다.

상태 파일은 도구가 쓰는 파일입니다. 사람이 JSON 을 열어 고치면 짝이 어긋나기 쉽습니다. 상태 파일을 손봐야 할 때는 테라폼이 주는 명령을 씁니다.

하고 싶은 일 명령
상태 파일에 적힌 자원 목록 보기 terraform state list
설정 파일에서 이름을 바꾼 자원을 옮겨 적기 terraform state mv
상태 파일에서만 빼고 자원은 남기기 terraform state rm
손으로 만든 자원을 상태 파일에 들이기 terraform import

네 명령 모두 상태 파일만 고칩니다. 클라우드의 자원은 건드리지 않습니다.

state mv 가 없으면 설정 파일에서 web 을 api 로 이름만 바꿔도 도구는 옛 이름의 서버를 지우고 새 이름으로 다시 만들려 듭니다. 상태 파일에 적힌 이름과 설정 파일의 이름이 달라 서로 다른 자원으로 보기 때문입니다.

비밀 값이 그대로 남는다

상태 파일에는 자원을 만들 때 넣은 속성이 암호화 없이 들어갑니다. 데이터베이스를 만들며 넣은 비밀번호나 발급받은 접속 키도 상태 파일에 글자 그대로 적힙니다.

그래서 상태 파일은 설정 파일과 다르게 다룹니다. 설정 파일은 Git 저장소에 넣어 이력을 남깁니다. 상태 파일은 Git 에 넣지 않습니다. 대신 접근 권한을 좁힌 파일 보관 서비스에 둡니다. 그 서비스가 파일을 암호화해 보관하게 합니다.

여럿이 함께 쓸 때

상태 파일이 한 사람의 노트북에만 있으면 다른 사람은 그 인프라를 고칠 수 없습니다. 각자 자기 상태 파일로 실행하면 서로의 자원을 모른 채 만들거나 지웁니다.

팀은 상태 파일을 네트워크 너머의 보관 장소 한 곳에 둡니다. 이 보관 장소를 원격 백엔드라 부릅니다. Amazon S3(Simple Storage Service) 같은 파일 보관 서비스가 흔히 쓰입니다. 모든 사람의 도구가 같은 상태 파일을 읽고 씁니다.

한곳에 모으면 새 문제가 생깁니다. 두 사람이 동시에 실행하면 둘 다 같은 판을 읽고 각자 고친 판을 적습니다. 나중에 적은 쪽이 먼저 적은 쪽을 덮어씁니다. 한 사람이 만든 자원이 상태 파일에서 사라집니다. 이를 막는 장치가 상태 잠금입니다. 실행을 시작한 쪽이 잠금을 쥡니다. 쥔 동안 다른 실행은 기다리거나 실패합니다.

sequenceDiagram
    participant A as 개발자 A
    participant 원격 as 원격 백엔드
    participant B as 개발자 B
    A->>원격: 잠금 요청
    원격-->>A: 잠금 허락
    A->>원격: 상태 파일 읽기
    B->>원격: 잠금 요청
    원격-->>B: 이미 잠겨 있다
    Note over B: 기다리거나 실패로 끝난다
    A->>원격: 새 상태 파일 쓰기
    A->>원격: 잠금 풀기

그림에서 B 는 A 가 잠금을 푼 뒤에야 상태 파일을 읽습니다. 그래서 B 가 읽는 판에는 A 가 고친 내용이 이미 들어 있습니다.

상태를 누가 들고 있나

모든 인프라 도구가 상태 파일을 사용자에게 맡기지는 않습니다. 상태를 누가 들고 있는지로 갈립니다.

도구 상태를 들고 있는 쪽
테라폼 · OpenTofu 사용자가 정한 원격 백엔드나 작업 폴더
Pulumi 사용자가 정한 보관 장소나 Pulumi 가 운영하는 서비스
CloudFormation AWS 가 서비스 안에 들고 있다. 사용자는 파일을 보지 않는다
앤서블 상태 파일이 없다. 실행할 때마다 서버를 둘러보고 설정 파일과 견준다

상태를 서비스가 들고 있으면 잠금과 보관을 사용자가 챙길 일이 없습니다. 대신 그 서비스가 다루는 클라우드만 쓸 수 있습니다.

상태 파일이 없는 도구는 잃어버릴 파일도 없습니다. 대가는 설정 파일에서 지운 것을 모른다는 점입니다. 설정 파일에서 패키지 한 줄을 지워도 서버에 이미 깔린 패키지는 남습니다. 지우려면 「없어야 한다」를 설정 파일에 따로 적어야 합니다. 만들고 지우는 일이 잦은 클라우드 자원에는 상태 파일을 두는 도구가 흔히 쓰입니다. 이미 있는 서버의 안을 맞추는 일에는 상태 파일이 없는 도구가 흔히 쓰입니다.

관련 항목

상태 파일을 쓰는 인프라 관리 방식

코드형 인프라 · 선언적 설정 · 원하는 상태 · 실제 상태 · 멱등성 · GitOps · 불변 인프라

상태 파일을 두고 쓰는 도구

테라폼 · OpenTofu · Pulumi · CloudFormation · 앤서블 · HCL

상태 파일을 지키는 장치

원격 백엔드 · 상태 잠금 · Amazon S3 · 암호화 · 접근 제어 · 비밀 관리

상태 파일이 짝짓는 대상

자원 · 식별자 · 클라우드 · 리소스 (테라폼) · 의존 관계 · 의존성 그래프

상태 파일이 어긋나 터지는 문제

구성 드리프트 · 경쟁 상태 · 고아 자원 · 갱신 손실

다른 이름: state file · 테라폼 상태 파일 · tfstate · terraform.tfstate