모험가

AEWS 8주차 - K8S CI/CD(ArgoCD in k8s) 본문

쿠버네티스/AEWS

AEWS 8주차 - K8S CI/CD(ArgoCD in k8s)

라리음 2025. 3. 28. 16:13
본 글은 가시다님이 진행하시는 AEWS(AWS EKS Workshop Study)를 참여하여 정리한 글입니다. 
모르는 부분이 많아서 틀린 내용이 있다면 말씀 부탁드리겠습니다!

 

 

 

 

 


Argo CD + k8s(kind)

 

 

ArgoCD란?

ArgoCD는 쿠버네티스를 위한 선언적 GitOps 지속적 배포(CD) 도구로, Git 저장소를 사용하여 애플리케이션 정의와 구성을 관리합니다. 클러스터의 실제 상태와 Git 저장소의 상태를 자동으로 동기화하며, 직관적인 웹 UI를 통해 배포 상태를 모니터링할 수 있습니다. 인프라의 코드화와 자동화된 배포 프로세스를 통해 운영 효율성을 높이고, 여러 쿠버네티스 클러스터를 중앙에서 효율적으로 관리할 수 있습니다.

[출처] https://argo-cd.readthedocs.io/en/stable/

 

API Server : Web UI 대시보드, k8s api 처럼 API 서버 역할

Repository Server : Git 연결 및 배포할 yaml 생성

Application Controller : k8s 리소스 모니터링, Git과 비교

Redis : k8s api와 git 요청을 줄이기 위한 캐싱

Notification : 이벤트 알림, 트리거

Dex : 외부 인증 관리

ApplicationSet Controller : 멀티 클러스터를 위한 App 패키징 관리

 

[출처] https://argo-cd.readthedocs.io/en/stable/developer-guide/architecture/components/

 

 

ArgoCD 설치

# 네임스페이스 생성 및 파라미터 파일 작성
cd cicd-labs

kubectl create ns argocd
cat <<EOF > argocd-values.yaml
dex:
  enabled: false

server:
  service:
    type: NodePort
    nodePortHttps: 30002
  extraArgs:
    - --insecure  # HTTPS 대신 HTTP 사용
EOF

# 설치
helm repo add argo https://argoproj.github.io/argo-helm
helm install argocd argo/argo-cd --version 7.8.13 -f argocd-values.yaml --namespace argocd # 7.7.10

# 확인
kubectl get pod,svc,ep,secret,cm -n argocd

 

초기 비번 확인 후 admin으로 로그인

# 최초 접속 암호 확인
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d ;echo
XxJMMJUv8MHZa-kk

# Argo CD 웹 접속 주소 확인 : 초기 암호 입력 (admin 계정)
open "http://127.0.0.1:30002" # macOS
# Windows OS경우 직접 웹 브라우저에서 http://127.0.0.1:30002 접속

 

User info → UPDATE PASSWORD 로 admin 계정 암호 변경 (qwe12345)

 

 

ops-deploy Repo 등록

- connection method : VIA HTTPS
- Type : git
- Project : default
- Repo URL : `http://***<자신의 집 IP>***:3000/devops/ops-deploy`  [http://192.168.254.127:3000/devops/ops-deploy](http://192.168.254.124:3000/devops/ops-deploy)
    - ***Windows (WSL2) 사용자는 자신의 WSL2 Ubuntu eth0 IP***
- Username : devops
- Password : ***<Gogs 토큰>***

 

 

 

 

ArgoCD를 선언형으로 사용하겠습니다.

ArgoCD Declarative Setup - Project, applications(ArgoCD App 자체를 yaml로 생성)

 

[출처] https://kubernetes.io/blog/2021/05/14/using-finalizers-to-control-deletion/

 

 

  • ArgoCD Finalizers의 목적
    1. 리소스 정리 보장: 애플리케이션 삭제 시 관련 리소스가 남지 않도록 보장합니다. 이는 GitOps 워크플로우에서 선언적 상태를 유지하는 데 중요합니다.
    2. 의도치 않은 삭제 방지: finalizer가 없으면 실수로 Argo App을 삭제해도 K8S 리소스가 남아 혼란이 생길 수 있습니다. finalizer는 이를 방지합니다.
    3. App of Apps 패턴 지원: 여러 애플리케이션을 계층적으로 관리할 때, 상위 애플리케이션 삭제 시 하위 리소스까지 정리되도록 합니다.

 

 

dev-nginx App 생성 및 Auto SYNC

#
echo $MyIP

cat <<EOF | kubectl apply -f -
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: dev-nginx
  namespace: argocd
  finalizers:
  - resources-finalizer.argocd.argoproj.io
spec:
  project: default
  source:
    helm:
      valueFiles:
      - values-dev.yaml
    path: nginx-chart
    repoURL: http://$MyIP:3000/devops/ops-deploy
    targetRevision: HEAD
  syncPolicy:
    automated:
      prune: true
    syncOptions:
    - CreateNamespace=true
  destination:
    namespace: dev-nginx
    server: https://kubernetes.default.svc
EOF


#
kubectl get applications -n argocd dev-nginx

 

삭제 후 확인

kubectl delete applications -n argocd dev-nginx

 

prd-nginx App 생성 및 Auto SYNC

#
cat <<EOF | kubectl apply -f -
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: prd-nginx
  namespace: argocd
  finalizers:
  - resources-finalizer.argocd.argoproj.io
spec:
  destination:
    namespace: prd-nginx
    server: https://kubernetes.default.svc
  project: default
  source:
    helm:
      valueFiles:
      - values-prd.yaml
    path: nginx-chart
    repoURL: http://$MyIP:3000/devops/ops-deploy
    targetRevision: HEAD
  syncPolicy:
    automated:
      prune: true
    syncOptions:
    - CreateNamespace=true
EOF

#
kubectl get applications -n argocd prd-nginx

 

 

 

Repo(ops-deploy) 에 Webhook 를 통해 Argo CD 에 즉시 반영 trigger하여 k8s 배포 할 수 있게 설정합니다.

 

- Repo(**ops-deploy**) 에 webhooks 설정 : **Gogs** 선택
    - Payload URL : http://192.168.254.127:30002/api/webhook
        - ***Windows (WSL2) 사용자는 자신의 WSL2 Ubuntu eth0 IP***
    - 나머지 항목 ‘기본값’ ⇒ Add webhook
    - 이후 생성된 webhook 클릭 후 Test Delivery 클릭 후 정상 응답 확인

 

 

 

아까와 같이 dev-nginx를 배포하고 gogs의 코드를 수정해서 자동으로 auto sync됨을 확인하시면 됩니다.

 

 

 


Jenkins CI + Argo CD + K8S(Kind)

 

[출처] 가시다님 스터디

 

 

Repo(ops-deploy)  기본작업

#
cd ops-deploy

#
mkdir dev-app

# 도커 계정 정보
DHUSER=<도커 허브 계정>

# 버전 정보 
VERSION=0.0.1

#
cat > dev-app/VERSION <<EOF
$VERSION
EOF

cat > dev-app/timeserver.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: timeserver
spec:
  replicas: 2
  selector:
    matchLabels:
      pod: timeserver-pod
  template:
    metadata:
      labels:
        pod: timeserver-pod
    spec:
      containers:
      - name: timeserver-container
        image: docker.io/$DHUSER/dev-app:$VERSION
        livenessProbe:
          initialDelaySeconds: 30
          periodSeconds: 30
          httpGet:
            path: /healthz
            port: 80
            scheme: HTTP
          timeoutSeconds: 5
          failureThreshold: 3
          successThreshold: 1
      imagePullSecrets:
      - name: dockerhub-secret
EOF

cat > dev-app/service.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
  name: timeserver
spec:
  selector:
    pod: timeserver-pod
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
    nodePort: 30000
  type: NodePort
EOF

#
git add . && git commit -m "Add dev-app deployment yaml" && git push -u origin main

 

 

 

 

Repo(ops-deploy) 를 바라보는 ArgoCD App 생성

cat <<EOF | kubectl apply -f -
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: timeserver
  namespace: argocd
  finalizers:
  - resources-finalizer.argocd.argoproj.io
spec:
  project: default
  source:
    path: dev-app
    repoURL: http://$MyIP:3000/devops/ops-deploy
    targetRevision: HEAD
  syncPolicy:
    automated:
      prune: true
    syncOptions:
    - CreateNamespace=true
  destination:
    namespace: default
    server: https://kubernetes.default.svc
EOF

#
kubectl get applications -n argocd timeserver

 

 

Repo(dev-app) 코드 작업

 

기존에 있던 jenkinsfile을 수정하여 사용하였습니다.

pipeline {
    agent any
    environment {
        DOCKER_IMAGE = '<자신의 도커 허브 계정>/dev-app' // Docker 이미지 이름
        GOGSCRD = credentials('gogs-crd')
    }
    stages {
        stage('dev-app Checkout') {
            steps {
                 git branch: 'main',
                 url: 'http://<자신의 집 IP>:3000/devops/dev-app.git',  // Git에서 코드 체크아웃
                 credentialsId: 'gogs-crd'  // Credentials ID
            }
        }
        stage('Read VERSION') {
            steps {
                script {
                    // VERSION 파일 읽기
                    def version = readFile('VERSION').trim()
                    echo "Version found: ${version}"
                    // 환경 변수 설정
                    env.DOCKER_TAG = version
                }
            }
        }
        stage('Docker Build and Push') {
            steps {
                script {
                    docker.withRegistry('https://index.docker.io/v1/', 'dockerhub-crd') {
                        // DOCKER_TAG 사용
                        def appImage = docker.build("${DOCKER_IMAGE}:${DOCKER_TAG}")
                        appImage.push()
                        appImage.push("latest")
                    }
                }
            }
        }
        stage('ops-deploy Checkout') {
            steps {
                 git branch: 'main',
                 url: 'http://<자신의 집 IP>:3000/devops/ops-deploy.git',  // Git에서 코드 체크아웃
                 credentialsId: 'gogs-crd'  // Credentials ID
            }
        }
        stage('ops-deploy version update push') {
            steps {
                sh '''
                OLDVER=$(cat dev-app/VERSION)
                NEWVER=$(echo ${DOCKER_TAG})
                sed -i '' "s/$OLDVER/$NEWVER/" dev-app/timeserver.yaml
                sed -i '' "s/$OLDVER/$NEWVER/" dev-app/VERSION
                git add ./dev-app
                git config user.name "devops"
                git config user.email "a@a.com"
                git commit -m "version update ${DOCKER_TAG}"
                git push http://${GOGSCRD_USR}:${GOGSCRD_PSW}@<자신의 집 IP>:3000/devops/ops-deploy.git
                '''
            }
        }
    }
    post {
        success {
            echo "Docker image ${DOCKER_IMAGE}:${DOCKER_TAG} has been built and pushed successfully!"
        }
        failure {
            echo "Pipeline failed. Please check the logs."
        }
    }
}

 

그러면 이전에 생성했던 SCM-Pipeline을 탑니다.

 

이제 git에서 version을 0.0.5로 업데이트하고 push만하면 jenkinsfile로 build가 자동 실행하여 

레포지토리로 보내고 webhook를 통해 argocd에 자동 반영됩니다.