본문으로 바로가기
반응형

Intro

오늘은 git action을 사용하여 전체 어플리케이션의 CI/CD자동화를 구축 해보도록 하겠습니다.

우선 CI/CD의 흐름도와 인프라/플랫폼/어플리케이션 구성을 살표 보겠습니다.

CI/CD 흐름도

아래 흐름도의 특징은 code repo와 k8s gitOps repo가 별도로 구성되어 있다는 점입니다. 또한 kustomize를 통해서 이미지 태그를 업데이트하며, ArgoCD를 통해 배포를 진행합니다.

인프라

  • AWS EKS Cluster
  • Code Repository : github
  • Docker Registry : AWS ECR

플랫폼

CI/CD 파이프라인

  • github action workflow

CD툴

  • ArgoCD
  • kustomize

어플리케이션

Frontend

  • 사용언어 : node.js
  • 빌드 : npm

Backend

  • 사용언어 : Java spring boot (JDK 11)
  • 빌드 : Maven

gitaction workflow

frontend-cicd.yaml

npm build는 소스코드안에 있는 dockerfile의 설정에 의해 진행됩니다.

name: frontend web - CI CD

on:
  workflow_dispatch:
    inputs:
      logLevel:
        description: 'Log level'
        required: true
        default: 'warning'
      tags:
        description: 'Test scenario tags'

env:
  AWS_REGION: ap-northeast-2                   # set this to your preferred AWS region, e.g. us-west-1
  ECR_REPOSITORY: frontend-web # set this to your Amazon ECR repository name

jobs:
  ecr-build-push-and-deploy:
    name: ecr-build-push-and-deploy
    runs-on: ubuntu-latest
    environment: production

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

    - 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: ${{ env.AWS_REGION }}

    - name: Login to Amazon ECR
      id: login-ecr
      uses: aws-actions/amazon-ecr-login@v1

    - name: Docker Build and ECR Push
      id: docker_build
      uses: docker/build-push-action@v2
      with:
        context: .
        file: ./Dockerfile
        platforms: linux/amd64
        push: true
        tags: ${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:${{ github.sha }}

    - name: Get verion
      id: image
      run: |
        VERSION=$(echo ${{ github.sha }} | cut -c1-8)
        echo VERSION=$VERSION
        echo "::set-output name=version::$VERSION"

    # kustomize 명령을 가져온다.
    - name: Setup Kustomize
      uses: imranismail/setup-kustomize@v1

    - name: Checkout kustomize repository
      uses: actions/checkout@v2
      with:
        # kubernetes 설정정보 저장소
        repository: kimdragon50/emp-gitops
        ref: frontend-web
        # 다른 저장소에 push 하려면 Personal Access Token이 필요.
        token: ${{ secrets.ACTION_TOKEN }}
        path: emp-gitops
    # 새 이미지 버전으로 파일 수정
    - name: Update Kubernetes resources
      run: |
        pwd
        cd emp-gitops/overlays/prd/
        echo \${{ steps.login-ecr.outputs.registry }}/\${{ env.ECR_REPOSITORY }}
        echo \${{ steps.login-ecr.outputs.registry }}/\${{ env.ECR_REPOSITORY }}:\${{ github.sha }}
        kustomize edit set image \${{ steps.login-ecr.outputs.registry }}/\${{ env.ECR_REPOSITORY }}=\${{ steps.login-ecr.outputs.registry }}/\${{ env.ECR_REPOSITORY }}:\${{ github.sha }}
        cat kustomization.yaml

    # 수정된 파일 commit & push
    - name: Commit minifest files
      run: |
        cd emp-gitops
        git config --global user.email "github-actions@github.com"
        git config --global user.name "github-actions"
        git commit -am "Update image tag"
        git push -u origin frontend-web

backend-cicd.yaml

name: backend emp - CI CD

on:
  workflow_dispatch:
    inputs:
      logLevel:
        description: 'Log level'
        required: true
        default: 'warning'
      tags:
        description: 'Test scenario tags'

env:
  AWS_REGION: ap-northeast-2                   # set this to your preferred AWS region, e.g. us-west-1
  ECR_REPOSITORY: backend-emp # set this to your Amazon ECR repository name
  KUBE_NAMESPACE: backend

jobs:
  mvn-build:
    name: mvn-build
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - name: Set up JDK 11
      uses: actions/setup-java@v2
      with:
        java-version: '11'
        distribution: 'adopt'
        cache: maven
    - name: Build with Maven
      run: mvn -B package --file pom.xml

  ecr-build-push-and-deploy:
    name: ecr-build-push-and-deploy
    runs-on: ubuntu-latest
    needs: mvn-build
    environment: production

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

      - 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: ${{ env.AWS_REGION }}

      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v1

      - name: Docker Build and ECR Push
        id: docker_build
        uses: docker/build-push-action@v2
        with:
          context: .
          file: ./Dockerfile
          platforms: linux/amd64
          push: true
          tags: ${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:${{ github.sha }}

      - name: Get verion
        id: image
        run: |
          VERSION=$(echo ${{ github.sha }} | cut -c1-8)
          echo VERSION=$VERSION
          echo "::set-output name=version::$VERSION"

      # kustomize 명령을 가져온다.
      - name: Setup Kustomize
        uses: imranismail/setup-kustomize@v1

      - name: Checkout kustomize repository
        uses: actions/checkout@v2
        with:
          # kubernetes 설정정보 저장소
          repository: kimdragon50/emp-gitops
          ref: backend-emp
          # 다른 저장소에 push 하려면 Personal Access Token이 필요.
          token: ${{ secrets.ACTION_TOKEN }}
          path: emp-gitops
      # 새 이미지 버전으로 파일 수정
      - name: Update Kubernetes resources
        run: |
          pwd
          cd emp-gitops/overlays/prd/
          echo \${{ steps.login-ecr.outputs.registry }}/\${{ env.ECR_REPOSITORY }}
          echo \${{ steps.login-ecr.outputs.registry }}/\${{ env.ECR_REPOSITORY }}:\${{ github.sha }}
          kustomize edit set image \${{ steps.login-ecr.outputs.registry }}/\${{ env.ECR_REPOSITORY }}=\${{ steps.login-ecr.outputs.registry }}/\${{ env.ECR_REPOSITORY }}:\${{ github.sha }}
          cat kustomization.yaml

      # 수정된 파일 commit & push
      - name: Commit minifest files
        run: |
          cd emp-gitops
          git config --global user.email "github-actions@github.com"
          git config --global user.name "github-actions"
          git commit -am "Update image tag"
          git push -u origin backend-emp

Source Code 주소

code repository

k8s gitops repository

kustomize

kustomize는 k8s deployment에 들어가는 image tag를 변경 해주는 툴입니다. 물론 deployemnt.yaml을 읽어와서 sed 와 같은 쉘 명령어로 텍스트를 변경해줄 수 있긴하지만 그렇게되면 변경에 대한 이력관리가 어렵습니다.

kustomize는 폴더규칙을 준수하고 간단히 yaml 설정을 한뒤 kustomize cli를 사용하여 tag변경을 할 수 있습니다. 이미지 태그에 대한 변경 이력관리가 되기때문에 k8s 리소스를 배포에 유용하게 사용되고 있습니다. 위에 backend-cicd.yaml에서 kustomize edit set image 부분이 kustomize를 통해서 이미지 태그 정보를 업데이트하는 부분 입니다.

kustomize 폴더 구조

.
├── overlays
│   └── prd
│       └── kustomization.yaml
└── resources
    ├── deployment.yaml
    ├── gateway.yaml
    ├── kustomization.yaml
    ├── namespace.sh
    ├── service.yaml
    └── virtualservice.yaml

overlays/prd/kustomization.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
images:
- name: /
  newName: /
resources:
- ../../resources

resources/kustomization.yaml

resources:
- deployment.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

ArgoCD

ArgoCD설치를 한 뒤 Create App을 하여 아래와 같이 설정합니다.

github action을 통해서 CI/CD가 완료 되면 ArgoCD에서 sync를 맞춰주면 완성입니다.

참고로 Auto sync 설정을 통해 Sync가 맞지 않으면 자동으로 Sync해주는 설정도 할 수 있습니다만 휴먼에러가 발생할 수 있으므로 직접 확인하여 Sync 하는 것을 추천드립니다.

gitAction 사용후기

저는 과거에 MSA로 설계된 어플리케이션을 jenkins로 CI/CD를 구축 운영을 해본 경험이 있습니다. 경험을 바탕으로 gitAction 대비 jenkins의 단점은 jenkins 서버를 별도로 구성해야하며, jenkins와 Plugin설치가 꽤나 번거로웠습니다. 또한 ci/cd 에 필요한 여러가지 툴을 OS내부에 설치해야 했고 linux OS에서 사용자권한 관리까지 해야했습니다.

그런데 gitAction을 사용하면 이런 설정이 전혀 필요 없습니다. 이 모든게 갖추어져 있기 때문에 관리자는 yaml 설정만 잘 해주면 그만입니다. (정말 너~~어무 편한 것 같습니다.)

하지만 여전히 젠킨스의 장점은 있는 것 같습니다. MSA로 설계가되면 서비스모듈이 1,2개가 아닌 20-30개 이상으로 구성됩니다. 젠킨스는 빌드배포 Job에 대한 전체 대시보드를 제공해주기 때문에 한눈에 배포 진행 상태를 확인할 수 있습니다. 하지만 gitaction은 repository에 의존되기 때문에 배포할때 각각의 repository에 접근하여 배포를 해야하며 한 눈에 전체 배포에 대한 대시보드를 확인할 수가 없습니다.

또한, 젠킨스는 서버를 별도로 관리할 수 있기 때문에 빌드 배포시 발생하는 서버 성능을 스스로 컨트롤 할 수 있다는 장점이 있는 것 같습니다.

그럼에도 불구하고 저는 gitAction을 사용할 것 같습니다. 몇가지 단점에 비해 장점이 너무나 뚜렷하기 때문인데요, 가장 큰 장점은 간단함 때문입니다. gitaction을 사용하면 빠르고 쉽게 CI/CD를 구축할 수 있으며 관리 포인트가 단순해집니다. 간단하고 안정적으로 CI/CD를 구축하고 운영할 수 있다면 사용하지 않을 이유가 없어 보입니다.

반응형