devops의 설명을 들으면서, 과거의 CI/CD 방식과 현재의 분리 방식이 나오게 된 차이를 작성해보겠다.
우선, 전통적 방식을 작성하자면
deploy.yaml)에 직접 반영한 뒤, kubectl apply 명령어로 쿠버네티스 클러스터에 직접 밀어넣는(Push) 구조- **빌드 및 이미지 생성**: 애플리케이션 코드를 빌드하고 새 버전의 도커 이미지를 만듭니다.
- **배포 파일 수정**: Jenkins 작업 공간(workspace) 내에 있는 `deploy.yaml` 파일의 이미지 태그를 새 버전으로 **임시 수정**을 진행한다.
- **직접 배포 (Push)**: Jenkins가 `kubectl apply` 명령어를 실행하여 수정된 명세서를 클러스터에 직접 적용하고 배포를 완료한다.
형상 관리 부재: 가장 큰 문제.
deploy.yaml = 배포하기위한 명세. 이는 로컬에 있음. 그 형상에 대한 정보를 알 수 없음.
배포에 사용된 deploy.yaml은 Jenkins 작업 공간에만 존재하며,
Git에 저장된 deploy.yaml은 여전히 이전 이미지 태그를 가리킵니다.
이로 인해 Git과 실제 클러스터의 상태가 달라지는 '환경 드리프트(Environment Drift)' 발생.
불명확한 진실의 원천(Source of Truth): 현재 클러스터에 배포된 버전이 무엇인지 확인하려면 kubectl 명령어로 직접 클러스터를 조회해야 합니다. Git 저장소는 더 이상 신뢰할 수 있는 정보 소스가 아닙니다.
보안 취약점 : Jenkins가 쿠버네티스 클러스터를 직접 제어할 수 있는 강력한 권한(Credentials)을 가져야 함. Jenkins가 해킹당하면 전체 클러스터가 위험에 노출될 수 있습니다.
복잡한 롤백: 이전 버전으로 롤백하려면 이전 Jenkins 빌드를 다시 실행하거나, kubectl rollout undo 같은 명령어를 수동으로 실행해야 합니다.
과정이 복잡하고 실수가 발생하기 쉽습니다.
사실 이 방식의 가장 큰 단점은, 운영 (Devops의 ops)에서의 차이인데,
운영을 하면서 진행하면서 시스템이 안정적이고, 신속하게 장애를 대응해야합니다.
이 방식은 Push를 jenkins가 스스로 명세서에 반영해서 push해주는데, 정작 개발자는 그 컨테이너 이미지 태그를 모르기 때문입니다.
그래서 장애가 발생하면, 원인을 파악하기 어렵고 복잡합니다. 그리고 롤백하기 위해선 위의 단점에 작성했다시피, 이전 빌드를 찾아서 다시 실행해야하는데, 수동으로 진행하면서 위험부담이 큽니다.
또한, 시스템의 현재 상태를 알기 위해서 k8s 명령, 프로메테우스, jenkins 대시보드 등 모두 따로 확인해야해서 일관된 정보를 얻기 힘들고, 로그가 계속 남는다고 보장할 수 없고, 정보를 취합하는데 많은 시간이 소요되게 됩니다.
그럼 이제 현재 사용되는 Jenkins / ArgoCD로 나뉘는 방식에 대해서 정리해보자면,
deploy.yaml)를 Git 저장소에 커밋하고 푸시하는 것만. deploy.yaml 파일의 이미지 태그를 새 버전으로 수정한 뒤, 이 변경사항을 Git 저장소('gitops' 브랜치)에 커밋하고 푸시합니다.완벽한 형상 관리: 배포에 사용되는 deploy.yaml의 모든 변경 이력이 Git에 기록됩니다.
Git이 바로 클러스터 상태를 나타내는 '진실의 원천(Single Source of Truth)'이 됩니다.
한가지의 source가 되는거죠.
명확한 감사 및 추적: git log를 통해 누가, 언제, 어떤 변경사항을 배포했는지 명확하게 추적할 수 있습니다.
github는 신이야
git revert 명령어로 이전 커밋으로 되돌리고 푸시하면 GitOps 에이전트가 알아서 클러스터를 이전 상태로 복원해 줍니다. 매우 빠르고 안정적입니다.git 명령어나 Pull Request를 통해 배포를 요청하고 관리할 수 있습니다.직접 배포를 진행하면, Jenkins에서 Jenkins파일로 빌드를 진행할 수 있었는데요,
그러면 기존 Repo에 자동으로 gitops 라는 브랜치가 생기게 됩니당
그 다음, ArgoCD에서 git-repo를 connect하고, create application을 진행합니다
이때 !!!!
application이 바라보는 브랜치는 gitops, source를 선택한다? 하면 k8s라는 폴더가 됩니다(deploy, service가 있는 폴더)
이해가 대충 되셨나요?
그래서 이전과 현재 방식을 비교하자면,
절차적방식과 선언적 방식이라고 차이를 얘기할 수 있겠죠??
kubectl을 실행해라" 와 같이 Jenkins에게 어떻게(How) 배포할지 절차를 하나하나 명령합니다.deploy.yaml과 같아" 라고 Git에 무엇을(What) 원하는지 선언합니다. 그러면 GitOps 에이전트가 현재 상태와 원하는 상태의 차이를 파악하고 그 차이를 맞추는 작업(배포)을 스스로 수행.