From d440b1ca7afdf01fd915d5802693e00c850d1599 Mon Sep 17 00:00:00 2001 From: Stefan Bethke Date: Tue, 3 Sep 2024 14:36:49 +0200 Subject: [PATCH] WIP: add runner --- README.md | 38 +++++++++++- templates/_helpers.tpl | 49 ++++++++++++++++ templates/gitea/deployment.yaml | 42 ++++++++++++++ templates/gitea/init.yaml | 11 ++++ templates/gitea/runner-secret.yaml | 26 +++++++++ templates/gitea/runner.yaml | 92 ++++++++++++++++++++++++++++++ values.yaml | 20 +++++++ 7 files changed, 276 insertions(+), 2 deletions(-) create mode 100644 templates/gitea/runner-secret.yaml create mode 100644 templates/gitea/runner.yaml diff --git a/README.md b/README.md index 427db75..7f59190 100644 --- a/README.md +++ b/README.md @@ -46,16 +46,22 @@ - [Init](#init) - [Signing](#signing) - [Gitea](#gitea) + - [`app.ini` overrides](#appini-overrides) + - [Actions Runner](#actions-runner) + - [Registration Secret](#registration-secret) - [LivenessProbe](#livenessprobe) - [ReadinessProbe](#readinessprobe) - [StartupProbe](#startupprobe) - - [redis-cluster](#redis-cluster) - - [redis](#redis) + - [RedisĀ® Cluster](#redis-cluster) + - [RedisĀ®](#redis) - [PostgreSQL HA](#postgresql-ha) - [PostgreSQL](#postgresql) - [Advanced](#advanced) - [Contributing](#contributing) - [Upgrading](#upgrading) + - [To v8.0.0](#to-v800) + - [To v7.0.0](#to-v700) + - [To v6.0.0](#to-v600) [Forgejo](https://forgejo.org/) is a community managed lightweight code hosting solution written in Go. It is published under the MIT license. @@ -1076,6 +1082,34 @@ blocks, while the keys themselves remain in all caps. | `gitea.config.actions` | Configuration for [Forgejo Actions](https://forgejo.org/docs/latest/user/actions/) | `{}` | | `gitea.config.other` | Uncategorized configuration options | `{}` | +### Actions Runner + +The chart can deploy an [Actions Runner](https://forgejo.org/docs/latest/admin/actions/#forgejo-runner). + +**Note** You also need to set `gitea.config.actions.enabled=true` if you want to use runners. + +The available runner tags are listed here: + +| Name | Description | Value | +|-----------------------------------------------|------------------------------------------------------------|--------------------| +| `gitea.actions.runner.enabled` | Enable automatic deployment of a runner. | `false` | +| `gitea.actions.runner.image.pullPolicy` | Overrides the pull policy set globally for actions runners | | +| `gitea.actions.runner.image.registry` | Image registry, e.g. gcr.io,docker.io | `code.forgejo.org` | +| `gitea.actions.runner.image.repository` | Image to start for this pod | `forgejo/runner` | +| `gitea.actions.runner.image.tag` | Tag to deploy | | +| `gitea.actions.runner.registrationSecretName` | Name of secret containing the registration secret | ~ | +| `gitea.actions.runner.replicas` | Number of replicas to automatically deploy | 1 | +| `gitea.actions.runner.runnerLabels` | Forgejo Runner labels to assign to the runner | `["docker"]` | + +#### Registration Secret + +The Runner needs to register itself with Forgejo. The chart will use the +secret named by `gitea.actions.runner.registrationSecretName`, key +`runner-registration-secret` to both add a runner with that secret to +Forgejo at the application level, as well as register the runner when it +starts up. If `registrationSecretName` is not set, the chart will create +a secret for you. An existing secret will be reused. + ### LivenessProbe | Name | Description | Value | diff --git a/templates/_helpers.tpl b/templates/_helpers.tpl index 234c839..8d2d47b 100644 --- a/templates/_helpers.tpl +++ b/templates/_helpers.tpl @@ -63,6 +63,20 @@ Create image name and tag used by the deployment. {{- end -}} {{- end -}} +{{/* +Create image name and tag used by the actions runner. +*/}} +{{- define "gitea.actions-image" -}} +{{- $registry := .Values.gitea.actions.runner.image.registry | default (.Values.global.imageRegistry | default .Values.image.registry) -}} +{{- $name := .Values.gitea.actions.runner.image.repository -}} +{{- $tag := .Values.gitea.actions.runner.image.tag -}} +{{- if $registry -}} + {{- printf "%s/%s:%s" $registry $name $tag -}} +{{- else -}} + {{- printf "%s:%s" $name $tag -}} +{{- end -}} +{{- end -}} + {{/* Docker Image Registry Secret Names evaluating values as templates */}} @@ -108,6 +122,26 @@ app.kubernetes.io/name: {{ include "gitea.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end -}} +{{/* +Actions runner labels +*/}} +{{- define "gitea.actions.runner.labels" -}} +helm.sh/chart: {{ include "gitea.chart" . }} +app: actions-runner +{{ include "gitea.actions.runner.selectorLabels" . }} +app.kubernetes.io/version: {{ .Values.gitea.actions.runner.image.tag | quote }} +version: {{ .Values.gitea.actions.runner.image.tag | quote }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Actions runner selector labels +*/}} +{{- define "gitea.actions.runner.selectorLabels" -}} +app.kubernetes.io/name: actions-runner +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + {{- define "postgresql-ha.dns" -}} {{- if (index .Values "postgresql-ha").enabled -}} {{- printf "%s-postgresql-ha-pgpool.%s.svc.%s:%g" .Release.Name .Release.Namespace .Values.clusterDomain (index .Values "postgresql-ha" "service" "ports" "postgresql") -}} @@ -247,6 +281,9 @@ https {{- if not (hasKey .Values.gitea.config "metrics") -}} {{- $_ := set .Values.gitea.config "metrics" dict -}} {{- end -}} + {{- if not (hasKey .Values.gitea.config "actions") -}} + {{- $_ := set .Values.gitea.config "actions" dict -}} + {{- end -}} {{- if not (hasKey .Values.gitea.config "database") -}} {{- $_ := set .Values.gitea.config "database" dict -}} {{- end -}} @@ -286,6 +323,9 @@ https {{- if not (hasKey .Values.gitea.config.metrics "ENABLED") -}} {{- $_ := set .Values.gitea.config.metrics "ENABLED" .Values.gitea.metrics.enabled -}} {{- end -}} + {{- if not (hasKey .Values.gitea.config.actions "ENABLED") -}} + {{- $_ := set .Values.gitea.config.actions "ENABLED" .Values.gitea.actions.enabled -}} + {{- end -}} {{- /* redis queue */ -}} {{- if or ((index .Values "redis-cluster").enabled) ((index .Values "redis").enabled) -}} {{- $_ := set .Values.gitea.config.queue "TYPE" "redis" -}} @@ -416,3 +456,12 @@ https {{ printf "gitea.admin.passwordMode must be set to one of 'keepUpdated', 'initialOnlyNoReset', or 'initialOnlyRequireReset'. Received: '%s'" .Values.gitea.admin.passwordMode | fail }} {{- end -}} {{- end -}} + +{{- define "gitea.randHex" -}} + {{- $result := "" }} + {{- range $i := until . }} + {{- $rand_hex_char := mod (randNumeric 4 | atoi) 16 | printf "%x" }} + {{- $result = print $result $rand_hex_char }} + {{- end }} + {{- $result }} +{{- end }} \ No newline at end of file diff --git a/templates/gitea/deployment.yaml b/templates/gitea/deployment.yaml index f321f22..0af19a1 100644 --- a/templates/gitea/deployment.yaml +++ b/templates/gitea/deployment.yaml @@ -261,6 +261,48 @@ spec: {{- include "gitea.init-additional-mounts" . | nindent 12 }} resources: {{- toYaml .Values.initContainers.resources | nindent 12 }} + - name: add-runner-secret + image: "{{ include "gitea.image" . }}" + command: ["/usr/sbin/add_runner_secret.sh"] + imagePullPolicy: {{ .Values.image.pullPolicy }} + securityContext: + {{- /* By default this container runs as user 1000 unless otherwise stated */ -}} + {{- $csc := deepCopy .Values.containerSecurityContext -}} + {{- if not (hasKey $csc "runAsUser") -}} + {{- $_ := set $csc "runAsUser" 1000 -}} + {{- end -}} + {{- toYaml $csc | nindent 12 }} + env: + - name: GITEA_APP_INI + value: /data/gitea/conf/app.ini + - name: GITEA_CUSTOM + value: /data/gitea + - name: GITEA_WORK_DIR + value: /data + - name: GITEA_TEMP + value: /tmp/gitea + {{- if .Values.image.rootless }} + - name: HOME + value: /data/gitea/git + {{- end }} + - name: RUNNER_SECRET + valueFrom: + secretKeyRef: + name: {{ include "gitea.fullname" . }}-runner-registration + key: runner-registration-secret + volumeMounts: + - name: init + mountPath: /usr/sbin + - name: temp + mountPath: /tmp + - name: data + mountPath: /data + {{- if .Values.persistence.subPath }} + subPath: {{ .Values.persistence.subPath }} + {{- end }} + {{- include "gitea.init-additional-mounts" . | nindent 12 }} + resources: + {{- toYaml .Values.initContainers.resources | nindent 12 }} terminationGracePeriodSeconds: {{ .Values.deployment.terminationGracePeriodSeconds }} containers: - name: {{ .Chart.Name }} diff --git a/templates/gitea/init.yaml b/templates/gitea/init.yaml index 434486a..bd065b5 100644 --- a/templates/gitea/init.yaml +++ b/templates/gitea/init.yaml @@ -224,3 +224,14 @@ stringData: configure_oauth echo '==== END GITEA CONFIGURATION ====' + + add_runner_secret.sh: |- + #!/usr/bin/env bash + + set -euo pipefail + + echo '==== BEGIN ADD RUNNER SECRET ====' + + forgejo forgejo-cli actions register --name "{{ include "gitea.fullname" . }}-runner" --secret "${RUNNER_SECRET}" + + echo '==== END ADD RUNNER SECRET ====' diff --git a/templates/gitea/runner-secret.yaml b/templates/gitea/runner-secret.yaml new file mode 100644 index 0000000..9f6bc16 --- /dev/null +++ b/templates/gitea/runner-secret.yaml @@ -0,0 +1,26 @@ +{{/* +Runner registration secret. Will only be created if it does not exist. + +https://forgejo.org/docs/latest/admin/actions/#registration + +The secret must be a 40-character long string of hexadecimal numbers. +The first 16 characters will be used as an identifier for the runner, +while the rest is the actual secret. It is possible to update the +secret of an existing runner by running the command again on the +Forgejo machine, with the last 24 characters updated. +*/}} +{{- if and (.Values.gitea.actions.runner.enabled) (not .Values.gitea.actions.runner.registrationSecretName) -}} +{{- $secretName := printf "%s-%s" (include "gitea.fullname" .) "runner-registration" -}} +{{- $secret := lookup "v1" "Secret" .Release.Namespace $secretName -}} +{{- if not $secret }} +apiVersion: v1 +kind: Secret +metadata: + annotations: + helm.sh/resource-policy: keep + name: {{ $secretName }} +type: Opaque +data: + runner-registration-secret: {{ include "gitea.randHex" 40 | b64enc }} +{{- end }} +{{- end }} diff --git a/templates/gitea/runner.yaml b/templates/gitea/runner.yaml new file mode 100644 index 0000000..742e154 --- /dev/null +++ b/templates/gitea/runner.yaml @@ -0,0 +1,92 @@ +{{- if .Values.gitea.actions.runner.enabled -}} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "gitea.fullname" . }}-runner + labels: + {{- include "gitea.actions.runner.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.gitea.actions.runner.replicas }} + selector: + matchLabels: + {{- include "gitea.actions.runner.selectorLabels" . | nindent 6 }} + serviceName: {{ include "gitea.fullname" . }}-runner + template: + metadata: + labels: + {{- include "gitea.actions.runner.labels" . | nindent 8 }} + spec: + {{- if .Values.schedulerName }} + schedulerName: "{{ .Values.schedulerName }}" + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: "{{ .Values.priorityClassName }}" + {{- end }} + {{- include "gitea.images.pullSecrets" . | nindent 6 }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + initContainers: + - name: configure-runner + image: "{{ include "gitea.actions-image" . }}" + imagePullPolicy: {{ default .Values.image.pullPolicy .Values.gitea.actions.runner.image.pullPolicy }} + command: [ "forgejo-runner" ] + args: + - "create-runner-file" + - "--connect" + - "--secret-file" + - "/runner-secret/runner-registration-secret" + - "--instance" + - "http://{{ .Release.Name }}-http:{{ .Values.service.http.port }}" + - "--labels" + - "{{ join "," .Values.gitea.actions.runner.runnerLabels }}" + volumeMounts: + - name: data + mountPath: /data + - name: runner-secret + mountPath: /runner-secret + - name: temp + mountPath: /tmp + containers: + - name: {{ .Chart.Name }} + image: "{{ include "gitea.actions-image" . }}" + imagePullPolicy: {{ default .Values.image.pullPolicy .Values.gitea.actions.runner.image.pullPolicy }} + env: + - name: DOCKER_HOST + value: tcp://localhost:2376 + - name: DOCKER_CERT_PATH + value: /certs/client + - name: DOCKER_TLS_VERIFY + value: "1" + command: [ "forgejo-runner" ] + args: + - daemon + volumeMounts: + - name: certs + mountPath: /certs + - name: data + mountPath: /data + - name: temp + mountPath: /tmp + - name: daemon + image: docker:23.0.6-dind-rootless + env: + - name: DOCKER_TLS_CERTDIR + value: /certs + # NOTE: the container needs to run as root to configure dockerd, but + # dockerd itself is NOT run as root + securityContext: + privileged: true + volumeMounts: + - name: certs + mountPath: /certs + volumes: + - name: certs + emptyDir: {} + - name: data + emptyDir: {} + - name: temp + emptyDir: {} + - name: runner-secret + secret: + secretName: {{ include "gitea.fullname" . }}-runner-registration +{{- end }} diff --git a/values.yaml b/values.yaml index 7e67426..8990b37 100644 --- a/values.yaml +++ b/values.yaml @@ -355,6 +355,26 @@ gitea: email: 'gitea@local.domain' passwordMode: keepUpdated + ## @param gitea.actions.runner.enabled Enable automatic deployment of a runner. You also need to set gitea.config.actions.enabled + ## @param gitea.actions.runner.image.registry Image registry, e.g. gcr.io,docker.io + ## @param gitea.actions.runner.image.repository Image to start for this pod + ## @param gitea.actions.runner.image.tag Visit: [Image tag](https://code.forgejo.org/forgejo/-/packages/container/runner/versions). + ## @param gitea.actions.runner.image.pullPolicy Overrides the pull policy set globally for actions runners + ## @param gitea.actions.runner.registrationSecretName Name of secret containing the registration secret. If unset, the chart will create one + ## @param gitea.actions.runner.replicas Number of replicas to automatically deploy + ## @param gitea.actions.runner.runnerLabels Forgejo Runner labels to assign to the runner + actions: + runner: + enabled: false + image: + registry: "code.forgejo.org" + repository: forgejo/runner + tag: "3.5.1" + pullPolicy: IfNotPresent + registrationSecretName: ~ + replicas: 1 + runnerLabels: ["docker"] + ## @param gitea.metrics.enabled Enable Forgejo metrics ## @param gitea.metrics.serviceMonitor.enabled Enable Forgejo metrics service monitor metrics: