- Multipass 이용한 kubernetes 로컬 구축
- 로컬 k8s 에서 ngrok ingress controller 로 서비스 인터넷 노출하기 (expose kubernetes services to internet for test)
- Github Self-hosted runner 구축 후 배포 Pipeline 만들기
- ArgoCD 설치 및 github action 배포 환경 구성
소개
로컬환경 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 를 구축하는 과정을 남겨봅니다.
전체적인 절차를 요약하면 아래와 같습니다.
- ARC install (Actions Runner Controller)
- Install cert-manager – github API 와의 TLS 통신등 ARC의 인증서 관리를 위해 필요
- Create github token – github 인증용 token 생성
- Deploy ARC with helm – helm 을 이용한 ARC 배포
- 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
- github action docker build & push guide detail