gitea: deploy in-cluster action runner

This commit is contained in:
2026-08-22 12:15:30 +02:00
parent 19fb650b8d
commit 8abd2add2e
5 changed files with 194 additions and 0 deletions
@@ -0,0 +1,35 @@
# Registration token for the Gitea Actions runner.
apiVersion: v1
kind: Secret
metadata:
name: gitea-actions-runner-token
namespace: gitea
type: Opaque
stringData:
token: ENC[AES256_GCM,data:rw08OD2BsIUgZ7eWoYPN4S7LPdbjnE2bPatGrmH2LovCghV8T06OEw==,iv:EDEO3BUMJ3I9ApHYgqtWp91PSzW0tkhVmgSLkeYJ3mk=,tag:jpxIEYFWTrUnZWECFr4Oqw==,type:str]
sops:
lastmodified: "2026-08-22T10:07:49Z"
mac: ENC[AES256_GCM,data:wXXd9sVPoDz8kNPiYnbaAG0f52e3DfSdTPSw8qYmf4C9PVLf4DJ8/xr2tPfoK9hJK+99jt3fqLfKv/PqM673Udn9X5EHiVSBG7o6N9OC6Brq7KfkO0d7bVg3n596xE4VOYi2v1RC+IzR1VNp8nqwTt9sG9hRqwhkYx5awGlzML8=,iv:GB4/aUbajc4qXuZZbT+fAH0HIx+yaADGWKewcPePC5M=,tag:/bfQ0ROsUQ1mO2R/kd9ilA==,type:str]
pgp:
- created_at: "2026-08-22T09:53:39Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA7uy4qQr71wiAQ//SMQVc2JU4VOzEfHh1PhI/oWOTKiZipezvGm3g8F1wik8
VU9Miu0zgMpa6o2OqEg4kzsUyrYY1Zl7lO5ALM74i2Wd4ln/ABA7/sc+rfw73c0b
PFRVoWqXDdhQMXVrUmY48/sUuv0HRtlVpkMjVwKIWdOU17cG8ueMFrM2GRHM8jTC
bxyE2pXMuV04RnQCdXxUkrD2uWxnzqrm6JYa3C7cktU3KGqNgl/m1XBOdm/UBlwW
XqYtpCJrCbpagEB5miSVxpWtqtF7Sq1Plabst+xajVdHhBDFD5Uw6F6EkKsNZbJu
WbaBENV8mkKNC0UwztECd1yw0JdHaejeOib67g6b4rX8l6W5TRLKfkM/Gev0FjOD
uenYUOq+VqlaVhG6lxsAodZ2078kj71JD0tn+DmXYH0le7+IlsqpNmWZyceGtmUJ
5iKoRRyjyeKjoLLkZ/vQwBmp9cbAGCt3O5uV9LiatXEfpHU1QBi8ulXo34uAXAu/
YqWZxkSry+myV31hALTq6iOAb33VY9ha+X+HOHo11XhLae4fImIpFzBNAFtc2kh7
Mbycef0i1C9WsfOIWHzZW6/bkgE8RtpjJmWUhNzvj/pHLbOzUhESC1LjjqbhutTj
ydDTkkXunWu1MEfiqJM1vsZ/c/YQH4MG94ZEfOC+iFay+We6Wd5884EIPP/EC4LS
XAFkt2IABG1C3D86tbBLKvody2+xGnmquUhYqmOhVCmz2jpt5bm/qnLTQw3nKdBe
Y5LyaiJ8wAcRrD5qSK1gzqlCRDPeMSj4+kYFrcInWA24ToBvyYAtBKCzs3Mb
=lonh
-----END PGP MESSAGE-----
fp: DC6910268E657FF70BA7EC289974494E76938DDC
encrypted_regex: ^(data|stringData|.*key|.*crt)$
version: 3.10.2
+7
View File
@@ -5,9 +5,16 @@ resources:
- namespace.yaml
- repository.yaml
- release.yaml
# Gitea Actions runners (gitea/helm-actions "actions" chart, same HelmRepository)
- priorityclass-actions.yaml
- actions-token-secret.yaml
- release-actions.yaml
secretGenerator:
- name: gitea-values
files:
- values.yaml=values.yaml
- name: gitea-actions-values
files:
- values.yaml=values-actions.yaml
configurations:
- kustomizeconfig.yaml
@@ -0,0 +1,17 @@
# Low priority class for Gitea Actions runners.
#
# Negative value + Never preemption policy means runner pods never displace
# other workloads, and are always the first candidates for kubelet eviction
# and the kernel OOM killer when a node runs out of resources. Combined with
# the hard resource limits on the runner pod, an intensive CI job can only
# ever fail itself — it cannot take the node down with it.
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: gitea-actions-runner-low
value: -1000
preemptionPolicy: Never
globalDefault: false
description: >-
Low priority for Gitea Actions runner pods. Under node pressure these pods
are evicted (and OOM-killed) first, protecting system and app workloads.
+34
View File
@@ -0,0 +1,34 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: gitea-actions-runner
namespace: gitea
spec:
interval: 1m
dependsOn:
- name: gitea
chart:
spec:
sourceRef:
kind: HelmRepository
name: gitea
namespace: gitea
chart: actions
version: '0.1.2'
interval: 1m
valuesFrom:
- kind: Secret
name: gitea-actions-values
# The chart has no priorityClassName support: inject a low-priority class so
# runner pods are the first to be evicted/OOM-killed under node pressure,
# instead of starving system or application workloads.
postRenderers:
- kustomize:
patches:
- target:
kind: StatefulSet
name: gitea-actions-runner-runner
patch: |
- op: add
path: /spec/template/spec/priorityClassName
value: gitea-actions-runner-low
+101
View File
@@ -0,0 +1,101 @@
# Values for the gitea-actions (Actions runner) chart.
#
# Hard resource caps: CI jobs can be very intensive, so every layer is capped
# so that a runaway job gets OOM-killed/throttled inside the runner pod instead
# of exhausting the node and taking it (and everything running on it) down.
#
# Layers of protection:
# 1. dind container limits -> hard cap for the Docker daemon and ALL job
# containers it spawns (they run inside the dind cgroup).
# 2. Per-job docker options -> each job container additionally capped below
# the dind limit, keeping headroom for the daemon + image cache.
# 3. Low PriorityClass (injected via postRenderers in release-actions.yaml)
# -> under node pressure the runner is evicted/OOM-killed first.
enabled: true
# Register against the in-cluster Gitea service (chart "gitea" release).
giteaRootURL: http://gitea-http.gitea.svc.cluster.local:3000
existingSecret: gitea-actions-runner-token
existingSecretKey: token
statefulset:
# Single-node cluster, no point in more replicas
replicas: 1
timezone: Europe/Paris
runner:
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
config: |
log:
level: info
cache:
enabled: false
runner:
# One job at a time keeps resource usage predictable
capacity: 1
# Raise if jobs need longer than 3h (Gitea server-side job
# timeout applies as well)
#timeout: 3h
container:
require_docker: true
docker_timeout: 300s
# Hard per-job caps (docker create args). Slightly below the
# dind limits so the daemon and image cache keep headroom.
options: --memory=7g --cpus=3
dind:
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
cpu: 4
memory: 8Gi
# Same failover tolerations/affinity as the gitea release, so runners can
# be scheduled wherever Gitea itself runs (p330 during r740 outage).
tolerations:
- key: ENC[AES256_GCM,data:jC1B3zH0XQ1O,iv:nGWUUNvIB+WBDG4MatKdzXKwWuXjkK2IsaDC8LCakC4=,tag:lp6Uv/aJaUt8XTXXhXQuXA==,type:str]
operator: Equal
value: failover
effect: NoSchedule
- key: ENC[AES256_GCM,data:pmPj2H2dChGATTl5oUJCt6Fq0A64zt/VFxRG6yy0XFKXlUkpgA==,iv:pmNCnZqu4j9TleelYDrtV7u9pjjgDO806lyKXeL3V38=,tag:+MKVAYraGF29PPQlJhQmxg==,type:str]
operator: Exists
effect: NoSchedule
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: ENC[AES256_GCM,data:zTvzBWPLKcDoRMcNlOB0injDajw=,iv:x4yI3vUBThzKTNHEaxelPmMV1fvArLu/avAAeeBP30c=,tag:uJqnx5qIFVYDONvp7Lu31Q==,type:str]
operator: NotIn
values:
- "true"
sops:
lastmodified: "2026-08-22T09:53:39Z"
mac: ENC[AES256_GCM,data:dSUMCCs5iobsQtiktm0YepMqHCjXwPpq35jimoS+IUIeBUO6lLuzt4gS6emVJUBUbNB4rptyqyCxX1GMXj+9iBUwKx2SR+FqXa+AzIJ4JMegF60GBIpBc2rSA7I/jSrv+6DC/7Kq1w5EQ9hhTOXAhhzDxkQjgBJF3jMmMrqU2lw=,iv:pu929/yRvhuMZGY6Yt75RpWCcg4Xr2beZZT2NZVPrOI=,tag:6OavMlfiKjH0w4F47ZJXHg==,type:str]
pgp:
- created_at: "2026-08-22T09:53:39Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA7uy4qQr71wiAQ/+OgDT+QcY0FWtbrwMhUKn9Up6fn5yDy6dUnzr/Uvd+u/G
+5fBBh2oDsLQXyBNIX/OXj6YLq2dBHlrnxGAPVXyoXQtel3OuPWYVVp3bbxR4hOw
XZlqnVU+BYemRHHh/wy1FY/17z2QemKXDieVb51cxYxWXiXc02XVOOH2alglf3M6
X4cTz0iDu+tbLw1rBo9zwuCDJBQ6pCiyvTUdQrJOH8QwSpjd/kXS9BewJLv511LU
9sv0jWkd3O0JPp5SJ2GsmWLZLDE0QHoKmxmSCVWVQVsq85rod6/Ab2oGMeWNaTRn
X96XKyveBRKEbi/d7kCPeTLpKB0qxgAHgxCdQ9yVFucBEibGzHoC8qv0hH68pj46
XInzUjMseTnNNm5xvxrosMA3BMOs0ByYiRY85+x6pO4y9KxehhFTdNnq3XPYFD8x
y7yrmcgDrNXvj6btMt2QvX33idmi73QMQIDghjq3Sejjvg7dGJZgY1k4wZYqyXCD
UMQQ6512utS/RhZ44MUxdD2mhQ9RsCZhmeTXACyYiGW+cBTWkNu6negUIzjA7b4+
H0GOmaiZHlv/oDhM6+IHkV7B8kh/pkQ4em8Qhb6F38lohYyu7V3VBvQzK2egCoE3
7F6XfHa73DPr6/BWepRUcMr9M1YqyQOigx1RaxkIr+7CZwAO3acEbtEzgMY3GBbS
XgHcPOjXwU5N9XZRCzrpLD4iwYbQSSxZdxwKkpME+YRyNJ1edHW4HPNbY+2XC/he
Z55AJsoEPLFyoJQn47BMl8x5RzViSliEtIvwGJDYiO4W1QV+R54j9wm7zelJVMQ=
=Otyl
-----END PGP MESSAGE-----
fp: DC6910268E657FF70BA7EC289974494E76938DDC
encrypted_regex: ^(data|stringData|.*key|.*crt)$
version: 3.10.2