ArgoCD를 배워보자 1일차 - ArgoCD 개론

0

ArgoCD

목록 보기
1/2

Gitops란

gitops란 용어는 flux라는 gitops 도구를 만든 웨이브웍스(waveworks) 직원들이 2017년에 처음 사용했다.

gitops의 정의는 정말 다양하다. pull request를 통한 운영으로 정의하기도 하고, 개발 관행(버전 제어, 협업, 규정 준수, CI/CD)을 인프라 자동화에 적용하는 것으로 정의하기도 한다.

CNCF에서 제안하고 있는 gitops의 5가지 원칙은 다음과 같다.
1. Declarative Configuration
2. Immutable storage(버전이 제어되는 불변의 저장소)
3. 자동화된 배포
4. 소프트웨어 에이전트
5. closed loop(폐쇄된 loop: 일종의 app관리를 위한 루프로 application의 생명주기 동안 발생하는 배포-모니터링-수정 등의 전체 수명 주기를 자동화하는 것을 말한다.)

Declarative Configuration은 '선언적인 구성'이라는 말로, 명령적인 표현과는 다른 의미를 가진다. 가령 CLI를 통해서 사용자가 직접적으로 명령을 하는 것은 imperative Configuration이라고 하는데, 이는 사용자가 일일히 모든 설정을 CLI로 치거나, 이를 자동화시켜주는 script를 만들어야 한다는 것이다.

반면에 declarative configuration은 yaml파일과 같은 구성 파일을 통해서 사용자가 입력한 내용에 따른 상태를 software agent가 자동으로 구성해주는 것이다.

중요한 것은 gitops라고 해서 무조건 git을 써야한다는 것은 아니다. 흔히들 하는 착각인데, CNCF에서는 엄연히 Immutable storage라는 정의로 git과 같이 application의 version을 fix하여 수정할 수 없도록 하는 VCS(Version Control System)이면 된다는 것이다. 가령, svn, p4도 상관없다.

자동화된 배포는 vcs에 반영된 수정 사항에 대해 software agent가 app에 반영되도록 한다는 것을 의미한다. 즉, 수정 사항을 일일히 개발자가 app에 반영하도록 하지 않도록 한다는 것이다. 이 과정에서 app의 일련의 주기를 반복적으로 겪으며 하나의 closed loop를 지나는 것이다.

ArgoCD

ArgoCD는 kubernetes 상에서 선언적인 방식을 통해 GitOps CD(continuous Delivery)도구다. ArgoCD 핵심 구성요소 중 application controller가 있다. application controller는 운영 중인 application을 지속적으로 관찰하고 현재 application 상태와 원천 소스인 git repository에 작성된 의도한 상태를 비교한다. 다음의 사용 사례를 살펴보자.

  • 배포 자동화(automated deployment): git commit 또는 CI 파이프라인이 동작하고, 수동 동기화를 트리거한 후에 ArgoCD controller는 자동으로 cluster를 git repository에 의도한 상태로 push하게 된다. 이 방법은 Argo event 자동화 framework를 사용하거나(argo-events), 사용자의 수동적인 요청을 통해서 가능하다.

  • 관찰 가능성(observability): ArgoCD는 application 상태가 git에서 의도한 상태와 동기화되어 있는 지 식별할 수 있는 UI와 CLI를 제공하고 ArgoCD Notification 엔진을 제공한다.

  • 멀티 테넌스(multi-tenancy): 인증을 위한 RBAC 정책을 사용해 여러 클러스터를 관리하고 배포하는 기능이 가능하다.

Argo Project는 다음과 같이 다양한 도구를 갖는다.

  • ArgoCD
  • Argo Rollouts
  • Argo Events
  • Argo Workflows

ArgoCD reconciliation(조정)

reconciliation은 kubernetes controller 또는 operator에서 현재의 상태를 원하는 상태로 바꾸기 위해서 동작하는 loop이다. ArgoCD 역시도 하나의 kubernetes operator로, reconciliation loop를 가지는데 git repository를 기반으로 kubernetes cluster의 상태를 조정하기 위해 사용된다.

ArgoCD는 바라보는 git repository에 있는 helm chart를 kubernetes yaml로 렌더링한다. 그리고 클러스터를 의도한 상태와 비교한다. 이걸 동기화 상태(sync status)라고 부른다. 만약 ArgoCD가 다르다고 판단하면 자동 혹은 수동으로 kubectl apply를 사용하여 template화된 파일을 적용시키고 kubernetes를 의도한 상태로 변경한다. 또한, ArgoCD는 운영 중인 kubernetes resource와 kubernetes의 의도한 상태를 비교하면서 application의 상태 체크를 진행한다.

재밌는 점은 ArgoCD는 helm install을 사용하지 않고 kubectl apply를 사용하여 kubernetes를 배포한다는 것이다. 이는 gitops 원칙에 맞도록 ArgoCD는 하나의 declarative(선언적) 도구로서 시스템의 원하는 상태(desired state)를 유지 관리하는 데 초점이 맞춰져 있기 때문이다. 즉, 원하는 상태(desired state)를 유지 관리하기 위해서 다른 helm, kustomize와 같은 도구의 힘을 받아 원하는 상태를 맞추는 것이 아니라, ArgoCD 자체가 declarative(선언적) 도구로서 원하는 상태를 맞추기위한 기능을 한다는 것이다.

단, 이 과정 이전에 다양한 도구(helm, kustomize)가 생성한 선언적 yaml 파일을 받는 것은 지원한다. 상태를 맞추는 것은 ArgoCD의 몫이기 때문에 다른 도구에 의존하지 않고, 직접 kubectl apply를 통해 세밀한 제어를 동작하는 것이다.

ArgoCD에서 사용하는 용어들에 대해서 정리해보도록 하자.

  1. Application: kubernetes resource group은 manifest으로 규정되는데, ArgoCD에서의 application은 CRD에서 규정된다.
  2. Application source type: helm, kustomize와 같이 application을 구축하는데 사용하는 도구를 말한다.
  3. Target state: application의 의도한 상태를 말하며, 원천 소스인 git repository에 정의하면 된다.
  4. Live state: application의 현재 상태로 kubernetes cluster에 배포된 상태를 의미한다.
  5. Sync state: 현재 상태와 타깃 상태가 일치하는 지 확인한다. 즉, kubernetes에 배포된 application이 git repository에서 설명된 의도한 상태와 일치하는 지 여부를 확인한다.
  6. Sync: kubernetes cluster에 변화를 적용해 application을 원하는 target state로 변경한다.
  7. Sync operation status: 동기화 단계에서 작업이 실패인지 성공인지 여부를 보여준다.
  8. Refresh: git repository의 최신 code와 live state의 차이점을 비교한다.
  9. Health state(서비스 상태): application이 요청을 받을 수 있고, 운영 중인 상태인지 말해준다.

ArgoCD 아키텍처

ArgoCD 핵심 구성 요소는 kubernetes controller로 구성되어 있다. kubernetes controller는 cluster의 상태를 관찰한 다음 필요한 경우 변경 사항을 적용하거나 요청한다. 따라서, controller는 클러스터의 현재 상태를 의도한 상태와 비슷하게 유지하려고 한다. controller는 Kubernetes resource object를 지속적으로 관찰하며, 이 resource object는 Spec field를 통해 의도한 상태를 나타낸다.

ArgoCD는 다양한 component와 도구로 구성되어 있다. (아래의 CI/CD tools는 jenkins, circleCI와 같은 것들을 생각하면 된다.)

  1. API server: ArgoCD는 kubernetes와 비슷하게 API서버가 있다. 이 API서버는 웹 UI, Argo event, CI/CD system과 같이 다른 시스템과도 API를 통해 상호작용한다. API 서버의 역할은 다음과 같다.
  • Application 관리 및 상태 보고
  • Application trigger 작업
  • git repository와 kubernetes cluster 관리
  • 인증과 SSO 지원
  • RBAC 정책 강화
  1. Repository server: repository서버의 주요 역할은 application manifest를 보관하는 git repository의 local cache를 유지하는 것이다. 다른 Argo component는 Repository server를 통해 kubernetes manifest를 가져오는 것이다. 요청에 필요한 매개 변수는 다음과 같다.
  • repository URL
  • git version
  • application path
  • template 세부 설정: ex) helm의 values.yaml
  1. Application contrller: 지속적으로 application의 상태를 확인하여 git repository의 의도한 상태와 비교해 동기화시켜준다. 또한, 사용자가 hook을 추가하여 생명 주기 동안 실행시켜주도록 한다.

기본적으로 ArgoCD는 3분마다 git repository(또는 사용자가 직접 요청을 보내는 CRD나 CLI)를 확인하여 '원하는 상태'를 확인한다. 따라서, 즉시 반영되지 않기 때문에 지원을 피하기 위해서는 동기화 단계를 즉시 트리거 할 수 있는 몇 가지 다른 옵션이 있다.

  1. ArgoCD에는 동기화 단계를 수동으로 진행할 수 있는 UI가 포함되어있다.
  2. ArgoCD의 CLI를 사용해 application 동기화를 시킬 수 있다. argocd app sync myapp를 사용하면 된다. 이를 통해서 CI tool에서 마지막 단계에서 실행하도록 할 수 있다.
  3. 동기화 단계를 즉시 시작하는 webhook 구성을 설정하는 것이다. ArgoCD는 github, gitlab, bitbucket 등에서 webhook을 알림을 지원한다.

ArgoCD의 핵심 object와 resource

ArgoCD Application, Project, Repository, cluster의 자격 증명과 같은 설정 값들은 kubernetes manifest를 이용해 선언적으로 정의할 수 있다. 이것을 CRD라고 부르는 것이다. 이제 ArgoCD의 핵심 object와 resource를 자세히 알아보자.

  1. Application: ArgoCD는 실제 kubernetes cluster에 배포하려는 application의 인스턴스를 Application이라는 CRD로 구현한다.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: guestbook
  namespace: argocd
spec:
  project: guestbook-project
  source:
    repoURL: https://github.com/argoproj/argocd-example-apps.git
    targetRevision: HEAD
    path: guestbook
  destination:
    server: https://kubernetes.default.svc
    namespace: guestbook
  • project: AppProject를 지정하는 것이다.
  • source: source code를 받아오는 git repository를 지정한다.
  • destination: application이 배포될 cluster 서버와 namespace를 특정한다.
  1. AppProject: Application CRD에 정의된 application들에 대해 proejct라는 group을 묶어주는 것이다. proejct group안의 application들은 어떤 git repository를 사용할 지 source가 제한되고, 배포되는 cluster도 어떤 서버에 어떤 네임스페이스로 배포될지 제한된다.
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: guestbook-project
  namespace: argocd
  finalizers:
    - resources-finalizer.argocd.argoproj.io
spec:
  description: Example Project
  # Allow manifests to deploy from any Git repos
  sourceRepos:
  - '*'
  # Only permit applications to deploy to the guestbook namespace in the same cluster
  destinations:
  - namespace: guestbook
    server: https://kubernetes.default.svc
  # Deny all cluster-scoped resources from being created, except for Namespace
  clusterResourceWhitelist:
  - group: ''
    kind: Namespace
  • sourceRepos: AppProject안에 있는 application이 접근할 수 있는 git repository 목록을 정의한다. *이면 어디든 상관없다.
  • destinations: AppProject안에 있는 application이 배포될 수 있는 cluster 서버와 namespace 목록을 정의한다.
  • clusterResourceWhitelist: AppProject 내 application이 관리할 수 있는 cluster 범위 resource를 제한하거나 허용하는 관리 도구이다. 이를 통해서 특정 AppProject가 접근할 수 있는 kubernetes resource 범위를 줄여서 cluster 전체에 줄 임팩트를 줄일 수 있다. 가령 NamespaceclusterResourceWhitelist에 없으면 Application에 Namespace가 있어도 ArgoCD가 생성하지 않는다.. 참고로 cluster 범위의 resource만 제한하므로 ConfigMap, Secret, Service, Deployment 등은 상관없다.

AppProject는 주로 system business logic을 담당하는 application들에 대한 AppProject와 utility 기능을 하는 application들에 대한 AppProject로 나누어 관리하도록 한다.

  1. Repository Credentials: ArgoCD가 해당 repository에 접근하기 위해서 접근 가능한 자격 증명이 필요하다. ArgoCD는 이를 kubernetes secret과 configMap을 사용해 해결했다. 따라서, Secretrgocd.argoproj.io/secret-type: repository라는 라벨을 추가해야한다.
apiVersion: v1
kind: Secret
metadata:
  name: private-repo
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: repository
stringData:
  url: Error! Hyperlink reference not valid.
  sshPrivateKey: |
    -----BEGIN OPENSSH PRIVATE KEY-----
    ...
    -----END OPENSSH PRIVATE KEY-----
  1. Cluster credentials: ArgoCd가 여러 클러스터를 관리하고, ArgoCD가 이미 실행 중인 cluster에 포함되지 않은 경우, 다른 kubernetes cluster에 대한 액세스 권한을 얻어야 한다. secret에 argocd.argoproj.io/secret-type: cluster 라벨을 추가해주면 된다.
apiVersion: v1
kind: Secret
metadata:
  name: mycluster-secret
  labels:
    argocd.argoproj.io/secret-type: cluster
type: Opaque
stringData:
  name: mycluster.com
  server: https://mycluster.com
  config: |
    {
      "bearerToken": "<authentication token>",
      "tlsClientConfig": {
        "insecure": false,
        "caData": "<base64 encoded certificate>"
      }
    }

ArgoCD 설치

helm으로 설치하는 방법은 매우 간단하다.

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

argo-cd가 설치될 것이다. UI에 접근하기 위해서 다음의 명령어를 사용하도록 하자.

kubectl port-forward service/ch02-argocd-server -n argocd 8080:443

port-forward로 임시로 ui서버에 접근할 수 있도록 설정되었다면, 다음의 명령어로 secret에서 password를 가져오면 된다.

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

ArgoCD 첫 application을 동작시켜보도록 하자. 첫번째로 ArgoCD Application에 필요한 CRD를 생성하고, Nginx cluster에 적용시켜 설치해보도록 하자.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: nginx
  namespace: argocd
  finalizers:
  - resources-finalizer.argocd.argoproj.io
spec:
  syncPolicy:
    automated:
        prune: true
        selfHeal: true
    syncOptions:
      - CreateNamespace=true
  destination:
    namespace: nginx
    server: https://kubernetes.default.svc
  project: default
  source:
    chart: nginx
    repoURL: https://charts.bitnami.com/bitnami
    targetRevision: 13.2.10

이 CRD를 잘 살펴보면 ArgoCD에 application을 설치하기 위해 helm을 사용한다는 것을 알 수 있다.

  source:
    chart: nginx
    repoURL: https://charts.bitnami.com/bitnami
    targetRevision: 13.2.10

https://charts.bitnami.com/bitnami helm repo에 있는 nginx chart를 가져온다는 것을 알 수 있다.

kubectl apply -f argo-app/

UI화면으로 가서 SYNC버튼을 눌러보자, 만약 성공적으로 동작하고 있다면 UI상에 초록색 상태 표시가 보이고, replicaSet과 같이 방금 배포한 kubernetes resource들을 확인할 수 있다.

위와 같이 CRD로 배포하는 방법 이외에 argocd cli를 통해 배포하는 방법도 있다. 그러나, 이는 언제나 실험을 할 때만 사용할 것을 권장한다.

먼저, ArgoCD server에 login해야한다. login 시에는 admin/secret-password를 사용하면 된다.

argocd login localhost:8080

성공적으로 login되었다면 다음의 log가 나온다.

'admin:login' logged in successfully
  Context 'localhost:8080' updated

login 성공 후에 ArgoCD API server에 CLI를 통해 상호작용 할 수 있게 된다. 이제 NGINX argoCD application을 CLI를 통해서 배포해보도록 하자.

argocd app create nginx --repo https://charts.bitnami.com/bitnami \
--helm-chart nginx --revision 13.2.10 \
--dest-server https://kubernetes.default.svc \
--dest-namespace nginx

아직 argoCD에서 cluster로 sync를 하지 않으므로 argocd cli로 sync를 시켜주도록 하자.

argocd app sync nginx

동기화 원칙(Synchronization principles)

ArgoCD 동기화 단계는 resource hook이나 sync wave를 사용하여 관리할 수 있다.

ArgoCD는 kubernetes cluster에 변경 내용을 적용해 application을 target state로 만든다. 이러한 작업은 여러 단계로 거쳐 실행되는데 동기화 단계(phase)는 다음과 같다.

  • pre sync
  • sync
  • post sync

이를 resource hook이라고 하며 동기화 단계 전, 중, 후에 다른 작업을 실행할 수 있는 권한을 제공한다.

  • PreSync: 동기화 단계 전에 완료되어야 하는 작업을 수행할 때 사용한다. 가령 database migration이 있다.
  • Skip: ArgoCD에 applicaiton manifest가 적용되지 않도록 할 때 사용한다.
  • Sync: 블루-그린, 카나리 배포와 같은 kubernetes 롤링 업데이트 전략보다 더 정교하고 복잡한 배포를 오케스트레이션하는데 사용한다.
  • PosySync: 배포 후에 통합 및 상태 확인을 하거나, 새로운 릴리즈나 다른 시스템과 통합 같은 내용을 알리는데 사용한다.
  • SyncFail: 동기화 작업이 실해했을 경우 로직을 정리 또는 종료 시킬 때 사용한다.

resource hook은 특정 kubernetes manifest에 적용된다. 가령, database schema migration을 kubernets job을 통해서 실행한다고 해보자. kubernetes annotation을 통해서 ArgoCD에게 동기화 작업 이전에 실행되어야 하는 job이라는 것을 알려줄 수 있다.

apiVersion: batch/v1
kind: Job
metadata:
  generateName: schema-migrate-
  annotations:
    argocd.argoproj.io/hook: PreSync

기본적으로 ArgoCD는 Application을 배포할 때 kubernetes resource들을 병렬적으로 배포한다. 그러나, 이 resource들 간에는 순서가 있을 수 있다. 가령, A deployment가 먼저 실행된다음 B deployment가 실행되어야 한다면, sync wave(동기화 wave)로 이 순서를 지정해줄 수 있다.

가령, wave 0으로 설정된 resource는 먼저 배포하고, 다음은 1, 다음은 2로 배포하는 것이다.

sync wave를 설정하는 것은 annotation을 통해 간단히 설정할 수 있다.

metadata:
  annotations:
    argocd.argoproj.io/sync-wave: "5"

참고로 default가 0이다.

이 두 가지 동기화 방식을 병렬적으로 같이 사용할 수도 있다.

  • resource hook
  • sync wave

특정 resource에 대한 수정이 발생하면, ArgoCD는 다음 순서에 따라 resource를 변경한다.

  1. resource의 현재 Phase Annotation 확인 -> 현재 sync인지, pre-sync인지 확인
  2. sync wave annotation 확인 -> 낮은 값부터 배포
  3. kubernetes 'kind' 순서대로 배포 -> namespace가 deployment보다 먼저 배포된다.
  4. name 순서(오름차순)

참고로, ArgoCD는 wave 순서대로 동기화 resource 배포 중에 sync에 실패하거나 비정상 리소스가 발생하면, 동기화되고 정상화 될 때까지 해당 단계의 wave를 반복한다. 즉, 바로 다음으로 넘어가지 않는다.

0개의 댓글