argocd로 App of apps 패턴 적용해서 Kubeflow 배포하기

argocd로 App of apps 패턴 적용해서 Kubeflow 배포하기

argoCD란? 언제 사용해야할까? App of Apps패턴을 적용해보자

argoCD 왜 사용해야할까?



argoCD는 공식 홈페이지에서 선언적으로 GitOps를 Continuous Delivery 할 수 있게 해주는 툴이라고 소개가 되어 있습니다. 설명만으로는 사실 이게 어떤 툴이고 왜 사용해야 하는지 잘 와닿지 않을 것 같습니다. argoCD를 왜 사용하려고 했는지 그 배경을 먼저 말씀드리도록 하겠습니다. 현재 회사에서 Kubernetes기반의 Kubeflow를 이용한 MLOps 및 ML Platform을 만들고 있습니다. 이 플랫폼을 만드는 데에 있어서 kubeflow의 각 컴포넌트들을 관리해야 했는데 가장 처음 사용한 것은 Kustomize였습니다. Kubeflow 공식 manifest 레포에서도 manifest 관리를 Kustomize를 이용하고 있었고 이것을 그대로 활용해 보았습니다. Kustomize를 활용한 manifest관리는 나쁘지 않았습니다. 한번에 작성된 manifest를 클러스터에 적용할 수 있어서 굉장히 편리했었습니다. 하지만 kubeflow를 혼자 관리하지 않았고, 이에 따라 시간이 지날 수록 코드 관리가 필요해지게 되었으며, 언제 누가 어떤 변경을 했는지 기록을 할 필요가 생기기 시작했습니다. Continuous Integration의 필요성이 느껴지고 있었고 이에 따라 누구나 사용하기 쉬운 github과 같은 도구로 관리하면 좋겠다고 생각을 했습니다. Devtron, RancherCD 등 다양한 도구를 찾아보고 시도를 해봤습니다만, 맘에 쏙 드는 기능은 없었고 그러던 찰나에 argoCD라는 툴을 알게 되었습니다. argoCD는 딱 제가 원하던 기능을 갖고 있던 툴이었습니다. Github으로 코드관리가 가능하고, Kubernetes클러스터로 배포가 가능했으며, UI로 배포상황을 확인할 수 있고, 편하게 배포된 컴포넌트를 수정, 삭제가 가능했습니다.

argoCD 사용예시



argoCD

argoCD는 위에서 설명한 대로 GitOps를 가능하게 하는, CI/CD에 활용할 수 있는 툴입니다. Kubernetes위에 설치하고 원하는 레포를 등록하면 깃헙에 반영되는 내용을 쿠버네티스로 배포할 수 있습니다. 커밋이 되었을때마다 자동으로 이를 확인하는 AutoSync 기능이 있고, 커밋 후에 수동으로 이를 확인하여 Sync할 수도 있습니다. 운영환경이라면 수동으로 Sync하는게 심적으로 더 안정적일 수 있겠습니다.

argoCD 구조

argoCD architecture

argoCD의 구조는 위 그림과 같습니다. 한 눈에 그림이 들어오지 않기 때문에, 하나하나 이해해보도록 하겠습니다. argoCD를 이루는 큰 구성요소들은 다음과 같습니다.

  • argocd-repo-server: 검색을 담당합니다. 센싱하는 소스 github repository의 파일들을 가져와서 kubernetes manifest를 생성하고 이를 로컬에 저장하는 역할을 합니다. 해당 파드에 argocd-vault-plugin을 셋팅해 두면 해당 플러그인을 기반으로 vault에서 credential 정보를 retrieve 한뒤 파일에 주입시켜 manifest를 완성할 수 있습니다.
  • argocd-application-controller: 조정, reconcile을 담당합니다. argocd-repo-server가 생성한 manifest와 현재 쿠버네티스에 배포된 manifest의 데이터와 비교합니다. 만일 다른 점이 있다면 이를 기반으로 새로운 object들을 배포합니다.
  • argocd-server: argocd web UI를 담당합니다. stateless web으로서 reconcile의 결과를 단순 출력하는 역할만 담당합니다.

그리고 그 외의 캐싱의 역할을 하기 위해 레디스가 설치되고 인증 등을 위해 dex등이 추가로 설치됩니다. 실제로 설치가 된 이후의 파드들은 다음과 같이 생성됩니다.

argocd를 설치했을 때 등장하는 Pods



argoCD 설치하기

argoCD를 설치하는 방법은 두 가지로 나뉩니다. Helm으로 설치할 수도 있고, install.yaml을 이용할 수도 있습니다. 두 방법 모두 설치가 잘 되지만 개인적으로는 helm으로 설치하는게 깔끔하다고 생각됩니다.



Helm으로 설치하기

ArgoCD helm레포를 등록하고 설치를 진행해줍니다. argocd만의 namespace를 만들고 이 namespace에 argocd 설치하는 것을 권장합니다.

  • helm repo add argo https://argoproj.github.io/argo-helm
  • kubectl create namespace argocd
  • helm -n argocd install argocd argo/argo-cd



설치를 진행하면서 주의할 점이 있습니다. 설치가 한 번에 된다면 다행이지지만, 잘 되지않아 여러번 설치를 진행하게 되었을 때 마주하기 쉬운 에러 메세지입니다.

이미 CRD로 applications.argoproj.io 가 설치되어있다면, 다음의 에러메세지가 발생할 수 있습니다.

Error: INSTALLATION FAILED: rendered manifests contain a resource that already exists. Unable to continue with install: CustomResourceDefinition “applications.argoproj.io” in namespace “” exists and cannot be imported into the current release: invalid ownership metadata; label validation error: missing key “app.kubernetes.io/managed-by”: must be set to “Helm”; annotation validation error: missing key “meta.helm.sh/release-name”: must be set to “argo-cd”; annotation validation error: missing key “meta.helm.sh/release-namespace”: must be set to “argocd”



이러한 경우에는 해당하는 CRD를 완전히 삭제 후에 설치를 진행해줍니다.

  • kubectl delete crd applicationsets.argoproj.io applications.argoproj.io appprojects.argoproj.io
  • 만약 제거를 했지만 Removing 으로 남아있는 경우 다음의 명령어를 통해 삭제한다.
  • kubectl patch crd/{CRD-NAME} -p '{"metadata":{"finalizers":[]}}' --type=merge



install.yaml로 설치하기

  • kubectl create namespace argocd
  • kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml



설치내용 삭제하기 위해서는 다음의 명령어를 사용합니다.

  • kubectl delete -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml



설치가 된 이후에는 argocd-server를 통해 web ui를 사용할 수 있습니다. kubernetes에 설치를 했다면 argocd가 사용하는 Service가 구성되어 있습니다. 이 Service에 port-forward로 접근하면 service에 연결된 argocd-server로 접속할 수 있습니다.

kubectl port-forward svc/argocd-server -n argocd 8080:80

이 명령어는 로컬 시스템의 포트 8080과 Kubernetes 클러스터 내의 포트 80을 연결하는 명령어 입니다. 포트 포워딩에 대해 첨언을 하자면, 포트 포워딩은 로컬 시스템과 Kubernetes 클러스터 사이에서 특정 포트의 트래픽을 전달하는 메커니즘입니다. 위의 명령어에서 8080:80은 로컬 시스템의 포트와 Kubernetes 클러스터 내의 포트를 연결하기 위해 사용됩니다. 따라서, 로컬 시스템의 8080 포트로 들어오는 트래픽은 Kubernetes 클러스터 내의 80 포트로 전달됩니다.

이 명령어를 실행하면 로컬 시스템의 8080 포트를 통해 Argo CD 서비스에 접근할 수 있게 됩니다. 각자의 환경에 맞게 조정하면 Web UI가 다음과 같이 등장합니다.

argocd Web UI, 반갑다 꼴뚜기

하지만 바로 이 UI에 로그인을 할 수는 없습니다. 유저와 초기 비밀번호를 알아야 하기 때문입니다.



초기 비밀번호 알아내기, 비밀번호 설정

argocd에는 기본으로 생성되는 아이디와 비밀번호가 존재합니다. 기본 아이디는 admin이며 초기 비밀번호는 다음의 명령어를 통해 알아낼 수 있습니다.

초기 비밀번호

  • kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d

이 명령어를 통해 비밀번호가 등장한다면 이 비밀번호로 로그인이 가능합니다. 하지만 길고 기억하기 힘든 비밀번호이기 때문에, 비밀번호 재설정을 하는 것이 필수적입니다.

비밀번호 설정

  • argocd-server 파드의 쉘로 접속합니다.
  • argocd login $ARGOCD_SERVER_HOST:80 --grpc-web 또는 argocd login $ARGOCD_SERVER_HOST:8080 --grpc-web 으로 로그인, 초기 비밀번호를 사용해줍니다.
  • 로그인 후 비밀번호를 업데이트 한다.
    • argocd account update-password



Repo 등록하기

Public Repo를 등록하는 것은 간단합니다. 사실 가이드도 필요없이 UI에서 보고 알아서 등록을 할 수 있을 정도입니다. 하지만 중요한 것은 Private Repository입니다. 보통 회사에서 또는 공개하고 싶지 않은 이유로 Private Repository를 많이 사용하고 있기 때문에 이를 위한 연결방법을 아는 것이 필요합니다.

GitOps 파이프라인을 만들기 위해서는 레포를 등록해야하며, 회사의 레포는 비공개 레포지토리입니다. 따라서 일반 방법으로는 레포지토리를 아예 찾을 수 없고 이로인해 연결도 불가능합니다. 여러 연결 방법들이 있지만, 간단하게 연결하는 방법은 PAT를 이용한 방법입니다. PAT의 발급을 위해서는 github로그인을 한 상태에서 메뉴 -> Settings -> Developer settings -> Personal access token 의 경로에서 Generate new token 버튼을 눌러 토큰을 생성합니다.

이렇게 생성된 토큰을 레포를 연결할 때 username 하단에 있는 password에 넣어주면 끝입니다!

username, password 설정




App of Apps

argoCD도 설치했고 Repo도 등록했고 이제 문제없이 kubeflow manifest를 배포하면 끝입니다. 하지만 또 다른 문제가 있었습니다. 이는 사실 무시해도 되는 문제일 수도 있습니다. kubeflow의 manifest를 바로 argocd를 이용해 배포를 하게 된다면, kubeflow manifest에 굉장히 많은 컴포넌트들이 있기 때문에 argocd의 스크롤이 엄청나게 길어지게 됩니다. 배포 상황을 편하게 보려고 argocd를 사용하는 것인데, 오히려 보기가 어려워져버린 것입니다. 그래서 어떻게 해야 할까 고민하다가 다음의 아티클을 읽어보게 되었습니다. 이 아티클은 글의 저자가 만든 argoflow를 통해 kubeflow를 설치하는 글인데 argoflow를 사용해볼까 하다가 눈에 들어온 것은 다음의 그림이었습니다.

kubeflow를 컴포넌트 별로 분리

kubeflow의 주요 컴포넌트들을 관리하기 쉽게 나눠 놓은 것이었습니다. 이미 manifest는 갖고 있고 이를 분리하기만 하면 되기 때문에 생각보다 간단하게 진행할 수 있겠다 싶어서 바로 나눠보았습니다. 대략 16-17개의 요소로 나눠지게 되었고 각각의 요소들을 argocd에 등록하기 시작했습니다. 이 작업을 하다보니 현타가 오기 시작했습니다. 관리하기 편할려고 이렇게 나눈건데 노가다로 하나하나 등록해야되나 싶은 것이었습니다. 일일이 나누는 것도 일이었고 하나하나 등록하는 것도 힘들었습니다. manifest를 한 번에 배포하기 위해서 argoCD를 사용하는 것인데, 이렇게 배포하는 방식은 사용목적에 어긋나는 것으로 생각되었습니다. 그러던 와중에 App of Apps라는것을 발견하게 됩니다.

App of Apps는 무려 공식 페이지에 소개되어있습니다. Cluster Bootstrapping 파트에 나와있는데 cluster bootstrapping이란 구축한 쿠버네티스 클러스터에 필요한 쿠버네티스 리소스를 빠르게 배포하는 것을 말합니다. 다시말하면, 클러스터에 쉽게 manifest를 배포할 수 있는 방식인 것입니다. 공식 홈페이지에서 소개하는 방식은 Helm을 사용하는 방식입니다.

1
2
3
4
5
6
7
├── Chart.yaml
├── templates
│ ├── guestbook.yaml
│ ├── helm-dependency.yaml
│ ├── helm-guestbook.yaml
│ └── kustomize-guestbook.yaml
└── values.yaml

위와 같이 차트를 구성하고 해당하는 구성요소를 yaml로 넣어 큰 어플리케이션 안에 여러 어플리케이션을 넣어 관리할 수 있게 됩니다. values.yaml은 다음과 같이 구성할 수 있습니다.

  • values.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
server:
additionalApplications:
- name: kubeflow-app-of-apps
namespace: argocd
project: default
source:
repoURL: {repo url}
targetRevision: {repo branch}
path: {repo path}
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
syncOptions:
- CreateNamespace=true
#automated:
# selfHeal: true
# prune: true

values.yaml name에는 큰 묶음의 이름을 명시해줍니다. 저의 경우에는 kubeflow 내지 kubeflow-app-of-apps로 넣었습니다. 이렇게 놓고 해당 values.yaml이 바라볼 path를 넣어주면 되는데 이 path가 실제로 배포될 앱들이 모여있는 곳이면 됩니다. 해당 path에 있는 한 앱의 구성 방식을 보여드리겠습니다.

  • application.yaml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    apiVersion: argoproj.io/v1alpha1
    kind: Application
    metadata:
    name: jupyter
    namespace: argocd
    spec:
    project: default
    source:
    repoURL: {repo url}
    targetRevision: {repo branch}
    path: {app path}
    destination:
    server: https://kubernetes.default.svc
    namespace: default
    syncPolicy:
    syncOptions:
    - CreateNamespace=true
    automated:
    selfHeal: true
    prune: true

이렇게 application에 대한 yaml을 작성할 수 있습니다. 저의 경우에는 여기서 바라보는 path가 하나 더 있습니다. 이렇게 구성한 이유는 kubeflow의 jupyter에 대한 manifest를 살펴보면 아실 수 있습니다. kubeflow는 위에서 소개해드렸듯 kustomize를 사용하고 있었고 앱을 실제로 배포하는 것은 kustomization.yaml로 감싸져 있었습니다. 저는 앱을 이전에 한 번 분기한 적이 있었기 때문에 이것을 그대로 활용한 것입니다. 따라서 정리하자면 jupyter앱을 배포한다고 했을 때, argocd가 바라보게 되는 작업 경로는 values.yaml -> application.yaml -> 해당 위치에 있는 kustomization.yaml -> kustomization이 바라보는 실제 deployment 등의 yaml들 이 됩니다. 결론적으로 app of apps를 위한 큰 껍데기를 values.yaml과 application.yaml를 활용해 기존의 manifest에 감싸놓은 꼴인 것입니다.



이렇게 App of Apps 패턴까지 적용하고 나면 kubeflow에 대한 관리를 쉽게 할 수 있게 되고, dev과 같은 prod 환경을 구성해야 한다고 할지라도 manifest들을 활용해 prod 쿠버네티스에 배포할 수 있게 됩니다. argoCD를 활용해서 각 구성 요소의 어떤 부분에서 Sync가 잘 안되고 있는지, 어디가 지금 최신상태가 아닌지, 커밋 내역을 어디까지 반영했는지도 쉽게 파악할 수 있게 되죠. github을 통해서 누가 어떤 커밋을 보냈는지, 언제 보냈는지 확인할 수 있고 롤백을 할 수 있는 점은 덤입니다. 이렇게 argoCD를 활용해서 kubeflow를 쉽게 관리하고 배포할 수 있는 방법에 대해서 소개해 봤습니다. kubeflow를 운영, 배포하셔도 좋고, 이 방법을 활용해서 다른 manifest들에 적용하셔도 좋을 것 같습니다.


Reference

argocd로 App of apps 패턴 적용해서 Kubeflow 배포하기

http://tkdguq05.github.io/2023/05/29/argocd/

Author

SangHyub Lee, Jose

Posted on

2023-05-29

Updated on

2023-12-08

Licensed under

Comments