5. EKS CI/CD 도입하기

sangjinsu·2024년 5월 26일
0

포코팡타운 프로젝트에서 사용하고 있었던 CI/CD 구조는 비용 문제로 인하여 사용하지 않게 되었다. 그러나 작업 브랜치별 테스트용 서버는 클라이언트와의 작업에서 편리하였고 클라이언트 분들도 동의해주셨다.

이후 1 주일 후에 더 큰 소식이 왔다. 인프라팀과 협력하여 라이브 운영실에 EKS 를 전면적으로 도입하는 것이다. AWS에서 퍼블릭 IP 에 요금을 부과하면서 현재 EC2로 사용 중이던 서비스들에 요금 부담이 생긴 점이 컸다. 4월 중순에 인프라팀은 먼저 사내에서 사용하고 있던 EKS CI/CD 를 보여줬다.

인프라팀이 선보인 EKS CI/CD 는 Argo Workflow, Argo CD, EKS로 이어지는 GitOps 형태였다. Argo Workflow 는 Argo 프로젝트에서 제작한 컨테이너 기반 워크플로우이다. 이전에 포코팡 타운 프로젝트에서 사용하고 있던 구조는 Jenkins + EKS 이였고 Jenkins 의 역할을 Argo Workflow 가 대신 수행해주게 되었다.

인프라팀에서 보여준 설계 구조는 아래와 같이 동작하였습니다.

  1. Jenkins 가 Git polling 을 하여 저장소의 변경점을 주기적으로 확인 합니다.
  2. 변경점이 감지가 되면 Jenkins 는 변경된 저장소에 있는 Argo Workflow 파일을 기반으로 Argo Workflow 에게 Workflow 를 시작하게 합니다.
  3. Argo Workflow 는 도커 이미지 빌드, 이미지 레지스터리 등록, 배포 파일들이 저장된 저장소의 도커 이미지 digest 를 갱신합니다.
  4. Argo CD 는 변경된 파일을 확인하고 EKS 에 재배포를 실시합니다.

쿠버네티스는 "K8s라고도 알려진 쿠버네티스는 컨테이너화된 애플리케이션을 자동으로 배포, 스케일링 및 관리해주는 오픈소스 시스템입니다." 라고 홈페이지에 적어놓은 것처럼 배포에 주로 사용된다. 개발팀은 배포보다는 개발과 테스트에 목적을 두고 사용하기에 추가적인 요구사항이 있었다.

고정적인 환경별 서버와 작업별로 생성/삭제가 필요한 서버가 필요하다. 고정적인 환경별 서버는 인프라팀에 제공해준 방식과 동일하게 사용해도 문제가 없었다. 그러나 작업별로 생성/삭제가 상대적으로 빈번한 서버는 추가적인 동작이 필요했다.

  1. CRD(CustomResourceDefinitions), 커스텀 리소스가 담긴 폴더와 설정 파일의 브랜치별로 자동 생성/삭제가 필요하다.
  2. 작업 브랜치에는 별도 추가 작업이 필요하다.
  3. ECR, 도커 레지스터리는 구성을 어떻게 할 것인가?
  4. ArgoCD 는 영어 소문자, 숫자로 구성된 명칭이여야 하는데 한글로 구성된 작업 브랜치는 어떻게 구분할 것인가?
  5. Argo Workflow 에서 Git 동작시에 충돌은 어떻게 막을 것인가?

ECR, 도커 레지스터리는 구성을 어떻게 할 것인가?

가장 빠르게 결정된 문제부터 살펴보도록 해보겠습니다. 환경별로 도커 이미지는 빌드될 것이고 이에 대한 구분이 필요했습니다. 그래서 처음 생각한 것은 환경별로 레지스터리를 구분하자는 것이었습니다. 하지만 작업별 브랜치에서 생성된 도커 이미지는 feature 로 구분이 될 것이고 결국 여러 작업이 한 레지스터리에 쌓여간다는 점일 알게 되었습니다. 그리고 배포파일에서 수정되는 도커 다이제스트는 도커 이미지 업로드 당시 수정된다는 점을 파악하였습니다. 서버, 어드민, 툴과 같이 서브 프로젝트 별로 도커 레지스터리를 한 개만 사용하고 각 환경 구분 없이 업로드하기로 하였습니다.

ArgoCD 는 영어 소문자, 숫자로 구성된 명칭이여야 하는데 한글로 구성된 작업 브랜치는 어떻게 구분할 것인가?

브랜치명을 한글로 주로 사용하고 있습니다. 그래서 ArgoCD 에 올릴 때는 영어 소문자, 숫자로 구성된 형식으로 변경이 필요했고 브랜치별로 고유 값이 나와 구분도 가능해야했습니다. 브랜치명을 "server-abc23def" 와 같이 해시화하여서 서로 중복되는 일이 없도록 하였고 추가적인 정보는 metadata에 한글 브랜치명 등을 자동으로 추가 기재하도록 하였습니다.

작업 브랜치에는 별도 추가 작업이 필요하다.

작업 브랜치는 환경별 고정 브랜치와 다르게 추가 작업이 일부 필요하였습니다. 그래서 Argo Workflow 에서 제공하는 DAGConditional 을 사용하여 조건별로 분기하여 처리하도록 하였습니다. 물론 스크립트 안에서 if 를 사용하여 분기할 수도 있겠지만 스크립트는 읽기 힘들고 유지보수도 하기 불편하다고 생각되어 워크플로우의 스텝을 따로 분리하여 별도로 실행하도록 하였습니다.

CRD(CustomResourceDefinitions), 커스텀 리소스가 담긴 폴더와 설정 파일의 브랜치별로 자동 생성/삭제가 필요하다.

고정적인 환경별 서버라면 이미 CRD 폴더가 만들어진 상태여서 인프라팀이 제공해준 CI/CD 에서 문제 없이 동작하였다. 하지만 개발 및 테스트 환경에서는 브랜치의 생성과 삭제가 빈번하였고 매번 사람이 폴더를 생석과 삭제를 체크하면서 작업하는 것은 비효율적으로 느껴졌다. 그래서 우리는 문제를 해결하는 개발자이기에 Argo Workflow 의 한 스텝에서 해당 깃헙의 feature 작업 브랜치명을 읽고 CRD 브랜치를 생성 및 삭제하는 실행 파일을 만들게 되었다. 이후에는 CLI 도커 이미지 환경을 만들어서 배포해볼 생각으로 개인 프로젝트를 생성해보았다.

Argo Workflow 에서 Git 동작시에 충돌은 어떻게 막을 것인가?

Argo Workflow 는 동시에 여러개의 Workflow 를 실행시킬 수가 있었고 개발자 별로 언제 동일한 Workflow 를 실시할지 모른다는 문제가 있었다. 인프라팀에서 제공해주신 구조에서는 효율성을 위해서 하나의 볼륨에서 저장소를 관리하고 있었다. Workflow 스텝에서 저장소에 대한 수정 사항이 발생하고 다른 Workflow 에서 다른 수정 사항이 있을 때 가끔씩 충돌이 발생하여 제대로 동작하지 않는다는 문제점이 있었다. 그래서 두가지 추가 설정을 하기로 하였다.

  1. Workflow 별로 Instant Volumn 을 생성하도록 한다. Workflow 시작시 생성하고 종료시 삭제된다.
  2. Template Lock 을 사용한다. Workflow 의 특정 스텝에서 Workflow 들이 순차적으로 동작하도록 하기 위해 Lock 자원을 사용하게 하였다. 그러므로 CRD 폴더 생성 및 삭제, 도커 이미지 다이제스트 수정 작업에서 Workflow 별로 충돌이 발생하지 않도록 방지하였다.

현재는 아래와 같이 동작하고 있고 각 작업 담당자의 브랜치에 적용해보면서 동작에 이상점은 없는지 테스트해보고 있다.

  1. Jenkins 가 Git polling 을 하여 저장소의 변경점을 주기적으로 확인 합니다.
  2. 변경점이 감지가 되면 Jenkins 는 변경된 저장소에 있는 Argo Workflow 파일을 기반으로 Argo Workflow 에게 Workflow 를 시작하게 합니다.
  3. Workflow 별로 Volumn 을 생성하도록 합니다. Workflow 종료시 삭제 됩니다.
  4. Argo Workflow 는 도커 이미지 빌드, 이미지 레지스터리 등록 합니다.
  5. Workflow 에서 작업 저장소의 feature 브랜치를 확인하고 CRD 폴더를 자동 생성 및 삭제합니다.
  6. 도커 이미지 digest 를 갱신합니다.
  7. 배포 파일을 kubectl 명령어를 사용해 갱신, 생성합니다.
  8. Argo CD 는 변경된 파일을 확인하고 EKS 에 재배포를 실시합니다.
profile
개발에 집중할 수 있는, 이슈를 줄이는 환경을 만들고 싶습니다.

0개의 댓글