Files
homelab/k8s/infra/forgejo-runner/templates/deployment.yaml
T
rock 913cfc2f40 fix: add CoreDNS api.riotpiao.com rewrite + fix runner Alpine base image (#1)
1. Forgejo CI is broken across all repos

 Every workflow fails because runner labels point to a bare Alpine image with nothing in it.

 ┌────────────────────────────────────────┬──────────────────────────────────────┐
 │ Before                                 │ After                                │
 ├────────────────────────────────────────┼──────────────────────────────────────┤
 │ golang:docker://forgejo/runner:6       │ golang:docker://golang:1.26-bookworm │
 ├────────────────────────────────────────┼──────────────────────────────────────┤
 │ No Go, no Node.js, no apt-get, no root │ Go, git, apt-get, root               │
 └────────────────────────────────────────┴──────────────────────────────────────┘

 Plus the docker socket isn't shared between dind sidecar and runner, so even if docker CLI existed, it can't reach the daemon.

 ┌───────────────────────────────────────────┬─────────────────────────────────────────────────────────────┐
 │ Before                                    │ After                                                       │
 ├───────────────────────────────────────────┼─────────────────────────────────────────────────────────────┤
 │ dind creates socket in its own filesystem │ Shared /run emptyDir volume                                 │
 ├───────────────────────────────────────────┼─────────────────────────────────────────────────────────────┤
 │ Runner can't see it                       │ Both containers see /run/docker.sock                        │
 ├───────────────────────────────────────────┼─────────────────────────────────────────────────────────────┤
 │ No docker_host config                     │ docker_host: automount passes socket to workflow containers │

Co-authored-by: rock <[email protected]>
2026-09-07 05:19:39 +00:00

130 lines
4.6 KiB
YAML

apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Release.Name }}
spec:
replicas: 1
strategy:
type: Recreate # RWO PVCs — old pod must terminate before new one mounts them
selector:
matchLabels:
app: {{ .Release.Name }}
template:
metadata:
labels:
app: {{ .Release.Name }}
spec:
# runner image runs as UID 1000; fsGroup makes the Longhorn /data PVC
# group-writable so `register` can write /data/.runner (else permission denied).
securityContext:
fsGroup: 1000
tolerations:
{{- toYaml .Values.tolerations | nindent 8 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
initContainers:
- name: register
image: {{ .Values.runner.image.repository }}:{{ .Values.runner.image.tag }}
command: ["sh", "-c"]
args:
- |
test -f /data/.runner || forgejo-runner register --no-interactive \
--instance {{ .Values.runner.forgejoUrl }} \
--token $(RUNNER_TOKEN) \
--name {{ .Values.runner.name }} \
--labels "{{ .Values.runner.labels }}"
env:
- name: RUNNER_TOKEN
valueFrom:
secretKeyRef:
name: {{ .Values.runner.tokenSecret }}
key: token
volumeMounts:
- name: runner-data
mountPath: /data
- name: homelab-ca
mountPath: /etc/ssl/certs/homelab-ca.pem
subPath: ca.crt
workingDir: /data
containers:
- name: runner
image: {{ .Values.runner.image.repository }}:{{ .Values.runner.image.tag }}
command: ["sh", "-c", "forgejo-runner daemon --config /etc/forgejo-runner/config.yaml"]
workingDir: /data
env:
- name: DOCKER_HOST
value: tcp://localhost:2376
- name: DOCKER_TLS_VERIFY
value: "1"
- name: DOCKER_CERT_PATH
value: /docker-certs/client
volumeMounts:
- name: runner-data
mountPath: /data
- name: docker-certs
mountPath: /docker-certs
- name: docker-sock
mountPath: /run
- name: homelab-ca
mountPath: /etc/ssl/certs/homelab-ca.pem
subPath: ca.crt
- name: runner-config
mountPath: /etc/forgejo-runner
readOnly: true
resources:
{{- toYaml .Values.runner.resources | nindent 12 }}
- name: dind
image: {{ .Values.dind.image.repository }}:{{ .Values.dind.image.tag }}
securityContext:
privileged: true # required for DinD; cicd namespace is labelled privileged
env:
- name: DOCKER_TLS_CERTDIR
value: /docker-certs
volumeMounts:
- name: docker-certs
mountPath: /docker-certs
- name: docker-sock
mountPath: /run
- name: dind-storage
mountPath: /var/lib/docker
- name: homelab-ca
mountPath: /etc/ssl/certs/homelab-ca.pem
subPath: ca.crt
# dockerd resolves per-registry CAs from /etc/docker/certs.d/<host>/
# before falling back to the system pool. Mounting it here is what
# makes `docker push forgejo.riotpiao.com/...` trust the homelab CA
# rather than failing x509: signed by unknown authority.
- name: homelab-ca
mountPath: /etc/docker/certs.d/forgejo.riotpiao.com/ca.crt
subPath: ca.crt
resources:
{{- toYaml .Values.dind.resources | nindent 12 }}
volumes:
- name: runner-data
persistentVolumeClaim:
claimName: {{ .Release.Name }}-reg
- name: dind-storage
persistentVolumeClaim:
claimName: {{ .Release.Name }}-dind
- name: docker-certs
emptyDir: {} # DinD regenerates mTLS certs on each start
- name: docker-sock
emptyDir: {} # Shared docker socket between dind and runner
- name: homelab-ca
# homelab-ca is a ConfigMap (public CA trust bundle), not a Secret.
# The volumeMounts use subPath: ca.crt to project the single cert file.
configMap:
name: homelab-ca
- name: runner-config
configMap:
name: {{ .Release.Name }}-config