본문 바로가기
서버/Azure

[Azure] AKS ACR과 ArgoCD GitOps 배포 (feat 불변 태그 전략)

by jamong1014 2025. 9. 5.
반응형

아키텍처 구성

불변 태그 전략 적용 ArgoCD GitOps

 


* 웹 소스 코드 구성

from flask import Flask, jsonify
import os

app = Flask(__name__)

@app.get("/")
def root():
    return "hello from jamong1014125"

@app.get("/healthz")
def health():
    return jsonify(status="ok", version=os.getenv("GIT_SHA", "dev"))

if __name__ == "__main__":
    port = int(os.getenv("PORT", "8000"))
    app.run(host="0.0.0.0", port=port)
  • 간단하게 Python Flask로 빌드하여 배포할 수 있도록 소스 구성 (backend/main.py)

 

FROM python:3.12-slim

WORKDIR /app

ARG GIT_SHA=dev
ENV GIT_SHA=${GIT_SHA}
ENV PORT=80

# 필요 패키지만 설치
COPY backend/requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 앱 소스
COPY backend/ .

EXPOSE 80

# 경량 WSGI 서버(gunicorn)로 실행 (PORT 환경변수 사용)
CMD ["python", "-m", "gunicorn", "-w", "2", "-b", "0.0.0.0:80", "main:app"]
  • Dockerfile 통해서 이미지 빌드

1. workflows/build-acr.yml 작성

name: build-and-push-to-acr

on:
  push:
    branches: [ "main" ]
  workflow_dispatch:

env:
  IMAGE: ${{ vars.ACR_LOGIN_SERVER }}/backendweb   # jamong1014.azurecr.io/backendweb

permissions:
  contents: write   # Git 커밋/푸시하려면 필요

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: ACR Docker Login (admin creds)
        uses: azure/docker-login@v1
        with:
          login-server: ${{ vars.ACR_LOGIN_SERVER }}     # jamong1014.azurecr.io
          username: ${{ secrets.ACR_USERNAME }}
          password: ${{ secrets.ACR_PASSWORD }}

      - name: Build image
        run: |
          echo "Building image..."
          docker build -t $IMAGE:latest -t $IMAGE:${{ github.sha }} .

      - name: Push image
        run: |
          echo "Pushing image to ACR..."
          docker push $IMAGE:latest
          docker push $IMAGE:${{ github.sha }}

      - name: Show pushed tags
        run: |
          echo "Pushed:"
          echo " - $IMAGE:latest"
          echo " - $IMAGE:${{ github.sha }}"

      # ===== 여기부터 GitOps 매니페스트에 새 태그 반영 =====
      - name: Install kustomize  # kustomize 설치
        uses: imranismail/setup-kustomize@v2
        with:
          kustomize-version: '5.4.1'

      - name: Update manifests with new image tag  # 태그 주입 + 커밋/푸시
        run: |
          cd manifests/backend
          # kustomization.yaml 반드시 존재해야 함
          kustomize edit set image jamong1014.azurecr.io/backendweb=${{ env.IMAGE }}:${{ github.sha }}

          git config user.name "github-actions"
          git config user.email "actions@github.com"
          git add kustomization.yaml
          git commit -m "deploy backendweb ${{ github.sha }}" || echo "No changes to commit"
          git push
  • ACR_LOGIN_SERVER와 ACR_USERNAME은 각각 Repository secrets, Repository variables을 사용
  • kustomize edit을 통해 불변 태그 전략 적용 (트러블 슈팅 부분에서 자세히 다룸)

2. AKS에 ArgoCD 설치

# 네임스페이스 생성
kubectl create namespace argocd

# 공식 매니페스트로 설치
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
  • 설치 후 Pod 상태 확인
kubectl -n argocd get pods

 

1. argocd-application-controller

  • Git 리포와 kubernetes 클러스트를 동기화하는 실행 엔진
  • 차이를 감지하고 sync 동작을 수행

2. argocd-applicationset-controller

  • ApplicationSet CRD를 관리
  • 다수의 애플리케이션을 템플릿 기반으로 자동 생성

3. argocd-dex-server

  • 인증 담당
  • 기본 admin 계정 로그인도 여길 거침

4. argocd-notifications-controller

  • 알림 기능 담당
  • 동기화 성공/실패, 배포 에러 등을 Slack, Email, Webhook으로 알림
  • 원하는 이벤트를 트리거로 알림 규칙 작성 가능

5. argocd-redis

  • 캐시 DB
  • ArgoCD가 Git 리포 상태, 클러스터 상태를 매번 풀 스캔하지 않도록 빠른 조회용 캐시

6. argocd-repo-server

  • Git 리포지토리에서 매니페스트를 렌더링

7. argocd-server

  • API 서버 + 웹 UI
  • argocd CLI와 웹 대시보드가 연결되는 게이트웨이

3. Argo CD 접속 및 로그인

kubectl -n argocd port-forward deploy/argocd-server 8081:8080 >/dev/null 2>&1 &
  • 기본적으로 ArgoCD 공식 설치 매니페스트가 agrocd-server 컨테이너를 8080에서 가동되도록 정의해 둠
  • 그 위에 서비스는 80/443으로 얹어주는 형태

 

 argocd login localhost:8081 --username admin --password "$NEWPASS" --plaintext
  • 로그인 하는 과정에 있어서 argocd-server가 강제로 HTTPS로 리다이렉트 해서 인증서 경고가 나와 멈추는 현상이 발생

 

# 1) 서버를 insecure 모드로 설정
kubectl -n argocd patch configmap argocd-cmd-params-cm --type merge \
  -p '{"data":{"server.insecure":"true"}}'

# 2) 서버 롤아웃 재시작
kubectl -n argocd rollout restart deploy/argocd-server
kubectl -n argocd rollout status deploy/argocd-server
  • 서버를 Insecure(HTTP) 모드로 전환

 

# 기존 포워딩 종료 후, 8080 → 로컬 8081로 포워딩 (HTTP)
ps -ef | grep 'port-forward .*argocd-server' | grep -v grep | awk '{print $2}' | xargs -r kill
kubectl -n argocd port-forward deploy/argocd-server 8081:8080 >/dev/null 2>&1 &

# 평문으로 로그인 (URL 스킴 없이 host:port 형식)
argocd login localhost:8081 \
  --username admin \
  --password "$NEWPASS" \
  --plaintext
  • 이후 다시 포워딩 + 로그인 진행

 

로그인 성공 결과


4. ACR 권한 연결

az aks update -n <aks-cluster-name> -g <resource-group> --attach-acr <acr-name>

5. deploy.yaml와 kustomization.yaml 작성

apiVersion: apps/v1
kind: Deployment
metadata:
  name: backendweb
  namespace: demo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: backendweb
  template:
    metadata:
      labels:
        app: backendweb
    spec:
      containers:
      - name: backendweb
        image: jamong1014.azurecr.io/backendweb   # 태그 없음
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: backendweb
  namespace: demo
spec:
  type: LoadBalancer
  selector:
    app: backendweb
  ports:
  - port: 80
    targetPort: 80
  • deploy.yaml 작성

 

resources:
- deploy.yaml

images:
- name: jamong1014.azurecr.io/backendweb
  newName: jamong1014.azurecr.io/backendweb
  newTag: REPLACED_BY_CI   # GitHub Actions이 여기 SHA로 바꿈

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
  • kustomization.yaml

6. ArgoCD 애플리케이션 생성

argocd app create backendweb \
  --repo https://github.com/<username>/<repo>.git \
  --path manifests/backend \
  --dest-server https://kubernetes.default.svc \
  --dest-namespace demo \
  --sync-policy automated --self-heal --auto-prune \
  --sync-option CreateNamespace=true

 

argocd app get backendweb
  • 동기화 상태 확인

 

동기화 상태

 

kubectl -n demo get pods,svc
  • pods, svc 상태 확인

현재 상태


결과

위에 이미지에선 replicas가 2개인 상태

4개로 변경

 

2~3분 후 포드가 4개로 올라온것을 확인


트러블 슈팅

  • 현재 아키텍처에서 ArgoCD가 deploy.yaml(코드 변경)을 참조하여 AKS 클러스터 동기화가 이루어짐
  • 하지만 image: jamong1014.azurecr.io/backendweb:latest 형식으로 구성하게 되면 새로운 내용으로 이미지를 ACR에 푸쉬했을 때 코드에서 태그는 변함없이 똑같기 때문에 변경된 이미지의 태그로 직접 수정하지 않은 이상 바뀌지 않음
  • 그렇기에 kustomize을 통해 불변 태그 전략을 적용 (매니페스트 재사용과 커스마이징을 쉽게 해주는 도구)
  • Git 리포에 Push 했을 때 워크플로우가 jamong1014.azurecr.io/backendweb:${GITHUB_SHA} 태그로 ACR에 푸쉬
  • kustomize edit set image을 실행해서 이번 빌드 SHA로 업데이트
  • 워크플로우가 Git 리포 안에서 봇이 수정한 kustomization.yaml을 다시 git push함
  • kustomization.yaml(deploy.yaml 참조) 또한 ArgoCD의 Gitops 경로 안에 있기 때문에 내용이 바뀐걸 감지
  • 새 이미지 태그(:${SHA})로 Deployment 매니페스트를 다시 렌더링
  • 최종적으로 kustomize가 deploy.yaml을 읽어서 image: jamong1014.azurecr.io/backendweb:0e7ca40822d51f4630dedf5fdc0ccfdb62a0353e
    이런식으로 치환하여 ArgoCD가 배포함
반응형