Post

Argo CI/CD 노트

Argo CI/CD 노트

지난 가천 카카오엔터프라이즈 SW 아카데미 기간동안 프로젝트를 진행하면서 노션에 작성한 Argo 프로젝트들을 사용한 CI/CD 구축 노트 내용을 옮긴 것이다.

쿠버네티스 기반의 CI/CD를 구축하는 과정을 정리한 내용이다.

Team Github: https://github.com/KEA-ACCELER
A-Log(동시편집 기반 릴리즈 노트 공유 시스템) : https://github.com/KEA-ACCELER/alog-cluster
A-Form(GPT 기반 설문 플랫폼) : https://github.com/KEA-ACCELER/aform-cluster

Reference

Argo를 사용해보자

[Kubernetes]ArgoCD, Argo Workflows&Events 도입기

Argo프로젝트 란?

Argo 프로젝트는 Kubernetes에서 워크플로우를 실행하고 클러스터를 관리하며 GitOps를 수행하는 데 사용되는 오픈 소스 도구 모음이다. Argo 프로젝트는 Argo workflows, Argo CD, Argo rollout, Argo event로 구성되어 있다.

Argo Workflows는 Kubernetes에서 병렬 작업을 오케스트레이션 하기 위한 워크플로우 엔진이다. Argo Workflows는 Kubernetes CRD(Custom Resource Definition)로 구현되어 있으며, 각 단계가 컨테이너인 워크플로우를 정의할 수 있다.

Argo CD는 GitOps를 지원하는 Continuous Delivery 도구로서, GitOps란 Git을 이용하여 클러스터의 상태를 관리하는 방식이다. Argo CD는 GitOps의 핵심인 선언적 배포(Declarative Deployment)를 지원하며, Kubernetes의 Custom Resource Definition(CRD)을 이용하여 배포 자원을 정의한다.

Argo Rollouts는 Kubernetes에서 롤아웃을 관리하기 위한 도구이다. 롤아웃은 새 버전의 애플리케이션을 배포하고 이전 버전과 교체하는 작업이다. Argo Rollouts는 새 버전의 애플리케이션 배포 전략을 정의하고 이전 버전과 새 버전 사이의 트래픽 분배를 제어할 수 있다.

Argo Events는 Kubernetes에서 이벤트를 처리하기 위한 이벤트 브로커이다. Argo Events는 이벤트 드리븐 아키텍처를 구현할 수 있도록 다양한 이벤트 소스와 이벤트 라우터를 제공한다.

여기서는 Argo Workflows를 사용해 CI를 구축하고, Argo CD를 사용해 CD를 구축하고자 한다.

Argo 설치

Argo Workflow

Installation - Argo Workflows - The workflow engine for Kubernetes

About - Argo Workflows - The workflow engine for Kubernetes

Argo CD

Getting Started - Argo CD - Declarative GitOps CD for Kubernetes

argocd를 위를 참고해 helm을 사용해 설치해 주었다.

주의할점은 values 파일을 생성해 서비스 타입을 NodePort로 변경해주어야 외부에서 접속하기 수월하다.

Argo-CD 설치가 끝나면 웹 대쉬보드를 접속할 수 있는데 기본 비밀번호는 아래 명령으로 확인 가능하다.

1
2
3
4
5
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d

# Example
URL: 172.16.211.57:30443
Password: Everpass2023!

Argo Rollouts

Installation - Argo Rollouts - Kubernetes Progressive Delivery Controller

rollouts는 배포된 pod들을 업데이트 할때 여러 방식을 지원하기 위해 사용하는데, 현재 ci/cd를 구축하는데 있어서는 kubernetes의 기본 deployments가 지원하는 업데이트만 사용해도 될거 같아 생략하였다.

Argo Events

Argo Events는 이벤트가 발생하면 어떤 동작을 수행할지 정의할 수 있게 해주는 역할이다.

CI를 위해 github에 push가 일어나면 webhook을 발생시킬 수 있도록 하여 event가 트리거 될 수 있도록 하고, 이벤트가 발생하면 argo-workflow를 통해 CI 프로세스가 동작할 수 있도록 하였다.

Getting Started - Argo Events - The Event-Based Dependency Manager for Kubernetes

CI/CD 설정

argo 프로젝트들을 사용해 ci/cd를 구축하는 시나리오는 아래와 같다고 할 수 있다.

  • argo-events를 사용해 github과 웹훅을 설정해 레포에 새로운 커밋이 수정되었다는 알림(이벤트)를 받는다.
  • argo-events의 sensor가 깃헙 업데이트된 깃헙 레포를 빌드하는argo-workflows의 workflow를 호출한다.
  • workflow가 빌드가 끝나면 argo-cd를 호출해 배포를 시작한다.

이러한 설정을 위해서는 argo를 사용해 EventBus, EventSource, ServiceAccount, Role, RoleBinding, Sensor, Workflow등을 설정해야 하는데 아래 링크의 예제를 참고하면 좋다.

argo-events/examples at master · argoproj/argo-events

Dockerfile을 기반으로 이미지를 빌드하고 푸쉬하는 설정은 아래 링크를 참고했다.

Buildkit 설정

kubernetes는 최근에 docker 지원을 제거했기 때문에 container이미지를 빌드하기 위해서는 빌드 툴을 사용해야 한다. 따라서 처음에는 buildkit을 사용한 설정을 진행하였다. (현재는 아래 kaniko로 변경)

argo-workflows/buildkit-template.yaml at master · argoproj/argo-workflows

moby/buildkit을 사용해 이미지를 빌드하고 푸쉬하도록 설정했다.

moby/buildkit을 사용하기 위해서는 rootless로 도커 데몬을 실행해야 한다고 하는데 centos 7에서는 권한 문제가 있는것 같다.(확실하지 않음) (필요없을지도)

따라서 아래 두 링크를 참고해 /etc/sysctl.conf 파일을 수정해 주었다.

Rootless buildkitd throws permission error inside container

Run the Docker daemon as a non-root user (Rootless mode)

Kaniko 설정

컨테이너 빌드 도구 선택을 위한 특성 및 성능 비교 (Kaniko, Buildah, Buildkit)

하지만 buildkit을 설정한 후에 위의 글을 확인하였는데 보안에 유리하고 커뮤니티 규모가 더 큰 kaniko를 사용하는 것도 괜찮을것 같다는 생각을 해 kaniko로 다시 설정을 해주았다. (buildkit을 사용해도 된다)

webhook을 보낸 git repository를 클론한다음 해당 레포에 있는 Dockerfile을 기반해 컨테이너 이미지가 빌드 될 수 있도록 구성하였다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
- name: build
  inputs:
      artifacts:
      - git:
          branch: develop
          depth: 1
          repo: ""
          singleBranch: true
          name: source
          path: /workspace
  container:
      name: kaniko
      image: gcr.io/kaniko-project/executor:debug
      command: 
      - executor
      workingDir: /workspace
      args:
      # - "--insecure-registry=<private docker-registry>"" # if you are using a private docker registry as insecure (http)
      - "--dockerfile=Dockerfile"
      - "--context=."
      - "--build-arg=REACT_APP_CLIENT_ID"
      - "--build-arg=REACT_APP_CLIENT_SECRET"
      - "--build-arg=REACT_APP_ALOG_API_URL"
      - "--build-arg=REACT_APP_YORKIE_API_URL"
      - "--build-arg=REACT_APP_YORKIE_API_KEY"
      # - "--destination=<private docker-registry>/:latest" # if you are using a private docker registry
      - "--destination=chromato99/:develop-"
      - "--destination=chromato99/:develop"
      env:
      - name: REACT_APP_CLIENT_ID
          valueFrom:
          secretKeyRef:
              key: REACT_APP_CLIENT_ID
              name: alog-secret
      - name: REACT_APP_CLIENT_SECRET
          valueFrom:
          secretKeyRef:
              key: REACT_APP_CLIENT_SECRET
              name: alog-secret
      - name: REACT_APP_ALOG_API_URL
          valueFrom:
          secretKeyRef:
              key: REACT_APP_ALOG_API_URL
              name: alog-secret
      - name: REACT_APP_YORKIE_API_URL
          valueFrom:
          secretKeyRef:
              key: REACT_APP_YORKIE_API_URL
              name: alog-secret
      - name: REACT_APP_YORKIE_API_KEY
          valueFrom:
          secretKeyRef:
              key: REACT_APP_YORKIE_API_KEY
              name: alog-secret
      volumeMounts:
      - name: kaniko-secret
          mountPath: /kaniko/.docker
  volumes:
      - name: kaniko-secret
      secret:
          secretName: regcred
          items:
          - key: .dockerconfigjson
              path: config.json

**troubleshooting

--build-arg=REACT_APP_USER_API_URL=$REACT_APP_USER_API_URL

build-arg를 위와 같이 설정하였더니 환경변수로부터 인자 주입이 제대로 되지 않는 문제가 있었다.

https://github.com/GoogleContainerTools/kaniko/issues/713

검색결과 ‘$’ 특수문자를 사용해 환경변수 이름을 지정할 필요 없이 단순히 arg 이름을 환경변수와 동일하게 하면 자동으로 주입된다는 것을 확인 할 수 있었다.

ArgoCD를 사용한 A-Form 프로젝트 배포

현재 구성에서 배포를 위헤서는 Rook+Ceph 스토리지 구성과 Ingress Controller 설치가 필요하다.

1
2
3
4
5
# A-Form Cluster 배포
argocd app create aform --repo https://github.com/KEA-ACCELER/aform-cluster.git --path k8s --dest-server https://kubernetes.default.svc --dest-namespace default

# CI 프로세스 배포
argocd app create aform-ci --repo https://github.com/KEA-ACCELER/aform-cluster.git --path ci --dest-server https://kubernetes.default.svc --dest-namespace argocd

ArgoCD Image Updater 설정

위의 설정으로 CI 프로세스가 완성되었지만 아직 배포가 자동으로 이루어지지 않는다. 이를 자동으로 해주기 위해서는 argocd-image-updater를 사용해 새로운 이미지가 dockerhub에 푸쉬되면 이를 감지하고 최신 으로 업데이트 해준다.

특히, 태그가 단순히 latest여도 digest를 비교해 최신으로 업데이트 해주는 기능을 제공한다.

따라서 아래 helm chart를 사용해 설치를 진행해 주었다.

argocd-image-updater 0.9.1 · argoproj/argo

주의할 점은 argocd에서 배포한 앱의 auto-sync 설정을 켜주어야 한다.

이를 해주어야 업데이트된 버전의 이미지로 sync가 이루어 질 수 있다.

그리고 또 한가지 주의할점은 argocd와 같은 네임스페이스에 설치되어야 자동으로 argocd를 감지한다.

그리고 argocd로 배포한 앱의 설정에 아래와 같이 annotation을 추가해주어야 image updater와 연동된다.

annotations

Develop 서버, Publish 서버

위 내용을 기반으로 Develop 서버와 Publish 서버를 분리하여 CI/CD 파이프라인을 구축하였다.

develop-publish

Develop 서버 구축

  • 환경: 학교의 On-Premise 서버
  • 가상화 플랫폼: XCP-ng
  • 오케스트레이션: Kubernetes
  • ArgoCD: Develop 서버의 애플리케이션 배포를 자동화하기 위해 ArgoCD를 사용했다. GitOps 방식으로 원하는 상태를 Git 리포지토리에 정의하고, ArgoCD가 이를 감지하여 자동으로 Kubernetes 클러스터에 배포한다.

Develop 서버는 alog github 레포지토리들의 develop 브랜치를 통합/배포 하도록 구성한다.

Publish 서버 구축

  • 환경: Kakao i Cloud
  • 가상화 플랫폼: Kubernetes
  • ArgoCD: Publish 서버의 애플리케이션 배포 또한 GitOps 워크플로우를 따른다. ArgoCD를 활용하여 클라우드 환경에 정상적으로 배포된다.

Publish 서버는 alog github 레포지토리들의 main 브랜치를 통합/배포 하도록 구성한다.

CI/CD 파이프라인

pipeline

CI/CD 파이프라인 구성

CI/CD 파이프라인을 다시 한번 정리하면 아래와 같다.

  1. Github 웹훅: 개발 사항이 Github에 커밋되면 웹훅을 통해 서버로 전달된다.
  2. Argo Events: Github 웹훅을 감지하여 이벤트를 발생시킨다.
  3. Argo Workflow: Argo Events가 발생한 이벤트를 감지하고, CI를 위한 프로세스들을 정의한 워크플로우를 생성한다.
  4. Kaniko 빌드 툴: 쿠버네티스에서는 도커 지원이 제거되어 별도의 빌드 툴을 사용해야 합니다. 우리는 구글이 개발한 kaniko를 활용하여 쿠버네티스 컨테이너 내부에서 이미지를 빌드한다.
  5. 도커 허브: 빌드된 이미지는 도커허브에 푸쉬된다.
  6. Argo CD Image Updater: 푸쉬된 이미지를 감지하고, argo CD에 sync하여 배포를 진행한다.
  7. GitOps 스타일 배포: 설정 파일이 올라가있는 레포지토리를 참조하여 배포가 이루어진다.

사용한 도구

사용한 도구들을 정리하면 아래와 같다.

  1. Argo Workflow: CI를 위한 프로세스들을 정의하는 워크플로우를 생성하는 데 사용된다.
  2. Argo Events: Github 웹훅을 감지하여 이벤트를 발생시키는 데 사용된다.
  3. Argo CD: GitOps 스타일의 배포를 제공하는 도구이다.
  4. Argo CD Image Updater: 컨테이너 이미지가 업데이트 됐는지 확인하고 자동으로 업데이트해 준다.
  5. Kaniko: 쿠버네티스 컨테이너 내부에서 도커 이미지를 빌드하는 데 사용된다.

배포 형식

시스템에 서비스 배포는 GitOps 스타일의 배포 형식으로 설정 파일이 올라가있는 alog-cluster 레포지토리를 기반으로 배포가 이루어진다. Github 웹훅을 통해 이벤트가 감지되면 Argo Events가 이를 처리하고, Argo Workflow를 통해 CI를 위한 프로세스들을 실행하여 이미지를 빌드하고, 빌드된 이미지를 도커허브에 푸쉬한다. 이후 Argo CD Image Updater가 푸쉬된 이미지를 감지하고, ArgoCD에 sync하여 실제 배포가 이루어진다.

장점

  • ArgoCD와 Argo Workflows를 사용하여 개발자는 Kubernetes 시스템에서 GitOps 방식으로 배포를 자동화할 수 있다.
  • Argo Events를 활용하여 코드 푸시와 같은 변경 사항이 발생했을 때, CI/CD 파이프라인이 자동으로 시작되므로 빌드와 배포를 신경쓰지 않아도 된다.
  • ArgoCD Image Updater를 이용하여 Publish 서버의 이미지 업데이트를 자동으로 수행하므로 빠른 배포가 가능하다.

Conclusion

https://github.com/KEA-ACCELER/alog-cluster

CI/CD와 쿠버네티스 구성을 위한 설정파일들은 모두 alog-cluster 레포지토리에 정리하였다.

ArgoCD와 Argo Workflows를 사용하여 Develop 서버와 Publish 서버를 분리한 CI/CD 파이프라인을 구축한 결과, 개발자들은 더 효율적으로 개발하고 배포할 수 있으며, GitOps 방식으로 원하는 상태를 정의하여 안정적이고 신뢰성 높은 서비스를 제공할 수 있었다. 또한 Argo Events와 ArgoCD Image Updater를 통해 CI/CD 파이프라인을 자동화하여 개발과 배포의 생산성을 향상시켰다.

This post is licensed under CC BY 4.0 by the author.