From 8abd2add2eb4257814bf11b254502f479e466ece Mon Sep 17 00:00:00 2001 From: Valentin Haudiquet Date: Sat, 22 Aug 2026 12:15:30 +0200 Subject: [PATCH] gitea: deploy in-cluster action runner --- .../dev/gitea/actions-token-secret.yaml | 35 ++++++ kubernetes/dev/gitea/kustomization.yaml | 7 ++ .../dev/gitea/priorityclass-actions.yaml | 17 +++ kubernetes/dev/gitea/release-actions.yaml | 34 ++++++ kubernetes/dev/gitea/values-actions.yaml | 101 ++++++++++++++++++ 5 files changed, 194 insertions(+) create mode 100644 kubernetes/dev/gitea/actions-token-secret.yaml create mode 100644 kubernetes/dev/gitea/priorityclass-actions.yaml create mode 100644 kubernetes/dev/gitea/release-actions.yaml create mode 100644 kubernetes/dev/gitea/values-actions.yaml diff --git a/kubernetes/dev/gitea/actions-token-secret.yaml b/kubernetes/dev/gitea/actions-token-secret.yaml new file mode 100644 index 0000000..57acf31 --- /dev/null +++ b/kubernetes/dev/gitea/actions-token-secret.yaml @@ -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 diff --git a/kubernetes/dev/gitea/kustomization.yaml b/kubernetes/dev/gitea/kustomization.yaml index a1f88e7..1e79569 100644 --- a/kubernetes/dev/gitea/kustomization.yaml +++ b/kubernetes/dev/gitea/kustomization.yaml @@ -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 diff --git a/kubernetes/dev/gitea/priorityclass-actions.yaml b/kubernetes/dev/gitea/priorityclass-actions.yaml new file mode 100644 index 0000000..c89f50d --- /dev/null +++ b/kubernetes/dev/gitea/priorityclass-actions.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. diff --git a/kubernetes/dev/gitea/release-actions.yaml b/kubernetes/dev/gitea/release-actions.yaml new file mode 100644 index 0000000..f430e76 --- /dev/null +++ b/kubernetes/dev/gitea/release-actions.yaml @@ -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 diff --git a/kubernetes/dev/gitea/values-actions.yaml b/kubernetes/dev/gitea/values-actions.yaml new file mode 100644 index 0000000..c525b85 --- /dev/null +++ b/kubernetes/dev/gitea/values-actions.yaml @@ -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