서론
최근, AWS에서 운영되고 있는 EC2 인스턴스 기반의 서비스를 Kubernetes 기반의 AWS EKS로 마이그레이션하는 작업을 진행하고 있다. 기존 방식에서는 수동으로 EC2 인스턴스를 관리하면서 발생하는 복잡성과, 세부적인 AutoScaling 설정의 어려움이 많은 리소스를 소모하고 있었으며, 특히 지속적인 통합 및 배포(CI/CD)에 대한 부분이 많이 미흡하였다.
이러한 과정에서 멀티 컨테이너 환경에서 지속적인 통합 및 배포(CI/CD)를 어떻게 효율적으로 구성할 수 있는지에 대한 고민을 진행하게 되었다. 이전까지는 AWS ECS와 CodePipeline을 중심으로 한 CI/CD를 구성하였지만, Kubernetes 환경에서는 Argo CD라는 도구를 이용하여 지속적인 배포(CD) 과정을 관리할 수 있다는 것을 알게 되었다.
이번 글에서는 Argo CD와 그 기반인 GitOps에 대해 알아볼 것이다. Argo CD를 통해 Kubernetes 환경에서 어플리케이션을 어떻게 자동으로 배포하고 관리할 수 있는지, 그 과정을 통해 우리는 어떠한 점을 얻을 수 있는지 알아볼 예정이다.
GitOps란?
GitOps는 인프라와 어플리케이션의 구성을 Code 형태로 Git에 저장하고, 이를 통해 Infra와 Application의 상태를 관리(Ops)하는 접근 방식이다.
GitOps는 DevOps의 한 분야로, 소프트웨어 개발(Dev)과 운영(Ops)의 모든 단계를 Git을 통해 관리하는 접근 방식이다. GitOps를 통해, Git Repository가 인프라와 어플리케이션의 모든 구성요소 및 상태를 코드 형태로 관리할 수 있게 되는 장점을 가지게된다.
여기서, GitOps를 사용하는 가장 큰 이유는 인프라를 코드로써 관리하는 것(IaC, Infreastructure as Code)과 지속적 통합 및 배포(CI/CD)를 Git과 결합할 수 있게 되는것이다. 그로인해, 개발(Dev), 테스트(Test), 배포(Deploy) 과정을 자동화 할 수 있게 되어, 프로젝트의 변경 사항을 관리하는것과 문제점이 발생하였을 때 원하는 시점으로 롤백하는 것 또한 용이해지게 되는 장점을 가지게 된다.
GitOps는 왜 탄생하게 되었는가?
GitOps는 AWS와 같은 클라우드 네이티브 기술의 발전과 Kubernetes가 확대되면서 만들어지게 된 개념이다.
GitOps가 도입 되기 전, 수동으로 인프라를 관리하던 방식은 복잡한 환경에서 발생할 수 있는 오류를 관리하기 어려움을 겪었을 것이다. 만약, 인프라의 일부만 변경된 사항이 반영되고, 일부는 누락되는 상황이 발생하게 된다면, 우리는 매번 수동으로 인프라에 구성된 각 인스턴스에 접근하여 확인해야 했을것이다. 또한, 지속적인 통합 및 배포(CI/CD)에 대한 필요성이 커지게 되면서, 이를 더욱 효과적으로 운영하기 위한 방법론이 필요하게 되었다.
이러한 필요성에 의해 Git을 중심으로 인프라와 어플리케이션을 구성하게 되었고, 인프라를 관리하기 위해 소모되는 리소스를 최소화 하여 더욱 효율적으로 관리할 수 있게 되었다.
Argo CD 란?
Argo CD는 GitOps 워크플로우를 구현하기 위한 도구 중 하나로, Kubernetes 클러스터를 위한 선언형 지속적 배포 (CD, Continuous Deployment) 도구이다.
Argo CD는 GitOps를 기반으로 하여, Git Repository에 저장된 구성 파일과 Kubernetes 클러스터의 현재 상태를 동기화 하는 작업을 담당하게된다. 이를 통해, 어플리케이션의 배포를 더욱 효율적으로 관리할 수 있게 되며, 배포 과정을 안정적이며 예측 가능하게 관리할 수 있게된다.
Argo CD는 Git Repository에 업로드한 Manifest 파일을 가져와 Kubernetes와 동기화하는 역할을 담당한다. 변경된 사항을 kubectl apply
와 같은 명령어를 이용하여 배포하지 않고도, 어플리케이션이 원하는 네임스페이스에 변경된 사항을 업로드하게된다.
일반적으로 AWS ECS를 사용하였을 때는 아래와 같은 흐름으로 CI/CD가 구성되었다.
- Git Push → Code Pipeline( Code Build → Code Deploy ) → ECR → ECS task definition 갱신
Argo CD를 도입하게 된다면, 위의 과정에서 Code Deploy에 해당하는 지속적인 배포(CD) 과정을 대체할 수 있게 될 것이다.
Argo CD의 주요 기능
- Argo CD는 지속적 배포(Continuous Deployment, CD)를 담당한다.
- 자동화된 배포 프로세스와 API 호출을 통해 쿠버네티스의 클러스터를 선언적으로 관리할 수 있다.
- 지정된 대상 환경에 어플리케이션을 자동 배포하여, Git Repository의 변경 사항을 즉시 반영한다.
- 다양한 Template Manifest 제공하여, Helm, Kustomize과 같은 여러 구성 방식을 지원한다.
- GitOps가 의도된 상태(Desired State)로 어플리케이션을 자동 또는 수동으로 동기화한다.
- 어플리케이션의 현재 상태를 실시간 동기화하거나 헬스체크를 제공하는 CLI 및 UI를 지원한다.
Argo CD 시작하기
Argo CD를 이용하여 어플리케이션을 배포하기 위해서는 별도의 Docker Image와 Git Repository가 필요하다.
아래의 예제에서는 3000
번 포트로 요청한 사용자의 IP 를 반환하는 단순한 Nest.js의 이미지를 이용하여 배포할 예정이다.
- Docker Image: https://hub.docker.com/repository/docker/archepro84/nest_ip
- Github Repository: https://github.com/archepro84/prac-k8s/tree/main/kubernetes/setup-argo-cd
1️⃣ Argo CD 준비하기
Argo CD는 Kubectl 만으로도 구축이 가능하다. 다만, 이번 예제에서는 Argo CD CLI를 이용하여 어드민 계정을 관리하거나, 세부적인 설정을 정의할 예정이다.
# [Mac] Argo CD CLI 설치
brew install argocd
# Argo CD를 구성하기 위한 Namespace 생성
kubectl create namespace argocd
# Argo CD를 Kubernetes에 배포
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# argocd-server의 type을 LoadBalancer로 변경하여, 외부에서 접근 가능하도록 설정
kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'
# Argo CD를 포트 포워딩 하여 8080 Port로 접속할 수 있도록 설정
kubectl port-forward svc/argocd-server -n argocd 8080:443
# Argo CD Web UI 접속시 admin 패스워드 확인한다.
argocd admin initial-password -n argocd
# Argo CD CLI를 이용하여 Argo CD 로그인
argocd login localhost:8080
# Argo CD 어드민의 비밀번호 변경
argocd account update-password
2️⃣ Application.yaml 파일 구현하기
Application.yaml
파일은 Kubernetes에 배포된 어플리케이션을 선언적으로 정의하기 위한 파일이다.
아래의 정의된 내용과 같이, Git Repository와 Manifest 파일의 경로를 지정하여 해당 프로젝트를 불러와 GitOps를 구현할 수 있게된다.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: nest-ip # Application 이름
namespace: argocd # Application을 생성할 Namespace
spec:
destination:
namespace: nest-ip
server: https://kubernetes.default.svc
project: default # ArgoCD Project
source:
path: kubernetes/setup-argo-cd/manifest # 쿠버네티스 매니페스트의 경로 지정
repoURL: https://github.com/archepro84/prac-k8s.git # Git Repository 주소
targetRevision: HEAD # Git의 Head 기준으로 동기화
syncPolicy:
automated:
selfHeal: true
syncOptions:
- CreateNamespace=true # Namespace가 없으면 생성
3️⃣ Kubernetes Manifest (Deployment) 구현하기
deployment.yaml
은 Kubernetes의 Deployment를 정의하는 Manifest 이다.
해당 파일에서 어플리케이션의 Docker Image 및 ReplicaSet을 정의하는 역할을 담당한다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nest-ip # Deployment의 이름 설정
spec:
replicas: 2
revisionHistoryLimit: 3
selector:
matchLabels: # Pod의 Label 설정
app: nest-ip
template:
metadata:
labels: # Template의 Label 설정
app: nest-ip
spec:
containers:
- image: archepro84/nest_ip
name: nest-ip-container
ports:
- containerPort: 3000
4️⃣ Kubernetes Manifest (Service) 구현하기
svc.yaml
은 Kubernetes의 Service를 정의하는 Manifest 이다.
해당 파일에서는 NodePort 타입으로 정의된 서비스를 배포하는 역할을 담당한다.
apiVersion: v1
kind: Service
metadata:
name: nest-ip # Service의 이름
labels:
app: nest-ip
spec:
type: NodePort
ports:
- port: 80 # Service의 Port
targetPort: 3000 # Pod의 Port
protocol: TCP
name: http
selector:
app: nest-ip # Pod의 Label과 일치해야 함
serviceName: nest-ip # Service의 이름
externalTrafficPolicy: Cluster # 클러스터에 있는 모든 Pod에 Routing하도록 설정
sessionAffinity: None # 세션을 유지하지 않도록 설정
5️⃣ Argo Application 배포하기
Deployment와 Service의 Manifest 파일을 모두 Git Repository에 업로드하였다면, Argo CD 어플리케이션을 하는 과정만 남았다. 아래의 명령어를 이용하여 어플리케이션을 배포한다면, 최종적으로 nest-ip 라는 어플리케이션이 생성되며, 도식화된 쿠버네티스 어플리케이션을 한눈에 볼 수 있게된다.
# application.yaml 파일을 이용하여 쿠버네티스 어플리케이션을 배포한다.
kubectl apply -f application.yaml -n argocd
Argo CD의 문제점
Argo CD는 Kubernetes에서 지속적인 배포(CD)를 지원하지만, 이는 Git Repository의 상태를 기반으로 수행한다. 즉, Docker 이미지가 갱신되어도, 이 변경사항이 Git Repository에 자동으로 반영되지 않는 한, ArgoCD는 새로운 이미지를 어플리케이션에 배포하지 않는다.
이 문제를 해결하기 위해, CI 파이프라인에서 빌드 및 테스트를 완료된 후 Deployment
Manifest 파일의 이미지 태그를 자동으로 최신 버전으로 업데이트하고 Git Repository에 Push 하는 방식으로 해결할 수 있다.
예를 들어, Github Action, AWS Code Build를 사용한다면 아래와 같은 과정을 구성할 수 있다.
- Build: Docker 이미지를 빌드하고 태그를 붙여 Docker Registry에 Push 한다.
- Update:
Deployment
Manifest 파일의 이미지 태그를 최신으로 업데이트 한다. - Commit & Push: 변경된
Deployment
Manifest 파일을 Git Repository에 Commit 하고 Push한다.
이 과정을 통해 Argo CD는 Repository에 최신 상태를 바탕으로 새로운 이미지를 지속적으로 배포할 수 있게 된다.
결론
일반적으로 CI/CD를 구축하였을때 EC2 또는 ECS와 같은 환경에서는 AWS와 같은 Cloud Service Provider에 대한 이해도가 가장 중요할텐데, Argo CD를 도입하게 된다면 우리는 단순하게 Git과 Kubernetes에 대한 개념만 가지고 서비스를 제공할 수 있게 될 것이다.
또한, Argo CD를 도입하게 된다면, Argo Rollouts, 서드 파티 도구 및 플러그인을 함께 워크플로우에 적용할 수 있게 된다. 이를 통해, Blue/Green 배포, Canary 배포 등 고급 배포 전략을 도입할 수 있고, 세부적인 배포 전략을 정의할 수 있게 될 것이다.
'Infrastructure' 카테고리의 다른 글
제로부터 시작하는 IRSA (feat.terraform) (1) | 2024.11.10 |
---|---|
ALB를 이용해 EKS 단일 장애점 개선하기 (이론) (0) | 2024.04.14 |
ISMS 인증을 받기 위한 인프라 개선 요구사항 (0) | 2024.03.17 |