Post

배포 자동화 리팩토링, 젠킨스에서 ArgoCD로 (3) — 실전 설계: AS-IS 전수조사와 values 구조

짐작이 아니라 파일을 읽어야 했다

샘플 앱으로 ArgoCD 자체는 손에 익혔으니, 이제 진짜 서비스(aidt-lm-service)를 옮길 차례였다. 근데 여기서부터는 더 이상 “감”으로 설계할 수 없었다. 지금까지 이 서비스를 배포해온 젠킨스 스크립트는 1,000줄이 넘었고, 그 안에서 계산되는 값이 30개 가까이 됐다. 이 값들 중 어떤 게 지금도 실제로 쓰이고 있고, 어떤 게 예전에 쓰였다가 지금은 아무도 안 읽는 죽은 값인지 — 이걸 확인 안 하고 새 구조로 옮기면, 죽은 값을 그대로 복사해서 옮기거나 반대로 실제로 필요한 값을 빠뜨릴 위험이 있었다.

그래서 이 단계의 원칙은 하나였다.

실제 헬름 차트 템플릿과 실제 젠킨스 스크립트를 직접 열어서, 값 하나하나가 어디서 와서 어디로 가는지 손으로 추적한다.

값 하나를 추적하는 방법

예를 들어 이미지 태그 값 하나를 추적해보면 이렇다. 헬름 차트의 기본 values.yaml에는 deploy.image.tag라는 필드가 정의돼 있었다. 근데 실제 템플릿 파일(Deployment.yaml)을 열어보니, 이미지 태그를 참조하는 부분은 이렇게 돼 있었다.

1
image: ":"

.Values.deploy.tag를 읽고 있었다 — .Values.deploy.image.tag가 아니라. 즉 기본 values.yaml에 정의된 그 필드는 애초에 아무도 읽지 않는 죽은 값이었다. 실제 태그는 젠킨스가 배포 시점에 deploy.tag라는, 기본값 파일과는 다른 경로의 필드를 직접 주입해서 결정되고 있었다.

이런 식으로 하나씩 짚어가다 보니, 죽은 값이 꽤 여럿 나왔다.

  • lr(LimitRange) 관련 값 10개 — 젠킨스가 배포 시점마다 계산해서 넘기고 있었는데, 정작 차트 안에 LimitRange라는 리소스를 만드는 템플릿 자체가 없었다. 어느 시점엔가 이 리소스를 쓰다가 템플릿만 지워지고, 값 계산 로직은 그대로 남은 걸로 보인다.
  • deploy.proxyImage — Istio 프록시 이미지 경로를 젠킨스가 매번 계산해서 넘기고 있었는데, 실제 템플릿은 이 값이 아니라 mesh.proxy.image라는 다른 경로를 읽고 있었다. 즉 프록시 이미지는 사실 항상 차트에 박힌 기본값으로 고정되고 있었던 셈이다.

이런 값들을 눈치채지 못했으면, 새 구조로 옮기면서 쓸모없는 필드까지 그대로 복사했을 거다. 전수조사를 제대로 안 하면 “깔끔한 새 구조” 안에 옛날 죽은 코드가 그대로 옮겨붙는 역설이 생긴다는 걸 이때 체감했다.

클러스터 토폴로지를 착각했던 순간

전수조사 도중, 제일 크게 잘못 짚었던 부분이 하나 있다. 젠킨스 스크립트에는 배포 대상을 정하는 값으로 buildcluster라는 값이 있었는데, 처음엔 이걸 그냥 “배포 로그에 남기는 라벨 정도”로 대충 넘겼다. 그래서 설계를 “네임스페이스만 다르고 클러스터는 하나”라고 가정하고 한참을 진행했다.

근데 실제로는 아니었다. 스테이징 환경 자체가 물리적으로 서로 다른 클러스터 두 대로 나뉘어 있었고, 교과목(수학/영어)에 따라 어느 클러스터로 갈지가 정해져 있었다.

클러스터 토폴로지

이걸 놓치고 있다가, 실제로 ArgoCD Application을 설계하는 단계에서 뒤늦게 발견해서 바로잡았다. 다행히 설계 단계에서 걸러졌지, 이대로 배포까지 갔으면 엉뚱한 클러스터로 배포를 시도했을 거다. 이 경험 이후로 “이 값이 그냥 라벨인지, 실제로 물리적인 무언가를 가리키는지”를 짐작하지 않고 꼭 다시 확인하는 습관이 붙었다.

values를 4단으로 나누기로 한 이유

전수조사가 끝나고 나니, 흥미로운 패턴이 보였다. 같은 환경(스테이징) 안에서, 교과목이 달라도 값이 거의 다 똑같았다. 실제로 다른 건 네임스페이스 이름, 소속 클러스터, 그리고 거기서 파생되는 몇 개의 문자열뿐이었다.

그래서 값을 이렇게 4단으로 나눴다.

1
2
3
1. 환경 공통값     ← 스테이징/운영 전체에 공통 (배포 전략, 리소스 제한, 서비스 메시 설정 등)
2. 도메인 전용값    ← 교과목(네임스페이스)별로 다른 값 (네임스페이스 이름, 소속 클러스터 등)
3. 이미지 태그       ← 배포마다 바뀌는 딱 하나의 값, CI가 patch하는 파일

이렇게 나눈 이유는 두 가지다.

첫째, 중복을 없애기 위해서. 공통값을 도메인마다 반복해서 적으면, 나중에 하나를 고칠 때 도메인 수만큼 다 찾아서 고쳐야 한다.

둘째, CI가 건드릴 파일을 딱 하나로 좁히기 위해서. 이미지 태그만 담은 파일을 따로 빼둔 덕분에, 젠킨스가 배포마다 손대는 파일이 정확히 하나로 고정된다. 여러 파일에 걸쳐 값을 흩어놓았으면, 배포 자동화 스크립트도 그만큼 복잡해졌을 거다.

Vault 켜고 끄기에 따라 생기는 대칭 구조

전수조사하면서 재밌는 대칭을 하나 발견했다. 이 서비스는 시크릿을 두 가지 방식 중 하나로 관리한다 — Vault를 쓰거나, 아니면 평범한 쿠버네티스 Secret 오브젝트를 쓰거나. 스테이징은 후자, 운영은 전자를 쓰고 있었다.

그런데 이 두 방식에 필요한 값들이 서로 정반대로 “죽는” 구조였다.

 스테이징 (Vault 끔)운영 (Vault 켬)
Vault 인증 경로 값안 쓰임 (Vault 관련 설정 자체가 렌더링 안 됨)쓰임
쿠버네티스 Secret 마운트 값쓰임안 쓰임 (조건이 거짓이 돼서 마운트 자체가 안 일어남)

즉 스테이징 값 파일엔 Vault 인증 경로 값이 들어있어도 사실 무의미하고, 운영 값 파일엔 Secret 마운트 값이 들어있어도 사실 무의미하다. 당장은 안 쓰이지만, 나중에 이 설정이 바뀔 가능성을 생각해서 두 값 다 지우지 않고 남겨두기로 했다 — 지금 죽어있다고 완전히 지워버리면, 나중에 설정이 바뀌었을 때 그 값을 다시 알아내야 하는 수고가 생기기 때문이다.

다음 편 예고

이렇게 만든 값 구조를 실제로 클러스터에 적용해보는 단계로 넘어가면, 여기서부터는 설계가 아니라 진짜 실전 트러블슈팅이 시작된다. 기존에 젠킨스가 이미 배포해둔 리소스를 ArgoCD가 매끄럽게 이어받게(편입) 만드는 과정에서 마주친 예상 밖의 문제, 그리고 젠킨스 스크립트에 숨어있던 실제 버그까지 — 다음 편에서 이어간다.

(회사·인프라 관련 실명, 클러스터 식별자, 내부 호스트 주소 등은 전부 임의로 재구성해 게시했다.)

This post is licensed under CC BY 4.0 by the author.

© noah. Some rights reserved.