Table of contents
- 클러스터가 하나일 때는 몰랐던 것
- 클러스터 등록하기
- ApplicationSet이 필요한 이유
- List Generator — 가장 단순한 시작
- Cluster Generator — 등록된 클러스터에서 자동 생성
- Git Generator — 레포지토리 구조가 곧 설정
- Generator 조합하기
클러스터가 하나일 때는 몰랐던 것
ArgoCD를 처음 도입할 때는 보통 하나의 클러스터에 설치하고, 같은 클러스터에 애플리케이션을 배포한다. 설정이 간단하고 동작을 이해하기 쉬우니까.
그런데 조직이 커지면 클러스터도 늘어난다. 개발용, 스테이징용, 프로덕션용. 리전별로 나뉘기도 하고, 팀별로 분리되기도 한다. 이때 클러스터마다 ArgoCD를 따로 설치할 것인지, 하나의 ArgoCD로 여러 클러스터를 관리할 것인지 결정해야 한다.
하나의 ArgoCD가 여러 클러스터를 관리하는 허브-스포크 모델은 중앙 집중식 관리라는 명확한 장점이 있다. 모든 배포 상태를 한 곳에서 볼 수 있고, 정책도 일관되게 적용할 수 있다.
클러스터 등록하기
ArgoCD가 설치된 클러스터는 자동으로 in-cluster라는 이름으로 등록되어 있다. 외부 클러스터를 추가하려면 argocd cluster add 명령을 사용한다.
먼저 추가하려는 클러스터가 kubeconfig에 등록되어 있어야 한다. 현재 컨텍스트 목록을 확인하자.
kubectl config get-contexts
원하는 클러스터의 컨텍스트 이름을 확인했다면 ArgoCD CLI로 등록할 수 있다.
argocd cluster add staging-cluster-context
이 명령은 대상 클러스터에 argocd-manager라는 ServiceAccount를 생성하고, 필요한 RBAC 권한을 설정한 뒤, 해당 클러스터의 접속 정보를 ArgoCD의 Secret으로 저장한다. 등록된 클러스터 목록은 다음과 같이 확인할 수 있다.
argocd cluster list
출력은 대략 이런 모습이다.
SERVER NAME VERSION STATUS
https://kubernetes.default.svc in-cluster 1.28 Successful
https://10.0.1.100:6443 staging 1.28 Successful
https://10.0.2.100:6443 production 1.27 Successful
등록이 완료되면 Application을 만들 때 destination.server에 해당 클러스터의 API 서버 URL을, 또는 destination.name에 클러스터 이름을 지정하면 된다.
spec:
destination:
server: https://10.0.1.100:6443
namespace: my-app
또는 이름으로도 참조할 수 있다.
spec:
destination:
name: staging
namespace: my-app
이름 기반 참조가 URL보다 가독성이 좋고, 클러스터 API 서버 주소가 바뀌어도 Application 매니페스트를 수정할 필요가 없어서 실무에서는 이름 방식을 더 선호하는 편이다.
ApplicationSet이 필요한 이유
세 개의 환경(dev, staging, prod)에 같은 애플리케이션을 배포한다고 생각해보자. Application 리소스를 세 개 만들어야 하는데, 대부분의 내용이 동일하고 환경 이름과 클러스터 주소만 다르다. 이런 중복은 환경이 늘어날수록 관리 부담이 커진다.
ApplicationSet은 이 문제를 해결하기 위해 만들어졌다. 하나의 템플릿과 파라미터 소스(Generator)를 결합해서 여러 Application을 자동으로 생성한다. 새 환경이 추가되면 Generator의 목록에 한 줄만 넣으면 되니 확장성이 좋다.
ApplicationSet 컨트롤러는 ArgoCD 2.3부터 기본 포함되어 있으므로 별도 설치는 필요 없다.
List Generator — 가장 단순한 시작
List Generator는 파라미터 목록을 직접 정의하는 방식이다. 환경이 소수이고 명확할 때 쓰기 좋다.
세 개 환경에 동일한 애플리케이션을 배포하는 ApplicationSet을 작성해보자.
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: my-app-set
namespace: argocd
spec:
generators:
- list:
elements:
- cluster: dev
url: https://kubernetes.default.svc
namespace: my-app-dev
- cluster: staging
url: https://10.0.1.100:6443
namespace: my-app-staging
- cluster: production
url: https://10.0.2.100:6443
namespace: my-app-prod
template:
metadata:
name: "my-app-{{cluster}}"
spec:
project: default
source:
repoURL: https://github.com/my-org/my-app.git
targetRevision: main
path: "k8s/overlays/{{cluster}}"
destination:
server: "{{url}}"
namespace: "{{namespace}}"
syncPolicy:
automated:
prune: true
selfHeal: true
elements에 나열한 각 항목이 template의 {{변수명}}에 대입되어 Application이 생성된다. 결과적으로 my-app-dev, my-app-staging, my-app-prod 세 개의 Application이 만들어지는 셈이다.
직관적이라 이해하기 쉽지만, 환경이 수십 개로 늘어나면 목록 관리가 번거로워진다. 그럴 때는 Cluster Generator나 Git Generator를 쓰는 게 낫다.
Cluster Generator — 등록된 클러스터에서 자동 생성
Cluster Generator는 ArgoCD에 등록된 클러스터 정보를 자동으로 읽어서 Application을 만든다. 새 클러스터를 등록하면 Application이 알아서 생기고, 클러스터를 제거하면 Application도 사라진다.
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: monitoring-set
namespace: argocd
spec:
generators:
- clusters:
selector:
matchLabels:
env: production
template:
metadata:
name: "monitoring-{{name}}"
spec:
project: default
source:
repoURL: https://github.com/my-org/infra.git
targetRevision: main
path: monitoring/base
destination:
server: "{{server}}"
namespace: monitoring
syncPolicy:
automated:
prune: true
selfHeal: true
selector를 통해 특정 레이블이 붙은 클러스터에만 적용할 수 있다. 위 예시는 env: production 레이블이 있는 클러스터에만 모니터링 스택을 배포한다.
클러스터에 레이블을 붙이는 방법도 간단하다.
argocd cluster set staging --label env=staging
argocd cluster set production-us --label env=production --label region=us
argocd cluster set production-eu --label env=production --label region=eu
이렇게 해두면 env: production 클러스터가 추가될 때마다 모니터링이 자동으로 배포된다. 인프라 구성 요소처럼 모든 클러스터에 공통으로 깔아야 하는 것들에 특히 유용한 패턴이다.
Git Generator — 레포지토리 구조가 곧 설정
Git Generator는 Git 레포지토리의 디렉토리 구조나 파일 내용을 기반으로 Application을 생성한다. 레포에 디렉토리를 추가하면 Application이 생기고, 삭제하면 사라진다. 인프라 레포의 구조 자체가 배포 설정이 되는 방식이다.
두 가지 모드가 있다. 디렉토리 기반과 파일 기반이다.
디렉토리 기반은 특정 경로 아래의 디렉토리를 스캔한다. 아래와 같은 레포 구조가 있다고 해보자.
k8s/
├── apps/
│ ├── api-server/
│ │ ├── deployment.yaml
│ │ └── service.yaml
│ ├── web-frontend/
│ │ ├── deployment.yaml
│ │ └── service.yaml
│ └── worker/
│ ├── deployment.yaml
│ └── service.yaml
이 구조에서 각 서브 디렉토리마다 Application을 만들려면 다음과 같이 작성한다.
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: apps-set
namespace: argocd
spec:
generators:
- git:
repoURL: https://github.com/my-org/infra.git
revision: main
directories:
- path: k8s/apps/*
template:
metadata:
name: "{{path.basename}}"
spec:
project: default
source:
repoURL: https://github.com/my-org/infra.git
targetRevision: main
path: "{{path}}"
destination:
server: https://kubernetes.default.svc
namespace: "{{path.basename}}"
syncPolicy:
automated:
prune: true
selfHeal: true
{{path.basename}}은 디렉토리 이름(api-server, web-frontend, worker)이 되고, {{path}}는 전체 경로(k8s/apps/api-server 등)가 된다. 새 마이크로서비스를 추가할 때 디렉토리 하나만 만들면 배포가 자동으로 구성되는 셈이다.
파일 기반 모드는 JSON이나 YAML 파일에서 파라미터를 읽어온다. 더 세밀한 설정이 필요할 때 쓴다.
config/
├── api-server.json
├── web-frontend.json
└── worker.json
api-server.json의 내용이 다음과 같다면:
{
"appName": "api-server",
"namespace": "api",
"cluster": "https://kubernetes.default.svc",
"replicas": "3"
}
이 값들을 템플릿에서 참조할 수 있다.
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: apps-from-files
namespace: argocd
spec:
generators:
- git:
repoURL: https://github.com/my-org/infra.git
revision: main
files:
- path: config/*.json
template:
metadata:
name: "{{appName}}"
spec:
project: default
source:
repoURL: https://github.com/my-org/infra.git
targetRevision: main
path: "k8s/apps/{{appName}}"
destination:
server: "{{cluster}}"
namespace: "{{namespace}}"
syncPolicy:
automated:
prune: true
selfHeal: true
JSON 파일 하나가 Application 하나에 대응하니, 각 앱의 설정을 독립적으로 관리하면서도 템플릿은 하나로 유지할 수 있다.
Generator 조합하기
Generator는 단독으로도 강력하지만, 여러 개를 조합하면 더 복잡한 시나리오를 처리할 수 있다. Matrix Generator는 두 Generator의 결과를 교차(Cartesian product) 결합한다.
예를 들어 3개의 앱을 3개의 클러스터에 배포해야 한다면, 총 9개의 Application이 필요하다. Matrix Generator를 쓰면 이걸 간결하게 표현할 수 있다.
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: matrix-set
namespace: argocd
spec:
generators:
- matrix:
generators:
- git:
repoURL: https://github.com/my-org/infra.git
revision: main
directories:
- path: k8s/apps/*
- clusters:
selector:
matchLabels:
env: production
template:
metadata:
name: "{{path.basename}}-{{name}}"
spec:
project: default
source:
repoURL: https://github.com/my-org/infra.git
targetRevision: main
path: "{{path}}"
destination:
server: "{{server}}"
namespace: "{{path.basename}}"
syncPolicy:
automated:
prune: true
selfHeal: true
Git Generator가 앱 목록을 만들고, Cluster Generator가 클러스터 목록을 만들어서, 둘의 모든 조합에 대해 Application이 생성된다. 새 앱이나 새 클러스터가 추가되면 자동으로 확장되는 구조라 운영 부담이 크게 줄어든다.
여러 클러스터를 중앙에서 관리하고, ApplicationSet으로 반복 작업을 자동화하면 인프라 운영의 효율이 눈에 띄게 올라간다. 하지만 클러스터와 애플리케이션이 늘어나면 “누가 어디에 접근할 수 있는가”가 중요해진다. 다음 편에서는 ArgoCD의 RBAC 설정과 SSO 연동을 통해 팀 단위 접근 제어를 구성하는 방법을 알아본다.
Loading comments...