ArgoCD + GitHub Actions: Kubernetes 애플리케이션을 위한 완전한 GitOps CI/CD 워크플로우 🚀

ArgoCD, GitHub Actions, 그리고 Kubernetes를 활용한 실제 GitOps 워크플로우를 단계별로 살펴봅니다. :bullseye:

목표

  • 배포 파이프라인을 자동화하여 다음과 같은 과정을 구현하는 것입니다.
    • 애플리케이션은 GitHub Actions로 빌드됩니다. :gear:
    • Docker 이미지는 GitHub Container Registry(GHCR)에 푸시됩니다. :package:
    • ArgoCD는 GitOps 저장소에서 업데이트된 이미지 태그를 감지하고 Kubernetes 매니페스트를 자동으로 동기화합니다. :counterclockwise_arrows_button:

이 완전 자동화된 파이프라인은 일관성, 추적 가능성, 속도를 보장하며, 이는 현대 DevOps의 핵심 장점들입니다. :rocket:

아키텍처 개요

  • CI 파이프라인 (GitHub Actions)
    — 애플리케이션 빌드
    — Docker 이미지를 GHCR에 태그 후 푸시
    — GitOps 저장소에 이미지 태그 업데이트

  • GitOps 저장소
    — ArgoCD가 관리하는 Kubernetes 매니페스트 포함
    — ArgoCD 설정에 따라 변경 사항을 자동 또는 수동으로 Kubernetes에 동기화

  • ArgoCD
    — GitOps 저장소 모니터링
    — 원하는 상태(Git)와 실제 상태(Kubernetes)를 자동으로 맞춤

사전 준비사항

  • 실행 중인 Kubernetes 클러스터
  • 클러스터에 설치된 ArgoCD
  • 애플리케이션 코드용 GitHub 저장소 (CI repo)
  • Kubernetes 매니페스트용 별도 GitHub 저장소 (GitOps repo)
  • 활성화된 GitHub Container Registry
  • 로컬에 구성된 kubectl 및 ArgoCD CLI

먼저, 아래 저장소를 본인 GitHub 계정으로 클론하고 비공개로 설정하세요. :locked:

  • argocd-app
  • [argocd-deploy](https://github.com/mehmetkanus17/argocd-deploy)

이 저장소들은 각각 애플리케이션 소스 코드와 GitOps 배포 매니페스트를 담고 있습니다. :laptop::open_file_folder:

1단계 — Helm을 사용해 Kubernetes 클러스터에 ArgoCD 설치하기 :hammer_and_wrench:

먼저, 기존 Kubernetes 클러스터에 공식 Helm 차트를 이용해 ArgoCD를 배포합니다.
이 작업은 Git 저장소와 클러스터 간의 상태를 지속적으로 동기화하는 GitOps 컨트롤러를 설정합니다.

#!/bin/bash

helm repo add argo https://argoproj.github.io/argo-helm
helm repo update

kubectl create namespace argocd

# argocd-values.yaml
configs:
  cm:
    admin.enabled: true # -- Enable local admin user
    timeout.reconciliation: 15s # -- Timeout to discover if a new manifests version got published to the repository
    timeout.hard.reconciliation: 0s # -- Timeout to refresh application data as well as target manifests cache

helm upgrade --install argocd argo/argo-cd \
  --namespace argocd -f argocd-values.yaml

# We are setting configs.cm.timeout.reconciliation to 15s
# to reduce the default reconciliation interval (which is 180 seconds) 
# and allow ArgoCD to detect and apply changes more quickly.
# This value is configurable based on your desired sync frequency.

2단계 — ArgoCD 대시보드 접속 및 애플리케이션 저장소 등록하기 :globe_with_meridians:

ArgoCD 서버 서비스를 포트 포워딩하여 대시보드에 접속할 수 있습니다.

참고: 아래 명령어를 사용해 ArgoCD 관리자 비밀번호를 직접 설정하거나 업데이트할 수도 있습니다. :key:

htpasswd -nbBC 10 "" "yourNewPassword" | tr -d ':\n' | sed 's/$2y/$2a/'


kubectl -n argocd patch secret argocd-secret \
  -p '{"stringData": {
    "admin.password": "$2a$10$1p3WDFDfgfhdfnJQ0xJwahav.nLgZxDOzrJqnK.P0/rxgAoyQFJ3/rWa",
    "admin.passwordMtime": "'$(date +%FT%T%Z)'"
  }}'

kubectl -n argocd rollout restart deployment argocd-server

그 다음, 브라우저를 열고 아래 주소로 이동합니다. :globe_with_meridians:

:backhand_index_pointing_right: https://localhost:8080

로그인한 뒤에는, 제가 앞서 언급했던 “이전 글”의 단계들을 따라 애플리케이션 저장소를 연결하고, GitOps 배포 매니페스트를 가리키는 새로운 ArgoCD 애플리케이션을 생성합니다. :open_file_folder::sparkles:

이 단계가 완료되면 ArgoCD는 매니페스트를 지속적으로 모니터링하며, 업데이트 내용을 Kubernetes 클러스터에 자동으로 동기화하게 됩니다. :counterclockwise_arrows_button::cloud:

3단계 — GitHub Actions 워크플로 파일 알아보기 :gear:

이 단계에서는 메인 브랜치에 변경 사항이 푸시될 때마다 Docker 이미지를 빌드하고 GitHub Container Registry(GHCR)로 푸시하는 CI 워크플로를 정의합니다. 이는 애플리케이션을 지속적으로 통합하고 컨테이너화하는 GitOps 파이프라인의 첫 번째 부분입니다. :rocket:

아래는 워크플로 파일의 기본 구조에 대한 개요입니다. :page_facing_up::sparkles:

name: ArgoCD App

on:
  push:
    branches:
      - main
  # pull_request:
  #   branches:
  #     - main

env:
  IMAGE_NAME: ghcr.io/${{ github.repository }}/app
  GITOPS_REPO: mkanus/argocd-deploy

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source code
        uses: actions/checkout@v3

      - name: Log in to GitHub Container Registry
        uses: docker/login-action@v2
        with:
          registry: ghcr.io
          username: ${{ github.repository_owner }}
          password: ${{ secrets.CR_PAT }}

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2

      - name: Build and push Docker image
        uses: docker/build-push-action@v4
        with:
          context: .
          push: true
          tags: |
            ${{ env.IMAGE_NAME }}:latest
            ${{ env.IMAGE_NAME }}:${{ github.sha }}

      - name: Update GitOps deployment repo
        run: |
          git clone https://${{ secrets.GITOPS_PAT }}@github.com/${{ env.GITOPS_REPO }} gitops
          cd gitops
          
          # Update the manifest with the latest image tag
          export IMAGE_NAME="${{ env.IMAGE_NAME }}"
          export TAG="${{ github.sha }}"

          sed -i "s|image: ${IMAGE_NAME}:.*|image: ${IMAGE_NAME}:${TAG}|g" deployment.yaml

          # Git Commit and Push Steps
          git config user.name "GitHub Actions"
          git config user.email "actions@github.com"

          git add deployment.yaml
          git commit -m "Update image to ${{ github.sha }}"
          git push origin main

비공개 애플리케이션 저장소에서 Settings > Secrets and variables > Actions 경로로 이동한 뒤, 다음 시크릿 환경 변수를 추가합니다. :locked_with_key:

  • CR_PAT
  • GITOPS_PAT

이 시크릿 값에는 필요한 권한을 가진 Personal Access Token(PAT)을 직접 생성하여 할당할 수 있습니다. :key:

4단계 — 애플리케이션 네임스페이스에 ImagePullSecret 생성하기 :key:

저장소가 비공개이므로, GitHub Container Registry(GHCR)에 푸시된 컨테이너 이미지도 기본적으로 비공개 상태입니다. Kubernetes가 해당 이미지를 가져올 수 있도록, 애플리케이션 네임스페이스에 docker-registry 타입 시크릿을 생성해야 합니다.

5단계 — 비공개 argocd-app 저장소에서 CI 파이프라인 실행하기 :gear:

이제 비공개 argocd-app 저장소에서 CI 파이프라인을 실행합니다.
이 과정에서 GitHub Actions 워크플로가 시작되고, Docker 이미지를 빌드하여 GHCR로 푸시한 뒤, GitOps 저장소의 이미지 태그를 업데이트하게 됩니다. :rocket:

[출처] https://medium.com/@mehmetkanus17/argocd-github-actions-a-complete-gitops-ci-cd-workflow-for-kubernetes-applications-ed2f91d37641

1 Like