[운송장 정보보호 서비스] EKS-Github Action 연동

신현식·2023년 5월 31일
0

캡스톤디자인

목록 보기
5/7
post-thumbnail

CI/CD 파이프라인

📢 참고했던 사이트 CI/CD for EKS cluster with Github Action

  • 개발자가 git 저장소에 개발한 코드를 Push하면 github action이 해당 코드를 가져와서 Test와 Build를 하게 된다.
  • 백엔드의 경우 성공적으로 Build가 되었다면 결과물로 jar파일이 생성되게 된다. 이 jar 파일을 배포하고, Java기반의 Web Application을 실행시키기 위해 특정 디렉터리에 옮기고 실행시키는 작업을 진행하는 Dockerfile을 git에 추가한다.
  • 프론트엔드의 경우 성공적으로 Build가 되었다면 빌드되어 생성된 폴더 전체와 nginx의 설정을 수정하는 파일을 nginx의 특정 디렉터리에 옮기고 실행시켜주는 Dockerfile을 git에 추가한다.
  • 이후 AWS ECR에 Dockerfile을 사용해 Build하여 이미지로 만든 후, 생성된 이미지를 private ECR에 Push한다.
  • k8s manifest 코드가 들어있는 git 저장소와 개발 코드용 git 저장소가 분리되어있다.
  • ECR에 새로운 이미지가 Push가 되면 k8s용 git 저장소에서 방금 action를 진행한 저장소의 파일을 배포하는 Deployment에서 기존의 이미지에 Sed 명령을 통해 새로운 Image로 바꾼다.
  • 새로운 Image로 바뀐 Deployment를 ArgoCD가 감지하여 새로운 Image가 적용된, 즉 새로운 버전의 웹으로 Rolling Update를 통해 배포한다.

Github Action

Github Action은 github에서 공식적으로 제공하는 CI/CD 툴, 다시 말해 개발의 work flow를 자동화할 수 있게 도와주는 툴이다.

Github Action의 코어 개념

  • Workflow
    자동화된 전체 프로세스. 하나 이상의 Job으로 구성되고, Event에 의해 예약되거나 트리거될 수 있는 자동화된 절차를 말한다.
    Workflow 파일은 YAML으로 작성되고, Github Repository의 .github/workflows 폴더 아래에 저장된다. Github에게 YAML 파일로 정의한 자동화 동작을 전달하면, Github Actions는 해당 파일을 기반으로 그대로 실행시킨다.

  • Event
    Workflow를 트리거(실행)하는 특정 활동이나 규칙. 예를 들어, 누군가가 커밋을 리포지토리에 푸시하거나 풀 요청이 생성 될 때 GitHub에서 활동이 시작될 수 있다.

  • Job
    Job은 여러 Step으로 구성되고, 단일 가상 환경에서 실행된다. 다른 Job에 의존 관계를 가질 수도 있고, 독립적으로 병렬로 실행될 수도 있다.

  • Step
    Job 안에서 순차적으로 실행되는 프로세스 단위. step에서 명령을 내리거나, action을 실행할 수 있다.

  • Action
    job을 구성하기 위한 step들의 조합으로 구성된 독립적인 명령. workflow의 가장 작은 빌드 단위이다. workflow에서 action을 사용하기 위해서는 action이 step을 포함해야 한다. action을 구성하기 위해서 레포지토리와 상호작용하는 커스텀 코드를 만들 수도 있다. 사용자가 직접 커스터마이징하거나, 마켓플레이스에 있는 action을 가져다 사용할 수도 있다. (더 자세한 설명은 아래에!)

  • Runner
    Gitbub Action Runner 어플리케이션이 설치된 머신으로, Workflow가 실행될 인스턴스

EKS github action CI/CD 파이프라인 구성

프론트엔드 레포지토리 2개와 백엔드 레포지토리 3개에 모두 github action을 적용시켜야 하나 여기서는 예시로 exqress-admin-service 레포지토리에 적용시킨 것을 보여주겠다. 나머지 레포지토리에는 저장소 이름만 수정하여 똑같이 설정해주면 된다. 개발용 코드가 들어있는 저장소와 이전에 k8s manifest 파일들이 저장되어 있는 저장소 2개를 준비해둔다.

1. CI/CD 파이프라인을 위한 최소 권한의 IAM 생성

app을 빌드 하고, docker 이미지로 만든 다음 이를 ECR에 push 하는 과정은 gitHub Action을 통해 이루어진다. eks cluster를 생성했을때 사용한 IAM User와는 별도로 github-action만을 위한 최소 권한를 가진 User를 새로 생성해준다.

aws iam create-user --user-name github-action
  • ecr-policy.json 정책파일 생성하고 만들어진 파일을 통해 IAM policy를 생성한다. json 파일은 git 저장소에 따로 올리지 않고 로컬 저장소에서만 저장한 후 실행시켜주었다.
vi ecr-policy.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowPush",
            "Effect": "Allow",
            "Action": [
                "ecr:GetDownloadUrlForLayer",
                "ecr:BatchGetImage",
                "ecr:BatchCheckLayerAvailability",
                "ecr:PutImage",
                "ecr:InitiateLayerUpload",
                "ecr:UploadLayerPart",
                "ecr:CompleteLayerUpload"
            ],
            "Resource": "arn:aws:ecr:ap-northeast-2:<계정 ID>:repository/*"
        },
        {
            "Sid": "GetAuthorizationToken",
            "Effect": "Allow",
            "Action": [
                "ecr:GetAuthorizationToken"
            ],
            "Resource": "*"
        }
    ]
}


aws iam create-policy --policy-name ecr-policy --policy-document file://ecr-policy.json
  • iam에 정책 부여할 때 resource 부분에서 repository/* 로 수정하였는데 이유는 하나의 ecr에만 접근하는 권한이 아닌 생성한 모든 ecr 레포에 대한 접근 권한이 필요하기 때문이다. 하지만 특정 리포지토리로 범위를 지정하지 않고 이미지를 푸시하는 데 필요한 권한을 부여하는 방법도 있기에 밑 참조 사이트에 들어가서 확인해보면 될 것이다.
    📢 이미지 푸시에 필요한 IAM 권한

  • 생성한 ecr-policy를 새로 생성한 IAM user 에게 할당한다.

aws iam attach-user-policy --user-name github-action --policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/ecr-policy

2. githup secrets(AWS Credential, githup token) 생성

github action 에서 사용할 AWS credential, github token을 생성하고, 설정한다.

AWS Credential 생성

aws iam create-access-key --user-name github-action
  • 아래와 같은 출력 결과 가운데 "SecretAccessKey", "AccessKeyId"값을 따로 메모 저장한다. 이 값은 향후에 사용할 예정이다.
{
  "AccessKey": {
    "UserName": "github-action",
    "Status": "Active",
    "CreateDate": "2021-07-29T08:41:04Z",
    "SecretAccessKey": "***",
    "AccessKeyId": "***"
  }
}

github personal token 생성

github.com 로그인 후 User profile > Settings > Developer settings > Personal access tokens 으로 이동한다. 그리고 우측 상단에 위치한 Generate new token을 선택한다.
Note에 access token for github action라 입력 하고 Select scopes 에서 repo 를 선택한다. 그리고 화면 아래에서 Generate token 을 클릭한다.
화면에 출력되는 token 값을 복사한다. 한번 끄면 다시 확인이 불가능하기 때문에 저장해두는 것이 좋다.

github secret 설정

우리는 모든 레포지터리에 github action를 설정할 것임으로 각 레포지토리에 secret를 설정하는 것이 아닌 Organization account에 secret를 설정하여 모든 레포지토리에서 사용 가능하도록 할 것이다. 따라서 Organization account에서 Settings > Secrets and variables > Actions 를 선택한다. 그리고 이어 화면 우측 상단의 New Organization secret 을 클릭한다.

  • 아래 화면 같이 Name에 ACTION_TOKEN Value 에는 앞서 복사한 personal access token 값을 넣은 후 Add secret 을 클릭하면 된다. 마찬가지로 앞서 생성 후 기록해둔 IAM USER 인 github-action 의 AccessKeyId 와 SecretAccessKey의 값을 Secret 에 저장한다.

3. github action을 위한 build 스크립트 생성

gitub project 레포지토리의 Actions 탭에 들어가면 새로운 workflow를 만들 수 있다. yml 파일로 만들어지며, 생성된 파일은 default로 .github/workflows/{name}.yml 위치하게 된다.
아니면 직접 git 저장소를 클론해온 위치에 폴더와 파일을 만든 후 push를 진행해도 무관하다.

  • app 을 checkout 하고, build 한 다음, dockerfile를 이용하여 이미지를 만들어 ECR 로 push 한 후, k8s의 manifest 저장소에 해당하는 deploy의 이미지를 바로 전에 push한 이미지로 바꾸어 빌드하는 github action build 스크립트를 작성한다.

    다른 블로그에서는 & 문자를 탈출시키기 위해서 /를 붙이는 경우도 봤지만 내 경우에는 안붙여도 잘 돌아갔다.
    하지만 밑에 "" 안에 들어있는 &에서는 /로 문자를 탈출시켜줘야 제대로 작동하였음으로 참고하는 것이 좋다.

vi .github/workflows/build.yml

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

name: AWS ECR push & deploy k8s

jobs:
  deploy:
    name: Deploy
    runs-on: ubuntu-latest
    environment: production

    steps:
      # Github에 저장된 코드를 CI 서버로 내려받아 뒷 step에서 사용할 수 있도록 하는 과정
      - name: Checkout
        uses: actions/checkout@v2

      # Github Secret과 local env 에 저장된 값 불러오기
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}   # secret에 저장되어 있는 값 불러오기
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-2

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

      - name: Build, tag, and push the image to Amazon ECR
        id: build-image
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          ECR_REPOSITORY: back-admin
          IMAGE_TAG: ${{ github.run_number }}
        run: |
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
          docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
          echo "Pushing image to ECR..."
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
      
      # kustomize 명령을 가져온다.
      - name: Setup Kustomize
        uses: imranismail/setup-kustomize@v1

      - name: Checkout kustomize repository
        uses: actions/checkout@v2
        with:
          # kubernetes 설정정보 저장소
          repository: DGU2023xcapstone-parcel/exqress-kubernetes # k8s yaml 파일이 있는 repo
          ref: main # branch 이름
          # 다른 저장소에 push 하려면 Personal Access Token이 필요.
          token: ${{ secrets.ACTION_TOKEN }}
          path: exqress-kubernetes # 최상위 경로로 repository와 동일하게 설정

      # 새 이미지 버전으로 파일 수정
      - name: Update Kubernetes resources
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          ECR_REPOSITORY: back-admin
          IMAGE_TAG: ${{ github.run_number }}
        run: |
          cd exqress-kubernetes
          sed -i "s|image:.*|image: $ECR_REGISTRY\/$ECR_REPOSITORY:$IMAGE_TAG|g" back-admin-deploy.yaml # 새로 생성된 이미지로 교체하는 명령
          
      # 수정된 파일 commit & push
      - name: Commit files
        env:
          ECR_REPOSITORY: back-admin
          IMAGE_TAG: ${{ github.run_number }}
        run: |
          cd exqress-kubernetes
          git config --global user.email "<github 계정>@github.com"
          git config --global user.name "<github 계정>"
          git commit -am "Update image $ECR_REPOSITORY tag $IMAGE_TAG"
          git push -u origin main
  • 깃허브 액션 이미지 태그 설정 : 기존 환경변수 사용
    github.run_number : 리포지토리에서 특정 워크플로의 각 실행에 대한 고유 번호이다. 이 숫자는 워크플로의 첫 번째 실행에 대해 1부터 시작하여 각각의 새로운 실행에 따라 증가한다. 따라서 새로 생성된 이미지가 겹칠 일이 없다.
    📢 github 기본 환경 변수

💡 에러발생, 퍼블릭 ecr 주소사용 불가능

steps.login-ecr.outputs.registry
이유를 찾아보니 내가 현재 만들었던 ecr 저장소는 퍼블릭 저장소로 만들었는데 위와 같은 형식의 github action을 사용하여 ecr 저장소에 이미지를 저장하는 방식은 프라이빗 방식에서만 가능하였다. 그래서 프라이빗 ecr 저장소를 만들어서 실행했더니 제대로 수행되었다.
-> 퍼블릭 저장소에 넣는 방법도 나중에 찾아볼 예정이다.

  • 성공적으로 이미지를 생성한 이후 ecr에 이미지가 저장된다. 이후 k8s 레포지토리를 확인해보면 이미지가 수정된것을 확인할 수 있고 argoCD를 확인했을때 새로 생성된 이미지로 파드가 잘 배포된 것을 확인할 수 있다.



도커 캐시 삭제 -> build가 오류남
docker system prune --volumes

profile
전공 소개

0개의 댓글