[Github] Self hosted runner 운영하기

김지환·2023년 3월 17일
0

Github self-hosted runner

Github Action

빌드, 테스트, 배포 파이프라인을 자동화 할 수 있도록 해주는 CI/CD platform 을 제공해주는 github 서비스이다.

repository 마다 github action workflow를 생성하여서 PR, merge 등 다양한 git action에 대해서 workflow를 만들어서 필요한 빌드, 테스트 등을 진행할 수 있다.

Github action runner 의 한계점

  1. 6시간 타임아웃 제한이 있음.
  2. 작업을 진행하기 전에 필요한 apt-get 설치등이 전제로 깔리다보니 속도가 느린부분.

Self-hosted runner

self-hosted runner란 github이 관리하는 instance에서 github action application을 띄우는게 아닌 사용자가 직접 hosting한 서버에서 github action application을 띄우는 것을 말한다. 따라서 기존에 있던 시간제한 이나 prerequisite문제를 해결할 수 있다.


How to install

self-hosted runner는 단일 instance에 대한 hosting도 가능하지만 github action 특성상 multiple 하게 작업이 일어날 수 있기 때문에 오토스케일링을 제공해주는 오케스트레이터가 필요하다.

따라서 기존 Kubernetes cluster 가 구축되어 있다면 해당 cluster 에 올려서 관리하는것이 best solution이라고 할 수 있다. 또한 job 특성상 간헐적으로 일어나기 때문에 spot instance를 통한 관리를 해준다면 더욱 cost-effective한 관리가 가능하다.

action-runner-controller 를 설치하자.

github-action에서 공식적으로 제공해주는 self-hosted runner를 사용하고자 하는 유저를 위한 EKS 에 올라갈 controller이다. 공식적으로 관리가 되고 있기는 하나 아직은 major버전이 나오지 않아서 부족한 부분이 있을 수 있을 것으로 판단된다. 운영하면서 주의해야할 것 같다.

  1. Cert manager 를 설치
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.8.2/cert-manager.yaml

설치되는 resource 들

namespace/cert-manager created
customresourcedefinition.apiextensions.k8s.io/certificaterequests.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/certificates.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/challenges.acme.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/clusterissuers.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/issuers.cert-manager.io created
customresourcedefinition.apiextensions.k8s.io/orders.acme.cert-manager.io created
serviceaccount/cert-manager-cainjector created
serviceaccount/cert-manager created
serviceaccount/cert-manager-webhook created
configmap/cert-manager-webhook created
clusterrole.rbac.authorization.k8s.io/cert-manager-cainjector created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-issuers created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-clusterissuers created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-certificates created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-orders created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-challenges created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-ingress-shim created
clusterrole.rbac.authorization.k8s.io/cert-manager-view created
clusterrole.rbac.authorization.k8s.io/cert-manager-edit created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-approve:cert-manager-io created
clusterrole.rbac.authorization.k8s.io/cert-manager-controller-certificatesigningrequests created
clusterrole.rbac.authorization.k8s.io/cert-manager-webhook:subjectaccessreviews created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-cainjector created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-issuers created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-clusterissuers created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-certificates created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-orders created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-challenges created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-ingress-shim created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-approve:cert-manager-io created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-controller-certificatesigningrequests created
clusterrolebinding.rbac.authorization.k8s.io/cert-manager-webhook:subjectaccessreviews created
role.rbac.authorization.k8s.io/cert-manager-cainjector:leaderelection created
role.rbac.authorization.k8s.io/cert-manager:leaderelection created
role.rbac.authorization.k8s.io/cert-manager-webhook:dynamic-serving created
rolebinding.rbac.authorization.k8s.io/cert-manager-cainjector:leaderelection created
rolebinding.rbac.authorization.k8s.io/cert-manager:leaderelection created
rolebinding.rbac.authorization.k8s.io/cert-manager-webhook:dynamic-serving created
service/cert-manager created
service/cert-manager-webhook created
deployment.apps/cert-manager-cainjector created
deployment.apps/cert-manager created
deployment.apps/cert-manager-webhook created
mutatingwebhookconfiguration.admissionregistration.k8s.io/cert-manager-webhook created
validatingwebhookconfiguration.admissionregistration.k8s.io/cert-manager-webhook created
  1. Helm 을 통해서 설치를 진행한다.

Add repository

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

Install

helm upgrade --install --namespace actions-runner-system --create-namespace\
  --set=authSecret.create=true\
  --set=authSecret.github_token=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\
  --wait actions-runner-controller actions-runner-controller/actions-runner-controller

github token에는 충분한 권한이 부여가 돼 있어야한다.

repo: (all)
admin:org (all) (mandatory for organization-wide runner)
admin:public_key - read:public_key
admin:repo_hook - read:repo_hook
admin:org_hook
notifications
workflow

설치 완료시 port forwarding을 통해서 application 에 접근해볼 수 있다.

export POD_NAME=$(kubectl get pods --namespace actions-runner-system -l "app.kubernetes.io/name=actions-runner-controller,app.kubernetes.io/instance=actions-runner-controller" -o jsonpath="{.items[0].metadata.name}")
  export CONTAINER_PORT=$(kubectl get pod --namespace actions-runner-system $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
  echo "Visit http://127.0.0.1:8080 to use your application"
  kubectl --namespace actions-runner-system port-forward $POD_NAME 8080:$CONTAINER_PORT

Repo 관리자가 만든 github token을 통한 접근만 가능한 것으로 보임 권한이 없는 다른 token으로 작업시 authorization 문제가 발생함 혹은 404 not found error

조직 최고 관리자가 만든 github token을 활용해서 secret 을 만들어야함.

RunnerDepoyment 적용

ARC 설치가 끝났다면 runner 등록을 진행해야한다. runner 등록은 RunnerDeployment resource를 생성함으로서 github 과 연동되게 된다.

apiVersion: actions.summerwind.dev/v1alpha1
kind: RunnerDeployment
metadata:
  name: tech-org-runner
spec:
  replicas: 0
  template:
    spec:
      repository: my-organization/my-repository
      group: k8s-group
      labels:
        - k8s-runner
      affinity: # node affinity
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: name
                    operator: In
                    values:
                      - github-runner
---
apiVersion: actions.summerwind.dev/v1alpha1
kind: HorizontalRunnerAutoscaler # Like Deployment
metadata:
  name: tech-runner-deployment-autoscaler
spec:
  # Runners in the targeted RunnerDeployment won't be scaled down
  # for 5 minutes instead of the default 10 minutes now
  scaleDownDelaySecondsAfterScaleOut: 300
  scaleTargetRef:
    name: tech-org-runner
    # Uncomment the below in case the target is not RunnerDeployment but RunnerSet
    #kind: RunnerSet
  minReplicas: 1
  maxReplicas: 5
  metrics:
  - type: PercentageRunnersBusy
    scaleUpThreshold: '0.75'    # The percentage of busy runners at which the number of desired runners are re-evaluated to scale up
    scaleDownThreshold: '0.3'   # The percentage of busy runners at which the number of desired runners are re-evaluated to scale down
    scaleUpFactor: '1.4'        # The scale up multiplier factor applied to desired count
    scaleDownFactor: '0.7'

실제 적용한 runner.yml 명세이다. 위와 같이 적용을 완료하면 github runner 에 다음과 같이 연동이 되게 된다.

ARC Component

ARC는 기본적으로 사용자 지정 리소스 집합으로 구성된다.

적용이 되면 Github runner 가 실행되는 Pod를 띄우게 되고, Github은 해당 pod 를 통해서 workflow를 배치하게 된다.

추가 적용할 부분

helm 을 통해서 배포된 actions-runner-controller 라던가 기타 secret, service, custom resource들이 여러 node에 산재할 수 있을 수 있기 때문에 node-affinity를 적용할 수 있는 pod는 적용해서 하나의 node-group에서 관리할 수 있도록 하면 좋을 것.

Data Workflow

profile
Developer

0개의 댓글