Infrastructure as Code · 멱등성 · 이론
두 번 돌려도 같아야 한다
한 줄 요약
멱등성은 같은 작업을 여러 번 실행해도 결과가 동일한 성질이고, 이것이 없으면 자동화는 돌릴 때마다 결과가 달라지는 도박이 된다.
왜 이게 필요했나
자동화는 한 번만 실행되지 않는다. 러너가 타임아웃으로 죽어 재실행되고, 다른 사람이 같은 플레이북을 또 돌리고, 스케줄러가 매시간 같은 것을 적용한다. 이때 "이미 되어 있으면 아무 일도 하지 않는다"가 보장되지 않으면 재실행 자체가 위험해진다. 결국 사람들은 자동화를 무서워하게 되고, 무서우니까 손으로 하게 되고, 손으로 하니까 다시 눈송이 서버가 된다.
증명 방법은 의외로 단순하다. apply 를 두 번 연속 돌리고, 두 번째 plan 이 변경 없음(종료코드 0)인지 보면 된다. 이 한 줄짜리 검사가 통과하지 않는 자동화는 아직 신뢰할 수 없다.
어떻게 동작하나
멱등성은 "실행 전에 현재 상태를 확인한다"에서 나온다. 디렉터리를 만들기 전에 있는지 보고, 파일을 쓰기 전에 내용이 같은지 보고, 권한을 바꾸기 전에 현재 권한을 읽는다. 그래서 잘 만든 모듈은 항상 두 갈래다. 바꿨으면 changed, 이미 맞으면 unchanged.
멱등성이 깨지는 가장 흔한 자리는 전용 모듈 대신 shell 이나 command 로 명령을 직접 실행할 때다. 도구는 그 명령이 무엇을 하는지 모르므로 매번 실행한다. 그래서 creates= 나 removes= 같은 조건을 붙여 이미 끝난 작업은 건너뛰게 만든다. 대표적인 버그는 설정 파일에 한 줄을 추가한다면서 >> 로 덧붙이는 것이다. 실행할 때마다 같은 줄이 하나씩 쌓여 열 번 돌리면 열 줄이 된다. 올바른 구현은 그 줄이 이미 있는지 먼저 확인하고, 같은 키의 다른 값이 있으면 그 자리를 교체하는 것이다.
적용 전에 무엇이 바뀔지 미리 보려면 check mode 와 diff 를 함께 쓴다(--check --diff). 실제로 바꾸지 않고 바뀔 내용만 보여 주므로 운영 서버에 처음 적용할 때 필수다. 그리고 결과는 반드시 세어서 보여 줘야 한다. changed 와 unchanged 를 집계한 리포트가 있어야 두 번째 실행에서 changed 가 0 이라는 사실을 사람이 확인할 수 있다.
현장에서 만나는 모습
"플레이북이 성공했는데 왜 설정이 이상하죠"라는 질문의 절반은 멱등하지 않은 태스크에서 나온다. 로그에는 ok 만 찍혔지만 실제로는 같은 줄이 세 번 들어갔거나, 재시작이 매번 일어나 서비스가 주기적으로 끊긴 것이다. 그래서 성숙한 팀은 CI 에서 플레이북을 두 번 돌린다. 두 번째 실행의 changed 가 0 이 아니면 빌드를 깬다. 멱등성을 문서가 아니라 테스트로 강제하는 것이다.
또 하나, 상태를 기록해 두면 감지 능력이 생긴다. 적용 시점에 각 리소스의 경로와 해시를 남겨 두면 나중에 그 파일이 밖에서 바뀌었는지 비교만으로 알 수 있다. 상태 파일이 있는 도구들이 하는 일이 정확히 이것이다.
다음 실습에서 할 것
디렉터리·파일·줄·권한을 보장하는 작은 스크립트 네 개를 만들고, 각각이 changed 와 unchanged 를 정확히 구분하게 한다. 그다음 이 넷을 묶은 러너를 두 번 연속 실행해 두 번째에는 changed 가 0 이 나오는지로 멱등성을 증명한다. 마지막에는 상태 파일과 드리프트 감지, 그리고 동시 실행을 막는 잠금까지 붙인다.