SaFi Bank Space : GitHub Actions self-hosted runners

Installation

Actions-runner-controller

We use self-hosted runners for tasks where we need to access services inside our private network.

To deploy self-hosted runners we use helm chart for actions-runner-controller. It’s deployed with ArgoCD ApplicationSet to every apps cluster.

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: actions-runner-controller
spec:
  generators:
  - clusters:
      selector:
        matchLabels:
          cluster: apps
  template:
    metadata:
      name: '{{name}}-actions-runner-controller'
      annotations:
        argocd.argoproj.io/manifest-generate-paths: .
    spec:
      project: dev-infra
      source:
        repoURL: 'https://github.com/SafiBank/SaFiMono.git'
        path: devops/argocd/environments/common/infra/actions-runner-controller
        targetRevision: HEAD
        plugin:
          name: helm-argocd-vault-replacer
      destination:
        server: '{{server}}'
        namespace: actions-runner-controller
      syncPolicy:
        automated:
          prune: true
        syncOptions:
        - CreateNamespace=true
        retry:
          limit: 5
          backoff:
            duration: 5s
            factor: 2
            maxDuration: 3m

values.yaml

To be able to access Github repo you need to get token and save it in Vault.

actions-runner-controller:
  authSecret:
    create: true
    github_token: <secret:secret/data/cicd/actions-runner-controller~GITHUB_TOKEN>

Actions-runner

https://github.com/SafiBank/SaFiMono/tree/main/devops/argocd/environments/common/infra/actions-runner

After actions runner controller is deployed we can deploy runner with CRD RunnerDeployment and HorizontalRunnerAutoscaler.

For every cluster we deploy the same HorizontalRunnerAutoscaler which scale number of runners from 1 to 50 based on number of workflows in queue.

apiVersion: actions.summerwind.dev/v1alpha1
kind: HorizontalRunnerAutoscaler
metadata:
  name: runner-deployment-autoscaler
spec:
  scaleTargetRef:
    name: runner-deployment
  minReplicas: 1
  maxReplicas: 50
  metrics:
  - type: TotalNumberOfQueuedAndInProgressWorkflowRuns
    repositoryNames:
    - SafiBank/SaFiMono

And for every cluster we deploy different RunnerDeployment so that we able to label runners based on environment. Also we put nodeSelector and tolerations to run runners on separate nodepool.

For example for brave:

apiVersion: actions.summerwind.dev/v1alpha1
kind: RunnerDeployment
metadata:
  name: runner-deployment
spec:
  template:
    spec:
      repository: SafiBank/SaFiMono
      labels:
        - brave
      resources:
        limits:
          cpu: "2"
          memory: "4Gi"
        requests:
          cpu: "500m"
          memory: "2Gi"
      nodeSelector:
        cloud.google.com/gke-role: "github-runner"
      tolerations:
      - key: "safi_nodegroup_class"
        operator: Equal
        value: "github_runner"
        effect: NoSchedule

After deployment you can verify that your runners are up and running in repository settings.

Usage

https://docs.github.com/en/actions/hosting-your-own-runners/using-self-hosted-runners-in-a-workflow

To run workflow on selfhosted runners we need to specify runs-on: parameter in job.

For example:

jobs:
  Sonarqube-Test:
    runs-on: [ brave ]
    steps:
       - name: Check out repository code
         uses: actions/checkout@v3

       - name: Set up JDK 17
         uses: actions/setup-java@v3
         with:
            java-version: '17.0.5+8'
            distribution: 'temurin'

       - name: Run Sonarqube tests
         working-directory: services/${{ inputs.microservice_name }}
         run: >
           ./gradlew sonarqube
           -Dsonar.projectKey=${{ inputs.microservice_name }}
           -Dsonar.host.url=${{ secrets.SONARQUBE_NEW_ADDRESS }}
           -Dsonar.login=${{ secrets.SONARQUBE_NEW_TOKEN }}

Attachments: