쿠버네티스 교육

Github Action Self-hosted 세팅

Jerry_이정훈 2023. 4. 6. 06:30
728x90

EKS를 1.23 to 1.24 업그레이드하고 컨테이너 런타임으로 docker를 더이상 사용하지 못한다. 우리 회사는 젠킨스를 사용하고 이미지 Build를 docker를 사용하는데 Kaniko로 변경해야한다. 그런데 젠킨스는 전임자가 설치하였고 내가 젠킨스를 잘알지 못해 동료가 Kaniko 변경 작업에 시간이 많이 걸렸다. 또한 Kaniko로 변경하면 Jenkinsfile도 다 변경하는 나름 거대한 추가 작업이 있다.

 

전부터 젠킨스는 UI도 불편하여 개발자도 그리 좋아하지 않는 등 레거시 느낌이 있어 교체하고 싶었는데 잘되었다 싶었다. 다른 오픈소스 대안으로 Tekton을 검토했는데 설치가 쉽지 않았다. 그런데 마침 회사 개발자분이 깃헙 액션을 Self-hosted로 사용하면 기존 3,000분(github team plan 사용하면 3,000분 무료) 초과해서 무료로 사용할 수 있다고 알려(너무 고맙다)주어 검토중이다. 나는 그동안 깃업 액션은 기본 제공을 넘게 사용하면 유료만 가능한지 알았다. 그런데 self-hosted 사용하면 공짜로 사용 가능하다니.(나만 모르고 있었나... 난 깃헙 엔터프라이즈만 로컬에 사용 가능하지 깃헙 액션만 분리해서 로컬에 설치되는지 몰랐다.) 물론 self-hosted를 사용하면 self-hosted 하드웨어 비용은 발생하지만 이건 젠킨스, Tekton들도 동일하다.

 

그동안 CI는 이미 구축되어 있는것만 사용해서 항상 개념이 흐릿했는데 이번에 새로 구축하는 기회가 생겨 나름 자세히 들여다 볼 수 있었다.(그래서 어렵기는 하다.)

 

구축하는 CI 목표 시스템은

  • Github에 개발자가 Main, Branch, Tag 등으로 push 하면
  • 자동으로 깃헙 액션이 docker 이미지 build하고 AWS ECR(이미지 레지스트리)에 이미지를 push 한다.
  • 이미지 태그 이름은 자동으로 branch(feature/test01 이면 '/' 이 후 test01만 split) 이름 또는 깃헙 Tag를 붙힌다. 

 

아마도 대부분의 서비스에 공통으로 필요한 부분일 것이다.

 

self-hosted 하드웨어는 로컬 M1 애플 맥북을 사용하는 사례도 있고 Raspberry 등 다양한 옵션이 있다. 개발용이 아니라 업무 용도라 나에게 선택지는 EC2다. 쿠버네티스도 가능한 것 같은데, 굳이 어렵게 갈 필요가 없을 것 같아 EC2 가상 머신을 선택했다. 가성비가 좋은 t4g.large(2vCPU/8Gi) 인스턴스를 사용했다. (ARM64 이미지 build 이슈가 있어 AMD64 인스턴스 사용 예정)

 

공식 가이드에 따라 설치한다. 깃헙 Organization의 Runners 탭에서 아래 "New runner"를 선택한다. 개별 깃헙 레포가 아닌 Organization에서 선택해야 조직 전체가 사용할 수 있다.

 

사용하는 하드웨어 환경에 따라 적절한 설치 방법을 따른다. 나는 t4g ARM 계열이라 Linux - ARM64 선택했다.

 

위 가이드에 따라 작업을 진행하는데 나는 docker 기반으로 이미지 build, push 작업을 할 예정이니 사용하는 EC2에 미리 docker를 설치했다. 그리고 위 가이드를 따라 설치하되 ./config.sh 까지 작업하고 ./run.sh 을 실행하지 않는다.

ubuntu@ip-10-13-221-248:~/actions-runner$ ./config.sh --url

--------------------------------------------------------------------------------
|        ____ _ _   _   _       _          _        _   _                      |
|       / ___(_) |_| | | |_   _| |__      / \   ___| |_(_) ___  _ __  ___      |
|      | |  _| | __| |_| | | | | '_ \    / _ \ / __| __| |/ _ \| '_ \/ __|     |
|      | |_| | | |_|  _  | |_| | |_) |  / ___ \ (__| |_| | (_) | | | \__ \     |
|       \____|_|\__|_| |_|\__,_|_.__/  /_/   \_\___|\__|_|\___/|_| |_|___/     |
|                                                                              |
|                       Self-hosted runner registration                        |
|                                                                              |
--------------------------------------------------------------------------------

# Authentication


√ Connected to GitHub

# Runner Registration

Enter the name of the runner group to add this runner to: [press Enter for Default]

This runner will have the following labels: 'self-hosted', 'Linux', 'ARM64'
Enter any additional labels (ex. label-1,label-2): [press Enter to skip]

√ Runner successfully added
√ Runner connection is good

# Runner settings

Enter name of work folder: [press Enter for _work]

√ Settings Saved.

가이드에 나오는 앱 실행(./run.sh) 부문은 리눅스 기반이라 system service로 대신한다. 서비스로 실행하는 방법은 아래와 같이 공식 가이드를 따른다.

 

설정을 하면 아래처럼 system service라 systemctl 명령어를 사용할 수 있어 편리하다.

ubuntu@ip:~$ systemctl status actions.runner.XXXXXX
● actions.runner.goodatlas.XXXXXXX.service - GitHub Actions Runner

 

정상 실행되면 깃헙 액션 탭에서 Runner를 확인할 수 있다.

 

self-hosted 러너가 녹색 idle 상태다.

이제 이미지 빌드하는 action.yml 파일을 만든다. 이미지 빌드 액션 파일은 공통 파일이라 별도 레포에 action.yml 파일로 저장한다. 이를 원격 repo 액션 파일에서 'uses'로 불러와서 사용할 수 있다.

name: Docker Image Build and Push

inputs:
  repository:
    description: "Name of ECR Repository"
    required: true
  docker-context:
    description: "Docker context"
    required: false
    default: "."
  docker-file:
    description: "Docker file"
    required: false
    default: "Dockerfile"
  access-key-id:
    description: "Access Key Id of AWS"
    required: true
  secret-access-key:
    description: "Secret Access Key of AWS"
    required: true

runs:
  using: "composite"

  steps:
    - name: Check out code
      uses: actions/checkout@v3

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

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

    - name: Split branch name
      env:
        BRANCH: ${{ github.ref_name }}
      id: split
      shell: bash
      run: echo "::set-output name=fragment::${BRANCH##*/}"

    - name: Build and push (with target)
      uses: docker/build-push-action@v3
      with:
        context: ${{ inputs.docker-context }}
        file: ${{ inputs.docker-file }}
        push: true
        tags: ${{ steps.login-ecr.outputs.registry }}/${{ inputs.repository }}:${{ steps.split.outputs.fragment }}
  • docker-context, docker-file
    개발자에 따라 별도 디렉토리에 (server/config.json, ci/dockerfile) 파일을 지정하는 경우가 있어 변수로 입력 가능하게 했다. 
  • actions/checkout@v3, aws-actions/xxx 등 공통 모듈(맞는 표현인가?)을 사용했다.
    로그인, build 등의 기능을 별도로 파일을 만들지 않고 이미 있는 벤더 사 공식 모듈을 사용했다. 
  • Split branch name
    이것 찾고 적용하느라 시간이 많이 걸렸다. feature/test01 등 '/' 슬래시를 기준으로 깃헙 푸쉬하는 경우가 많아 '/' 이 후 이름을 Split 하는 스크립트를 넣었다. 이를 steps.split.outputs.fragment를 이용하여 이미지 tag로 사용한다. 

 

이제 이 레포를 이용하도록(uses: goodatlas/atlas-actions@main) 깃헙 액션 파일을 작성한다. 아래 파일을 기본으로 전사에 공지하여 사용할 계획이다.

name: Docker Image Build and Push to ECR

on:
  - push
  - workflow_dispatch

jobs:
  deploy:
    # if fail, you can use 'ubuntu-latest' instead of 'self-hosted
    runs-on: self-hosted

    steps:
      - name: Deploy
        uses: goodatlas/atlas-actions@main
        with:
          repository: remove-old-es-index
          docker-context: "."
          docker-file: "Dockerfile"
          access-key-id: ${{ secrets.SWITCH_AWS_ACCESS_KEY_ID }}
          secret-access-key: ${{ secrets.SWITCH_AWS_SECRET_ACCESS_KEY }}
  • on: - push
    깃헙에 push 되면 항상 깃헙액션이 실행한다. push 될 때 마다 이미지 build, push 너무 잦지 않나 싶은데 어떤게 좋을지 잘 모르겠다.
  • runs-on: self-hosted
    깃헙 호스트가 아닌 self-hosted를 사용한다. 혹시 self-hosted 문제가 발생하면 기존처럼 ubuntu-latest 사용한다. 기존 3,000분이면 백업으로 충분히 사용할 수 있는 수준은 되는 것 같다.
  • steps: uses
    uses로 위에서 만든 goodatlas/atlas-actions 레포의 main 브랜치의 action.yml 파일을 이용해서 이미지 build, push 작업을 한다.
  • with: docker-context, docker-file
    default 위치가 다르면 개발자가 지정한다. 
  • access-key-id, secret-access-key
    깃헙 액션은 secret 기능을 제공해서 편하게 사용할 수 있는게 아주 강력하다. tekton 등 다른 것 사용하면 secret 처리가 어려웠다.
    (다른 이야기인데, 깃헙에 올라가는 secret도 깃헙의 환경 변수 파일을 사용하면 편할 것 같은데...)

 

이제 설정이 완료되었다. 이제 레포에 push 되면 자동으로 깃헙 액션이 실행된다. 레포의 Actions 탭에서 실행 내역을 확인할 수 있다.

숱하게 실패하다 겨우 성공하였다.

이게 머라고 그동안 당연한 것, 쉬운 것 아닌가 라고 생각했는데, 여러날 고생하고 많은 사람 도움을 받아서 겨우겨우 성공했다. 세상에 참 쉬운게 없다. 안되는 것도 없고.

 

추가로 많이 사용하면 오토스케일링, 스팟인스턴스, Launch Template 통한 자동화 등이 필요한데 이건 차차 검토할 예정이다.

 

참조

https://docs.github.com/en/actions/hosting-your-own-runners/adding-self-hosted-runners 

https://docs.github.com/en/actions/hosting-your-own-runners/configuring-the-self-hosted-runner-application-as-a-service

반응형

'쿠버네티스 교육' 카테고리의 다른 글

Tracing - OpenTelemetry + Tempo  (2) 2023.05.31
AWS ALB & LoadBalancer Controller  (2) 2023.04.11
파일시스템 기반 Loki 설치  (8) 2023.04.01
원격 EKS 접속 환경 설정  (0) 2022.11.08
EKS OJT 교육 실습 목차  (2) 2022.11.08