Pipeline

“Helm + ArgoCD + ApplicationSet으로 구축하는 PR Preview 환경 (3편: Preview 환경 배포하기)”

황동리 2025. 9. 16. 17:23
반응형

“Helm + ArgoCD + ApplicationSet으로 구축하는 PR Preview 환경 (1편: 아키텍처)”
“Helm + ArgoCD + ApplicationSet으로 구축하는 PR Preview 환경 (2편: Helm 차트 구성)”


앞선 글과 이어지는 내용 입니다.


3편 글에서는 Helm 차트로 만들어준 Preview 환경을 PR이 발생하였을 때, 어떻게 만들어지는지 설명해보겠습니다.


Github에서 PR이 발생하면 Argo ApplicationSet 리소스가 해당 PR을 감지하고 Helm 차트를 배포 하는 방식으로 진행 해보겠습니다.

Argo ApplicationSet 이란 ?

ArgoCD의 Application을 자동화해서 관리할 수 있도록 도와주는 컨트롤러 리소스 입니다.


Prview 환경에서 Application 리소스가 아닌, ApplicationSet 리소스를 사용하는 이유는,


Preview 환경은 보통 이런 요구사항을 가집니다:

1.    PR 마다 새로운 환경이 필요 → 예: pr-123.myapp.dev.company.com
2.    PR이 닫히면 환경 삭제
3.    공통 템플릿은 유지하면서, PR 번호에 따라 환경이 달라짐

👉 이런 상황에는 동적인 Application 생성이 필요합니다.

•    Application은 정적인 YAML이라 PR마다 새로 쓰기엔 비효율적
•    ApplicationSet의 Pull Request Generator를 쓰면
→ GitHub/GitLab PR을 감지해서 자동으로 Application 생성
→ PR이 닫히면 자동 삭제

따라서, PR마다 새로운 동적 환경이 자동으로 생성·삭제되어야 하므로, 정적인 Application 대신 동적 생성을 지원하는 ApplicationSet을 사용하였습니다.

이제 ApplicationSet 리소스를 어떻게 정의하고 사용했는지 알아보겠습니다.

ApplicationSet 리소스 정의

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: pr-generator
  namespace: argocd
spec:
  generators:
    - pullRequest:
        github:
          owner: Suhan-Powertask  # ← 조직/유저
          repo: pr-test # ← 레포지토리 이름
          tokenRef:
            secretName: gh-token # ← 레포지토리에 접근 할 수 있도록 github-token 값을 가지고 있는 secret 이름
            key: token # ← Secret에 저장해둔 github-token value의 key 이름
        requeueAfterSeconds: 30
  template:
    metadata:
      name: outcode-pr-{{number}}
      finalizers: # ← ApplicationSet이 생성한 Application 이 삭제될 때, 단순히 Kubernetes의 Application 리소스만 지우는 게 아니라
👉 그 Application이 관리하고 있던 하위 Kubernetes 리소스(Namespace) 도 같이 정리(prune)하도록 하는 역할
        - resources-finalizer.argocd.argoproj.io 
    spec:
      project: dev
      destination:
        server: https://kubernetes.default.svc
        namespace: pr-{{number}}
      syncPolicy:
        automated:
          prune: true
          selfHeal: true
        syncOptions:
        - CreateNamespace=true
      source:
        chart: <Helm 차트>
        repoURL: <ECR 주소>
        targetRevision: <Helm 차트의 버전>   # ← 차트 버전 고정. 템플릿 바뀔 때만 갱신
        path: . # ← OCI 차트는 항상 .
        helm:
          valueFiles:
            - values.yaml # 이 파일을 차트 패키지 내부에 있어야 함
          parameters: # ← 여기서부터 values.yaml 파일을 내용을 동적으로 수정을 해줍니다.
            - name: components.front.tag
              value: "fe-260"  # ← front 이미지를 빌드/배포 할 때 마다 이미지 태그 값을 values.yaml 파일에서 변경하지 않고 여기서 바꿔주어 적용을 시킵니다.

ApplicationSet 리소스의 설명은 주석에 해두었습니다.


간략하게 정리를 하자면,

Github 레포에서 PR이 발생하면 위 ApplicationSet 리소스가 PR 감지를 하여 ECR에 있는 Helm 차트의 변수를 동적으로 변경 시킨 후 배포를 합니다.

이제 ArgoCD가 ECR 레포에 접근 할 수 있도록 Repository 에 등록 시켜주면 됩니다.


ArgoCD Repository에 ECR 등록

먼저 AWS ECR에서 get-login-password 혹은 GetAuthorizationToken 을 통해 발급되는 인증 토큰(비밀번호)은 12시간(valid for 12 hours)만 유효 합니다.


따라서 저는 ArgoCD의 RepoServer.serviceAccount 가 ECR에 접근할 수 있도록 역할을 생성해주었습니다.

역할 생성 후 serviceAccount의 annotation에 등록

ID 제공업체는 EKS의 OIDC로 선택해주면 됩니다.


그리고 AmazonEC2ContainerRegistryPullOnlyAmazonEC2ContainerRegistryReadOnly 두 정책을 역할에 넣어주었습니다.


그리고 저는 ArgoCD를 Helm 차트로 설치를 했었어서 values.yaml 파일에서 아래와 같이 수정 해주었습니다.

repoServer:
    serviceAccount:
        annotations:
            eks.amazonaws.com/role-arn: <앞서 생성한 역할의 ARN>

그리고 ArgoCD UI에서 Repository 등록 아래 이미지와 같이 설정을 해서 등록하였습니다.


동작 확인

이제 PR을 발생시켜서 실제로 어플리케이션들이 생성이 되는지 확인해보겠습니다.


PR을 Merge하면 생성된 리소스들과 네임스페이스까지 모든게 다 사라지게 됩니다.


이렇게 3편에 걸쳐, Preview 환경을 만들어보는 작업을 해보았습니다.


처음 해보는 작업이여서 처음엔 감도 안오고, 지금도 이렇게 생성을 하는게 맞나 싶기도 합니다.


"이 사람은 이러한 방식으로 작업을 Preview 환경을 생성했구나" 라고 생각 하고 봐주시면 될 듯 합니다.


혹여 이 글을 보고 다른 방법으로 Preview 환경을 만든 경험이 계신 분은 댓글 달아주시면 감사하겠습니다.


감사합니다.

반응형