Argo CD

개요

image.png
argo cd는 쿠버네티스 환경에서 선언적으로 CICD 중 CD를 관리할 수 있도록 도와주는 툴이다.
아주 대표적인 GitOps 툴이다.

아르고cd의 기능과 특징은 다음과 같이 정리할 수 있다.

아무래도 깃옵스 툴로서는 거의 가장 유명한 것 같고, ui도 깔끔하면서 사용이 그렇게 어렵지도 않아서 크게 사랑받는 것 같다.

참고로 아르고라고 하면 가장 유명한 것은 아르고 cd이지만, 아르고는 사실 여러 개의 프로젝트를 가진 집합체이다.
아르고는 DevOps를 위한 각종 여러 프로젝트를 진행하고 있는데, 다른 것으로는 워크플로우, 롤아웃 등이 있다.

개념

기본적으로 알아야 할 만한 개념은 다음 정도가 있는 것 같다.

참고로 여기에서 application, project는 클러스터 내의 CRD로도 생성된다.

아키텍처


아르고cd에서 궁극적인 설정 흐름은 다음을 따른다.
운영자가 깃에 상태를 업데이트 - 아르고가 이를 클러스터에 그대로 반영
이 사이에서 여러 설정을 얹고, 알림을 넣거나 하는 등 다양한 기능을 추가할 수 있는 것이다.

아르고cd의 구조는 다음과 같이 구성된다.

dex 서버는 필수사항은 아니고, api 서버 단에서도 인증 인가를 수행할 수 있다.
아르고 CD는 아르고 시리즈 중에서 가장 강력하게 인증 인가 관련 설정을 제공한다.
클러스터 배포를 총체적으로 관리하는 툴인 만큼, api를 통해 할 수 있는 동작들도 매우 강력하기 때문에 강한 보안이 요구되는 애드온 중 하나이다.

App of Apps 패턴


어플리케이션이 CRD로 만들어진다고 이야기했는데, 어플리케이션은 쿠버의 리소스 묶음이라고 했다.
여기에서 조금만 더 생각해보면, 어플리케이션이라는 CRD 리소스를 묶는 어플리케이션을 만드는 방법을 떠올릴 수 있을 것이다.
이렇게 어플을 관리하는 어플을 두는 방식을 App of Apps 패턴이라고 부른다.[1]

이게 언제 필요한가?
가장 흔한 케이스는 클러스터를 부트스트래핑할 때이다.
운영 간 차질이 없게 하기 위해 멀티 클러스터를 구축하는 상황이라고 생각해보자.
이때 클러스터의 기본 세팅을 기존 클러스터와 똑같이 세팅을 하고 싶다면, 관련 어플리케이션들을 전부 세팅되게 해야 할 것이다.
그렇다면 해당 어플리케이션들을 묶어 관리하는 어플리케이션을 둔 뒤에, 새로 만들어질 클러스터에는 이 어플만 설정을 해주면 편하게 똑같은 클러스터 환경을 세팅할 수 있을 것이다.


직접적으로 세팅하는 방법도 존재하나, ApplicationSet이라는 CRD를 이용하는 방법도 존재한다.[2]
이 crd는 제너레이터 방식을 이용해 여러 클러스터, 여러 깃 주소를 관리할 수 있다.[3]
다만 이 방식이 불편하여 오히려 다른 방식으로 구현하는 케이스도 찾아볼 수 있다.[4]

설정법

각종 설정법들은 web ui로 관리하는 것도 가능하나, 역시 나는 cli로 설정할 수 있는 것들을 먼저 위주로 다루겠다.

Application

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: guestbook
  namespace: argocd
  finalizers:
    - resources-finalizer.argocd.argoproj.io
spec:
  project: default
  source:
    repoURL: https://github.com/argoproj/argocd-example-apps.git
    targetRevision: HEAD
    path: guestbook
  destination:
    server: https://kubernetes.default.svc
    namespace: guestbook

아주 기본적인 설정법은 이렇다.
모든 어플리케이션은 특정 프로젝트에 속한다.
그리고 소스로는 특정 깃 저장소를 넣고, 목적지로는 쿠버 클러스터의 네임스페이스를 넣어주는 것이다.

Finalizer를 설정하는 것은 이 어플리케이션이 지워질 때 해당하는 리소스가 전부 지워지도록 하기 위해 세팅한다.
이 부분은 솔직히 아직 감이 안 잡히는 게, 파이널라이저는 오히려 리소스가 지워지는 것을 막기 위해 세팅하는 건데 문서에 설명이 이렇게 돼있다.
어쩌면 파이널라이저를 통해 소유자를 디스커버리하는 건가 싶기도 한데, 이건 한번 테스트해봐야겠다.

AppProject

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: my-project
  namespace: argocd
  finalizers:
    - resources-finalizer.argocd.argoproj.io
spec:
  description: Example Project
  # 프로젝트 단위에서 소스 레포를 설정
  sourceRepos:
  - '*'
  # 프로젝트 단위에서 목적지를 설정
  destinations:
  - namespace: guestbook
    server: https://kubernetes.default.svc
  # 클러스터 범위 리소스 중 생성 가능한 것
  clusterResourceWhitelist:
  - group: ''
    kind: Namespace
  # 네임스페이스 범위 리소스 중 생성할 수 없는 것.
  namespaceResourceBlacklist:
  - group: ''
    kind: ResourceQuota
  - group: ''
    kind: LimitRange
  - group: ''
    kind: NetworkPolicy
  # 네임스페이스 범위 리소스 중 생성할 수 있는 것.
  namespaceResourceWhitelist:
  - group: 'apps'
    kind: Deployment
  - group: 'apps'
    kind: StatefulSet
  # 프로젝트 내의 rbac 설정
  roles:
  # 프로젝트의 어플리케이션들의 읽기 가능 정책
  - name: read-only
    description: Read-only privileges to my-project
    policies:
    - p, proj:my-project:read-only, applications, get, my-project/*, allow
    groups:
    - my-oidc-group
  - name: ci-role
    description: Sync privileges for guestbook-dev
    policies:
    - p, proj:my-project:ci-role, applications, sync, my-project/guestbook-dev, allow
    # 토큰 생성 설정도 가능한데, 당연히 영속적인 토큰이 아니다.
    jwtTokens:
    - iat: 1535390316

프로젝트 설정은 이렇게 한다.
프로젝트 단위에서 권한 세팅을 하게 된다.

기타 설정 파일

image.png
아르고cd에서 각종 설정들은 전부 ConfigMap, Secret으로 관리된다.
각각의 기능이 무엇을 하는지, 어떻게 설정하는지는 간략하게 보자.

아르고 cd 전역 설정

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namspace: argocd
data:
  resource.exclusions: |
    - apiGroups:
      - "*"
      kinds:
      - "*"
      clusters:
      - https://192.168.0.20
  resource.inclusions: |
    - apiGroups:
      - "*"
      kinds:
      - Deployment
      clusters:
      - https://192.168.0.20
  resource.respectRBAC: "strict"
  resource.includeEventLabelKeys: team,env*

아르고가 추적하지 않거나, 추적해야할 리소스를 정의할 때 이렇게 설정할 수 있다.
직접적으로 설정하지 않고, resource.respaceRBAC 필드를 설정하면 아르고 컨트롤러가 가진 rbac 권한에 대해서만 정확하게 권한을 가지도록 세팅할 수 있다.
어떤 이벤트를 추적할지도 설정이 가능하다.

  accounts.alice: apiKey, login
  # disables user. User is enabled by default
  accounts.alice.enabled: "false"

유저를 설정할 때는 이렇게 넣어준다.
앞에도 말했지만, 웹 ui로도 가능한 부분이니 꼭 이런 방식으로 해야하는 건 아니다!

  oidc.config: |
    name: Auth0
    issuer: https://<yourtenant>.<eu|us>.auth0.com/
    clientID: <theClientId>
    clientSecret: <theClientSecret>
    domain_hint: <theDomainHint>
    requestedScopes:
    - openid
    - profile
    - email
    # not strictly necessary - but good practice:
    - 'http://your.domain/groups'

OIDC를 활용하는 것도 가능하다.

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-rbac-cm
  namspace: argocd
data:
  policy.csv: |
    # let members with group someProjectGroup handle apps in someProject
    # this can also be defined in the UI in the group-definition to avoid doing it there in the configmap
    p, someProjectGroup, applications, *, someProject/*, allow
    # let the group membership argocd-admins from OIDC become role:admin - needs to go into the configmap
    g, argocd-global-admins, role:admin
  policy.default: role:readonly
  # essential to get argo to use groups for RBAC:
  scopes: '[http://your.domain/groups, email]' 

rbac 관련 설정은 argocd-rbac-cm에 있다.
csv 형식으로 넣어주는 식으로 설정할 수 있다.
관련한 자세한 설정은 문서를 참고하자.[5]

깃 레포 관련 설정

apiVersion: v1
kind: Secret
metadata:
  name: private-repo
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: repository
stringData:
  type: git
  url: https://github.com/argoproj/private-repo
  password: my-password
  username: my-username
  project: my-project
---
...
stringData:
  type: git
  url: git@github.com:argoproj/my-private-repository.git
  sshPrivateKey: |
    -----BEGIN OPENSSH PRIVATE KEY-----
    -----END OPENSSH PRIVATE KEY-----

플젝, 어플 단위에서 레포 설정을 할 때 신원 정보나 설정을 이렇게 시크릿으로 관리할 수도 있다.
라벨을 달아두는 것이 주된 관건이다.

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-tls-certs-cm
  namespace: argocd
  labels:
    app.kubernetes.io/name: argocd-cm
    app.kubernetes.io/part-of: argocd
data:
  server.example.com: |
    -----BEGIN CERTIFICATE-----
    -----END CERTIFICATE-----
---	
apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    app.kubernetes.io/name: argocd-ssh-known-hosts-cm
    app.kubernetes.io/part-of: argocd
  name: argocd-ssh-known-hosts-cm
data:
  ssh_known_hosts: |
    # This file was automatically generated by hack/update-ssh-known-hosts.sh. DO NOT EDIT
    [ssh.github.com]:443 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
    [ssh.github.com]:443 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl

tls, ssh 설정에 대해 이렇게 미리 세팅을 하는 것이 가능하다.
그냥 설치해도 기본적으로 만들어지는데, 아무튼 이것들은 아르고cd의 api 서버, 레포 서버가 깃에 접근할 때 사용된다.

클러스터 관련 설정

apiVersion: v1
kind: Secret
metadata:
  name: mycluster-secret
  labels:
    argocd.argoproj.io/secret-type: cluster
type: Opaque
stringData:
  name: mycluster.example.com
  server: https://mycluster.example.com
  config: |
    {
      "bearerToken": "<authentication token>",
      "tlsClientConfig": {
        "insecure": false,
        "caData": "<base64 encoded certificate>"
      }
    }

클러스터에 대한 설정을 할 때는 이런 식으로 한다.
이것도 라벨을 잘 달아두는 것이 관건이다.

username: string
password: string
bearerToken: string
awsAuthConfig:
    clusterName: string
    roleARN: string
    profile: string
execProviderConfig:
    command: string
    args: [ ]
    env: { key: value }
    apiVersion: string
    installHint: string
proxyUrl: string
tlsClientConfig:
    # Base64 encoded
    caData: string
    certData: string
    insecure: boolean
    keyData: string
    # 서버의 인증서 검증을 위한 도메인 확인용. 이거 없으면 호스트이름이 쓰인다.
    serverName: string
disableCompression: boolean

config 부분의 세팅은 이런 식의 필드를 가질 수 있고, 이걸 json으로 넣어주면 된다.

apiVersion: v1
kind: Secret
metadata:
  name: mycluster-secret
  labels:
    argocd.argoproj.io/secret-type: cluster
type: Opaque
stringData:
  name: "eks-cluster-name-for-argo"
  server: "https://xxxyyyzzz.xyz.some-region.eks.amazonaws.com"
  config: |
    {
      "awsAuthConfig": {
        "clusterName": "my-eks-cluster-name",
        "roleARN": "arn:aws:iam::<AWS_ACCOUNT_ID>:role/<IAM_ROLE_NAME>"
      },
      "tlsClientConfig": {
        "insecure": false,
        "caData": "<base64 encoded certificate>"
      }        
    }

이건 EKS에서 설정할 때의 예시인데, IRSA 같은 설정들은 알아서 해줘야 한다.[6]

알림 기능

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-notifications-cm
data:
  trigger.on-sync-status-unknown: |
    - when: app.status.sync.status == 'Unknown'     # trigger condition
      send: [app-sync-status, github-commit-status] # template names
  service.slack: |
      token: $slack-token
  template.my-custom-template-slack-template: |
    message: |
      Application {{.app.metadata.name}} sync is {{.app.status.sync.status}}.
      Application details: {{.context.argocdUrl}}/applications/{{.app.metadata.name}}.
--- 
apiVersion: v1
kind: Secret
metadata:
  name: <secret-name>
stringData:
  slack-token: <Oauth-access-token>

보안 - 유저 관리

위에서 잠시 언급했듯이 아르고 CD는 유저 관리에 진심인 애드온이다.
그래서 다양한 설정 방법이 존재한다.

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
  labels:
    app.kubernetes.io/name: argocd-cm
    app.kubernetes.io/part-of: argocd
data:
  #   apiKey - api 키 생성 가능allows generating API keys
  #   login - ui로 로그인 가능
  accounts.alice: apiKey, login
  # 유저 비활성화
  accounts.alice.enabled: "false"

가장 기본적으로는 쿠버 Authentication#정적 토큰 파일 마냥 간단하게 유저를 관리하는 방법이 있다.

argocd account list

cli로는 이런 식으로 유저를 확인 관리할 수 있다.

SSO

아르고 워크플로우에서 SSO를 지원하듯이 아르고 CD도 SSO를 지원하는데, 이 녀석은 아예 자체 인증 서버도 번들로 같이 제공한다.
이때 사용되는 인증 제공자가 Dex인데, 물론 다른 OIDC 제공자를 쓰더라도 상관 없다.

data:
  url: https://argocd.example.com

  dex.config: |
    connectors:
      # GitHub example
      - type: github
        id: github
        name: GitHub
        config:
          clientID: aabbccddeeff00112233
          clientSecret: $dex.github.clientSecret # Alternatively $<some_K8S_secret>:dex.github.clientSecret
          orgs:
          - name: your-github-org

      # GitHub enterprise example
      - type: github
        id: acme-github
        name: Acme GitHub
        config:
          hostName: github.acme.example.com
          clientID: abcdefghijklmnopqrst
          clientSecret: $dex.acme.clientSecret  # Alternatively $<some_K8S_secret>:dex.acme.clientSecret
          orgs:
          - name: your-github-org

선언적으로 세팅할 때는 이런 식으로 또 컨피그맵을 사용할 수 있다.
Keycloak이랑도 같이 쓸 수 있다![7]

설치

###############################################################################
#### Argo CD
###############################################################################
resource "helm_release" "argo_cd" {
  repository = "https://argoproj.github.io/argo-helm"
  chart = "argo-cd"
  version = "7.8.14"
  name = "argo-cd"
  namespace = "argo-cd"

  create_namespace = true
  values = [
    <<-EOF
    createAggregateRoles: true

    global:
      domain: argocd.zertoay.com

    configs:
      cm:
        create: true
        server.rbac.log.enforce.enable: true
        exec.enabled: true
        admin.enabled: true

      params:
        create: true

      rbac:
        create: true
        policy.csv: |
          p, role:org-admin, applications, *, */*, allow
          p, role:org-admin, clusters, get, *, allow
          p, role:org-admin, repositories, *, *, allow
          p, role:org-admin, logs, get, *, allow
          p, role:org-admin, exec, create, */*, allow
          g, your-github-org:your-team, role:org-admin

        policy.matchMode: "glob"

      cmp:
        create: false

    controller:
      name: application-controller
      replicas: 1

    dex:
      enabled: true

    redis:
      enabled: true

    server:
      name: server
      replicas: 1

    repoServer:
      name: repo-server
    applicationSet:
      name: applicationset-controller
    notifications:
      enabled: true
    commitServer:
      enabled: false
    EOF
  ]
}

아르고 cd는 설치할 때부터 설정할 수 있는 것들이 매우 많다.
헤드리스 모드로 정말 동기화만 하는 최소한의 기능만 설치하고 싶다면 코어를 설치한다.[8]

VERSION=$(curl -L -s https://raw.githubusercontent.com/argoproj/argo-cd/stable/VERSION)
curl -sSL -o argocd-linux-amd64 https://github.com/argoproj/argo-cd/releases/download/v$VERSION/argocd-linux-amd64
sudo install -m 555 argocd-linux-amd64 /usr/local/bin/argocd
rm argocd-linux-amd64

아르고 cd 역시 자체적인 cli 툴을 제공하기에, 활용해주면 유용하다.[9]

관련 문서

이름 noteType created
Argo CD knowledge 2025-03-24
Argo Workflows knowledge 2025-03-24
아르고 롤아웃과 이스티오 연계 knowledge 2025-04-22
8W - 아르고 워크플로우 published 2025-03-30
8W - 아르고 CD published 2025-03-30
8W - CICD published 2025-03-30
10W - Vault를 활용한 CICD 보안 published 2025-04-16
3W - 트래픽 가중치 - flagger와 argo rollout을 이용한 점진적 배포 published 2025-04-22
E-buildKit을 활용한 멀티 플랫폼, 캐싱 빌드 실습 topic/explain 2025-03-30

참고


  1. https://argo-cd.readthedocs.io/en/stable/operator-manual/cluster-bootstrapping/ ↩︎

  2. https://cwal.tistory.com/90 ↩︎

  3. https://argo-cd.readthedocs.io/en/stable/operator-manual/applicationset/Use-Cases/ ↩︎

  4. https://www.youtube.com/watch?v=dWLEUfXloA8&t=973s ↩︎

  5. https://argo-cd.readthedocs.io/en/stable/operator-manual/rbac/ ↩︎

  6. https://argo-cd.readthedocs.io/en/stable/operator-manual/declarative-setup/#eks ↩︎

  7. https://argo-cd.readthedocs.io/en/stable/operator-manual/user-management/keycloak/ ↩︎

  8. https://argo-cd.readthedocs.io/en/stable/operator-manual/core/ ↩︎

  9. https://argo-cd.readthedocs.io/en/stable/cli_installation/ ↩︎