CloudFormation 의 UserData 를 다시 돌려서 벤더 패치를 새로 내려받게 해야 했다. 스크립트 안에 # rev 2 같은 의미 없는 값을 하나 넣고 그것을 바꿔 변경을 만드는 흔한 기법을 썼다.
Table of contents
Open Table of contents
배경 — 돌지 않은 재실행
값을 바꿔서 배포했는데 스크립트가 안 돌았고 패치도 받아지지 않았다. 인스턴스 상태를 보니 정지했다가 시작만 됐을 뿐 교체는 일어나지 않았다.
AWS 공식 문서에서 AWS::EC2::Instance 의 UserData 갱신 방식을 확인하니 Some interruptions 였다. 루트 볼륨이 EBS 면 재시작하고 인스턴스 스토어일 때만 교체한다고 적혀 있었다. 새 인스턴스를 만드는 것이 아니라 기존 인스턴스를 정지했다가 다시 시작하는 동작이었다.
원인 — 인스턴스당 한 번
cloud-init 의 사용자 스크립트는 인스턴스당 한 번만 도는 것이 기본 동작으로 돼 있다. 처음 생성될 때 한 번 돌고 /var/lib/cloud/instances/ 에 표식이 남으므로 정지와 시작만으로는 다시 돌지 않는다.
이미 한 번 돌았던 인스턴스이므로 이번에 안 돈 것이 당연했다. 값을 바꿔 재실행을 유도하는 기법은 그 속성이 교체를 유발할 때만 성립하므로 이 리소스에서는 성립하지 않았다.
검증 — 미리 확인할 수 있는 것
비슷한 성격의 다른 속성으로도 시도해 봤지만 같은 이유로 실패했다. 교체를 유발하지 않는 속성이면 어느 것을 바꿔도 결과가 같다.
그런데 어느 방식이든 배포 전에 변경 세트로 무엇이 바뀌는지를 미리 볼 수 있었다. 거기에 Replacement 열이 표시되므로 돌리기 전에 알 수 있었고 그것을 먼저 봤으면 값만 바꿔서는 안 된다는 것을 미리 알았을 것이다.
조치 — 제안 상태로 적기
교체가 확실히 일어나는 경로를 써야 했다. 두 가지 방법이 있었는데 인스턴스를 콘솔에서 손으로 교체하는 것과 UserData 를 AWS::EC2::LaunchTemplate 로 분리해 그 갱신이 교체를 유발하는 성질을 쓰는 것이다. 뒤쪽을 골랐다. 이유는 손 교체는 다음에 같은 일이 생기면 또 손으로 해야 해서다. 대신 템플릿 구조를 바꾸는 배포가 한 번 더 필요한 것을 감수했다. 다만 이 방안은 아직 실측하기 전이었다.
그래서 이 시점에는 INFRA.md 에 제안 상태라고 적고 된다고 쓰지 않았다. 해 보기 전에 된다고 적으면 다음 사람이 그것을 확정된 방법으로 읽게 되기 때문이다.
주의 — 구분하지 못하는 관찰
조사하면서 이전 기록이 애매하다는 것도 함께 드러났다. 그 인스턴스가 교체 없이 재부팅됐다는 관찰만 적혀 있고 초기화가 다시 돌았는지는 적혀 있지 않았다.
그 기록만으로는 재실행 여부를 알 수 없고 갈리려면 PrivateIpAddress 가 바뀌었는지를 함께 봐야 한다. 교체되면 그 주소가 바뀌고 정지와 시작이면 그대로 유지되기 때문이다. 그래서 이전 기록에 구분하지 못하는 관찰이라고 붙였는데 관찰과 그 관찰이 무엇을 못 가르는지를 같이 적어야 나중에 근거로 쓸 때 오해가 없다.
정리
- 값을 바꿔 재실행을 유도하는 기법이 모든 리소스에서 되는 것이 아니다
- 그 속성이 교체가 아니라 중단만 유발하면 안 된다
- 초기화 스크립트는 인스턴스당 한 번만 돈다
- 정지와 시작으로는 다시 돌지 않는다
- 배포 전에 교체 여부를 미리 확인할 수 있다
- 해 보기 전에 된다고 쓰지 않고 제안 상태라고 적는다
- 이전 관찰이 구분하지 못하는 관찰일 수 있다
- 관찰과 그 한계를 같이 적는다