diff --git a/charts/dev/Chart.yaml b/charts/dev/Chart.yaml new file mode 100644 index 00000000..cf38d440 --- /dev/null +++ b/charts/dev/Chart.yaml @@ -0,0 +1,33 @@ +apiVersion: v2 +name: gha-runner-scale-set +description: A Helm chart for deploying an AutoScalingRunnerSet + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: "0.13.0" + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "0.13.0" + +home: https://github.com/actions/actions-runner-controller + +sources: + - "https://github.com/actions/actions-runner-controller" + +maintainers: + - name: actions + url: https://github.com/actions diff --git a/charts/dev/templates/_helpers.tpl b/charts/dev/templates/_helpers.tpl new file mode 100644 index 00000000..6188e443 --- /dev/null +++ b/charts/dev/templates/_helpers.tpl @@ -0,0 +1,20 @@ +{{- define "autoscaling-runner-set.name" -}} +{{- $name := .Values.runnerScaleSetName | default .Release.Name | replace "_" "-" | trimSuffix "-" }} +{{- if or (empty $name) (gt (len $name) 45) }} +{{ fail "Autoscaling runner set name must have up to 45 characters" }} +{{- end }} +{{- $name }} +{{- end }} + +{{- define "autoscaling-runner-set.namespace" -}} +{{- .Values.namespaceOverride | default .Release.Namespace -}} +{{- end }} + + +{{- define "githubsecret.name" -}} +{{- if not (empty .Values.auth.secretName) }} +{{- quote .Values.auth.secretName }} +{{- else }} +{{- include "autoscaling-runner-set.name" . }}-github-secret +{{- end }} +{{- end }} diff --git a/charts/dev/templates/autoscalingrunnserset.yaml b/charts/dev/templates/autoscalingrunnserset.yaml new file mode 100644 index 00000000..92bfdf41 --- /dev/null +++ b/charts/dev/templates/autoscalingrunnserset.yaml @@ -0,0 +1,94 @@ +apiVersion: actions.github.com/v1alpha1 +kind: AutoscalingRunnerSet +metadata: + name: {{ include "autoscaling-runner-set.name" . | quote }} + namespace: {{ include "autoscaling-runner-set.namespace" . | quote }} +spec: + githubConfigUrl: {{ required ".Values.auth.url is required" (trimSuffix "/" .Values.auth.url) | quote }} + githubConfigSecret: {{ include "githubsecret.name" . | quote }} + runnerGroup: {{ .Values.scaleset.runnerGroup | quote }} + + {{- if .Values.githubServerTLS }} + githubServerTLS: + {{- with .Values.githubServerTLS.certificateFrom }} + certificateFrom: + configMapKeyRef: + name: {{ .configMapKeyRef.name }} + key: {{ .configMapKeyRef.key }} + {{- end }} + {{- end }} + + {{- if and .Values.keyVault .Values.keyVault.type }} + vaultConfig: + type: {{ .Values.keyVault.type }} + {{- if .Values.keyVault.proxy }} + proxy: {{- toYaml .Values.keyVault.proxy | nindent 6 }} + {{- end }} + {{- if eq .Values.keyVault.type "azure_key_vault" }} + azureKeyVault: + url: {{ .Values.keyVault.azureKeyVault.url }} + tenantId: {{ .Values.keyVault.azureKeyVault.tenantId }} + clientId: {{ .Values.keyVault.azureKeyVault.clientId }} + certificatePath: {{ .Values.keyVault.azureKeyVault.certificatePath }} + secretKey: {{ .Values.keyVault.azureKeyVault.secretKey }} + {{- else }} + {{- fail "Unsupported keyVault type: " .Values.keyVault.type }} + {{- end }} + {{- end }} + + {{- if .Values.proxy }} + proxy: + {{- if .Values.proxy.http }} + http: + url: {{ .Values.proxy.http.url }} + {{- if .Values.proxy.http.credentialSecretRef }} + credentialSecretRef: {{ .Values.proxy.http.credentialSecretRef }} + {{- end }} + {{- end }} + {{- if .Values.proxy.https }} + https: + url: {{ .Values.proxy.https.url }} + {{- if .Values.proxy.https.credentialSecretRef }} + credentialSecretRef: {{ .Values.proxy.https.credentialSecretRef }} + {{- end }} + {{- end }} + {{- if and .Values.proxy.noProxy (kindIs "slice" .Values.proxy.noProxy) }} + noProxy: {{ .Values.proxy.noProxy | toYaml | nindent 6}} + {{- end }} + {{- end }} + + {{- if and (or (kindIs "int64" .Values.scaleset.minRunners) (kindIs "float64" .Values.scaleset.minRunners)) (or (kindIs "int64" .Values.scaleset.maxRunners) (kindIs "float64" .Values.scaleset.maxRunners)) }} + {{- if gt .Values.scaleset.minRunners .Values.scaleset.maxRunners }} + {{- fail "maxRunners has to be greater or equal to minRunners" }} + {{- end }} + {{- end }} + + {{- if or (kindIs "int64" .Values.scaleset.maxRunners) (kindIs "float64" .Values.scaleset.maxRunners)}} + {{- if lt (.Values.scaleset.maxRunners | int) 0 }} + {{- fail "maxRunners has to be greater or equal to 0" }} + {{- end }} + maxRunners: {{ .Values.scaleset.maxRunners | int }} + {{- end }} + + {{- if or (kindIs "int64" .Values.scaleset.minRunners) (kindIs "float64" .Values.scaleset.minRunners) }} + {{- if lt (.Values.scaleset.minRunners | int) 0 }} + {{- fail "minRunners has to be greater or equal to 0" }} + {{- end }} + minRunners: {{ .Values.scaleset.minRunners | int }} + {{- end }} + + {{- with .Values.listenerPodTemplate }} + listenerTemplate: + {{- toYaml . | nindent 4}} + {{- end }} + + {{- with .Values.listenerMetrics }} + listenerMetrics: + {{- toYaml . | nindent 4 }} + {{- end }} + + template: + spec: + containers: + - name: runner + {{- include "runner-container-spec" . | nindent 10 }} diff --git a/charts/dev/values.yaml b/charts/dev/values.yaml new file mode 100644 index 00000000..af752dd1 --- /dev/null +++ b/charts/dev/values.yaml @@ -0,0 +1,276 @@ +## By default .Release.namespace is used +namespaceOverride: "" +# Name of the scaleset +scaleset: + name: "" + runnerGroup: "default" + ## minRunners is the min number of idle runners. The target number of runners created will be + ## calculated as a sum of minRunners and the number of jobs assigned to the scale set. + # min_runners: 0 + ## maxRunners is the max number of runners the autoscaling runner set will scale up to. + # max_runners: 5 + +# Auth object provides authorization parameters. +# You should apply either: +# 1) secretName referencing the secret containing authorization parameters in the same namespace where the scale set is being installed in +# 2) app object parameters +# 3) github_tokne +# +# If multiple of them are set, only single one will be applied based on the above mentioned order. +auth: + url: "" # Required + githubToken: "" + secretName: "" + app: + clientId: "" + installationId: "" + privateKey: "" +# +## proxy can be used to define proxy settings that will be used by the +## controller, the listener and the runner of this scale set. +# +# proxy: +# http: +# url: http://proxy.com:1234 +# credentialSecretRef: proxy-auth # a secret with `username` and `password` keys +# https: +# url: http://proxy.com:1234 +# credentialSecretRef: proxy-auth # a secret with `username` and `password` keys +# noProxy: +# - example.com +# - example.org + +## listenerTemplate is the PodSpec for each listener Pod +## For reference: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodSpec +# listenerPodTemplate: +# spec: +# containers: +# # Use this section to append additional configuration to the listener container. +# # If you change the name of the container, the configuration will not be applied to the listener, +# # and it will be treated as a side-car container. +# - name: listener +# securityContext: +# runAsUser: 1000 +# # Use this section to add the configuration of a side-car container. +# # Comment it out or remove it if you don't need it. +# # Spec for this container will be applied as is without any modifications. +# - name: side-car +# image: example-sidecar + +# Template applied for the runner container +runner: + # metadata: + # labels: [] + # annotations: [] + + # container field is applied to the container named "runner". You cannot override the name of the runner container + container: + image: "ghcr.io/actions/actions-runner:latest" + command: ["/home/runner/run.sh"] + + dind: + # If default is set to true, we will expand the default spec for the `dind` container, and you can provide fields to override them + default: true + + kubernetesMode: + default: true + serviceAccountName: "" + extension: {} +## A self-signed CA certificate for communication with the GitHub server can be +## provided using a config map key selector. If `runnerMountPath` is set, for +## each runner pod ARC will: +## - create a `github-server-tls-cert` volume containing the certificate +## specified in `certificateFrom` +## - mount that volume on path `runnerMountPath`/{certificate name} +## - set NODE_EXTRA_CA_CERTS environment variable to that same path +## - set RUNNER_UPDATE_CA_CERTS environment variable to "1" (as of version +## 2.303.0 this will instruct the runner to reload certificates on the host) +## +## If any of the above had already been set by the user in the runner pod +## template, ARC will observe those and not overwrite them. +## Example configuration: +# +# githubServerTLS: +# certificateFrom: +# configMapKeyRef: +# name: config-map-name +# key: ca.crt +# runnerMountPath: /usr/local/share/ca-certificates/ + +## keyVault object if applied switches from the kubernetes secrets to the vault provider defined in `keyVault.type` +## Secret name is used to resolve the secret inside the vault +# keyVault: +# Available values: "azure_key_vault" +# type: "" +# Configuration related to azure key vault +# azure_key_vault: +# url: "" +# client_id: "" +# tenant_id: "" +# certificate_path: "" +# proxy: +# http: +# url: http://proxy.com:1234 +# credentialSecretRef: proxy-auth # a secret with `username` and `password` keys +# https: +# url: http://proxy.com:1234 +# credentialSecretRef: proxy-auth # a secret with `username` and `password` keys +# noProxy: +# - example.com +# - example.org + +## listenerMetrics are configurable metrics applied to the listener. +## In order to avoid helm merging these fields, we left the metrics commented out. +## When configuring metrics, please uncomment the listenerMetrics object below. +## You can modify the configuration to remove the label or specify custom buckets for histogram. +## +## If the buckets field is not specified, the default buckets will be applied. Default buckets are +## provided here for documentation purposes +# listenerMetrics: +# counters: +# gha_started_jobs_total: +# labels: +# ["repository", "organization", "enterprise", "job_name", "event_name", "job_workflow_ref", "job_workflow_name", "job_workflow_target"] +# gha_completed_jobs_total: +# labels: +# [ +# "repository", +# "organization", +# "enterprise", +# "job_name", +# "event_name", +# "job_result", +# "job_workflow_ref", +# "job_workflow_name", +# "job_workflow_target", +# ] +# gauges: +# gha_assigned_jobs: +# labels: ["name", "namespace", "repository", "organization", "enterprise"] +# gha_running_jobs: +# labels: ["name", "namespace", "repository", "organization", "enterprise"] +# gha_registered_runners: +# labels: ["name", "namespace", "repository", "organization", "enterprise"] +# gha_busy_runners: +# labels: ["name", "namespace", "repository", "organization", "enterprise"] +# gha_min_runners: +# labels: ["name", "namespace", "repository", "organization", "enterprise"] +# gha_max_runners: +# labels: ["name", "namespace", "repository", "organization", "enterprise"] +# gha_desired_runners: +# labels: ["name", "namespace", "repository", "organization", "enterprise"] +# gha_idle_runners: +# labels: ["name", "namespace", "repository", "organization", "enterprise"] +# histograms: +# gha_job_startup_duration_seconds: +# labels: +# ["repository", "organization", "enterprise", "job_name", "event_name","job_workflow_ref", "job_workflow_name", "job_workflow_target"] +# buckets: +# [ +# 0.01, +# 0.05, +# 0.1, +# 0.5, +# 1.0, +# 2.0, +# 3.0, +# 4.0, +# 5.0, +# 6.0, +# 7.0, +# 8.0, +# 9.0, +# 10.0, +# 12.0, +# 15.0, +# 18.0, +# 20.0, +# 25.0, +# 30.0, +# 40.0, +# 50.0, +# 60.0, +# 70.0, +# 80.0, +# 90.0, +# 100.0, +# 110.0, +# 120.0, +# 150.0, +# 180.0, +# 210.0, +# 240.0, +# 300.0, +# 360.0, +# 420.0, +# 480.0, +# 540.0, +# 600.0, +# 900.0, +# 1200.0, +# 1800.0, +# 2400.0, +# 3000.0, +# 3600.0, +# ] +# gha_job_execution_duration_seconds: +# labels: +# [ +# "repository", +# "organization", +# "enterprise", +# "job_name", +# "event_name", +# "job_result", +# "job_workflow_ref", +# "job_workflow_name", +# "job_workflow_target" +# ] +# buckets: +# [ +# 0.01, +# 0.05, +# 0.1, +# 0.5, +# 1.0, +# 2.0, +# 3.0, +# 4.0, +# 5.0, +# 6.0, +# 7.0, +# 8.0, +# 9.0, +# 10.0, +# 12.0, +# 15.0, +# 18.0, +# 20.0, +# 25.0, +# 30.0, +# 40.0, +# 50.0, +# 60.0, +# 70.0, +# 80.0, +# 90.0, +# 100.0, +# 110.0, +# 120.0, +# 150.0, +# 180.0, +# 210.0, +# 240.0, +# 300.0, +# 360.0, +# 420.0, +# 480.0, +# 540.0, +# 600.0, +# 900.0, +# 1200.0, +# 1800.0, +# 2400.0, +# 3000.0, +# 3600.0, +# ]