self-hosted-runner

소개

로컬환경 multipass에 kubernetes 을 구축하였었습니다. 그리고 kubernetes 환경에 application 을 배포하기 위한 CI/CD pipeline 은 github action 을 사용하고 있는데요.

로컬환경에 구성한 kubernetes 인 만큼 kubernetes API 의 외부 노출을 피하고 싶어, github self-hosted runner 를 구축해보았습니다.

Github Self-hosted runner 란?

github action 은 기본적으로 SaaS 형태로 github 에서 제공해주는 github-hosted runner 머신 위에서 워크플로우가 동작하도록 되어있습니다.

하지만, 보안이나 다른 이유로 인해 on-prem 이나 다른 resource 에 runner 를 구축하여 운영하고 싶을 경우도 있을텐데요. 그럴때 github self-hosted runner 를 사용할 수 있습니다.

Github Self-hosted runner 사용 이점

github self-hosted runner 를 사용하면 몇가지 이점이 있습니다.

  • Private 리소스 접근 환경 구성이 가능합니다.
  • Runner 의 사양, 기본 SW 구성등 커스터마이징이 가능합니다.
  • CI/CD pipeline 을 SaaS 이용이 아닌 Private 한 자사 환경에서 구성할 수 있어 Compliance 준수를 위해 필요할 수 있습니다.

github self-hosted 로 사용할 수 있는 runner 의 OS 종류가 한정적이기는 하지만, 위에서 언급한 이점의 가치가 높은 환경이라면 충분히 고려해보면 좋은 옵션일 듯합니다.

Self-hosted runner 구축

Self-hosted runner 구축에 대한 가이드는 docs 에서 친절히 제공해주고 있습니다.

github 에서는 ARC(Actions Runner Controller) 를 통해 Kubernets 에 contaner 로 쉽게 배포할 수 있도록 지원을 해주고 있는데요.

이를 기반으로 self-hosted runner 를 구축하는 과정을 남겨봅니다.

전체적인 절차를 요약하면 아래와 같습니다.

  1. ARC install (Actions Runner Controller)
    • Install cert-manager – github API 와의 TLS 통신등 ARC의 인증서 관리를 위해 필요
    • Create github token – github 인증용 token 생성
    • Deploy ARC with helm – helm 을 이용한 ARC 배포
  2. Create the Github self hosted runners deployments – runner 배포

Install cert-namager

먼저 github API 와 TLS 통신을 위한 인증서 관리용 cert-manager 를 설치합니다.

kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.8.2/cert-manager.yaml

Github token 생성

github 과의 통신을 위한 인증용 token 을 생성합니다.

여기 링크로 들어가서 인증 후 token 을 생성해줍니다. scopes 는 repo 만 선택합니다.

Helm 이용한 ARC 배포

github token 값만 바꿔 설치해줍니다.

# add repository
helm repo add actions-runner-controller https://actions-runner-controller.github.io/actions-runner-controller

# install helm chart
helm upgrade --install --namespace actions-runner-system --create-namespace\
  --set=authSecret.create=true\
  --set=authSecret.github_token="REPLACE_YOUR_TOKEN_HERE"\
  --wait actions-runner-controller actions-runner-controller/actions-runner-controller

Runner 배포

저는 replicas 를 2개로 설정하였습니다.

그리고 docker MTU 가 default 값으로 1500 이 설정 되는데, 저 같은 경우 container eni 의 MTU 가 1450 으로 설정이 되어있어, 이보다 낮게 설정해야지만 action 에서 네트워크 에러가 발생하지 않았습니다.

관련 내용을 여기를 참고 해보시면 될듯합니다.

apiVersion: actions.summerwind.dev/v1alpha1
kind: RunnerDeployment
metadata:
  name: runnerdeploy
spec:
  replicas: 2
  template:
    spec:
      dockerMTU: 1400
      # 아래 account/repository 정보 변경 필요 
      repository: gogoyeon/checkingress-local
      env:
        - name: ARC_DOCKER_MTU_PROPAGATION
          value: "true"

만일 또 다른 Repository 에 대한 runner 을 생성하고 싶다면, runner deployments 를 추가로 만들어 배포하면 되겠습니다.

잘 만들어졌습니다.

배포 Pipeline 구성

github self-hosted runner 를 배포하였으니 Action workflow 를 이용하여 배포 Pipeline 을 아래와 같이 구성하였습니다.

GitOps 를 이용하여 배포할 수도 있지만, 일단은 action 만으로 배포할 수 있도록 구성해 보았습니다.

그리고 kubectl 로 배포 하기 위해, pod 에 serviceAccount 를 할당해주고 적당한 Role 을 줘도 되지만, action 돌아갈때만 임시로 kubernetes api 접근권한을 주기 위해 github-secrets 에 kubeconfig 를 등록하여 인증하도록 하였습니다.

self-hosted runner 를 사용할 것이기 때문에 runner-on: self-hosted 로 설정해주면 되겠습니다.

name: cicd

on:
  push:
    branches:
      - main

permissions:
  id-token: write
  contents: read

jobs:
  cd:
    runs-on: self-hosted

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

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Log in to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_TOKEN }}

      - name: Build Docker image
        uses: docker/build-push-action@v5
        with:
          context: .
          load: true
          tags: ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPOSITORY }}:${{ github.sha }}
          build-args: |
            DB_HOST=${{ secrets.DB_HOST }}
            DB_PORT=${{ secrets.DB_PORT }}
            DB_USER=${{ secrets.DB_USER }}
            DB_PASSWORD=${{ secrets.DB_PASSWORD }}
            DB_DATABASE=${{ secrets.DB_DATABASE }}

      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: "${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPOSITORY }}:${{ github.sha }}"
          format: "table"
          exit-code: "0"
          ignore-unfixed: true
          vuln-type: "os,library"
          severity: "CRITICAL,HIGH"

      - name: Push Docker image
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPOSITORY }}:${{ github.sha }}
          build-args: |
            DB_HOST=${{ secrets.DB_HOST }}
            DB_PORT=${{ secrets.DB_PORT }}
            DB_USER=${{ secrets.DB_USER }}
            DB_PASSWORD=${{ secrets.DB_PASSWORD }}
            DB_DATABASE=${{ secrets.DB_DATABASE }}

      - name: Image digest
        run: echo "Image pushed with digest ${{ steps.build-and-push.outputs.digest }}"

      - uses: azure/setup-kubectl@v3

      - uses: azure/k8s-set-context@v4
        with:
          method: kubeconfig
          kubeconfig: ${{ secrets.KUBE_CONFIG }}

      - name: Install Kustomize
        run: |
          curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
          sudo mv kustomize /usr/local/bin/

      - name: Deploy
        env:
          KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }}
          REGISTRY: ${{ secrets.DOCKER_USERNAME }}
          REPOSITORY: ${{ secrets.DOCKER_REPOSITORY }}
          IMAGE_TAG: ${{ github.sha }}
        run: |
          cd manifest/overlays
          kustomize edit set image $REGISTRY/$REPOSITORY=$REGISTRY/$REPOSITORY:$IMAGE_TAG
          kustomize build . | kubectl apply -f -

결론

Github SaaS 를 이용하면서 Private 한 CI/CD 인프라를 이용하고 싶거나 runner 의 resource 에 대한 커스터마이징이 하고 싶다면 self-hosted runner 구성도 좋은 옵션이 됩니다. 구성을 위한 ARC 설치는 Docs 에 친절히 설명이 되어있어 어렵진 않지만, 운영 중 저와 같은 MTU 로 인한 네트워크 문제등이 발생한다면 추가적인 디버깅이 필요할 듯합니다.

Refs

Series Navigation<< 로컬 k8s 에서 ngrok ingress controller 로 서비스 인터넷 노출하기 (expose kubernetes services to internet for test)ArgoCD 설치 및 github action 배포 환경 구성 >>

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

Back To Top