mirror of
https://code.forgejo.org/forgejo/runner.git
synced 2025-07-27 17:28:35 +00:00
Improve doc and add full example for Kubernetes (#657)
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/657 Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org> Co-authored-by: Grégoire Bellon-Gervais <gregoire.bellon-gervais@docaposte.fr> Co-committed-by: Grégoire Bellon-Gervais <gregoire.bellon-gervais@docaposte.fr>
This commit is contained in:
parent
2fbe500d36
commit
d871b38c8d
3 changed files with 181 additions and 44 deletions
|
@ -1,7 +1,20 @@
|
|||
## Kubernetes Docker in Docker Deployment
|
||||
# Kubernetes Docker in Docker Deployment
|
||||
|
||||
Registers Kubernetes pod runners using [offline registration](https://forgejo.org/docs/v1.21/admin/actions/#offline-registration), allowing the scaling of runners as needed.
|
||||
Registers Kubernetes Pod runners using [offline registration](https://forgejo.org/docs/latest/admin/runner-installation/#offline-registration), allowing the scaling of runners as needed.
|
||||
|
||||
NOTE: Docker in Docker (dind) requires elevated privileges on Kubernetes. The current way to achieve this is to set the pod `SecurityContext` to `privileged`. Keep in mind that this is a potential security issue that has the potential for a malicious application to break out of the container context.
|
||||
|
||||
[`dind-docker.yaml`](dind-docker.yaml) creates a deployment and secret for Kubernetes to act as a runner. The Docker credentials are re-generated each time the pod connects and does not need to be persisted.
|
||||
[`dind-docker.yaml`](dind-docker.yaml) creates a Deployment and Secret for Kubernetes to act as a runner. The Docker credentials are re-generated each time the pod connects and does not need to be persisted.
|
||||
|
||||
Do not forget to update `FORGEJO_INSTANCE_URL` value.
|
||||
|
||||
# Build you first container image
|
||||
First, you will need to generate an Applications Access token with the permission `write:package` (see [doc](https://forgejo.org/docs/latest/user/token-scope/)), usually from https://your-forgejo.fr/user/settings/applications.
|
||||
|
||||
Then, you will create 2 forgejo Actions [Secrets](https://forgejo.org/docs/latest/user/actions/#secrets):
|
||||
- `USERNAME_WRITE_REPOSITORY` containing Token name
|
||||
- `PASSWORD_WRITE_REPOSITORY` containing Token value
|
||||
|
||||
And you can then, use the [`build.yaml`](build.yaml) file provided as exemple.
|
||||
|
||||
This file must be created in your repository under: `.forgejo/workflows/build.yaml`
|
||||
|
|
48
examples/kubernetes/build.yaml
Normal file
48
examples/kubernetes/build.yaml
Normal file
|
@ -0,0 +1,48 @@
|
|||
name: build
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- airflow/Dockerfile # Trigger only if Dockerfile is changed
|
||||
- airflow/requirements.txt # Trigger only if requirements.txt is changed
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: docker
|
||||
steps:
|
||||
- name: Checkout the repo
|
||||
uses: https://data.forgejo.org/actions/checkout@v4
|
||||
|
||||
- name: Extract the current airflow version from the Dockerfile and set it in a variable name airflow_version
|
||||
id: extract_airflow_version
|
||||
run: echo "::set-output name=airflow_version::$(grep -oP '(?<=FROM apache/airflow:)[0-9]+\.[0-9]+\.[0-9]+' airflow/Dockerfile)"
|
||||
|
||||
- name: Add variables
|
||||
id: add-vars
|
||||
run: |
|
||||
echo "::set-output name=registry::${GITHUB_SERVER_URL#*//}" # built-in env variable
|
||||
echo "::set-output name=repository::${GITHUB_REPOSITORY}" # built-in env variable
|
||||
echo "::set-output name=app::airflow"
|
||||
echo "::set-output name=context::airflow" # Dockerfile is in airflow folder, so context is airflow folder not .
|
||||
echo "::set-output name=dockerfile::airflow/Dockerfile" # Dockerfile path
|
||||
echo "::set-output name=tag::${{ steps.extract_airflow_version.outputs.airflow_version }}-${{ github.sha}}"
|
||||
|
||||
- name: Docker CLI installation
|
||||
run: |
|
||||
apt update
|
||||
apt install -y ca-certificates curl
|
||||
curl -fsSL https://get.docker.com -o get-docker.sh
|
||||
sh get-docker.sh
|
||||
|
||||
- name: Login to Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ steps.add-vars.outputs.registry }}
|
||||
username: ${{ secrets.USERNAME_WRITE_REPOSITORY }}
|
||||
password: ${{ secrets.PASSWORD_WRITE_REPOSITORY }}
|
||||
|
||||
- name: Image build
|
||||
run: docker build -f ${{ steps.add-vars.outputs.dockerfile }} -t ${{ steps.add-vars.outputs.registry }}/${{ steps.add-vars.outputs.repository }}:${{ steps.add-vars.outputs.app }}-${{ steps.add-vars.outputs.tag }} ${{ steps.add-vars.outputs.context }}
|
||||
|
||||
- name: Image push to registry
|
||||
run: docker push ${{steps.add-vars.outputs.registry }}/${{steps.add-vars.outputs.repository }}:${{steps.add-vars.outputs.app }}-${{ steps.add-vars.outputs.tag }}
|
|
@ -3,43 +3,58 @@
|
|||
# Alternatively, create this with
|
||||
# kubectl create secret generic runner-secret --from-literal=token=your_offline_token_here
|
||||
apiVersion: v1
|
||||
stringData:
|
||||
token: your_offline_secret_here
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: runner-secret
|
||||
stringData:
|
||||
token: your_offline_secret_here # Replace with your Forgejo offline registration token
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: forgejo-runner
|
||||
labels:
|
||||
app: forgejo-runner
|
||||
name: forgejo-runner
|
||||
app.kubernetes.io/component: forgejo-runner
|
||||
app.kubernetes.io/instance: forgejo-runner
|
||||
app.kubernetes.io/managed-by: Kustomize
|
||||
app.kubernetes.io/name: forgejo-runner
|
||||
annotations:
|
||||
argocd.argoproj.io/sync-wave: '1'
|
||||
spec:
|
||||
# Two replicas means that if one is busy, the other can pick up jobs.
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: forgejo-runner
|
||||
strategy: {}
|
||||
template:
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: forgejo-runner
|
||||
labels:
|
||||
app: forgejo-runner
|
||||
app.kubernetes.io/component: forgejo-runner
|
||||
app.kubernetes.io/instance: forgejo-runner
|
||||
app.kubernetes.io/managed-by: Kustomize
|
||||
app.kubernetes.io/name: forgejo-runner
|
||||
spec:
|
||||
automountServiceAccountToken: false
|
||||
restartPolicy: Always
|
||||
volumes:
|
||||
- name: docker-certs
|
||||
emptyDir: {}
|
||||
- name: runner-data
|
||||
emptyDir: {}
|
||||
# Initialise our configuration file using offline registration
|
||||
# https://forgejo.org/docs/v1.21/admin/actions/#offline-registration
|
||||
initContainers:
|
||||
- name: runner-register
|
||||
image: code.forgejo.org/forgejo/runner:6.0.1
|
||||
command: ["forgejo-runner", "register", "--no-interactive", "--token", $(RUNNER_SECRET), "--name", $(RUNNER_NAME), "--instance", $(FORGEJO_INSTANCE_URL)]
|
||||
image: code.forgejo.org/forgejo/runner:6.4.0
|
||||
command:
|
||||
- /bin/bash
|
||||
- -c
|
||||
args:
|
||||
- |
|
||||
while : ; do
|
||||
forgejo-runner register --no-interactive --token $(RUNNER_SECRET) --name $(RUNNER_NAME) --instance $(FORGEJO_INSTANCE_URL) && break ;
|
||||
sleep 1 ;
|
||||
done ;
|
||||
forgejo-runner generate-config > /data/config.yml ;
|
||||
sed -i -e "s|network: .*|network: host|" config.yml ;
|
||||
sed -i -e "s|^ envs:$$| envs:\n DOCKER_HOST: tcp://localhost:2376\n DOCKER_TLS_VERIFY: 1\n DOCKER_CERT_PATH: /certs/client|" config.yml ;
|
||||
sed -i -e "s|^ options:| options: -v /certs/client:/certs/client|" config.yml ;
|
||||
sed -i -e "s| valid_volumes: \[\]$$| valid_volumes:\n - /certs/client|" config.yml
|
||||
env:
|
||||
- name: RUNNER_NAME
|
||||
valueFrom:
|
||||
|
@ -51,37 +66,98 @@ spec:
|
|||
name: runner-secret
|
||||
key: token
|
||||
- name: FORGEJO_INSTANCE_URL
|
||||
value: http://forgejo-http.forgejo.svc.cluster.local:3000
|
||||
value: https://my-forgejo.fr # Replace with your Forgejo instance URL
|
||||
resources:
|
||||
limits:
|
||||
cpu: "0.50"
|
||||
memory: "64Mi"
|
||||
cpu: '0.5'
|
||||
ephemeral-storage: 100Mi
|
||||
memory: 64Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
ephemeral-storage: '0'
|
||||
memory: 64Mi
|
||||
volumeMounts:
|
||||
- name: runner-data
|
||||
mountPath: /data
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
privileged: false
|
||||
readOnlyRootFilesystem: true
|
||||
runAsNonRoot: true
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: runner
|
||||
image: code.forgejo.org/forgejo/runner:6.0.1
|
||||
command: ["sh", "-c", "while ! nc -z localhost 2376 </dev/null; do echo 'waiting for docker daemon...'; sleep 5; done; forgejo-runner daemon"]
|
||||
env:
|
||||
- name: DOCKER_HOST
|
||||
value: tcp://localhost:2376
|
||||
- name: DOCKER_CERT_PATH
|
||||
value: /certs/client
|
||||
- name: DOCKER_TLS_VERIFY
|
||||
value: "1"
|
||||
volumeMounts:
|
||||
- name: runner
|
||||
image: code.forgejo.org/forgejo/runner:6.4.0
|
||||
command:
|
||||
- /bin/bash
|
||||
- -c
|
||||
args:
|
||||
- |
|
||||
while ! nc -z localhost 2376 </dev/null ; do
|
||||
echo 'waiting for docker daemon...' ;
|
||||
sleep 5 ;
|
||||
done ;
|
||||
forgejo-runner --config config.yml daemon
|
||||
env:
|
||||
- name: DOCKER_HOST
|
||||
value: tcp://localhost:2376
|
||||
- name: DOCKER_CERT_PATH
|
||||
value: /certs/client
|
||||
- name: DOCKER_TLS_VERIFY
|
||||
value: '1'
|
||||
resources:
|
||||
limits:
|
||||
cpu: '1'
|
||||
ephemeral-storage: 3Gi
|
||||
memory: 4Gi
|
||||
requests:
|
||||
cpu: 100m
|
||||
ephemeral-storage: '0'
|
||||
memory: 64Mi
|
||||
volumeMounts:
|
||||
- name: docker-certs
|
||||
mountPath: /certs
|
||||
- name: runner-data
|
||||
mountPath: /data
|
||||
- name: tmp
|
||||
mountPath: /tmp
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
privileged: false
|
||||
readOnlyRootFilesystem: true
|
||||
runAsNonRoot: true
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
- name: daemon
|
||||
image: docker.io/docker:28.3.0-dind
|
||||
env:
|
||||
- name: DOCKER_TLS_CERTDIR
|
||||
value: /certs
|
||||
resources:
|
||||
limits:
|
||||
cpu: '1'
|
||||
ephemeral-storage: 3Gi
|
||||
memory: 4Gi
|
||||
requests:
|
||||
cpu: 100m
|
||||
ephemeral-storage: '0'
|
||||
memory: 64Mi
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
- name: docker-certs
|
||||
mountPath: /certs
|
||||
volumes:
|
||||
- name: docker-certs
|
||||
mountPath: /certs
|
||||
emptyDir: {}
|
||||
- name: runner-data
|
||||
mountPath: /data
|
||||
- name: daemon
|
||||
image: docker:27.4.1-dind
|
||||
env:
|
||||
- name: DOCKER_TLS_CERTDIR
|
||||
value: /certs
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
- name: docker-certs
|
||||
mountPath: /certs
|
||||
emptyDir: {}
|
||||
- name: tmp
|
||||
emptyDir: {}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue