사전 코드형 인프라
패턴

코드형 인프라

gabury1

서버와 네트워크를 손으로 만들지 않고 소스 코드에 적어 두기로 한 방식입니다. 코드를 도구에 넘기면 도구가 그 내용대로 환경을 만듭니다. 코드가 정본이라서 같은 코드는 매번 같은 환경을 냅니다.

상세

Martin Fowler 는 코드형 인프라를 컴퓨팅·네트워크 인프라를 소스 코드로 정의하는 접근이라고 적습니다. 그리고 그렇게 만든 코드를 여느 소프트웨어 시스템과 똑같이 다룬다고 적습니다. 그래서 이 코드를 버전 관리에 둘 수 있습니다. Fowler 는 그렇게 두면 감사 가능성과 재현 가능한 빌드를 얻는다고 적습니다. 테스트 실천과 지속적 전달의 규율 전체를 적용할 수 있다고도 적습니다.

마이크로소프트 문서는 같은 것을 IaC(Infrastructure as Code)라고 줄여 부릅니다. 데브옵스 방법론과 버전 관리를 쓰고 서술 모델로 인프라를 정의해 배포하는 일이라고 적습니다. 네트워크·가상 머신·로드밸런서·연결 토폴로지 같은 것이 여기서 말하는 인프라입니다. 같은 소스 코드가 언제나 같은 바이너리를 만들듯, IaC 모델은 배포할 때마다 같은 환경을 만든다고 적습니다.

Fowler 는 이 방식이 몇 가지 실천 위에 선다고 적고 여섯 개를 듭니다. 모든 설정을 실행 가능한 설정 정의 파일에 적습니다. 셸 스크립트·앤서블 플레이북·셰프 레시피·퍼펫 매니페스트 같은 것이 그 파일입니다. 사람이 문서를 읽고 손으로 실행하는 자리를 코드가 받습니다. Fowler 는 코드가 더 정확하고 일관되게 실행된다고 적습니다. 이 코드를 전부 버전 관리에 넣습니다. 시스템과 절차를 계속 테스트합니다. 인프라 갱신은 클수록 오류를 담을 확률이 높습니다. 그 오류를 찾아내기도 더 어렵습니다. 그래서 큰 묶음 대신 작은 변경으로 바꿉니다. 그리고 서비스를 계속 띄워 둡니다.

flowchart TD
    A[설정 정의 파일] --> B[버전 관리]
    B --> C[도구 실행]
    C --> D[서버와 네트워크]
    D -. 손으로 고침 .-> E[스노우플레이크 서버]

정의 파일을 적어 버전 관리에 넣습니다. 도구가 그 파일을 받아 서버와 네트워크를 만듭니다. 만들어진 실물을 손으로 만지면 그 서버는 코드가 설명하지 못하는 한 대가 됩니다. Fowler 는 그런 손질이 스노우플레이크 서버를 만들 위험이 있어 코드를 개발하는 동안에만 해야 한다고 적습니다.

대가

상태를 어딘가 저장해야 합니다. 테라폼 문서는 테라폼이 워크스페이스가 관리하는 인프라와 설정에 대한 상태를 반드시 저장해야 한다고 적습니다. 실제 세계의 자원을 설정에 대응시키고, 메타데이터를 추적하고, 큰 인프라에서 성능을 올리는 데 그 상태를 쓴다고 적습니다. 코드 말고 상태라는 관리 대상이 하나 더 생깁니다.

그 상태가 새 사고 경로를 냅니다. 테라폼 문서는 백엔드가 상태 잠금과 안전한 접근 제어를 지원하지 않으면 데이터 손실이나 상태 파일에 담긴 비밀 값의 노출로 이어질 수 있다고 적습니다. 여럿이 같은 설정을 돌리는 자리라면 잠금을 갖추는 일이 따라옵니다.

손으로 만지는 자유를 내줍니다. Fowler 는 실물을 손대는 일을 코드를 개발하는 동안에만 하라고 적습니다. 급할 때 서버에 들어가 고치고 넘어가는 길이 이 결정과 부딪힙니다.

코드와 실물이 어긋날 자리가 생깁니다. AWS(Amazon Web Services) CloudFormation 문서는 CloudFormation 으로 자원을 관리하는 중에도 사용자가 CloudFormation 밖에서 그 자원을 바꿀 수 있다고 적습니다. 자원을 만든 서비스에서 직접 고칠 수 있다는 것입니다. 그리고 CloudFormation 밖에서 이뤄진 변경은 스택 갱신이나 삭제 작업을 복잡하게 만들 수 있다고 적습니다.

그래서 어긋남을 찾는 절차가 따로 붙습니다. CloudFormation 은 이 어긋남을 드리프트라고 부릅니다. 문서는 드리프트 탐지가 스택의 실제 설정이 기대 설정과 다른지, 즉 드리프트했는지를 알아내는 기능이라고 적습니다. 자원의 실제 속성 값이 하나라도 기대 값과 다르면 그 자원은 드리프트한 것으로 봅니다. 속성이나 자원이 삭제된 경우도 여기 들어갑니다. 자원 하나라도 드리프트하면 스택이 드리프트한 것입니다.

flowchart TD
    T[스택 템플릿과 매개변수] --> E[기대 속성 값]
    R[스택 안의 실제 자원] --> A[실제 속성 값]
    E --> C{같나}
    A --> C
    C -->|같다| K[드리프트 아님]
    C -->|다르다| D[드리프트]

판정 절차는 이렇습니다. CloudFormation 은 스택 템플릿과 템플릿 매개변수로 넘어온 값에서 기대 속성 값을 정합니다. 그 다음 그 기대 값을 스택 안에 지금 존재하는 실제 속성 값과 견줍니다.

마이크로소프트 문서는 코드형 인프라가 릴리스 파이프라인의 환경 드리프트 문제를 풀려고 나왔다고 적습니다. 코드형 인프라가 없으면 팀이 배포 환경 설정을 하나하나 따로 관리해야 하고, 시간이 지나면 각 환경이 스노우플레이크가 된다고 적습니다. 자동으로 재현할 수 없는 고유한 설정이라는 뜻입니다. 코드가 정본이 된 뒤에도 실물은 밖에서 바뀔 수 있습니다. 어긋났는지를 따로 확인하는 일이 남습니다.

이름의 출처

이 이름을 지금 쓰이는 뜻으로 굳힌 글은 Martin Fowler 가 2016년 3월 1일 자기 사이트에 올린 "InfrastructureAsCode" 입니다. 글은 https://martinfowler.com/bliki/InfrastructureAsCode.html 에 있습니다.

Fowler 본인은 원전을 다른 사람에게 돌립니다. 글 끝의 감사 절에서 이 글이 Kief Morris 와의 저술과 여러 대화에 기반했고 그가 이 주제에 관한 결정판 책을 썼다고 적습니다. 그리고 실천 목록은 그 책에서 그대로 가져온 것이라고 적습니다. 글 앞머리에서도 Kief Morris 의 책을 이 주제를 더 깊이 보려면 읽을 핵심 텍스트로 가리킵니다.

그 책이 Kief Morris 의 『Infrastructure as Code』입니다. 부제는 "Effective design and delivery of dynamic infrastructure for the cloud age" 이고 오라일리에서 나왔습니다. 저자 본인 사이트 https://infrastructure-as-code.com/book/ 에 1판 2016년, 2판 2020년으로 적혀 있습니다.

누가 이 말을 처음 썼는지는 이 두 자리로 특정되지 않습니다. Fowler 의 글 어디에도 Fowler 와 Morris 이전에 이 말을 쓴 사람이 나오지 않습니다. 여럿이 굳힌 이름으로 두고, 처음 쓴 사람은 불분명하다고 적어 둡니다.

예시

테라폼 공식 튜토리얼이 서버 한 대를 만드는 최소 형태를 이렇게 적습니다.

hcl
provider "aws" {
  region = "us-west-2"
}

data "aws_ami" "ubuntu" {
  most_recent = true

  filter {
    name = "name"
    values = ["ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-amd64-server-*"]
  }

  owners = ["099720109477"] # Canonical
}

resource "aws_instance" "app_server" {
  ami           = data.aws_ami.ubuntu.id
  instance_type = "t2.micro"

  tags = {
    Name = "learn-terraform"
  }
}

provider "aws" 가 어느 클라우드를 상대할지를, region = "us-west-2" 가 어느 지역에 만들지를 정합니다. data "aws_ami" "ubuntu" 는 조건에 맞는 최신 이미지를 찾아오는 자리입니다. owners = ["099720109477"] 이 그 이미지를 낸 계정이고 주석에 Canonical 이라고 적혀 있습니다. resource "aws_instance" "app_server" 가 실제로 만들 서버입니다. instance_type = "t2.micro" 가 그 서버의 종류이고 Name = "learn-terraform" 은 붙일 태그입니다. 이 파일 어디에도 서버를 만드는 절차는 없습니다. 무엇이 있어야 하는지만 적혀 있습니다.

terraform init 을 돌리면 백엔드와 제공자 플러그인을 준비합니다.

Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 5.92"...
- Installing hashicorp/aws v5.98.0...

~> 5.92 가 이 설정이 요구한 판의 범위이고 실제로 받은 것은 v5.98.0 입니다. 이어서 terraform apply 를 돌리면 무엇을 할지 먼저 요약하고 그대로 실행합니다.

Plan: 1 to add, 0 to change, 0 to destroy.
...
aws_instance.app_server: Creating...
aws_instance.app_server: Creation complete after 14s [id=i-0c636e158c30e48f9]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Plan: 1 to add, 0 to change, 0 to destroy 가 계획입니다. 하나를 더하고 아무것도 바꾸거나 지우지 않습니다. 실행이 끝나면 만들어진 서버의 식별자 i-0c636e158c30e48f9 가 찍힙니다. 원문은 https://developer.hashicorp.com/terraform/tutorials/aws-get-started/aws-build 에 있습니다.

갈래

무엇을 코드에 적고, 그 코드를 받은 도구가 실물을 어떻게 맞추느냐가 축입니다. 세 자리에서 갈립니다.

선언형 정의와 명령형 스크립트

마이크로소프트 문서는 코드형 인프라가 가능하면 선언형 정의 파일을 써야 한다고 적습니다. 정의 파일은 환경에 필요한 구성 요소와 설정을 서술하지, 그 설정에 어떻게 도달할지를 반드시 서술하지는 않는다고 적습니다. 그리고 선언형 정의가 배포 스크립트 같은 명령형 코드를 유지하며 쌓이는 기술 부채를 줄이는 데 도움이 된다고 적습니다.

같은 문서는 멱등성을 코드형 인프라의 중요한 원칙으로 듭니다. 어떤 연산이 언제나 같은 결과를 내는 성질입니다. 배포 명령은 대상 환경의 출발 상태와 무관하게 언제나 그 환경을 같은 설정으로 만듭니다. 앤서블 쪽도 같은 자리를 짚습니다. 레드햇 문서는 앤서블 모듈이 가능한 경우 멱등하도록 설계되어 필요할 때만 시스템을 바꾼다고 적습니다. 그리고 언어가 읽기 쉽고 투명하게 남는다고 적습니다. 명시적인 순서 관계를 선언하거나 프로그래밍 언어로 코드를 짤 일이 없다고 적습니다. 원문은 https://www.redhat.com/en/ansible-collaborative/how-ansible-works 에 있습니다.

설정 관리와 자원 초기화

하시코프 문서는 설정 관리 도구가 이미 존재하는 머신 위에 소프트웨어를 설치하고 관리한다고 적습니다. 그리고 테라폼은 설정 관리 도구가 아니라고 적습니다. 기존 도구가 자기 강점에 집중하게 둔다고 적습니다. 그 강점은 자원의 부트스트래핑과 초기화라고 적습니다.

테라폼이 서는 자리는 그 위입니다. 같은 문서는 테라폼이 데이터센터와 그에 딸린 서비스라는 더 높은 추상에 집중한다고 적습니다. 개별 시스템에는 설정 관리 도구를 쓰게 한다고 적습니다. 원문은 https://developer.hashicorp.com/terraform/intro/vs/chef-puppet 에 있습니다.

불변 서버

Fowler 는 불변 서버를 한 번 배포되면 절대 수정되지 않고 갱신된 새 인스턴스로 교체될 뿐인 서버라고 적습니다. 잘 테스트된 기반 이미지에서 서버 인스턴스를 띄웠으면 설정 관리 도구를 돌리지 말라고 적습니다. 그것이 인스턴스에 테스트되지 않은 변경이 들어갈 틈을 만들기 때문이라고 적습니다.

변경은 기반 이미지 쪽에서 일어납니다. Fowler 는 필요한 변경을 기반 이미지에 가해 테스트한 뒤 굴려 내보낸다고 적습니다. 그 변경이 없는 서버는 내려서 교체한다고 적습니다. 이미지를 굽는 자리를 코드로 두는 도구가 따로 있습니다. Packer 문서는 Packer 를 단일 소스 설정에서 여러 플랫폼용으로 동일한 머신 이미지를 만드는 커뮤니티 도구라고 적습니다. 머신 이미지는 미리 설정된 운영체제와 설치된 소프트웨어를 담아 새 실행 머신을 빠르게 만드는 데 쓰는 하나의 정적 단위라고 적습니다.

관련 항목

정의 파일을 받아 실물을 만드는 도구

테라폼 · CloudFormation · Packer

이것과 자리를 나누는 설정 관리 도구

앤서블 · 셰프 · 퍼펫

이것을 가르는 서술 방식과 원칙

선언적 설정 · 명령형 스크립트 · 멱등성

이것과 자리를 나누는 배포 전략

설정 관리 · 불변 서버 · GitOps

이것이 다루는 파일과 이미지

정의 파일 · 머신 이미지 · 상태 파일

이것을 쓰면 새로 지는 위험

상태 잠금 · 드리프트 · 스노우플레이크 서버

이것이 요구하는 실천

버전 관리 · 지속적 전달 · 자동 테스트

이것을 공식 문서로 다루는 벤더

AWS · Microsoft · 하시코프 · 레드햇

다른 이름: Infrastructure as Code · IaC