Search

Argo CD - GitOps기반의 Kubernetes CD

들어가며

이 포스팅에서는 GitOps 와 이를 기반으로한 쿠버네티스의 CD(Continuous Deployment)도구인 Argo CD 에 대해서 설명해보려고 합니다.
한 마디로 말하자면, 우리가 잘 알고 있는 Git을 통해 쿠버네티스 기반 애플리케이션의 운영 및 배포를 한다는 이야기 입니다.
현재 ThinQ Anywhere 및 TCN 프로젝트를 진행하면서 쿠버네티스 위에 서비스를 배포하고 운영하고 있습니다. 그 과정 속에서 쿠버네티스 환경에서 "운영"을 한다는 것은 꽤나 쉽지 않은 일이라는 것을 종종 느끼곤합니다.
예를 들면, 다른 누군가 Deployment의 이미지 버전을 변경한다거나, Service의 타입 또는 포트를 변경하는 등의 작업으로인해 쿠버네티스에 배포된 전체 애플리케이션의 상태를 원하는 상태로 동일하게 보장할 수 없는 상황이 생기곤 했습니다.
이런 상황은 서비스가 커지고 리소스 양이 많아질수록 더 자주 발생하게되며, 쿠버네티스 안에서 일어나는 일들을 추적하고 관리하는 일이 점점 어려워지게 만듭니다.
이를 개선하고자 하던 중 알게 된 것이 GitOps이며, GitOps를 기반으로한 쿠버네티스 CD 도구인 Argo CD를 알게되었습니다.  이에 대한 지식을 조금이나마 공유하기 위해 부족하지만 설명을 시작해보겠습니다.

TL;DR

GitOps는 Git을 운영 환경 및 애플리케이션의 유일한 원천으로 보는 운영 및 배포 방식이다.
Argo CD는 쿠버네티스를 위한 GitOps로 구현체로 가장 널리 쓰인다.

CD(Delivery) vs CD(Deployment)

우리가 일반적으로 CD를 이야기하면 Continuous Delivery를 말합니다. 아마도 지금까지 경험해 온 것도 대부분 그럴 것이라 예상합니다.
사실 둘의 차이는 모호한 느낌이 있어서 종종 헷갈리는데, 간단히 말하면 자동화의 수준의 차이로 구분합니다.
Continuous Delivery의 경우 운영에 대한 "Deployment"는 수동으로 트리거 되는데, 이마저 자동화한 것을 Continuous Deployment라고 부르고 있습니다.

GitOps란?

GitOps는 쿠버네티스의 네트워크 프로바이더 중 하나인 Weaveworks에서 처음 제시한 것으로, 그 중에서도 클라우드 네이티브 애플리케이션의 운영 및 CD(Continuous Deployment)의 방법론입니다.
GitOps의 핵심 아이디어는 클라우드 네이티브 애플리케이션의 선언적 명세를 작성하여 Git으로 관리하고, 선언적 상태와 일치하도록 만드는 자동화된 배포 &운영(Ops)하는 프로세스를 갖추는 것을 말합니다.
핵심은 모든 선언적 상태와 변경이 Git에 커밋되어 버전 관리가 가능하게 된다는 점 입니다.
또한 모든 배포 및 관리가 PR & Merge로 관리된다는 의미이기도 합니다.
이로 인해 생기는 장점은 배포&운영에 대해 변경 사항 추적이 쉬워지고, Git을 통해 관리되기 때문에 신속하고 정확한 롤백도 가능하다는 점을 들 수 있습니다.
물론, GitOps는 "Declarative(선언형)" 형태로 표현할 수 있다면 어디든 적용할 수 있으나, 이 개념을 처음 제시한 Weaveworks에서는 쿠버네티스 기반의 애플리케이션에 대한 방법론이라고 명시할 정도로(cloud-native systems that are powered by Kubernetes) 햔재 GitOps는 쿠버네티스 기반 운영 방법으로써 De-facto로 여겨지고 있습니다.
개인적으로 생각하는 GitOps의 가장 중요한 Core Principle은 다음 2가지입니다.
Declatative Description(선언적 명세서)
단일 진실 공급원(SSOT)

Declarative: The entire system has to be described declaratively

GitOps가 동작하기 위해서는 전체 시스템이 "Declarative(선언적)"으로 설명/명세 되어야 합니다.
"선언적"이라함은 명령의 집합이 아닌, 사실의 집합으로 구성을 보장할 수 있다는 뜻 입니다. 이는 일련의 과정을 단계적으로 밟는 "명령형"과 다르게 단순히 우리가 "원하는 상태"를 시스템에게 알려주기만 하면 된다는 의미입니다.
우리가 원하는 애플리케이션의 배포 상태를 선언적으로 기술할 수 있으면, Git 저장소를 아래 설명할 단일 진실 공급원으로써 사용할 수 있게 됩니다.

SSOT(Single Source of Truth)

SSOT(단일 진실 공급원)의 의미는 사실, 진실(Truth)은 하나의 공급원(Single Source)에서 기인한다 는 뜻입니다.
실제 배포를 생각하면, 배포에는 다양한 방법이 있을 수 있고, 또한 여러 사람이 배포를 할 수 있는 등 다양한 변수가 존재합니다.
때문에 만약 배포에 있어서 문제가 발생한다면, 배포 방법, 배포한 사람 등 원인이 다양하여 추적은 그렇게 만만한 일이 아닙니다.
SSOT는 상태나 배포의 결과(Truth)가 단 하나의 공급원에서만 발생할 수 있도록 함으로써 운영 환경의 상태와 공급원을 1:1로 매핑 시킨다고 이해하면 좋을 것 같습니다.
정리하면, GitOps는 코드 저장소(Git)를 단일 진실 공급원으로 만들고, 운영과 배포에 관한 모든 사실을 코드 저장소에서 관리하도록 하는 것이 핵심입니다.

Why GitOps?

그렇다면 왜 GitOps를 자꾸 이야기하는 걸까요? 아래와 같은 이유가 있습니다.

Deploy Faster More Often

CD 도구는 기본적으로 배포를 더 빠르게, 더 자주할 수 있도록 도와주는 것이 목표입니다.
GitOps의 특징은 배포를 위해서 개발자가 추가적으로 할 일을 줄이고 단순화한다는 점입니다.
개발자는 기존에 개발하고 커밋하는 익숙한 방법을 그대로 활용하여 배포를 할 수 있고, 실시간으로 이를 확인할 수 있습니다.

Easy and Fast Error Recovery

배포 환경에 문제가 생기더라도 Git을 통해 배포에 대한 완전한 기록(Complete History)을 갖고 있으므로 단순히 git revert 명령어만 사용해도 즉시 이전 환경으로 롤백 또는 복원이 가능하게 됩니다.

Easier Credential Management

GitOps를 가능케하기 위해서는 Git에 접근할 권한과, 이미지 레지스트리에만 접근할 권한만 있으면 충분하며 배포 환경 내부에서 배포 관련 사항을 완전하게 관리할 수 있게 됩니다.
특히 개발자들에게 배포 환경에 직접 엑세스 권한을 부여할 필요가 없어짐으로써 보안적으로 더 나은 배포 환경을 만들 수 있습니다.

Self-documenting Deployments

GitOps를 사용하게되면, 애플리케이션 배포 환경의 모든 변경 사항은 곧 Git으로 관리되고 있는 선언적 Description의 변경으로 트리거 됨을 의미합니다.
따라서 모든 실제 배포 내용은 Commit 메세지, Pull Request, Merge등을 통해 Git에 전부 기록되며, “배포 == Git의 변경” 공식을 성립시킬 수 있습니다.
모든 배포는 무슨일이 있어도 Git에 기록되기 때문에 Self-documenting Deployments라고 말하기도 합니다.

Shared Knowledge in Teams

Git을 사용하여 배포된 인프라/애플리케이션에 대한 전체 Description을 저장하면 팀의 모든 사람에게 변경에 대한 자세한 사항을 공유할 수 있습니다.
커밋 메시지를 통해 모든 사람이 인프라/애플리케이션의 배포 히스토리를 파악할 수 있고, 이를 통해 새로운 시스템을 준비할 때 참고할 수 있는 좋은 예시가 될 수 있으며, 다 같이 고민할 수 있는 자료가 될 수 있습니다.

GitOps의 배포 방식 (Push vs Pull)

GitOps는 배포 방법을 Push 타입 또는 Pull 타입 2가지를 가이드하고 있습니다. 두 방법 간의 차이는 배포 상태와 저장소의 선언적 명세 간에 어떻게 Sync를 유지하는가로 분리할 수 있습니다.
가능하다면 더 안전하고 더 나은 Pull 타입을 주로 권장 하고 있습니다.

1) Push 타입

Push 타입은 Git 저장소의 변경이 발생했을 때 배포 파이프라인을 실행시키는 구조로 우리가 자주 접하는 구조입니다.
상대적으로 간단한 형태를 갖고 있지만, 배포 도구가 배포 환경(쿠버네티스 내부) 외부에 있기 때문에 접근을 위한 자격 증명 관리가 필요하며, 동시에 보안정보가 외부로 노출될 수 있는 위험이 있습니다.
또한 Push 방식은 저장소의 변경(Commit)으로 배포가 트리거됩니다.
따라서 항상 저장소와 Sync되어 있는 상태가 아니기 때문에 배포의 결과가 리포지토리와 일치하지 않을 가능성이 있어서 이를 모니터링 할 필요가 있습니다.

2) Pull 타입

Pull 타입은 배포가 될 환경 내부의 별도의 오퍼레이터가 배포 파이프라인을 실행하게 됩니다.
오퍼레이터는 저장소의 선언적 배포 명세와 배포 환경을 지속적으로 비교하며 변경이 발생할 경우 저장소를 기준으로 배포 환경을 유지할 수 있도록 합니다.
Pull 타입은 Push의 단점인 저장소의 변경으로만 배포가 트리거되는 부분이 해결됩니다.
또한 Push와 다르게 배포 관리자가 배포 환경 내부에 있기 때문에 접근 권한등의 설정 필요가 없어지고, 보안정보가 외부로 노출될 일도 현저히 줄어들게 됩니다.
현재 Pull 방식을 지원하는 배포 관리자로는 Argo CD, Flux CD, JenkinsX등이 있습니다.
다음은 Pull 타입을 사용한 GitOps 파이프라인의 참고 예시입니다.
위 구조를 간단히 설명하면,
소스 코드의 변경을 커밋하면, CI 파이프라인에 의해 소스 빌드 및 이미지를 생성하고, 이미지 레지스트리에 이미지를 업로드합니다.
그 다음 Config Update를 진행합니다. 여기서 Config Update는 배포 관련 선언적 명세 파일들을 업데이트하는 작업을 말합니다.
배포 관련 선언적 명세 파일들이 업데이트되어 Git에 커밋 되었기 때문에, 이를 감시하던 오퍼레이터는 쿠버네티스 배포 환경에 변경 사항을 자동으로 배포합니다.

Argo CD

GitOps 기반의 구현체는 Argo CD, Flux CD, JenkinsX등이 있는데, 현재 대표적인 쿠버네티스 기반 GitOps CD 도구로 자리잡은 Argo CD에 대해서 조금 더 알아보겠습니다.
아래는 최근 5년동안 각 구현체에 대한 전세계 단위 구글 검색을 구글 트렌드로 살펴본 표인데, 전세계적으로 Argo CD가 압도적인 인지도를 갖고 있는 것으로 볼 수 있습니다.

Argo CD란?

Argo CD는 위에서 설명한 GitOps를 기반으로한, 특히 쿠버네티스를 위한 GitOps기반의 CD 도구 입니다.
GitOps 기반으로 관리되는 선언적 명세 파일들의 변경사항을 모니터링하며, 현재 쿠버네티스에 배포된 리소스 상태와 Git에 정의된 원하는 상태를 동일하게 유지하는 역할을 수행합니다.
현재 GitOps 구현체로서 가장 많이 쓰이고 있으며, 멀티 클러스터 지원을 비롯한 다양한 기능을 제공할 뿐더러 잘 만들어진 Web UI도 장점이라고 볼 수 있습니다.

Argo CD를 활용한 쿠버네티스 배포 맛보기

Argo CD를 배포 쿠버네티스 환경에 설치하는 내용부터 차근차근 가이드하면 좋겠지만, 여기서는 Argo CD를 통해 Git 저장소와 동일하게 배포를 하는 큰 그림을 위주로 살펴보는 것이 좋을 것 같습니다.
Argo CD를 설치한 후, Web UI로 접속하면 다음과 같은 화면을 만날 수 있게 됩니다.
사실 미리 말씀드리자면, Web UI에서는 설정가능한 요소가 제한적입니다. 따라서 본격적으로 Argo CD를 사용하기 시작하면, Web UI로는 배포를 관리한다기보다는 Argo CD가 관리하는 배포 상태를 모니터링하는 용도로 주로 쓰입니다.
그럼 이제, Argo CD를 통해서 Wordpress 애플리케이션을 배포해보도록 하겠습니다.
앞서 설명한 GitOps를 이해하셨다면, Wordpress 애플리케이션 배포를 위한 쿠버네티스 리소스 명세 Git 리포지토리가 있어야한다는 것을 떠올리셨을겁니다.
고맙게도 이미 쿠버네티스 용으로 다양한 애플리케이션을 패키징 해놓은 저장소들이 아주아주 많이 존재합니다. 여기서는 Bitnami가 패키징한 Wordpress를 사용하겠습니다. (참고로 아래 링크 중 2번째는 특별한 설정 없이 쿠버네티스 환경에 그대로 배포될 수 있도록 제가 다시 패키징한 wordpress입니다.)
먼저 위 저장소를 구경해보겠습니다. 사실상 배포에 관한 "선언적 명세"는 모두 templates/ 디렉토리 아래에 있습니다.
templates/ 디렉토리를 들어가보면 알 수 없는 yaml 파일들의 향연을 보실 수 있습니다. 만약 쿠버네티스에 익숙하지 않은 분이라면, 이 yaml들의 내용들을 이해하는 것은 힘들 것으로 생각됩니다.

그러나, 걱정할 필요가 없습니다.

우리는 쿠버네티스 배포 용도로 선언적 명세가 만들어진 Git Repository를 이미 알고 있고, 이를 쿠버네티스에 그대로 옮겨다 줄 Argo CD가 있으니까요.그럼, 배포를 시작해보겠습니다.
스크린샷으로만 이해하기 힘드시겠지만, 위 내용은 Argo CD에게 Application(Argo CD의 배포 단위) 생성을 위해 정보를 넣는 것 입니다.위에서 눈여겨 보실 부분은 Source, Destination 탭입니다.
Source
Repository URL : Git Repo 주소
Revision : 브랜치 명
Path : 내부 디렉토리
Destination
Cluster URL : 배포할 쿠버네티스 클러스터 주소
Namespace : 배포할 namespace
Source는 SSOT의 공급원을 알려주는 곳입니다. 이 테스트에서는 제가 다시 패키징한 wordpress를 사용하겠습니다. Application 설정에 main 브랜치의 wordpress 디렉토리가 공급원임을 알려주었습니다.Destination은 배포가 될 쿠버네티스 클러스터 정보입니다. 여기서는 Argo CD가 배포된 쿠버네티스 클러스터에 그대로 배포할 것이기 때문에 https://kubernetes.default.svc 주소를 사용합니다.
이제 모든 준비가 끝났습니다. Create를 누르면 놀랍게도 Wordpress가 내 쿠버네티스 클러스터에 배포되고 있습니다.
Status를 보면 Synced, 즉 Git Repository와 싱크가 완료되었고, Progressing 상태는 현재 Git에 명세된 상태대로 쿠버네티스의 리소스를 생성 중임을 의미합니다. 조금만 기다리면, 오른쪽처럼 배포 및 Health체크까지 완료된 상태를 볼 수 있습니다.
애플리케이션을 클릭해보면, 더 상세히 배포 상태를 파악할 수 있습니다. Wordpress를 위해 쿠버네티스의 어떤 리소스들이 생성, 관리 중인지 UI로 확인 가능합니다.
왼쪽에 보이듯 많은 쿠버네티스 리소스를 클릭 한 번으로 Git Repository에 명세된 똑같은 상태로 Wordpress를 배포했습니다.
단순히 UI만으로 보면 쿠버네티스에 진짜 배포됐는지 의심이 될 수도 있습니다. 이를 확인하기 위해 쿠버네티스에 배포된 상황을 직접 확인하면 왼쪽과 같이 실제로 배포된 것을 확인할 수 있습니다.
이제 한 번 Git 저장소를 업데이트해보고, 어떻게 Argo CD가 동작하는지 살펴보겠습니다.
먼저, Git에서 Wordpress의 ReplicaCount를 1개에서 2개로 바꾸고 커밋해보겠습니다.커밋 후 얼마 지나지 않아, Argo CD에서 Git Repository와 현재 배포된 Wordpress가 다름을 감지하고 새로 배포가 진행 중인 것을 확인할 수 있습니다.
App Health를 보면 Progressing 상태로, 새로운 배포를 적용중인 것을 확인 가능합니다.
또한 Current Sync Status 항목의 Commit 메시지를 보면, 방금 Wordpress replica count를 2로 증가시킨 내용이 확인됩니다.
이로써, Git Repository의 변경내용이 Argo CD를 통해 감지되고, 쿠버네티스 배포 환경에 그대로 적용되는 것을 확인할 수 있습니다.

이렇게 배포에 관한 모든 사실이 Git에 기록되고, 이를 통해 배포 된다는 것, 이게 GitOps의 전부이며 이를 가능하게 해주는 것이 Argo CD입니다. 참 쉽죠? (...)

마치며

짧은 글 안에, GitOps의 개념과 Argo CD의 사용까지 설명을 하려니 너무 많은 양이 될 것 같아서 양을 줄였는데, 오히려 건너뛰며 설명한 것 같아서 이해하는데 도움이 될지 잘 모르겠습니다.
개인적으로 이 글에서 Argo CD 보다는 GitOps개념 을 이해가고 가시는게 가장 좋을 것 같습니다.
앞으로 우리 조직 내에서도 쿠버네티스를 좀 더 많이 사용하는 날이 곧 다가올 것이고, ThinQ Anywhere과는 차원이 다른 규모의 쿠버네티스 기반 애플리케이션을 배포하고, 관리해야 할 것으로 생각됩니다.
그 때도 쿠버네티스의 GitOps 기반의 CD 도구로써 Argo CD가 계속 사용 중이라면, 이 글로 인해 GitOps/Argo CD가 낯설지 않게 느껴질 수 있길 바래봅니다.
몇가지 내용을 마지막으로 요약하고 마무리하도록 하겠습니다.
GitOps는 클라우드 네이티브 애플리케이션 배포에서 최근에 가장 많이 사용 되는 방법
실제로 적용해봤을 때, 배포 관련 명세 파일들이 한 번만 잘 작성되면 배포 과정은 일관되게 구현체(Argo CD)에게 맡길 수 있고, 쿠버네티스 클러스터에 배포하는 과정 자체의 로드가 크게 감소
쿠버네티스에 배포하고 Healthy까지 체크함으로써 신뢰도 높은 배포 및 롤백 기능
배포 후 E2E 테스트는 또 다른 문제 → Argo CD, GitOps는 배포만 책임진다.

참고

GitOps
Argo CD