본문 바로가기
개발/k8s

[EKS] Github Action과 ArgoCD로 CI/CD 파이프라인 구축

by parkkingcar 2024. 1. 24.

 

AWS EKS환경에서 쿠버네티스 클러스터를 생성하고 CI/CD 파이프라인을 구축합니다.

 

CICD는 지속적통합 / 지속적배포라는 개념으로 애플리케이션 개발 단계를 자동화하여 애플리케이션을 더욱 짧은 주기로 고객에게 서비스를 제공하는 방법입니다. 코드를 통합하고 배포하는 과정의 파이프라인을 통해 자동화할 수 있습니다.

 

 

 

CI ( 지속적 통합)

CI는 작성한 코드를 지속적으로 통합하는 방법입니다. 코드 변경이 발생할 때마다 자동으로 빌드 및 테스트를 수행하여 품질을 높이고 문제를 빠르게 감지할 수 있습니다. 개발자가 코드를 원격 코드 저장소에 push하면 원격 코드 저장소에서 코드를 가져와 유닛테스트 후 빌드를 진행합니다. 이 결과물을 다른 컴포넌트와 잘 통합되는지 확인합니다.

 

 

CD (지속적 배포)

소프트웨어 개발 프로세스에서 지속적으로 소프트웨어 변경 사항을 테스트 및 프로덕션 환경에 배포하는 방식입니다. 코드 변경에 따라 자동으로 프로덕션 환경으로 배포되어 사용자에게 제공됩니다. 배포 가능한 소프트웨어 패키지를 작성하고 프로비저닝을 실행하여 서비스를 사용자에게 노출합니다. 실질적인 배포로 서비스 현황을 파악하고 생길 수 있는 문제를 감지합니다.

 

 

GitOps

소프트웨어 배포 및 인프라 관리를 git 리포지토리로 이동하여 코드 저장소와 git 환경을 사용하는 개념입니다. gihub action 과 argocd를 통해 cicd 파이프라인을 구축하는데 이때 코드 저장소 git 환경을 사용하기때문에 이를 gitops라고 합니다.

 

 

GitOps의 핵심 아이디어 

배포에 관련된 모든 것을 선언형 파일 형태로 작성하여 Config Repository에서 관리합니다. Config Repository의 선언형 기술서와 운영 환경 간 상태 차이가 없도록 유지시켜주는 자동화 시스템을 구성합니다.

 

gitops 방식은 인프라와 소프트웨어를 함께 관리하기 때문에 git 버전 관리 시스템과 운영 환경 간의 일관성을 유지하여 소프트웨어 간의 불일치 문제를 해결합니다. 또한 모든 코드와 인프라 변경 사항이 git 저장소에 저장되기 때문에, 변경 내역을 추적하고 롤백을 쉽게 수행할 수 있습니다.

 

ArgoCD는 GitOps를 구현하기 위한 도구 중 하나로 Kubernetes 애플리케이션의 자동 배포를 위한 오픈소스 도구입니다. Kubernetes 클러스터에 배포된 애플리케이션의 CI/CD 파이프라인에서 CD부분을 담당하며, Git 저장소에서 변경 사항을 감지하여 자동으로 Kubernetes 클러스터에 애플리케이션을 배포할 수 있습니다.


ArgoCD는 애플리케이션 배포를 위해 Declarative Application Management(선언적 애플리케이션 관리)를 사용합니다. 이는 애플리케이션을 배포할 때 명시적으로 원하는 상태를 정의하고, 이를 ArgoCD가 클러스터의 상태와 비교하여 원하는 상태로 유지하도록 합니다. 

 


 

 

이제 Github Action과 ArgoCD를 사용하여 CI/CD 파이프라인을 구축합니다. EKS 환경에서 웹 애플리케이션 3티어 구성 및 구축상태를 전제로 진행합니다.

 

[EKS] 3티어 아키텍처 (RDS, Redis, 인그레스, tls, 도메인연결)

AWS EKS를 이용하여 쿠버네티스 환경의 3티어 아키텍처를 구성합니다. 구성환경은 VScode를 사용합니다. 먼저, 로컬에서 kubectl 명령을 사용하기 위해 eksctl을 설치해야합니다. 아래 블로그를 참고하

parkkingcar.tistory.com

 

 

 

파이프라인 시나리오

출처 : https://thingsflow.com/blog/143

 

개발환경에서 애플리케이션 코드를 수정한 후 git commit을 하고 수정된 코드를 GitHub 저장소에 push합니다.

 

이후 GitHub Actions이 동작하여 다음 작업을 수행합니다: 코드 빌드, 도커 이미지 빌드 및 푸시, Kubernetes 매니페스트의 이미지 태그 수정 및 푸시

그런데, GitOps의 주요 특징 중 하나는 개발자가 직접 배포를 수행하는 것이 아니라 Git 저장소의 상태를 통해 자동화된 배포를 하는 것이기 때문에 ArgoCD가 다음 작업을 수행합니다: 가시성 확보, 배포, 매니페스트 내용과 클러스터 상태 간의 일관성을 유지하기 위한 컨트롤 플레인 동기화

 

주의해야 할 점은 GitHub Actions와 ArgoCD 각각이 특정 이벤트에 반응하여 동작하는 것이기 때문에 GitHub Actions에서 이미지를 빌드하고 푸시한 후, 그 변경사항을 ArgoCD에 전달하는 방식으로 설정되어야 합니다. 일반적으로는 ArgoCD가 GitOps 방식으로 작동하므로 Kubernetes 클러스터 내의 매니페스트가 직접 변경되지 않고, Git 저장소에서의 변경사항에 따라 자동으로 반영됩니다.

 

 

 

구축

EKS에 노드 3개를 가진 클러스터를 생성하고 3티어 웹 애플리케이션을 구성했습니다.

 

 

 

1. github 리포지토리생성 

 

원격 코드 저장소인 github 리포지토리를 생성합니다. 시나리오 사진에서는 애플리케이션 코드가 올라간 리포지토리와 매니패스트 코드가 올라간 리포지토리를 따로 두고있는데, 하나의 저장소에서 둘을 폴더 단위로 구분하여 관리하고자 합니다. 개발환경은 VScode를 사용하였습니다.

 

아래와 같은 폴더구조를 가지고 yaml 폴더에서 매니패스트를 관리합니다.

 

github에서 저장소를 생성합니다.

 

로컬에 개발환경에서 github 리포지토리와 연결을 위해 git init명령을 사용합니다. 

 

이후 아래 내용을 참고하여 push까지 완료합니다.

 

 

 

2. argoCD 구축

 

이제 실행중인 EKS 클러스터에서 argoCD를 구축하고, 생성한 github 리포지토리의 상태를 확인하도록 연동합니다. ingress를 통해 외부와 통신할 수 있도록 합니다.

 

먼저 kubectl을 이용하여 네임스페이스를 생성합니다.

kubectl create ns argocd

 

이제 외부 ArgroCD  리소스를 설치합니다.

kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

 

다음 명령으로 ArgroCD  설치를 확인합니다.

kubectl get pod ‒n argocd

 

받아온 argoCD resource 중 argocd-server deployment의 arg를 수정합니다. 여기서 --insecure는 ArgoCD 서버가 보안 연결을 사용하지 않도록 설정하는 옵션입니다. 이 옵션을 추가하면 ArgoCD 서버는 HTTPS를 사용하지 않고 HTTP로 통신합니다. 이렇게 하는 것은 보안상 취약하지만 테스트를 위해 추가하였습니다. / 윈도우 경우 WSL이나 Git bash등을 활용하면 됩니다.

# Bash로 아래명령 실행
kubectl -n argocd patch deployment argocd-server --type json -p='[ { "op": "replace", "path":"/spec/template/spec/containers/0/args","value": ["/usr/local/bin/argocd-server","--insecure"] }]'

 

직접 수정 하는 방법

kubectl.exe edit  deploy argocd-server   -n argocd

=====
spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - podAffinityTerm:
              labelSelector:
                matchLabels:
                  app.kubernetes.io/name: argocd-server
              topologyKey: kubernetes.io/hostname
            weight: 100
          - podAffinityTerm:
              labelSelector:
                matchLabels:
                  app.kubernetes.io/part-of: argocd
              topologyKey: kubernetes.io/hostname
            weight: 5
      containers:
      - args:
        - /usr/local/bin/argocd-server
        - --insecure #추가 부분

 

이제 ArgCD에서 사용할 레코드를 등록하고 해당 레코드로 ACM을 생성합니다.

 

[AWS] ACM 인증서 발급 후 적용 방법.

ACM 이란? AWS Certificate Manager는 AWS 서비스 및 연결된 내부 리소스에 사용할 공인 및 사설 SSL/TLS(Secure Sockets Layer/전송 계층 보안) 인증서를 손쉽게 프로비저닝, 관리 및 배포할 수 있도록 지원하는

support.bespinglobal.com

 

 

ArgoCD용 서비스 생성합니다.

# argocd-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: argocd-svc
  namespace: argocd
spec:
  selector:
    app.kubernetes.io/name: argocd-server
  ports:
  - port: 80
    targetPort: 8080
  type: NodePort

 

ArgoCD용 ingress를 생성합니다. ACM에서 argocd.suyong.store의 ARN 주소를 해당부분에 입력해야 합니다.

# argocd-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-ingress
  namespace: argocd
  annotations:
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/scheme: internet-facing 
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]'
    # ACM에서 argocd.suyong.store의 ARN 주소
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:<리전명>:111111111111:certificate/ACM아이디값
    alb.ingress.kubernetes.io/ssl-redirect: '443'
    alb.ingress.kubernetes.io/healthcheck-path: /healthz
    alb.ingress.kubernetes.io/healthcheck-protocol: HTTP
    alb.ingress.kubernetes.io/success-codes: '200'
spec:
  ingressClassName: alb
  rules:
  - host: argocd.suyong.store
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: argocd-svc #위에서 생성한 서비스 명 
            port: 
              number: 80

 

위 두 매니패스트를 apply 명령 실행합니다.

kubectl apply -f ./argocd-svc.yaml
kubectl apply -f ./argocd-ingress.yaml

 

ArgoCD용 ingress가 생성 된 것을 확인합니다.

kubectl get ingress -n argocd

 

생성된 로드밸런서의 DNS 주소를 Route53의 레코드에 등록합니다.

 

이제 ArgoCD 초기 패스워드 확인하기 Shell에서 다음과 같이 입력하거나 / 윈도우 경우 WSL이나 Git bash등을 활용하면 됩니다.

# Bash에서 실행
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d

또는

kubectl -n argocd get secret argocd-initial-admin-secret -o yam

나온 패스워드를 해당 사이트에서 디코딩 
https://www.base64decode.org/

 

이제 ArgoCD  도메인으로 접속합니다. Router53에 등록한 FQDN주소로 접속합니다. username은 admin이고 패스워드는 위에서 확인한 패스워드입니다.

 

 

 

3. 깃허브 리포지토리 연동

 

먼저 연동을 위한 깃허브 토큰을 발급합니다. 설정에서 Developer Settings의 Personal access tokens을 클릭하고 토큰을 발급합니다.

 

다시 argocd에서 설정을 클릭하고 connect repo를 클릭합니다.

 

해당 설정을 유지하고 깃허브 리포지토리 주소를 입력합니다. 깃허브 아이디와 발급받은 토큰을 입력합니다.

Successful을 확인하고 좌측탭의 Applications을 클릭합니다.

 

해당 설정을 유지하고 나머지는 기본값을 유지합니다.  Application은 argocd에서 관리하는 이름을 지정합니다.

 

 

이제 다시 test를 클릭하면 아래와 같이 클러스터의 상태를 볼 수 있고 깃허브 리포지토리의 was 폴더의 매니패스트 상태를 추적합니다.

 

 

 

4. 깃허브 액션

 

깃허브 액션을 통해 CI, argocd를 통해 CD 파이프라인을 구축합니다. 먼저 깃허브 리포지토리에서 설정탭을 클릭하고 좌측 Action탭의 General을 클릭합니다.

 

아래의 권한설정에서 Read and write 권한을 부여합니다.

 

이제 좌측의 Secrets and variables를 클릭하고 Actions에서 시크릿 변수를 부여합니다. AWS 액새스 키와 AWS 시크릿 액세스 키, AWS 계정 ID, ECR 리포지토리 URI, 위에서 생성한 깃허브 토큰을 변수로 사용합니다. 

 

 

이제 깃허브 리포지토리에서 Action탭을 클릭하고 set up a workflow yourself를 클릭합니다. ECR 로그인 부분을 알맞게 변경합니다. main.yaml을 통해 위에서 설명한 CD 시나리오를 실행합니다.

name: gradle_build_docker_push
on:
  push:
    branches: [ main ]
    # CD부분에서 다시 코드를 push하기 때문에 아래 경로의 변경은 무시함
    paths-ignore:
    - '.github/workflows/**'  
    - 'yaml/was/**'
    

jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v3
      - run : ls -al
      
      - name: Set env
        run: echo "RELEASE_VERSION=${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV

      - name: install jdk
        uses: actions/setup-java@v3
        with:
          distribution: 'temurin'
          java-version: '11'
          cache: 'gradle'

      - name: Set up Docker Buildx
        id: buildx
        uses: docker/setup-buildx-action@v1
        
      - name: chmod gradle
        run: chmod +x ./gradlew
          
      - name: build
        run: ./gradlew build --no-daemon
          
      - name: docker build
        run: |
          mv ./build/libs/*.war ./Dockerfile
          docker build -t ${{ secrets.ECR_URI }}:v${{ env.RELEASE_VERSION }} ./Dockerfile
          docker build -t ${{ secrets.ECR_URI }}:latest ./Dockerfile
          rm -Rf ./Dockerfile/*.war
          rm -Rf ./build  

      - name: docker images check
        run: docker images

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} 
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-2

      - name: Login to ECR
        run: aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws/1111111

        
      - name: docer push
        run: | 
          docker push ${{ secrets.ECR_URI }}:v${{ env.RELEASE_VERSION }}
          docker push ${{ secrets.ECR_URI }}:latest

      - name: change image tag
        run: |
          cd ./yaml/was
          kustomize edit set image cicd-image=${{ secrets.ECR_URI }}:v${{ env.RELEASE_VERSION }}
          cat ./kustomization.yml

      - name: Commit and Push Changes
        run: |
          git config --global user.email ${{ secrets.EMAIL }}
          git config --global user.name "parkkingcar"
          git add .
          git commit -m "Update image tags for myapp"
          git push --prune https://token:${{ secrets.G_TOKEN }}@github.com/parkkingcar/CICD_ECR.git

 

 

이제 git init이 된 로컬 개발환경에서 was 의 html을 수정합니다. 

 

이제 git add 부터 push 단계를 통해 깃허브 저장소에 push합니다. 

 

그러면 자동으로 깃허브 액션이 workflow를 실행합니다. 

AWS ECR에 해당 이미지가 정상적으로 push 되었습니다. (첫 시도라면 v1 태그로 push합니다.)

 

그러면 argocd에서 sync policy가 auto로 되어있기 때문에, 자동으로 매니패스트 변경을 확인하고 배포합니다.

 

 

 

 

 

 

 

참고자료

 

ArgoCD란? 개념부터 설치 배포까지

ArgoCD란? 기존의 소프트웨어를 배포하고 관리하는 방식은 문제점이 많았다. 인프라 환경을 수동적으로 관리하고, 소프트웨어와 인프라를 따로 관리하는 경우가 많았기에 이로 인해 인프라와 소

wlsdn3004.tistory.com

 

Argo CD 를 AWS EKS 에 사용하기

AWS EKS에 Argo CD 올려서 사용해보기 ⭐️

velog.io

 

댓글