リリースを開けてみる — 保存場所・保持ウィンドウ・復活
한국어 원문으로 표시합니다.
목표
Helm 릴리스가 클러스터의 어디에 무엇으로 저장되는지를 직접 풀어 보고, 보관 창이 얼마나 좁은지, 지운 릴리스를 어떻게 되살리는지까지 한 바퀴 돕니다.
왜 중요한가
helm rollback 이 무엇을 되돌리고 무엇을 못 되돌리는지는 전부 저장 구조에서
나옵니다. 릴리스는 네임스페이스 안의 시크릿 한 장이고, 그 안에 렌더링된
매니페스트가 통째로 눌려 들어 있습니다. 그래서 매니페스트에 적혀 있던 것은
되돌아오고 바깥에서 벌어진 일은 되돌아오지 않습니다.
같은 구조에서 따라 나오는 것이 둘 더 있습니다. 릴리스 이름이 네임스페이스
안에서만 유일하다는 것, 그리고 보관되는 리비전 개수에 상한이 있다는 것입니다.
"반년 전으로 롤백" 이 대개 불가능한 이유가 여기 있습니다. 사고가 났을 때
helm get values 로 "무슨 값으로 떴는가" 를 먼저 확인하는 습관도 이 구조를
알아야 몸에 붙습니다.
환경
이 파드는 kwok 으로 진짜 kube-apiserver 를 띄웁니다. 파드가 실제로 실행되지는
않지만 릴리스 시크릿과 리비전, 오브젝트 변경은 전부 진짜입니다. 그래서 채점도
파일이 아니라 helm 과 apiserver 에 다시 물어서 합니다. 작업 디렉터리는
/root/hs-rel 이고 산출물은 /root/hs-rel/out 아래에 둡니다.
단계
/root/hs-rel에서 차트를 만들고rel-a에shop으로 설치합니다.- 리비전 1의 릴리스 시크릿을 풀어
/root/hs-rel/out/release-v1.json에 저장합니다. - 같은 이름
shop을rel-b에도 설치합니다. --history-max 3으로 네 번 업그레이드해 옛 리비전이 사라지는 것을 봅니다.helm get values와helm get manifest결과를/root/hs-rel/out에 저장합니다.rel-b의 릴리스를--keep-history로 지우고 기록을 저장합니다.- 지운 릴리스를 롤백으로 되살립니다.
/root/hs-rel/out/report.txt에 일곱 줄로 정리합니다.
참고
- 시크릿을 풀 때
base64 -d는 두 번 입니다. 쿠버네티스가 한 겹, helm 이 또 한 겹 인코딩합니다. helm list는 기본값이deployed만 보여 줍니다. 지워진 것이나 갇힌 것을 보려면-a를 붙입니다.- 흔한 실수 하나는 6단계에서
--keep-history를 빠뜨리는 것입니다. 그러면 7단계에서 되살릴 것이 없습니다. - 또 하나는 5단계에서
--all을 붙여 받는 것입니다. 그러면 차트 기본값이 섞여 들어와 "사람이 무엇을 넣었나" 를 알 수 없게 됩니다.
차트를 만들고 이름을 붙여 배포한다
/root/hs-rel 에서 helm create webapp 으로 차트를 만들고, rel-a 네임스페이스에 shop 이라는 이름으로 설치하세요. 네임스페이스는 --create-namespace 로 함께 만듭니다.
helm install <릴리스이름> <차트경로> -n <네임스페이스> --create-namespace 입니다. 설치가 끝나면 kubectl -n rel-a get deploy 로 만들어진 Deployment 의 이름을 확인하세요. 차트가 정한 이름이 아니라 릴리스 이름이 앞에 붙습니다. 이 클러스터는 kwok 이라 파드가 실제로 실행되지는 않지만 릴리스와 오브젝트는 전부 진짜입니다.
릴리스가 저장된 시크릿을 풀어 본다
rel-a 의 helm 릴리스 시크릿 중 리비전 1의 것을 골라 내용을 풀고, 릴리스 JSON 전체를 /root/hs-rel/out/release-v1.json 에 저장하세요.
kubectl -n rel-a get secret -l owner=helm,name=shop 으로 이름을 확인합니다. -o jsonpath='{.data.release}' 로 값을 꺼낸 뒤 base64 -d 를 두 번 하고 gzip -d 를 하면 릴리스 JSON 이 나옵니다. 쿠버네티스가 한 겹, helm 이 또 한 겹 인코딩해 두었기 때문입니다. 렌더링된 YAML 은 그 JSON 의 .manifest 필드에 문자열로 들어 있으니, 이번에는 JSON 을 통째로 저장하세요.
같은 이름의 릴리스를 다른 네임스페이스에 하나 더
같은 차트를 rel-b 네임스페이스에 역시 shop 이라는 이름으로 설치하세요. 두 릴리스가 충돌 없이 각자 살아 있어야 합니다.
릴리스 이름은 클러스터 전역이 아니라 네임스페이스 안에서만 유일합니다. 기록이 그 네임스페이스의 시크릿에 들어가기 때문입니다. helm list -A 로 전체를 보고, kubectl -n rel-b get secret -l owner=helm 으로 기록이 어디에 생겼는지 확인하세요.
보관 창을 줄여 옛 리비전이 사라지는 것을 본다
rel-a 의 shop 을 --history-max 3 을 붙여 네 번 업그레이드하세요. 마지막 업그레이드에서 replicaCount 는 5가 되어야 합니다.
helm upgrade shop ./webapp -n rel-a --set replicaCount=<값> --history-max 3 을 replicaCount 2, 3, 4, 5 로 네 번 돌립니다. 그다음 helm history shop -n rel-a 와 kubectl -n rel-a get secret -l owner=helm,name=shop 을 나란히 보세요. 리비전 번호는 5까지 올라가는데 남아 있는 것은 세 개뿐입니다. 되돌릴 수 있는 창이 생각보다 좁다는 것이 이 단계의 요점입니다.
이 릴리스에 실제로 들어간 값과 매니페스트를 꺼낸다
helm get values 를 JSON 으로 받아 /root/hs-rel/out/values.json 에, helm get manifest 결과를 /root/hs-rel/out/manifest.yaml 에 저장하세요. 값은 사용자가 준 것만 담겨야 합니다.
helm get values shop -n rel-a -o json 은 사용자가 준 값만 보여 주고, --all 을 붙이면 차트 기본값까지 합쳐서 보여 줍니다. 사고 조사에서 먼저 보는 것은 앞쪽입니다. helm get manifest 는 그 릴리스가 실제로 적용한 YAML 이므로, 거기 적힌 replicas 와 kubectl get deploy 가 답하는 replicas 가 같아야 정상입니다.
기록을 남기고 지운다
rel-b 의 shop 을 --keep-history 를 붙여 삭제하고, helm list -n rel-b -a 와 helm history shop -n rel-b 의 출력을 함께 /root/hs-rel/out/uninstalled.txt 에 저장하세요.
helm uninstall shop -n rel-b --keep-history 입니다. 그냥 helm uninstall 하면 릴리스 시크릿까지 사라져 되살릴 수 없습니다. 삭제한 뒤 helm list -n rel-b 는 아무것도 보여 주지 않는데, -a 를 붙이면 uninstalled 상태로 남아 있는 것이 보입니다. helm list 의 기본값이 지워진 릴리스를 숨긴다는 점을 눈으로 확인하세요.
지운 릴리스를 되살린다
rel-b 의 shop 을 리비전 1로 롤백해 되살리세요. 되살린 뒤에도 uninstalled 리비전은 기록에 남아 있어야 합니다.
helm rollback shop 1 -n rel-b 입니다. 기록을 남겨 두었기 때문에 다시 설치하지 않고도 돌아올 수 있습니다. 다시 helm install 을 하면 히스토리가 1번부터 새로 시작해 무슨 일이 있었는지가 사라집니다. 롤백 뒤 helm history 를 보면 uninstalled 리비전 위에 'Rollback to 1' 이 적힌 새 리비전이 붙어 있습니다.
일곱 단계를 숫자로 정리한다
/root/hs-rel/out/report.txt 에 일곱 줄을 적으세요. RELEASES_TOTAL, STORAGE, HISTORY_MAX, REL_A_KEPT, REL_A_LATEST, RESOURCE_PREFIX, SCOPE 입니다.
값은 짐작하지 말고 클러스터에서 세어 적습니다. helm list -A -a 로 shop 이 몇 개인지, helm history shop -n rel-a 로 남은 리비전 개수와 가장 큰 번호가 몇인지 확인하세요. STORAGE 는 helm 3 이 릴리스를 어디에 두는지, SCOPE 는 릴리스 이름이 어디까지 유일한지를 한 단어로 적습니다. RESOURCE_PREFIX 는 1단계에서 본 Deployment 이름입니다.