사전 Packer
구현체

Packer

gabury1고친 사람 github-actions[bot]

Packer 는 서버를 띄울 때 쓸 원본 이미지를 자동으로 구워 내는 도구입니다. 필요한 프로그램과 설정을 미리 넣은 이미지를 설정 파일 하나로 만듭니다. 서버는 그 이미지에서 뜨자마자 바로 일할 수 있습니다. 같은 설정 파일로 여러 클라우드용 이미지를 한 번에 만들 수도 있습니다.

쉽고 빠른 이해

무슨 일을 하나 — 서버를 띄운 뒤에 프로그램을 까는 대신, 다 깔린 원본을 먼저 만들어 둡니다. 예를 들어 웹 서버 프로그램 nginx 와 앱 설정이 들어간 AWS(Amazon Web Services) 서버 이미지를 하나 굽습니다.

왜 쓰나 — 서버마다 뜬 뒤에 설치를 돌리면 느립니다. 설치가 중간에 실패한 서버도 섞입니다. 손으로 만든 원본은 무엇이 들어갔는지 기록이 안 남아 다시 만들 수 없습니다.

어떻게 도나

  1. 바탕이 될 이미지로 임시 서버를 하나 띄웁니다
  2. 그 서버에 접속해 설치 명령과 설정을 돌립니다
  3. 서버를 멈추고 디스크를 새 이미지로 저장한 뒤 임시 서버를 지웁니다

대가 — 설정 한 줄을 바꿔도 이미지를 다시 굽고 서버를 새로 띄워야 합니다. 굽는 데 몇 분씩 걸립니다. 쌓인 옛 이미지는 치워 주지 않으면 저장 비용이 됩니다.

언제 쓰나 — 같은 역할의 서버를 여러 대 띄우거나 부하에 따라 서버를 늘릴 때 씁니다. 서버 한 대를 오래 두고 쓰거나 설정이 자주 바뀌는 곳에는 맞지 않습니다.

상세

Packer 는 HashiCorp 가 만든 머신 이미지 제작 도구입니다. 머신 이미지는 운영체제와 프로그램이 이미 설치된 디스크의 원본입니다. 클라우드는 이 원본을 복사해 새 서버를 띄웁니다. Packer 는 명령줄 프로그램 하나입니다. 개발자 컴퓨터나 배포 파이프라인에서 돌립니다.

이 절은 AWS(Amazon Web Services)용 웹 서버 이미지 하나를 굽는 과정을 따라갑니다. 그 과정에서 템플릿 파일, 소스와 빌드 블록, 프로비저너, 후처리기를 차례로 봅니다. 끝에서는 Packer 가 맡지 않는 일과 맞지 않는 경우를 봅니다.

서버를 띄운 뒤에 설치할 때의 문제

서버를 띄우고 나서 프로그램을 설치하면 서버마다 설치를 한 번씩 돌립니다. 서버 열 대를 띄우면 같은 설치가 열 번 돕니다. 그동안 서버는 일을 못 합니다.

설치는 바깥에 기댑니다. 패키지 저장소가 잠깐 응답하지 않으면 한 대만 설치가 빠진 채 뜹니다. 같은 명령을 돌려도 오늘 받은 패키지와 다음 주에 받은 패키지는 판이 다를 수 있습니다. 그러면 같은 역할의 서버끼리 속이 조금씩 달라집니다.

그렇다고 서버 한 대를 손으로 꾸며 원본으로 떠 두면 기록이 안 남습니다. 무엇을 어떤 순서로 넣었는지 모르니 다음 달에 같은 원본을 다시 만들 수 없습니다.

Packer 는 설치를 서버가 뜨기 전으로 옮깁니다. 그 설치 과정은 파일로 적게 합니다. 이미지는 한 번만 굽습니다. 서버는 그 이미지에서 설치 없이 뜹니다.

템플릿 파일

Packer 설정은 템플릿이라고 부르는 글자 파일입니다. 확장자는 .pkr.hcl 입니다. 문법은 HCL(HashiCorp Configuration Language, 해시코프 설정 언어)입니다. 중괄호로 블록을 묶고 이름 = 값 으로 속성을 적습니다.

예시는 AWS 에서 굽습니다. Amazon EC2(Elastic Compute Cloud)는 AWS 의 가상 서버 서비스입니다. EC2 서버용 머신 이미지는 AMI(Amazon Machine Image)라고 부릅니다.

아래는 우분투 AMI 를 바탕으로 웹 서버 프로그램 nginx 가 깔린 AMI 를 굽는 템플릿입니다.

hcl
source "amazon-ebs" "web" {
  region        = "ap-northeast-2"
  source_ami    = "ami-0abc1234"
  instance_type = "t3.micro"
  ssh_username  = "ubuntu"
  ami_name      = "web-nginx-v1"
}

build {
  sources = ["source.amazon-ebs.web"]

  provisioner "shell" {
    inline = ["sudo apt-get update", "sudo apt-get install -y nginx"]
  }
}

source 블록은 「어디서 무엇으로 이미지를 구울지」를 적습니다. amazon-ebs 는 AWS 에서 AMI 를 만드는 방식의 이름입니다. web 은 이 파일 안에서 부를 이름입니다. source_ami 가 바탕 이미지입니다. ami_name 이 새로 만들 이미지의 이름입니다.

build 블록은 「그 소스에 무엇을 해서 이미지를 만들지」를 적습니다. 그 안의 provisioner 가 임시 서버에서 돌릴 설치 단계입니다.

빌더 — 어디에 굽는가

source 블록의 종류를 정하는 부품을 빌더라고 부릅니다. 빌더는 한 플랫폼에서 임시 서버를 띄우고 거두는 방법을 압니다.

빌더 예 무엇을 만드나
amazon-ebs AWS 의 AMI
googlecompute Google Cloud 의 머신 이미지
azure-arm Azure 의 머신 이미지
docker Docker 의 컨테이너 이미지
qemu · virtualbox-iso 로컬 가상 머신용 디스크 파일

build 블록의 sources 목록에 소스를 여럿 적으면 Packer 는 그 빌드를 동시에 돌립니다. AWS 소스와 Google Cloud 소스를 함께 적으면 같은 설치 단계로 두 클라우드의 이미지가 한 번에 나옵니다.

빌더와 프로비저너는 대부분 Packer 본체와 따로 배포됩니다. 이렇게 따로 받아 끼우는 부품을 플러그인이라고 부릅니다. 쓸 플러그인은 템플릿 맨 위의 packer 블록에 적습니다. 위 예시에서는 이 블록을 줄였습니다. packer init 명령은 이 블록을 읽고 적힌 플러그인을 내려받습니다.

프로비저너 — 무엇을 넣는가

프로비저너는 임시 서버 안에서 도는 설치 단계입니다. 템플릿에 적은 순서대로 돕니다.

프로비저너 하는 일
shell 셸 명령이나 스크립트를 돌린다
file 내 컴퓨터의 파일을 임시 서버에 복사한다
ansible 앤서블 플레이북(설치 절차를 적은 파일)을 돌린다

Packer 는 임시 서버에 SSH(Secure Shell)로 접속해 이 단계들을 돌립니다. 윈도 머신이면 WinRM(Windows Remote Management)을 씁니다. SSH 는 원격 서버에 암호화된 연결로 들어가 명령을 치는 방법입니다.

설정 관리 도구는 떠 있는 서버에 붙어 정해 둔 설치 상태를 맞춰 주는 도구입니다. 앤서블이 그런 도구입니다. 앤서블 같은 설정 관리 도구도 프로비저너로 부를 수 있습니다. 서버에 붙어 설치하던 플레이북을 손대지 않고 이미지를 구울 때 한 번 돌리는 데 씁니다.

한 번의 빌드

packer build 를 부르면 amazon-ebs 빌더는 아래 순서로 움직입니다.

sequenceDiagram
    participant 개발자
    participant Packer
    participant AWS
    participant 임시 서버
    개발자->>Packer: packer build
    Packer->>AWS: 임시 키와 방화벽 규칙을 만들고 바탕 이미지로 서버를 띄운다
    AWS-->>Packer: 임시 서버 주소
    Packer->>임시 서버: SSH 로 접속해 프로비저너를 차례로 돌린다
    임시 서버-->>Packer: 설치 끝
    Packer->>AWS: 서버를 멈추고 디스크로 새 AMI 를 만든다
    AWS-->>Packer: 새 AMI 식별자
    Packer->>AWS: 임시 서버 · 키 · 방화벽 규칙을 지운다
    Note over Packer: 후처리기가 있으면 여기서 돈다
    Packer-->>개발자: 새 AMI 식별자

Packer 는 빌드마다 임시 서버와 함께 접속용 임시 키, 접속을 허락하는 임시 방화벽 규칙을 만듭니다. 빌드가 끝나면 이 셋을 모두 지웁니다. 남는 것은 새 이미지뿐입니다.

설치 단계 하나가 실패하면 빌드는 거기서 멈춥니다. 그때도 임시 서버는 지우고 이미지는 만들지 않습니다. 그래서 설치가 반쯤 된 이미지는 남지 않습니다.

빌드 결과를 바꾸는 방법은 하나입니다. 템플릿을 고치고 다시 구워 새 이미지를 만듭니다. 이미 만든 이미지를 Packer 가 고치는 일은 없습니다.

후처리기 — 구운 뒤에 하는 일

후처리기는 이미지를 만든 뒤에 도는 단계입니다. build 블록 안에 post-processor 로 적습니다.

후처리기 예 하는 일
manifest 만든 이미지의 이름과 식별자를 파일로 적는다
vagrant 결과물을 Vagrant(개발용 가상 머신을 띄우는 도구)가 읽는 박스 파일로 바꾼다
docker-tag · docker-push 컨테이너 이미지에 태그를 붙이고 레지스트리에 올린다

manifest 가 남긴 파일은 다음 단계가 새 이미지의 식별자를 찾는 데 씁니다. 이어지는 이야기는 맞물림 절에 있습니다.

Packer 가 맡지 않는 일

Packer 는 이미지를 만들 뿐, 그 이미지로 서버를 띄우지 않습니다. 서버를 몇 대 띄우고 어느 네트워크에 둘지는 다른 도구의 몫입니다.

Packer 는 만든 이미지를 기억하지 않습니다. 테라폼은 서버와 네트워크 같은 인프라를 설정 파일대로 만들어 주는 HashiCorp 도구입니다. 테라폼은 자기가 만든 것을 상태 파일에 적어 두고 다음 실행 때 견줍니다. Packer 에는 이런 상태 파일이 없습니다. 빌드는 매번 처음부터 다시 돕니다. 그때마다 새 이미지가 하나 더 남습니다. 옛 이미지를 지우는 일도 Packer 가 하지 않습니다. 치우지 않은 이미지는 쌓이는 만큼 저장 비용이 됩니다.

돌고 있는 서버의 설정도 다루지 않습니다. 이미 떠 있는 서버를 고치려면 새 이미지를 굽고 서버를 새로 띄워 바꿔 끼웁니다. 이렇게 떠 있는 서버를 고치지 않고 새것으로 갈아 끼우는 방식이 불변 인프라입니다. Packer 는 그 방식에서 새것의 원본을 만드는 도구입니다.

맞는 경우와 안 맞는 경우

같은 역할의 서버를 여러 대 띄우는 곳에서 쓸모가 큽니다. 부하에 따라 서버를 저절로 늘리는 오토스케일링이 대표적입니다. 새 서버가 설치 없이 뜨니 늘어나는 속도가 빨라집니다.

설정이 자주 바뀌는 서버에는 부담이 큽니다. 설정 한 줄마다 굽고 갈아 끼우는 데 몇 분씩 듭니다. 그래서 자주 바뀌는 값은 이미지에 넣지 않고 서버가 뜰 때 받아 오게 나누는 경우가 많습니다. 비밀번호 같은 비밀 값도 이미지에 넣지 않습니다. 이미지를 복사할 수 있는 사람은 누구나 그 값을 꺼낼 수 있기 때문입니다.

서버 한 대를 오래 두고 쓰는 곳이라면 굽는 품이 얻는 것보다 큽니다.

맞물림

Packer 는 HashiCorp 의 다른 도구들과 앞뒤로 붙도록 만들어졌습니다. 아래 세 소절은 누가 무엇을 넘기는지와 그렇게 붙어서 치르는 값을 봅니다.

Packer 가 굽고 테라폼이 띄우는 순서

가장 흔한 조합은 Packer 가 이미지를 굽고 테라폼이 그 이미지로 서버를 띄우는 것입니다. 둘 사이에 오가는 것은 이미지 식별자 하나입니다.

테라폼 설정에서는 띄울 서버 하나하나를 자원(resource)으로 적습니다. 그 서버 자원에 AMI 식별자를 넣습니다. 식별자를 손으로 옮기지 않으려면 테라폼 쪽에서 이름 규칙으로 가장 최근 이미지를 찾아 쓰게 합니다.

테라폼은 실제로 바꾸기 전에 plan 단계에서 무엇이 바뀔지 먼저 보여 줍니다. 이미지를 새로 구우면 식별자가 바뀝니다. 그러면 plan 은 그 서버를 지우고 새로 만드는 변경으로 보여 줍니다.

flowchart TD
    T["Packer 템플릿을 고친다"] --> P["packer build"]
    P --> I["새 AMI 식별자 v2"]
    I --> F["테라폼 서버 자원의 이미지 값이 v2 로 바뀐다"]
    F --> PL["plan: 서버를 지우고 새로 만드는 변경"]
    PL --> S2["v2 이미지로 뜬 새 서버"]
    PL --> D["v1 이미지로 뜬 옛 서버는 지워진다"]

이미지를 바꾸면 서버가 갈아 끼워집니다. 이 조합이 불변 인프라를 굴리는 방식입니다. 대가로 이미지 이름 규칙이 두 도구 사이의 약속이 됩니다. Packer 쪽에서 이름을 바꾸면 테라폼이 엉뚱한 이미지를 집거나 못 찾습니다.

Packer 결과물을 Vagrant 가 받는 순서

Vagrant 는 개발자 컴퓨터에 가상 머신 개발 환경을 띄우는 HashiCorp 도구입니다. Packer 의 vagrant 후처리기가 결과물을 박스 파일로 바꾸면, Vagrant 는 그 박스로 가상 머신을 띄웁니다.

같은 템플릿에서 클라우드용 이미지와 박스를 함께 구우면 개발 환경과 운영 서버의 속이 같아집니다. 대신 박스 파일은 디스크 한 벌을 담은 큰 파일이라 굽고 나눠 주는 데 시간이 듭니다.

빌드 중에 Vault 에서 비밀 값을 받는 순서

설치 단계가 비공개 저장소의 토큰 같은 비밀 값을 쓸 때가 있습니다. Packer 템플릿은 빌드 중에 HashiCorp 의 비밀 값 저장소인 Vault 를 불러 값을 읽을 수 있습니다. 템플릿 파일에 비밀 값을 적지 않아도 됩니다.

이 값은 설치 단계에서 쓰고 끝나야 합니다. 설치 단계가 그 값을 디스크에 남기면 이미지에 같이 구워집니다. 그러면 「맞는 경우와 안 맞는 경우」에서 본 대로 이미지를 복사할 수 있는 사람은 누구나 그 값을 꺼냅니다.

관련 항목

Packer 가 따르는 인프라 관리 방식

불변 인프라 · 코드형 인프라 · 프로비저닝 · 설정 관리 · 불변 서버 · 구성 드리프트 · 스노우플레이크 서버

Packer 가 만들어 내는 결과물

머신 이미지 · 골든 이미지 · AMI · 컨테이너 이미지 · 스냅샷 · 가상 머신

Packer 템플릿을 이루는 구성 요소

HCL · 빌더 (Packer) · 프로비저너 (Packer) · 후처리기 (Packer) · 플러그인

Packer 가 이미지를 굽는 플랫폼

AWS · Amazon EC2 · Google Cloud · Azure · Docker · QEMU · VirtualBox · 하이퍼바이저

Packer 가 임시 서버에 들어가 설치하는 수단

SSH · WinRM · 셸 · 앤서블 · 패키지 매니저 · nginx

Packer 를 만든 회사와 그 형제 도구

HashiCorp · 테라폼 · Vagrant · Vault · HCP Packer

Packer 로 구운 이미지가 쓰이는 흐름

오토스케일링 · CI/CD · 블루-그린 배포 · 방화벽 규칙 · 비밀 관리

다른 이름: packer · 패커 · HashiCorp Packer