오늘은 GitOps에 대해서 이야기 해보고자 합니다. 결론부터 말씀 드리자면, Git으로 수행되는 DevOps를 의미한다고 보시면 좋을 것 같습니다. (엄밀히 이야기하지면 DevOps는 협업을 위한 문화에 가깝고, GitOps는 CD 영역의 방법론에 가깝습니다.)
GitOps는 2017년 KubeCon에서 시작되어 Cloud Native 환경에서 DevOps를 어떻게 받아들이고 구현하면 좋을 지, CI/CD 파이프라인을 어떻게 사용하는 것이 좋을 지에 대해 고민하기 시작했습니다. 본 문에서는 GitOps에 대해 이해해보고 어떻게 구축하는 방안들이 있을 지 함께 고민해 보겠습니다.
GitOps 란?
GitOps는 Weaveworks에서 이야기 하기 시작한 용어로 Cloud Native 프로젝트에 DevOps를 어떻게 적용할 지에 대한 실천적 방법론입니다. 통상 Kubernetes 환경에서 CD(Continuous Depolyment)를 중점적으로 다루지만, 넓은 범위에서 DevOps를 바라보는 관점으로 이해하면 보다 다양하게 활용할 수 있을 것 입니다.
용어에서 나타나듯 Git을 사용하는 프로젝트에서 DevOps를 실천적으로 구현하는 것을 의미 합니다. IaC(Infra as a Code) 도구들을 사용하여 선언적으로 인프라를 프로비저닝하는 개념에서 시작되어 Cloud Native Application 까지 확장되었습니다.
요컨데, Git Repository의 코드와 Production 환경이 일치하도록 자동화된 프로세스를 구축하는 것을 의미합니다. 새 Application을 배포하거나, 기존 Application을 업데이트 할 때, Code만 수정하여도 자동화된 프로세스를 통해 일관된 환경을 유지할 수 있게 됩니다. 따라서 선언된 인프라와 Application 모두를 실제 상태가 동일하도록 유지할 수 있습니다. 이는 유연하고 언제든 확장, 변경되는 Cloud Native 환경에서 안전한 상태 유지를 할 수 있게 해줍니다.
GitOps는 어떤 장점이 있을까?
https://www.gitops.tech/ 에서는 다음의 5가지 이유로 GitOps의 장점을 설명합니다.
1. Deploy Faster More Often
대부분의 CD(Continuous Deploy) 도구들은 배포 속도를 높이고 보다 자주 배포 할 수 있게 해줍니다. GitOps를 통해서 개발자는 개발하는 동안 사용하고 있던 Git Repository에서 형상 관리하던 방식 그대로 사용하기만 해도 실제 환경에 배포됩니다. 따라서 개발자는 배포 결과를 즉시 확인하고 보다 나은 방식을 다시 적용할 수 있게 됩니다.
2. Easy and Fast Error Recovery
Git을 통해 기록된 Commit 들은 Audit Log일뿐만 아니라 Transation Log 이기도 합니다. Application이 동작하고 있는 환경이 다운되거나 Error 가 발생하더라도 개발자는 단순히 git 명령어인 git revert 를 통해 즉시 실제 환경을 복원할 수 있습니다.
3. Easier Credential Management
GitOps를 통해서 개발자는 git repository 혹은 image registry만 접속하면 됩니다. 실제 환경에서 접근하여 kubectl 명령을 날리지 않아도 (직접 환경에 접근해서 작업하지 않아도) 괜찮습니다. 직접적인 접근 권한을 부여하지 않아도 되기 때문에 보안적으로 보다 안전할 수 있습니다.
4. Self-documenting Deployments
GitOps를 사용하는 것은 Application을 운영 하는 환경의 모든 변경 사항을 git을 통해 관리하는 것을 의미합니다. 따라서 코드, Commit 메세지, Pull Request, Merge Approve 등 실제 배포와 관련된 전체 기록들이 Git에 전부 남아 있습니다. 즉, 환경에 대한 실제 상태와 그 변경 이력이 git repository에 기록되게 됩니다.
5. Shared Knowledge in Teams
“모든 것을 기록하는” Git의 사상에 맞게 git repository에 기록된 변경사항들은 개발팀원들 간에 대규모 인프라에 대한 자세한 사항들을 공유됩니다. 변경에 대한 Commit들은 인프라가 어떻게 변화하고 있고, 새로운 시스템에 대한 통찰까지 가능하게 합니다. 선언적으로 구성된 인프라가 Cloud 환경에서 다양한 변화를 어떻게 수용하고 진화하는 지에 대해 모든 구성원이 함께 고민할 수 있게 됩니다.
GitOps 구현 방안
위 그림은 CI/CD flow에서 git을 통한 제어를 보여줍니다. GitOps는 CI/CD 과정에 대한 관리를 코드의 변경으로만 반영합니다. 그래서 “Immutability Firewall” 이라는 표현으로 Git 을 표현하기도 합니다. 개발자들은 git을 통한 모범적 workflow를 수행함으로 안전하고 현실적인 개발과 배포 과정이 통합될 수 있습니다.
1. Git Repository 구성 전략
git repository는 GitOps 구현에 중심에 있습니다. 통상 Application 코드의 repository와 인프라 환경 구성을 위한 repository로 구성 합니다.(일반적인 상황에 대해서 2가지 타입의 repository를 권장합니다)
GitOps는 Kubernetes 환경에 대해서 주로 다루기 때문에 Application 저장소의 경우, Image registry를 통해서 Container가 배포되고 CI 과정으로 통해 git repository에 있는 application 코드들이 Image registry로 반영 됩니다. 또한 선언적으로 작성된 인프라의 경우는 git repository를 통해 CI/CD 과정을 거쳐 실제 인프라 환경에 반영되게 됩니다.
- Application repository: application 소스 코드와 application 배포를 위한 배포 구성 파일(kubernetes yaml 등)을 포함합니다.
- 인프라 등 배포 환경 repository: 배포 환경에 대한 모든 구성을 포함합니다. 선언적으로 application과 인프라에 대한 구성이 코드로 작성되어 있습니다.
이 즈음에서 기존에 많은 개발 팀에서 사용하고 있는 DevOps와 큰 차이가 없음을 눈치 채셨을 겁니다. GitOps는 어렵지 않고 실제 곁에서 자연스럽게 적용되어 사용되고 있습니다. 서두에 언급 됐듯 Git을 사용한 DevOps 의 실천적 방법론 일 뿐입니다. 그렇다면 GitOps의 파이프라인을 구성하는 2가지 방식에 대해 알아 보겠습니다.
2. Push 방식 vs Pull 방식
GitOps에서는 Push 방식의 파이프라인과 Pull 방식의 파이프라인의 2가지 유형의 배포 전략이 있습니다. 두 가지의 유형은 배포 환경이 실제로 원하는 인프라와 유사한 지 확인 하는 과정에서만 차이점을 가집니다. 일반적으로 Pull 방식의 배포 전략이 더 안전한 방법으로 간주되어 선호 되곤 합니다.
보안적 이점에 대해서는 아래의 2개의 그림으로 이해해 볼 수 있습니다. Kubernetes Cluster를 이용하여 개발이 진행 될 때, 아래 1번째 그럼처럼 구간 별로 RW 작업이 발생할 수 있습니다. 이는 각 단계를 수행할 수 있는 권한에 해당하는 보안 Credential 등이 각 구간 마다 필요하게 됨을 의미 합니다. GitOps Workflow를 통하면 아래의 2번째 그림처럼 구간 별 보안 구획을 분리할 수 있고 각 구간에 해당하는 Credential 등은 다른 구간에서 요구되지 않습니다. 별도의 자격 증명을 사용하여 각 단계들이 서로의 security “zone” 내에서만 동작할 뿐 입니다. (편집 때, 삭제 가능 문단 …)
1) Push 방식 배포 전략
Push 방식 기반 배포 전략은 Jenkins, CircleCI, Travis CI와 같은 널리 사용되는 CI/CD 도구로 구현됩니다. Application의 소스 코드들은 Git Repository에 있으며 해당 코드가 업데이트(git workflow에 따라 배포 branch가 변경) 될 때, 빌드 파이프라인이 트리거 되어 빌드를 진행하고 배포를 수행 합니다. 선언적으로 작성된 인프라 매니페스트의 경우도 동일합니다. (저희 팀은 AWS CodePipeline을 이용하여 Terraform 파이프라인을 구성하여 사용하고 있습니다)
Push 방식은 크게 2가지 주의점이 있습니다. 1번째는 배포를 수행하는 도구들이 배포환경 외부 (혹은 분리) 되어 있기 때문에 배포 환경에 대한 자격 증명이 필요합니다. 따라서 세분화된 권한 관리가 필수적 입니다. 2번째는 저장소의 코드를 기반으로 인프라 환경의 변화가 트리거 되기 때문에 항상 코드와 실제 환경이 일치하지 않을 수도 있습니다. 따라서 배포 과정에 대한 모니터링 절차를 통해 실제 배포 시 환경과 코드의 격차를 확인하여야 합니다. (저희 팀의 경우, Terraform pipeline 에서 dry-run(plan) 을 수행 후 배포 Approve 단계를 추가하여 중간에 담당자의 확인을 받는 프로세스를 추가하여 구성하였습니다.)
2) Pull 방식 배포 전략
Pull 방식 기반의 배포 전략은 Push 방식과 유사하지만 배포 파이프라인이 작동하는 방식이 다릅니다. 예를 들면 Push 방식에서 CI/CD 파이프라인은 git repository가 변경될 때, 외부 이벤트(repo merge or push)에 의해 트리거 됩니다. Pull 방식에서는 git repo와 실제 환경을 비교하는 Operater가 중간에 위치하게 됩니다. ArgoCD, FluxCD, JenkinsX 등의 CD 도구를 사용하게 되는 데, 이를 실제 환경 내에 위치 시켜 내부 환경에 필요한 접근 권한을 환경 외부에 둘 필요가 없어지게 됩니다. 단순히 서비스가 동작하는 환경 외부에 저장소인 git repo 혹은 image registry 에 대한 접근 제어를 환경 안 쪽에서 사용하는 방식이므로 실제 환경에 대한 권한이 노출되지 않습니다. (Kubernetes를 사용할 때 RBAC 및 service account 등을 구성하여 kube 안쪽 뿐만 아닌 AWS 등 외부 환경에 대한 변경도 함께 가능합니다.)
특히 Pull 방식은 Kubernetes 등의 Container 환경에서 유용하게 활용됩니다. container 기반의 application이 사용하는 Image registry를 관찰하다가 변경점이 반영되면 application에 반영하고, 인프라에 대한 변경점도 repository를 관찰하다가 변경점이 발생할 경우 반영되게 됩니다. 이는 중간 과정에 대한 모니터링이 필요 없다는 의미는 아닙니다. 안전한 배포 라인 구성을 위해서 중간 과정에 담당자에 의한 관리 요소를 준비해두는 편이 현실의 작업 중간에서 다양한 경우의 디버깅을 유용하게 할 수 있을 것 입니다.
3. Working with Multiple Applications and Environments
git flow로 개발을 진행할 때, production 환경 외에 develop, staging 환경 등 개별 환경에 따라 다른 서비스 구성이 필요할 수 있습니다. MSA 기반의 다양한 서비스 구성 역시 분리된 git repository등을 사용하게 됩니다. gitops에서는 기본 방식을 확장해서 적용합니다. 환경, 서비스 별로 여러 빌드 파이프라인을 설정하여 각각의 분기에 따라 동작하도록 설정하면 Multiple 환경에 대한 gitops 방식이 적용되게 됩니다.
4. 참고 아키텍처
끝으로 AWS에서 gitops를 구현하는 참고 아키텍처를 첨부합니다. 원칙은 변하지 않습니다. SSOT(Single Source Of Truth) 인 git repository를 기준으로 선언적으로 작성된 인프라와 Application을 관리합니다. 개발 단계에서 익숙하게 사용하던 git flow를 사용하여 코드 및 실제 환경의 형상을 관리합니다. 배포 작업 중간에 혼선이 발생할 수 있던 여지는 gitops의 방법론을 통해 가둬진 구역 내에서만 디버깅하여 즉시 회복할 수 있게 됩니다. 아래는 AWS에서 소개한 다양한 gitops 참고 아키텍처 입니다. EKS에 적용된 예제가 많지만 기본 방법론이 변경되지는 않았습니다.
https://aws.amazon.com/ko/blogs/devops/ci-cd-on-amazon-eks-using-aws-codecommit-aws-codepipeline-aws-codebuild-and-fluxcd/
https://aws.amazon.com/ko/blogs/devops/ci-cd-on-amazon-eks-using-aws-codecommit-aws-codepipeline-aws-codebuild-and-fluxcd/
마치며
정리하자면 GitOps는 특별한 엔지니어링의 영역이 아닙니다. GitOps는 일련의 관행입니다. 개발 팀에서 그 동안 익숙하게 모범적으로 관리하였던 Git Workflow에 Ops(특히 CD) 영역의 확장이 있었을 뿐이었습니다. 다시 말하자면, 코드를 작성하고 리뷰하고 Merge하면 일련의 테스트와 배포 과정이 진행되면서 실제 운영 환경까지 이어지는 일련의 과정을 표현했을 뿐 입니다. 이러한 과정에서 GitOps의 실천적 방법론을 통해 개발 조직은 조금 더 안전하고, 명확한 Cloud 여정을 진행하실 수 있을 것 입니다.
마지막으로 gitlab 블로그에서 공감 되는 글로 마무리 하겠습니다.
긴 글 읽어주셔서 감사합니다.
With any collaborative effort, change can be tricky and GitOps is no exception. GitOps is a process change that will require discipline from all participants and a commitment to doing things in a new way. It is vital for teams to write everything down. The temptation to edit something directly in production or change something manually is going to be difficult to suppress, but the less “cowboy engineering” there is, the better GitOps will work.
As with any emerging technology term, GitOps isn’t strictly defined the same way by everyone across the industry. GitOps principles can be applied to all types of infrastructure automation including VMs and containers, and can be very effective for teams looking to manage Kubernetes-based infrastructure.
While many tools and methodologies promise faster deployment and seamless management between code and infrastructure, GitOps differs by focusing on a developer-centric experience. Infrastructure management through GitOps happens in the same version control system as the application development, enabling teams to collaborate more in a central location while benefiting from Git’s built-in features.
– https://about.gitlab.com/topics/gitops/