Terraform State의 목적

Terraform State의 목적

State(상태)는 테라폼이 동작하기 위해 반드시 필요한 요소예요. 종종 "테라폼이 state 없이도 동작할 수 있나요?" 또는 "state를 쓰지 않고 매번 실행할 때 실제 리소스를 그냥 조회하면 안 되나요?"라는 질문을 받곤 해요. 이 페이지는 테라폼 state가 왜 필요한지 설명할게요.

출처: 문서

본문

아래 이유들에서 볼 수 있듯이 state는 필수적이에요. 그리고 테라폼이 state 없이도 될 수 있는 시나리오에서도, 그렇게 하려면 한 곳(state)의 복잡성을 다른 곳(대체 개념)으로 엄청나게 옮겨야 해요.

실제 세계로의 매핑 (Mapping to the Real World)

테라폼은 테라폼 구성(config)을 실제 세계와 매핑하기 위한 일종의 데이터베이스가 필요해요. 예를 들어 구성에 resource "aws_instance" "foo"라는 리소스가 있을 때, 테라폼은 이 매핑을 통해 그 리소스가 원격 시스템에서 인스턴스 ID i-abcd1234를 가진 실제 객체를 나타낸다는 것을 알아요.

AWS 같은 일부 프로바이더의 경우, 테라폼이 이론적으로 AWS 태그 같은 것을 사용할 수도 있어요. 초기 테라폼 프로토타입은 실제로 state 파일이 없었고 이 방식을 사용했어요. 그러나 곧 문제가 생겼어요. 첫 번째 큰 문제는 단순한 것이었어요. 모든 리소스가 태그를 지원하는 것도, 모든 클라우드 프로바이더가 태그를 지원하는 것도 아니라는 점이에요.

그래서 테라폼은 구성을 실제 세계의 리소스에 매핑하기 위해 자체 state 구조를 사용해요.

테라폼은 각 원격 객체가 구성의 정확히 하나의 리소스 인스턴스에만 바인딩될 것을 기대해요. 원격 객체가 여러 리소스 인스턴스에 바인딩되면, 구성에서 원격 객체로의 매핑이 state 안에서 모호해지고 테라폼이 예상치 못하게 동작할 수 있어요. 테라폼은 객체를 만들고 그 정체성을 state에 기록할 때 일대일 매핑을 보장할 수 있어요. 테라폼 밖에서 만든 객체를 가져올(import) 때는 각각의 고유한 객체가 정확히 하나의 리소스 인스턴스로만 import되도록 해야 해요.

메타데이터 (Metadata)

리소스와 원격 객체 사이의 매핑과 함께, 테라폼은 리소스 의존성 같은 메타데이터도 추적해야 해요.

테라폼은 보통 구성을 사용해 의존성 순서를 결정해요. 그러나 테라폼 구성에서 리소스를 삭제하면, 테라폼은 원격 시스템에서 그 리소스를 어떻게 삭제할지 알아야 해요. 테라폼은 구성에 없는 리소스에 대한 매핑이 state 파일에 존재함을 보고 destroy를 계획할 수 있어요. 하지만 구성이 더 이상 존재하지 않기 때문에, 순서는 구성만으로는 결정할 수 없어요.

올바른 동작을 보장하기 위해 테라폼은 가장 최근의 의존성 집합의 사본을 state 안에 보관해요. 이제 구성에서 하나 이상의 항목을 삭제하더라도 state로부터 올바른 삭제 순서를 결정할 수 있어요.

테라폼은 리소스 타입 간의 기본적인 계층 순서를 사용하는 다른 접근 방식도 취할 수 있어요. 예를 들어 서버가 포함된 서브넷보다 먼저 서버가 삭제되어야 한다는 것을 알 수 있겠죠. 하지만 이 접근 방식의 복잡성은 곧 걷잡을 수 없이 늘어나요. 테라폼이 모든 프로바이더의 모든 리소스에 대한 순서 의미를 이해해야 할 뿐만 아니라, 프로바이더 간의 순서도 이해해야 하기 때문이에요.

테라폼은 비슷한 이유로 다른 메타데이터도 저장해요. 예를 들어 여러 별칭(aliased) 프로바이더가 있을 때 리소스에 가장 최근에 사용된 프로바이더 구성에 대한 포인터 같은 것들이요.

성능 (Performance)

기본 매핑 외에도 테라폼은 state 안에 모든 리소스의 속성 값 캐시를 저장해요. 이것은 테라폼 state의 가장 선택적인 기능이며, 순전히 성능 개선을 위해서만 수행돼요.

terraform plan을 실행할 때 테라폼은 원하는 구성에 도달하기 위해 필요한 변경 사항을 효과적으로 결정하려면 리소스의 현재 상태를 알아야 해요.

작은 인프라의 경우 테라폼이 프로바이더에 질의해서 모든 리소스의 최신 속성을 동기화할 수 있어요. 이것이 테라폼의 기본 동작이에요. 매 plan과 apply마다 테라폼은 state에 있는 모든 리소스를 동기화해요.

더 큰 인프라에서는 모든 리소스를 질의하는 것이 너무 느려요. 많은 클라우드 프로바이더가 여러 리소스를 한 번에 질의하는 API를 제공하지 않고, 리소스마다 왕복 시간이 수백 밀리초에 이르러요. 게다가 클라우드 프로바이더는 거의 항상 API 속도 제한(rate limit)이 있어서 테라폼은 일정 기간에 특정 개수의 리소스만 요청할 수 있어요. 테라폼의 규모가 큰 사용자들은 이를 우회하기 위해 -refresh=false 플래그와 -target 플래그를 적극적으로 사용해요. 이런 시나리오에서는 캐시된 state가 진실의 기록(record of truth)으로 취급돼요.

동기화 (Syncing)

기본 구성에서 테라폼은 state를 테라폼을 실행한 현재 작업 디렉터리의 파일에 저장해요. 시작 단계에서는 괜찮지만, 팀에서 테라폼을 사용할 때는 모든 사람이 동일한 state로 작업하는 것이 중요해요. 그래야 작업이 동일한 원격 객체에 적용되거든요.

원격 state(Remote state)가 이 문제의 권장 해결책이에요. 완전한 기능을 갖춘 state 백엔드를 사용하면 테라폼이 원격 잠금(remote locking)을 사용해서 두 명 이상의 사용자가 실수로 동시에 테라폼을 실행하는 것을 막고, 각 테라폼 실행이 항상 가장 최근에 갱신된 state로 시작하도록 보장할 수 있어요.

더 알아보기 (Learn more)