NKS 기반 컨테이너화 및 GitOps 체계 구축
SSH 기반 배포 환경을 NKS + ArgoCD GitOps 체계로 전환했습니다. 애플리케이션 컨테이너화를 통해 배포 패키징을 표준화하고 이미지 단위 즉시 롤백이 가능한 안정성을 확보했습니다. 운영팀 10명 대상 GitOps 온사이트 교육을 직접 수행했습니다.
Architecture
동기
고객의 요구는 배포 성숙도를 올리는 것이었고, 그 방법으로 GitOps 를 제안한 쪽은 저희입니다. 그때는 SSH 로 서버에 올리고 있었으니, 어느 서버에 무엇이 올라가 있는지가 사람의 기억과 그 서버 안에만 있었습니다.
앱을 나눠 옮기지 않고 한 번에 옮긴 뒤 넘겼습니다. 두 방식이 한동안 같이 도는 상태를 만들면 그 기간에는 어느 쪽이 정본인지가 다시 사람의 기억으로 돌아갑니다. 넘어간 뒤에 문제가 생겨도 이전 상태가 Git 이력에 남아 있으니 되돌릴 근거는 있었습니다.
내가 담당한 트랙
컨테이너화부터 CI 파이프라인, GitOps 체계, 운영팀 교육까지 제 쪽이었습니다. 항목별 내역은 오른쪽 「주요 업무」에 있습니다.
| 트랙 | 경계 |
|---|---|
| 개발자 쪽 | war 파일까지입니다. Maven 이 만든 war 를 Dockerfile 이 이미지 안으로 복사하는 지점부터가 제 몫이었습니다 |
무엇이 올라갔는지를 Git 에 남기기
배포될 환경은 커밋의 모양이 고릅니다. 기능 브랜치에서 머지 요청이 열리면 개발계, main 에 들어오면 검증계, 태그가 붙으면 운영계로 갑니다. 이 규칙도 저희가 먼저 제안한 것이고 고객이 받았습니다.
배포 단계가 하는 일은 매니페스트 저장소를 받아 그 환경 overlay 의 이미지 태그를 새 값으로 바꾸고 커밋해 올리는 것입니다. 그러면 ArgoCD 가 그 커밋을 보고 클러스터를 맞춥니다. 무엇이 올라가 있는지를 묻는 일이 서버에 들어가는 일에서 커밋을 읽는 일로 옮겨 오는 지점이 여기입니다.
운영으로 갈 때는 소스를 다시 빌드하지 않습니다. 검증계에서 쓰던 이미지에 태그만 새로 붙입니다. 다시 빌드하면 그때 받아 오는 의존성이 달라질 수 있고, 그러면 검증한 것과 운영에 올라가는 것이 같다고 말할 수 없게 됩니다.
이름을 풀어 줄 곳이 없어서
내부 DNS 가 없었습니다. 그래서 이름을 주소로 바꿔 주는 일을 계층마다 따로 해 줘야 했습니다. 호스트의 hosts 파일에 항목을 넣고, 컨테이너에는 extra_hosts 로 같은 항목을 다시 넣고, 러너에도 그 설정을 따로 넣었습니다. 한 곳만 해 두면 빌드는 되는데 실행이 안 되거나, 실행은 되는데 빌드가 안 되는 식으로 갈립니다.
Kubernetes 로 올라간 쪽은 매니페스트에 주소가 그대로 들어갑니다. 지금 남아 있는 운영 overlay 를 봐도 APM 서버가 호스트명이 아니라 IP 로 적혀 있습니다. 환경마다 달라지는 값은 overlay 로 밀어 넣어 이미지는 한 벌로 두는 것이 목표였는데, 이름을 못 쓰면 그 목표가 한 칸씩 밀립니다.
폐쇄망도 같은 방향으로 일을 늘립니다. 베이스 이미지, 빌드 도구, 스캐너까지 사내 레지스트리에 미리 넣어 둔 것만 쓸 수 있어서 새 도구를 하나 쓰려면 반입부터 시작합니다.
운영팀이 가장 어려워한 것
교육에서 제일 걸린 것은 저장소 사이의 인증이었습니다.
GitOps 로 오면 저장소가 둘이 됩니다. 앱 소스가 있는 저장소와 매니페스트가 있는 저장소입니다. 그리고 파이프라인은 첫 번째 저장소에서 돌면서 두 번째 저장소에 커밋을 밀어 넣어야 하므로, 자기가 아닌 저장소에 쓸 자격을 들고 있어야 합니다. SSH 로 배포할 때는 없던 관계입니다.
이 자격이 없으면 파이프라인이 배포 단계에서 조용히 실패합니다. 그래서 템플릿에 변수가 비어 있으면 그 자리에서 멈추고 GitLab 어느 화면에서 무엇을 만들어야 하는지 알려 주는 가드를 넣어 뒀습니다. 처음 붙는 사람이 반드시 한 번 밟는 자리라 그렇습니다.
앱 정의를 콘솔에 둔 결과
Application 은 웹 콘솔에서 만들었고 고객도 그 방식을 따랐습니다. 그리고 한 해가 지나 자동 동기화 설정이 자꾸 풀린다는 문의가 왔습니다.
어긋난 상태를 되돌려 주는 설정은 그 앱이 Git 에서 가져온 리소스를 지킵니다. 앱 자체는 콘솔에서 만들어져 Git 에 원본이 없으니, 무엇을 기준으로 되돌릴지가 없어서 그 설정이 앱 자신에게는 미치지 않습니다. 매니페스트는 Git 에 두었는데 그 매니페스트를 배포하는 앱은 Git 밖에 있었던 것입니다.
앱 정의도 Git 에 두고 그 정의들을 관리하는 상위 앱을 하나 얹는 구조를 가이드로 남겼습니다.
배운 점
- GitOps 구성을 이 프로젝트에서 처음 했습니다. 지금은 익숙해서 새삼스럽지도 않은 방식인데, 그때는 하나하나 새로 배우면서 세웠습니다.