LabHub

Infrastructure as Code · 선언형 사고 · 실습

desired / actual / plan 3분할 만들기

LabHub 에서 이어서 보기

이 실습은 진짜 VM 에서 돕니다

이 상자는 파드가 아니라 KubeVirt 가 띄운 가상머신입니다. 리눅스 커널이
따로 돌고 systemd 가 실제로 서비스를 관리하며, docker 는 흉내가 아니라
진짜 도커 엔진입니다. docker run 으로 띄운 컨테이너는 실제로 프로세스가
되고 docker execdocker logs 도 그대로 동작합니다.

예전에는 이 실습이 파드 안에서 돌았습니다. 커널 권한을 전부 내려놓은 상자라
컨테이너를 띄우는 단계가 막혀 있었고, 그래서 이미지 아카이브를 직접 풀어
보는 우회로 배웠습니다. 이제 우회가 필요 없습니다.

알아 둘 것이 둘 있습니다.

목표

원하는 상태(desired), 현재 상태(actual), 둘의 차이(plan)라는 3분할 구조를 직접 만들고, 드리프트가 어떻게 감지되고 수렴되는지 확인한다.

왜 중요한가

IaC 도구가 화면에 뿌리는 + create, - destroy, ~ update 는 마법이 아니라 두 상태를 비교한 결과다. 이 구조를 손으로 한 번 만들어 보면 plan 을 읽는 눈이 달라진다. 특히 자동화에서는 결과를 종료코드로 받아야 하므로 0 은 변경 없음, 1 은 오류, 2 는 변경 있음이라는 관례를 그대로 따른다. 3축 모델로 말하면 코드는 Desired, 상태 파일은 Last Known, 실제 인프라는 Actual 이고, 셋 중 둘이라도 어긋나면 드리프트다. GitOps 의 자가 치유도 결국 이 비교를 반복해서 돌리는 일이다.

단계

1. /root/iac1/desired.yaml 에 원하는 상태를 선언한다. 최상위에 containers: 한 줄을 두고 그 아래 항목 2개를 둔다. 이름은 각각 iac-webiac-cache 이고, 항목마다 image: 를 한 줄씩 적는다(파일 전체에서 image: 는 정확히 2줄). 이미지는 파드에 미리 있는 alpine:3.20, busybox:1.36, python:3.12-alpine, nginx:1.27-alpine 중에서만 고른다.
2. /root/iac1/parse.sh 를 만들어 그 YAML 을 /root/iac1/desired.json 으로 변환한다. JSON 모양은 {"containers":[{"name":"...","image":"..."}, ...]} 이고 원소는 2개, image 값이 비어 있으면 안 된다.
3. /root/iac1/actual.sh 를 만든다. 지금 실제로 떠 있는 관리 대상 컨테이너를 같은 모양의 JSON 으로 표준출력에 낸다. 각 원소에는 nameimage 가 모두 있어야 한다. 관리 대상은 이름이 iac- 로 시작하는 컨테이너만이며, 이미지 문자열은 localhost/docker.io/library/ 접두를 벗겨 desired 와 같은 표기로 맞춘다.
4. /root/iac1/plan.sh <desired.json> <actual.json> 을 만든다. desired 에만 있으면 + create <이름>, actual 에만 있으면 - destroy <이름>, 양쪽에 있는데 image 가 다르면 ~ update <이름> 을 한 줄씩 출력한다. 차이가 하나도 없으면 no changes 를 출력하고 종료코드 0 을 낸다. 차이가 있으면 종료코드 2 를 낸다(0=변경 없음, 1=오류, 2=변경 있음).
5. /root/iac1/apply.sh 를 만들어 실제 상태를 선언에 맞춘다. 끝나면 desired 에 적힌 두 컨테이너가 모두 running 이어야 한다.
6. 아무것도 바꾸지 않은 채 plan 을 다시 돌려 /root/iac1/plan2.txt 에 저장한다. 이 파일에는 no changes 가 있고 +, -, ~ 로 시작하는 줄이 하나도 없어야 한다.
7. 코드 밖에서 상태를 흔든다. docker rm -f iac-cache 로 컨테이너 하나를 지운 뒤 plan 을 돌려 /root/iac1/drift.txt 에 저장한다. 변경 줄은 정확히 하나여야 하고 그 줄은 + create iac-cache 여야 한다.
8. 다시 apply.sh 를 돌려 수렴시키고, 그 뒤의 plan 을 /root/iac1/plan3.txt 에 저장한다. no changes 가 나오고 두 컨테이너가 모두 running 이어야 한다.

참고

단계 8개

  1. 원하는 상태 선언하기
  2. 선언을 기계가 읽는 형식으로
  3. 현재 상태 읽어 오기
  4. 차이 계산하기
  5. 선언한 상태 만들기
  6. 다시 적용해도 변화 없음
  7. 밖에서 생긴 변경 잡아내기
  8. 자동 수렴