인사이트

인사이트

새로운 관점으로 깊이 있는 통찰을 제시합니다.

SW 테크놀로지

데브옵스의 확장 모델 – 깃옵스(GitOps) 이해하기

2021.01.29박종환
다운로드

들어가며

“개발과 운영의 벽을 허물어 더 빨리 더 자주 배포하자”

데브옵스(DevOps)의 핵심 개념을 나타내는 문장이다. 2020년 소프트웨어 업계 종사자라면 데브옵스의 영향을 직접 혹은 간접적으로라도 받고 있을 것이다.

데브옵스 개념이 등장한 지 10년이 흐른 지금, 가치를 따지는 것은 무의미한 일이 되었다. 그 동안 축적된 긍정적인 결과들은 데브옵스를 더이상 유행이 아니라 소프트웨어 개발과 운영에 꼭 필요한 표준의 영역으로 이끌었다.

개인적으로 데브옵스가 널리 사랑 받게 된 이유는 커다란 목표와 원칙을 공유할 뿐 상세한 규칙이나 절차는 비어 있다는 점, 즉 유연성과 확장성에 있다고 생각한다. 이는 급변하는 시장에서 살아 남을 수 있는 원동력이 되었고 지금도 여러가지 방식으로 또 데브섹옵스(DevSecOps), 깃옵스(GitOps), AI옵스(AIOps) 등의 다양한 이름으로 진화를 계속해 나가고 있다.

이들 중에서 개인적으로 많은 공감을 하였고 최근에 진행한 프로젝트에 직접 적용해 본 “깃옵스(GitOps)”에 대해 설명하고자 한다. 깃옵스의 기본 원칙과 패턴에 대해 알아본 다음 구현체 중 하나인 아르고CD(ArgoCD)를 활용해서 샘플 프로젝트에 적용하는 과정을 다루어 보겠다.

 

깃옵스란?

깃옵스는 위브웍스(Weaveworks Inc.)에서 처음 사용한 용어로 프로젝트에 데브옵스를 적용하는 실천 방법 중 하나이다. 그 중에서도 클라우드 네이티브 애플리케이션을 대상으로 한 지속적 배포(Continuous Deployment)에 초점을 두고 있다.

※ 클라우드 네이티브 애플리케이션이 아니어도 깃옵스를 적용할 수 있으나 아래에서 설명할 선언형 모델(Declarative Model)을 지원하는 최근 도구들이 클라우드 네이티브에 중점을 두기 때문에 어려움을 겪을 수 있다. 위브웍스는 아예 쿠버네티스 대상이라고 못박고 있다.

이름에서 나타나듯 애플리케이션의 배포와 운영에 관련된 모든 요소를 코드화 하여 깃(Git)에서 관리(Ops)하는 것이 깃옵스의 핵심이다. 기본 개념은 코드를 이용하여 인프라를 프로비저닝 하고 관리하는 IaC(Infrastructure as Code)에서 나온 것으로 깃옵스는 이를 인프라에서 전체 애플리케이션 범위로 확장했다.

깃옵스의 개요_ 깃옵스는 애플리케이션의 배포와 운영에 관련된 모든 요소를 코드화하여 깃(Git)에서 관리(Ops)하는 것이 핵심. 개발은 VCS Code Base에 소스코드를 읽고 쓰고 CI에서는 VCS Code Base를 읽어서 Container Registry에 배포하게 된다. 이러한 배포에 관련된 모든 것을 선언형 기술서(Declarative Descriptions) 형태로 작성하여 Config Repository에서 관리하는 구조이며, Config Repository의 선언형 기술서와 운영 환경 간 상태 차이가 없도록 유지시켜주는 자동화 시스템을 구성한다.

깃옵스의 핵심 아이디어는 다음과 같다.

1) 배포에 관련된 모든 것을 선언형 기술서(Declarative Descriptions) 형태로 작성하여 Config Repository(혹은 Environment Repository)에서 관리한다.

2) Config Repository의 선언형 기술서와 운영 환경 간 상태 차이가 없도록 유지시켜주는 자동화 시스템을 구성한다.

깃옵스 환경에서 새로운 버전의 애플리케이션을 배포하거나 기존의 운영 환경을 바꾸고 싶다면 선언형 기술서를 수정한 뒤 Config Repository에 반영하기만 하면 된다. 나머지 과정은 자동화된 시스템이 알아서 수행한다.

 

깃옵스를 움직이는 핵심 개념들

1) 선언형 모델(Declarative Model)

여러분이 원격에 위치한 대상(서버)에 작업(애플리케이션 배포, 설정 관리 등)을 자동화 한다고 했을 때 가장 먼저 떠오르는 방법은 명령어를 순서대로 나열하는 명령형 모델(Imperative Model)일 것이다.

“ssh로 접속 → cd로 이동 → mkdir로 디렉토리 생성”

간단한 방법인 만큼 단점도 명확하다. 우선 예외 상황을 모두 관리(이미 디렉토리가 존재 한다면? 권한은? 등)해야 하며 원격 대상에 대한 지식(OS 종류에 따른 명령어 차이 등)도 필요하다.

다른 방법으로 선언형 모델이 있다. 대상이 무엇이 되어야 하는지만 기술하면 된다. 이해하기 쉽도록 예를 들어보겠다.

원격 서버에 ‘/etc/some_directory’ 디렉토리가 필요한 상황이다. 선언형 모델에서는 아래와 같이 코드 형태로 세부 내용을 작성하기만 하면 된다.

선언형 모델 디렉토리(https://docs.ansible.com/ansible/latest/collections/ansible/builtin/file_module.html)_ -name:Creat a directory if it does not exist, File: _ path:/tec/some_directory_ state:directory

디렉토리가 이미 존재하는지 확인하거나 OS에 따라 바뀌는 명령어를 사용자가 알아야 할 필요가 없다. 이는 선언형 모델 구현체의 몫이다. 이 중 가장 대표적인 것이 쿠버네티스이며 깃옵스와 궁합이 잘 맞는다.

무엇보다도 가장 큰 장점은 인프라를 포함한 애플리케이션 배포와 운영에 관련된 모든 것을 코드로 관리할 수 있다는 점과 이 코드를 이용하여 언제든 똑같은 환경을 다시 만들어내거나 부분 소실 시 복원할 수 있다는 점이다.

2) 단일 진실 공급원(Single Source Of Truth, SSOT)

같은 데이터가 여러 곳에 있을 경우 문제를 일으킬 수 있다. 데이터의 중복은 당연하고 수정 시 한 곳이라도 빠지게 된다면 비정합성까지 발생한다. 때문에 한 곳에 두고 관리하고 다른 곳에서 필요 시 참조만 하도록 하여 문제를 해결한다.

대표적으로 데이터 정규화 작업 시 이용된다. 예를 들어 보겠다. “Employee”와 “Employees’ Skills” 테이블이 있다. 각 레코드들은 Employee Name, Employee Email 정보를 중복해서 포함하고 있다. ‘Tom’의 이메일 주소가 변경되었다. 여러 개의 테이블 레코드를 수정해야 하지만 하나라도 수정이 이루어지지 않을 경우 모순 상태가 된다. 조회하는 테이블에 따라 ‘Tom’ 이메일이 다르게 조회되기 때문이다.

TOM구조세팅_“Employee”와 “Employees’ Skills” 테이블이 있다. 각 레코드들은 Employee Name, Employee Email 정보를 중복해서 포함하고 있다. ‘Tom’의 이메일 주소가 변경되었다. 여러 개의 테이블 레코드를 수정해야 하지만 하나라도 수정이 이루어지지 않을 경우 모순 상태가 된다. 조회하는 테이블에 따라 ‘Tom’ 이메일이 다르게 조회

이런 경우 “Employees’ Skills” 테이블에서 Employee Email을 제거하고 employee_name를 이용해 “Employee” 테이블을 참조하도록 한다. Employee Email 정보는 오직 “Employee”라는 하나의 테이블에서만 관리하도록 하는 것이다.

깃옵스에서도 마찬가지이다. 깃을 단일 진실 공급원으로 지정하고 오직 이 곳에서만 관리하도록 한다. 모든 운영 활동의 시작은 깃이므로 사람 혹은 시스템 간의 혼선을 최소화 할 수 있다. 그리고 개발 단계에서만 누릴 수 있었던 깃의 강력하고 익숙한 기능을 운영 단계에서도 활용할 수 있게 된다. (History, Commit, Merge Request/ Review, Revert 등)

 

깃옵스 구현

실제로 깃옵스를 프로젝트에 적용할 때 고려해야 할 점들을 알아보겠다. 깃옵스는 어디까지나 방법론이기 때문에 정해진 도구가 따로 없다. 각자 익숙한 도구를 이용하면 된다. 그리고 깃옵스는 빌드와 테스트가 끝난 바이너리(이미지)를 저장소에 등록한 이후의 단계를 다루고 있기 때문에 지속적 통합(Continuous Integration) 부분은 생략하겠다.

1) 저장소 전략

최소 2개 이상의 Git 저장소를 사용하는 것을 권장한다.

– 애플리케이션 저장소: 애플리케이션 소스 코드와 애플리케이션 배포를 위한 배포 매니페스트(예: kubernetes yaml)를 포함한다.

– 배포 환경 구성 저장소: 배포 환경에 대한 모든 매니페스트를 포함한다. 애플리케이션과 인프라 서비스(모니터링, 메시지 브로커 등)가 어떤 버전으로 어떻게 구성되어야 하는지에 대한 정보가 들어있다.

애플리케이션 배포 매니페스트를 별도의 깃 저장소에 보관해도 되고 템플릿 형태로만 가지고 있다가 배포 시 배포 환경 구성 저장소와 합쳐서 매니페스트를 생성하는 방식으로도 사용이 가능하다.

2) 배포 전략

깃옵스는 푸시 타입(Push Type)과 풀 타입(Pull Type), 두 가지의 배포 전략을 가이드 하고 있다. 두 옵션 간의 차이점은 저장소에 있는 매니페스트와 배포 환경의 상태를 일치시키는 방법이다. 무엇을 선택해도 상관없으나 깃옵스는 보안상의 이유로 풀 타입 배포 전략을 권장한다. 각각에 대해 간략히 알아보겠다.

깃옵스푸시타입배포전략_ Application Repository, triggers, Build Pipeline, pushes container imates(image Registry), updates, (enviroment Repository), triggers, Deployment Pipeline, Deploys, Environment

■ 푸시 타입(Push Type)

저장소에 있는 매니페스트가 변경되었을 때 배포 파이프라인을 실행시키는 구조이다. 아키텍처가 단순하여 인기있는 방법이며 젠킨스(Jenkins), 서클CI(CircleCI) 등의 구현에 사용할 수 있는 도구들도 다양하다. 가장 큰 특징으로 배포 환경(Environment)의 개수에 영향을 받지 않는다. 접속 정보를 추가하거나 수정하는 것만으로도 간단하게 배포 환경을 추가하거나 변경할 수 있다.

그러나 항상 연결되어 있는 상태가 아니기 때문에 실제 배포 작업이 수행되는 시점에 실패할 수도 있다. 그리고 배포 환경이 손상되어 배포 환경 구성 저장소의 내용과 다를 경우 차이를 감지하고 배포 파이프라인을 다시 실행시키거나 알림을 줄 수 있는 별도의 모니터링 시스템이 필요하다.

깃옵스 풀타입_ 오퍼레이터가 배포 파이프라인을 대처, Application Repository, triggers, Build Pipeline, pushes container imates(image Registry), updates, (enviroment Repository), triggers, Deployment Pipeline, Deploys, Environment , operator-(observes, deploys)-Deployment, operator writes Environment Reposotory

■ 풀 타입(Pull Type)

배포 환경에 위치한 별도의 오퍼레이터가 배포 파이프라인을 대신한다. 이 오퍼레이터는 저장소의 매니페스트와 배포 환경을 지속적으로 비교하다가 차이가 발생할 경우 저장소의 매니페스트를 기준으로 배포 환경을 유지시켜 준다. 만약 누군가가 직접 손으로(허가 받지 않은 작업) 배포 환경을 변경했을 때도 다시 되돌려지게 되는데 이는 배포 환경의 변경은 저장소의 매니페스트를 통해서만 유효하다는 것을 보장한다. 다시 말해 배포 환경에 대한 모든 이력은 배포 환경 구성 저장소 즉, 깃에 존재한다는 것을 의미한다. 이런 방식을 지원하는 도구로는 아르고CD, 젠킨스X(JenkinsX), 그리고 깃옵스라는 용어를 만든 위브웍스에서 제작한 플럭스(Flux)가 있다.

앞에서 보안상의 이유로 깃옵스는 풀 타입 배포 전략을 권장한다고 언급했다. 이는 구조적 차이에서 발생하는 것으로 푸시 타입의 경우 배포 환경에 대한 자격 증명 정보를 외부에서 관리할 수 밖에 없다. 배포 환경 입장에서는 배포 파이프라인 자체가 외부 도메인이기 때문이다. 그리고 일반적으로 배포 파이프라인에게 배포 환경에 대한 읽기∙쓰기 권한을 부여하기 때문에 만의 하나 노출된다면 큰 피해를 볼 수도 있다.

반면 풀 타입의 경우 오퍼레이터가 애플리케이션과 동일한 환경에서 동작 중이어서 자격 증명 정보가 외부에 노출될 일이 없다. 그리고 배포 환경에 대한 자격 증명 정보도 오퍼레이터 관리를 위한 최소한의 인력으로 한정 지을 수 있다. 신경 써야 할 것은 배포 환경에서 깃 저장소와 이미지 저장소로의 접근 정도이다.

 

깃옵스 장점

배포 빈도 및 속도 상승, 생산성 향상, 오류 감소 등 여러 장점들이 있지만 이들 대부분은 다른 데브옵스 구현 방법을 사용해서도 달성할 수 있는 것들이다. 그렇기 때문에 깃옵스만의 장점만 설명하겠다.

1) 신뢰할 수 있는 정보의 공유

“스테이지 환경에 배포된 A 서비스의 설정 값이 뭐지?”

필자가 개발과 운영을 하던 당시 적지 않게 묻고 대답했던 것 같다. 적어도 깃옵스를 사용한다면 누군가의 희미한 기억에 의존하거나 제때 업데이트를 하고 있는지 파악하기 위해 문서를 찾아 본다거나 직접 서버에 접속하기 위해 힘겹게 ssh 명령어를 입력할 필요가 없다. 깃 이력을 보면 현재 상태는 물론 누가, 언제, 왜, 어느 곳을 수정했는지 쉽게 알 수 있다. 지금까지의 모든 이력을 포함하고 있는 이 시스템은 부가적인 문서 작업을 없애는 좋은 수단이기도 하다.

※ 에러 복구 시간 감소: 새롭게 서비스를 배포했는데 장애가 발생했을 때 해야 할 일은 ‘git revert’ 명령어, 그리고 배포 환경이 이전 버전으로 롤백될 때까지 기다리는 것이다.

2) 익숙한 절차

“git commit → push → merge request → review → merge”

개발자에게 굉장히 익숙한 절차이다. 그렇기 때문에 애플리케이션 배포를 위한 별도의 절차를 만들거나 교육시킬 필요가 없다. 그리고 리뷰 절차를 통해 휴먼 에러를 조기에 발견하고 책임을 나눌 수 있다.

 

GitOps 적용

풀 타입 구현체 중 하나인 아르고CD를 이용하여 깃옵스 시스템을 구축해보겠다.

그리고 저장소에 있는 배포 관련 디스크립션을 수정했을 때 아르고CD가 배포 환경(Kubernetes)에 변경 사항을 잘 반영하는지도 확인해 보겠다.

1) 구조

ArgoCD구조 _ 사용자가 GitHub 로 Description을 푸시 , argo가 GitHub Observe, Application에 Observe, Deploy 진행

2) Config Repo 생성

깃허브(GitHub)에 개인 프로젝트를 생성하고 아래와 같은 쿠버네티스용 디스크립션을 작성한다.
쿠버네티스용 디스크립션_ #nginx_deploy.yaml_apiVersion: apps/v1_kind: Deployment_metadata:_ name:nginx-deployment_lebels:_app: nginx_spec:_replicas: 1_ selector:_ matchLabels:_app:nginx_spec:_containers:_-name:nginx_image:nginx:latest_parts:_-containerPort: 80_ apiVersion:v1_ kind: Service_metadata:_name:nginx-service

3) 아르고CD 설치

쿠버네티스 클러스터 및 각종 도구(kubectl, helm)들은 이미 설치된 상태이다. 아래 명령어를 이용해 아르고CD를 설치한다.
아르고CD설치_ #namespace 생성_ kubectl create namespace argocd_ #argocd 리소스 배포_ kubectl apply -n argocd-f(https://raw.githubusercontent.com/argoprij/argo-cd/stable/mainfests/install.yaml)

아르고CD API 서비스를 이용하기 위해서는 외부 노출 설정을 해주어야 한다. 인그레스(Ingress) 생성, 쿠버네티스 서비스 타입 변경, 포트 포워딩 방법이 있는데 여기서는 서비스 타입을 변경하겠다.
서비스 타입을 변경_(#service type 수정_ kubectl path svc argocd-server-n argocd-p '{"spec": {"type": "LoadBalancer"}}' _ # 접근 주소 확인 _ kubectl get service -n argocd -l app.kubernetes.io/name=argocd-server -o jsonpath='{.items[*].status.loadBalancer.ingress[*].hostname}'

브라우저를 통해 주소로 접근한다. 설치형 CLI도 제공하나 별도로 설치해야 하기 때문에 웹 UI 쪽만 설명하겠다.
쿠버네티스 웹UI (로그인 화면)

계정명은 “admin”, 비밀번호는 아래 명령어를 통해 확인한다.
쿠버네티스 계정_kubectl get pods -n argocd -l app.kubernetes.io/name=argocd-server -o name | cut -d'/' -f 2
쿠버네티스 계정접속시 보이는 화면

4) 애플리케이션 생성

이제 아르고CD에게 일을 시켜보자. 로그인 후 왼쪽 상단의 “+NEW APP” 혹은 중앙의 “CREATE APPLICATION” 클릭한다.

애플리케이션 생성_로그인 후 왼쪽 상단의 “+NEW APP” 혹은 중앙의 “CREATE APPLICATION” 클릭

애플리케이션에 대한 기본적인 정보를 기입한다.

애플리케이션에 대한 기본적인 정보_ Appkication Name-아르고 CD에서 사용할 애플리케이션 이름, Project- 애플리케이션들을 구분하고 관리하기 위한 논리적 그룹이다. 프로젝트 단위로 배포 환경에 대한 권한이나 사용할 수 있는 자원들(Cluster, Namespace, Source 등)을 허영하거나 제한할 수 있다. SYNC POLICY(Manual | Automatic)- 깃에 정의된 디스크립션과 배포 환경을 비교하고 유지하는 작업을 주기적(3초)으로 수행할 지, 수동으로 수행할 지를 선택한다.

아르고CD가 참조할 소스 정보이다.

아르고CD가 참조할 소스 정보_ Repository URL- 깃 저장소 주소이다. Revision- 리비전 정보이다. 브랜치 명 이외에 태그도 가능하다. Path- 깃 저장소 내에 디스크립션이 위치한 디렉토리 정보를 입력한다.

아르고CD가 애플리케이션을 배포하고 감시할 쿠버네티스 클러스터 정보이다.

쿠버네티스 클러스터 정보_ Cluster URL- 아르고 CD와 동일한 환경에 배포하려면 https://kubernetes.default.svc 를 입력한다. 다른 클러스터에 배포할 수 있다. Namespace-쿠버네티스 namespace 정보이다.

작성 후 “Create” 버튼을 누르면 내부적인 검증을 거친 뒤 문제가 없을 경우 아래와 같이 “nginx” 애플리케이션이 생성된다. SYNC POLICY 값을 Automatic으로 설정했다면 아래처럼 자동으로 배포까지 진행된다.

nginx” 애플리케이션_작성 후 “Create” 버튼을 누르면 내부적인 검증을 거친 뒤 문제가 없을 경우 아래와 같이 “nginx” 애플리케이션이 생성된다. SYNC POLICY 값을 Automatic으로 설정했다면 그림처럼 자동으로 배포까지 진행된다.

애플리케이션 카드를 클릭하면 아래와 같이 각각의 쿠버네티스 리소스에 대한 정보는 물론 동작 상태에 대한 상세 정보가 제공된다.

쿠버네티스 리소스에 대한 정보는 물론 동작 상태에 대한 상세 정보 제공

5) 감시 기능 확인

마지막으로 아르고CD의 감시 기능이 제대로 동작하는지 확인하기 위해 깃에서 Deployment-replicas 값을 1에서 2로 수정하고 커밋하자.

Deployment-replicas 값을 1에서 2로 수정하고 커밋하는 화면

잠시 후 아르고CD에서 “nginx-deployment” pod가 두 개로 늘어난 것을 확인할 수 있다.

nginx-deployment pod가 두개로 늘어난 것을 보여주는 화면

그리고 배포 이력 조회 화면을 통해 정보를 확인할 수도 있고 원하는 시점으로 되돌릴 수도 있다.

배포 이력 조회 화면

마치며

데브섹옵스, 깃옵스, AI옵스 등 데브옵스를 확장하거나 특정 기술 혹은 업무에 특화된 모델들이 몇 해 전부터 등장하고 있다. 이는 데브옵스가 도입기를 넘어 모델의 다양성이 가속화 되는 성장기 혹은 그 다음 단계로 진입했음을 보여주는 것이라고 생각한다.

깃옵스도 지금까지 소개된 많은 모델 중 하나지만 대상과 장점이 아주 명확하다. 그렇기 때문에 클라우드 네이티브 대상, 그 중에서도 쿠버네티스로의 배포를 고려 중이거나 보안에 민감하여 권한과 정보를 엄격하게 관리하는 프로젝트일 경우 깃옵스는 좋은 선택지가 될 것이다.

새롭게 데브옵스 환경을 구축할 계획을 가지고 있거나 기존의 것이 아쉬운 개발자 분들에게 본 아티클이 조금이나마 도움이 되기를 바란다.

# References

https://www.gitops.tech/
https://www.weave.works/technologies/gitops/
https://www.cloudbees.com/gitops/what-is-gitops
https://aws.amazon.com/ko/blogs/korea/building-a-modern-ci-cd-pipeline-in-the-serverless-era-with-gitops/
https://www.atlassian.com/git/tutorials/gitops
https://www.red-gate.com/simple-talk/sysadmin/powershell/powershell-desired-state-configuration-the-basics/
https://docs.ansible.com/ansible/latest/collections/ansible/builtin/file_module.html
https://www.powershellmagazine.com/2013/08/26/pstip-create-an-empty-folderfile-using-desired-state-configuration-file-resource/
https://argoproj.github.io/argo-cd/

박종환 프로

에스코어㈜ 소프트웨어사업부 개발플랫폼그룹

데브옵스(DevOps) 엔지니어입니다. 주요 관심 분야는 Cloud Service와 Kubernetes, Microservices Architecture(MSA) 입니다.