Cloud Tech

Gitops Bridge를 통한 멀티클러스터 구성 자동화

Hanhorang31 2024. 3. 9. 16:46
 

 

Overview

멀티 EKS 클러스터를 편리하게 구성할 수 있는 방법을 찾아보는 중 Gitops Bridge이라는 프로젝트가 있어 테스트하고 정리한 글을 공유합니다.

 

멀티클러스터 구성 자동화

프로젝트를 확인하기 전, 멀티 EKS 구성 자동화의 필요성을 정리하겠습니다.

필자는 아래 단계대로 EKS 및 테스트 환경 구성합니다.

 

  1. EKS Cluster : eksctl 이나 Terraform를 통해 구성
  2. EKS addons : 필요 IAM 정책 생성 및 Helm chart를 통해 구성
  3. Application Workload : addon 에 따라 yaml 구성하여 배포

 

지금와서 생각해보면 테라폼을 통해 전부 구성하면 되는 거 아니야? 라고 생각할 수 있지만, 작년 기준으로 Terraform 의 yaml와 helm 모듈이 통일화되지 않고 형상관리가 어려움이 있었습니다. 필자는 테스트할 때마다 위 과정을 반복해서 테스트 환경을 구성했습니다. 단일클러스터의 경우라면 반복작업 한 번으로 감수할 수 있다고 생각했지만, 멀티클러스터 구성은 피로감이 들어 자동화 도구를 찾기 시작했습니다.

 

GitOps Bridge ?

GitOps Bridge는 Kubernetes 클러스터 생성 프로세스와 이후 GitOps를 통해 모든 것을 관리하는 프로세스를 연결하기 위한 모범 사례와 패턴을 보여주는 것을 목표로 하는 프로젝트입니다. 쉽게 말하자면 테라폼(IaC)를 통해 인프라를 구성하고, 저장된 메타데이터(git repo URL)에 따라 Kubernetes 애드온 및 애플리케이션을 자동으로 배포하고 관리할 수 있게 됩니다.

위 프로젝트를 활용하면 멀티클러스터 관리에 사용 할 수 있습니다. 깃 멀티프로젝트에서는 예제로 관리 클러스터(hub: control-plan)에서 ArgoCD를 통해 대상 클러스터에 대해 addons과 workloads를 관리하는 방법을 제공하고 있습니다.

말로는 어려우니 테스트를 먼저 진행하여 기능을 이해하겠습니다.

 

테스트

구성 이해를 위해 hub(관리) 클러스터를 배포하고 구성 확인 후 spkoe(원격) 클러스터를 배포하겠습니다.

관리 클러스터 배포

cd hub 

terraform init 
terraform apply -target="module.vpc" -auto-approve
terraform apply -target="module.eks" -auto-approve
terraform apply -auto-approve

약 20분 후 클러스터 및 addon 이 배포됩니다. 구성 파드를 보면 Argocd를 확인할 수 있습니다.

처음 ArgoCD UI를 확인하면 아무것도 없는 것을 확인할 수 있는데요.

 

아래 명령어를 통해 관리 클러스터 및 원격 클러스터의 추가 구성 addon을 배포하겠습니다.

 

kubectl --context hub apply -n argocd -f ../hub/bootstrap/addons.yaml

 

명령어를 실행하면 수분내로 addon들이 배포됨을 알 수 있습니다. 구성을 확인하면 cluster-addons을 통해 addons(aws-argocd, aws-load-balancer-controller, metrics-server)가 배포됩니다. 구성 addon은 테라폼(hub/local.tf)을 통해 선택하여 구성할 수 있습니다.

인상적인 것은 기존의 테라폼에서 addon 배포 방법인 헬름 차트 구성과 변수 선언이 필요했던 것을 단순 true로 구성할 수 있다는 점인데요. 구성 원리는 하단에서 다루겠습니다.

 

 

Remote Cluster 구성

이어서 원격 클러스터를 배포하겠습니다.

예제에서는 3개 클러스터를 구성하지만, 비용적인 문제로 dev 클러스터만 배포하겠습니다.

cd ../spokes
./deploy.sh dev

배포는 20분정도 소요됩니다. 아래 명령어로 spoke 클러스터로 스위칭하고 파드를 확인하면 관리 클러스터에서 설정한 addon이 그대로 배포됨을 확인할 수 있습니다.

 

aws eks --region ap-northeast-2 update-kubeconfig --name spoke-dev --alias dev

 

관리클러스터 ArgoCD UI로 돌아가서 확인하면 dev 환경의 클러스터 addon이 싱크되어 배포됨을 확인할 수 있습니다.

이어서 원격클러스터의 워크로드 애플리케이션을 배포하겠습니다. 배포 명령어는 아래와 같습니다.

 

kubectl --context hub apply -n argocd -f ../hub/bootstrap/workloads.yaml

배포한 워크로드는 addon과 마찬가지로 테라폼 변수에서 확인 가능합니다.

  • 워크로드는 원격 클러스터에서만 배포되었습니다. 배포 대상 설정은 아래 하단 동작 원리 이해를 참고하시면 됩니다.

 

위 예제 워크로드는 helm chart로 되어있어 배포되지만, 단순 yaml 도 배포가 가능합니다. 아래와 같이 테라폼 변수를 수정하여 게임 예제 2048.yaml를 배포할 수 있습니다.

# variables.tf
# Workloads Git
variable "gitops_workload_org" {
  description = "Git repository org/user contains for workload"
  type        = string
  default     = "https://github.com/aws-ia"
}
variable "gitops_workload_repo" {
  description = "Git repository contains for workload"
  type        = string
  default     = "terraform-aws-eks-blueprints"
}
variable "gitops_workload_revision" {
  description = "Git repository revision/branch/ref for workload"
  type        = string
  default     = "main"
}
variable "gitops_workload_basepath" {
  description = "Git repository base path for workload"
  type        = string
  default     = "patterns/gitops/"
}
variable "gitops_workload_path" {
  description = "Git repository path for workload"
  type        = string
  default     = "getting-started-argocd/k8s"
}

위 경로 Repo에는 게임 2048 메니페스트 파일이 있습니다.

 

동작 원리 이해

동작 원리를 확인하겠습니다. 위 테스트 단계에서 원격 클러스터 addon은 아래 명령어를 통해 구성되었습니다.

kubectl --context hub apply -n argocd -f ../hub/bootstrap/addons.yaml

../hub/bootstrap/addons.yaml 내용은 아래와 같습니다. 내용을 살펴보면 ArgoCD CRD인 Applicationset 가 사용되었습니다.

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: cluster-addons
  namespace: argocd
spec:
  syncPolicy:
    preserveResourcesOnDeletion: true
  generators:
    - clusters:
        selector:
          matchExpressions:
            - key: akuity.io/argo-cd-cluster-name
              operator: NotIn
              values: [in-cluster]
  template:
    metadata:
      name: cluster-addons
    spec:
      project: default
      source:
        repoURL: '{{metadata.annotations.addons_repo_url}}'
        path: '{{metadata.annotations.addons_repo_basepath}}{{metadata.annotations.addons_repo_path}}'
        targetRevision: '{{metadata.annotations.addons_repo_revision}}'
        directory:
          recurse: true
          exclude: exclude/*
      destination:
        namespace: 'argocd'
        name: '{{name}}'
      syncPolicy:
        automated: {}

ArgoCD Applicationset는 spec에서 3가지로 분류되어 정의됩니다.

  • syncPolicy: ArgoCD 동기화 정책을 정의합니다. 위 preserveResourcesOnDeletion: true 정책은 ApplicationSet에서 관리하는 애플리케이션을 삭제할 때, 해당 리소스를 보존하도록 설정합니다.
  • generators: 애플리케이션 세트의 대상 클러스터를 결정하는 데 사용되는 로직을 정의합니다. 여기서는 clusters 타입의 생성기가 사용되며, 특정 레이블(akuity.io/argo-cd-cluster-name)이 in-cluster에 해당하지 않는 클러스터들을 대상으로 합니다.
  • template: 각 클러스터에 배포될 애플리케이션의 템플릿을 정의합니다. 이 템플릿은 프로젝트 설정, 소스 리포지토리 정보(레포 URL, 경로, 리비전), 배포 목적지(클러스터와 네임스페이스) 및 동기화 정책을 포함합니다. 위 메타데이터 변수는 테라폼 파일에서 정의되어 ArgoCD Secret으로 배포됩니다.

 

아래 명령어를 통해 ArgoCD Secret을 확인하면 어떤 차트를 배포하고 어떤 addon을 배포할 것인지 알 수 있습니다. 먼저 annotation 값에는 애드온의 Helm 차트 및 ArgoCD ApplicationSet에 대한 메타데이터가 포함되어 있습니다.

kubectl get secret -n argocd -l argocd.argoproj.io/secret-type=cluster -o json | jq '.items[0].metadata.annotations'

라벨에는 구성 addon 확인할 수 있습니다.

kubectl get secret -n argocd -l argocd.argoproj.io/secret-type=cluster -o json | jq '.items[0].metadata.labels' | grep -v false | jq .

눈치채셨나요? ArgoCD Secret Label 값을 수정하면 클러스터를 운영 중에 addon을 변경할 수 있습니다.

배포 이후에는 수정이 불가능합니다.. ㅠㅠ

 

addon_repo_url을 따라가면, 구성 addon 리스트를 확인할 수 있습니다. 아래 cloudwatch metrics을 보면, applicationset을 통해 또 한 번(…) 감싸져있는 것을 확인할 수 있습니다.

  • 헬름 차트는 디렉토리 add-ons/ 에서, value 는 디렉토리 environments/ 에서 확인할 수 있습니다.

 

위 차트를 기반으로 테라폼에서 변수(true, false)를 통해 쉽게 addon을 구성할 수 있게 됩니다.

 

 

워크로드 예제로 배포했던 명령어도 확인해보면 아래 applicationset 코드로 구성되어 있습니다. addon과 별반 다를 것 없지만 차이점으로 대상 클러스터를 원격클러스터만 지정한 점과 구성 템플릿이 다른 것이 있겠습니다.

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: workloads
  namespace: argocd
spec:
  syncPolicy:
    preserveResourcesOnDeletion: false
  generators:
    - clusters:
        selector:
          matchExpressions:
            - key: environment
              operator: NotIn
              values: [control-plane]
  template:
    metadata:
      name: 'workload-{{metadata.labels.environment}}'
    spec:
      project: default
      source:
        repoURL: '{{metadata.annotations.workload_repo_url}}'
        path: '{{metadata.annotations.workload_repo_basepath}}{{metadata.annotations.workload_repo_path}}'
        targetRevision: '{{metadata.annotations.workload_repo_revision}}'
      destination:
        namespace: 'workload'
        name: '{{name}}'
      syncPolicy:
        automated: {}
        syncOptions:
          - CreateNamespace=true

 

 

리소스 삭제

구성했던 클러스터 삭제는 구성 폴더에서 아래 명령어를 실행하시면 됩니다.

# 관리 클러스터 삭제
cd hub
./destory

# 원격 클러스터 삭제
cd spoke
./destory dev