feat: add Kubernetes backend for native pod-based job execution #1472

Open
eleboucher wants to merge 1 commit from eleboucher/runner:feat/k8s-backend into main
Contributor

Summary

Adds a Kubernetes backend that executes workflow jobs as Pods in a K8s cluster, similar to GitLab CI Runner's Kubernetes executor and Woodpecker CI's Kubernetes backend.

Instead of requiring Docker-in-Docker to run the runner itself in Kubernetes (the current examples/kubernetes/dind-docker.yaml approach), this backend creates one Pod per job and executes steps via kubectl exec into the main container. Service
containers run as sidecars in the same Pod, sharing localhost.

Usage

# runner config
runner:
    labels:
      - ubuntu-latest:k8spod:///config/podspec.yaml

kubernetes:
    namespace: default
    poll_timeout: 10m

PodSpec templates give full control over resources, node selectors, tolerations, security context, and DinD sidecars. The runner waits for all containers (including native K8s init container sidecars) to be ready before running steps.

Limitations

  • docker:// step actions need a DinD sidecar
  • Image ENV vars not queryable ahead of time (falls back to default PATH)
  • features
    • PR: feat: add Kubernetes backend for native pod-based job execution
## Summary Adds a Kubernetes backend that executes workflow jobs as Pods in a K8s cluster, similar to GitLab CI Runner's Kubernetes executor and Woodpecker CI's Kubernetes backend. Instead of requiring Docker-in-Docker to run the runner itself in Kubernetes (the current examples/kubernetes/dind-docker.yaml approach), this backend creates one Pod per job and executes steps via kubectl exec into the main container. Service containers run as sidecars in the same Pod, sharing localhost. ## Usage ```yaml # runner config runner: labels: - ubuntu-latest:k8spod:///config/podspec.yaml kubernetes: namespace: default poll_timeout: 10m ``` PodSpec templates give full control over resources, node selectors, tolerations, security context, and DinD sidecars. The runner waits for all containers (including native K8s init container sidecars) to be ready before running steps. ## Limitations - docker:// step actions need a DinD sidecar - Image ENV vars not queryable ahead of time (falls back to default PATH) <!--start release-notes-assistant--> <!--URL:https://code.forgejo.org/forgejo/runner--> - features - [PR](https://code.forgejo.org/forgejo/runner/pulls/1472): <!--number 1472 --><!--line 0 --><!--description ZmVhdDogYWRkIEt1YmVybmV0ZXMgYmFja2VuZCBmb3IgbmF0aXZlIHBvZC1iYXNlZCBqb2IgZXhlY3V0aW9u-->feat: add Kubernetes backend for native pod-based job execution<!--description--> <!--end release-notes-assistant-->
eleboucher force-pushed feat/k8s-backend from ae319fa666
Some checks failed
issue-labels / release-notes (pull_request_target) Successful in 7s
Integration tests for the release process / release-simulation (pull_request) Has been cancelled
checks / Build Forgejo Runner (pull_request) Has been cancelled
checks / Build unsupported platforms (pull_request) Has been cancelled
checks / runner exec tests (pull_request) Has been cancelled
checks / Run integration tests with Docker (docker-latest) (pull_request) Has been cancelled
checks / Run integration tests with Docker (docker-stable) (pull_request) Has been cancelled
checks / Run integration tests with Podman (pull_request) Has been cancelled
checks / validate mocks (pull_request) Has been cancelled
checks / validate pre-commit-hooks file (pull_request) Has been cancelled
to a18f0d2808
Some checks failed
cascade / debug (pull_request_target) Has been skipped
cascade / forgejo (pull_request_target) Has been skipped
cascade / end-to-end (pull_request_target) Has been skipped
issue-labels / release-notes (pull_request_target) Successful in 10s
Integration tests for the release process / release-simulation (pull_request) Has been cancelled
checks / Build Forgejo Runner (pull_request) Has been cancelled
checks / Build unsupported platforms (pull_request) Has been cancelled
checks / runner exec tests (pull_request) Has been cancelled
checks / Run integration tests with Docker (docker-latest) (pull_request) Has been cancelled
checks / Run integration tests with Docker (docker-stable) (pull_request) Has been cancelled
checks / Run integration tests with Podman (pull_request) Has been cancelled
checks / validate mocks (pull_request) Has been cancelled
checks / validate pre-commit-hooks file (pull_request) Has been cancelled
2026-04-03 11:36:53 +00:00
Compare
eleboucher force-pushed feat/k8s-backend from a18f0d2808
Some checks failed
cascade / debug (pull_request_target) Has been skipped
cascade / forgejo (pull_request_target) Has been skipped
cascade / end-to-end (pull_request_target) Has been skipped
issue-labels / release-notes (pull_request_target) Successful in 10s
Integration tests for the release process / release-simulation (pull_request) Has been cancelled
checks / Build Forgejo Runner (pull_request) Has been cancelled
checks / Build unsupported platforms (pull_request) Has been cancelled
checks / runner exec tests (pull_request) Has been cancelled
checks / Run integration tests with Docker (docker-latest) (pull_request) Has been cancelled
checks / Run integration tests with Docker (docker-stable) (pull_request) Has been cancelled
checks / Run integration tests with Podman (pull_request) Has been cancelled
checks / validate mocks (pull_request) Has been cancelled
checks / validate pre-commit-hooks file (pull_request) Has been cancelled
to 6b75559371
Some checks failed
cascade / end-to-end (pull_request_target) Has been skipped
cascade / forgejo (pull_request_target) Has been skipped
cascade / debug (pull_request_target) Has been skipped
issue-labels / release-notes (pull_request_target) Successful in 5s
Integration tests for the release process / release-simulation (pull_request) Has been cancelled
checks / Build Forgejo Runner (pull_request) Has been cancelled
checks / Build unsupported platforms (pull_request) Has been cancelled
checks / runner exec tests (pull_request) Has been cancelled
checks / Run integration tests with Docker (docker-latest) (pull_request) Has been cancelled
checks / Run integration tests with Docker (docker-stable) (pull_request) Has been cancelled
checks / Run integration tests with Podman (pull_request) Has been cancelled
checks / validate mocks (pull_request) Has been cancelled
checks / validate pre-commit-hooks file (pull_request) Has been cancelled
2026-04-03 11:47:50 +00:00
Compare
Member

Thank you for you interest in making Forgejo Runner better. We currently do not accept new back-ends for Forgejo Runner, see forgejo/forgejo-actions-feature-requests#4 (comment) and forgejo/forgejo-actions-feature-requests#4 (comment) for the reasoning and what has to happen before new back-ends could be added.

New features without a previous design discussion are a tough sell, too. They usually happen in https://code.forgejo.org/forgejo/forgejo-actions-feature-requests.

Are you aware of https://codeberg.org/forgejo/discussions/issues/66, especially https://codeberg.org/forgejo/discussions/issues/66#issuecomment-9829238?

And while we're at it, there's also Forgejo's AI Agreement, just in case.

A potential way forward for this feature is to live in a fork to gather community feedback and to flesh out the design while working on extension points in Forgejo Runner that enable plug-ins. Let us know if that would be interesting to you.

Thank you for you interest in making Forgejo Runner better. We currently do not accept new back-ends for Forgejo Runner, see https://code.forgejo.org/forgejo/forgejo-actions-feature-requests/issues/4#issuecomment-75711 and https://code.forgejo.org/forgejo/forgejo-actions-feature-requests/issues/4#issuecomment-75729 for the reasoning and what has to happen before new back-ends could be added. New features without a previous design discussion are a tough sell, too. They usually happen in https://code.forgejo.org/forgejo/forgejo-actions-feature-requests. Are you aware of https://codeberg.org/forgejo/discussions/issues/66, especially https://codeberg.org/forgejo/discussions/issues/66#issuecomment-9829238? And while we're at it, there's also [Forgejo's AI Agreement](https://codeberg.org/forgejo/governance/src/commit/540ed55e040466e1c043a0e65ea17abc9835a7ae/AIAgreement.md), just in case. A potential way forward for this feature is to live in a fork to gather community feedback and to flesh out the design while working on extension points in Forgejo Runner that enable plug-ins. Let us know if that would be interesting to you.
eleboucher force-pushed feat/k8s-backend from 6b75559371
Some checks failed
cascade / end-to-end (pull_request_target) Has been skipped
cascade / forgejo (pull_request_target) Has been skipped
cascade / debug (pull_request_target) Has been skipped
issue-labels / release-notes (pull_request_target) Successful in 5s
Integration tests for the release process / release-simulation (pull_request) Has been cancelled
checks / Build Forgejo Runner (pull_request) Has been cancelled
checks / Build unsupported platforms (pull_request) Has been cancelled
checks / runner exec tests (pull_request) Has been cancelled
checks / Run integration tests with Docker (docker-latest) (pull_request) Has been cancelled
checks / Run integration tests with Docker (docker-stable) (pull_request) Has been cancelled
checks / Run integration tests with Podman (pull_request) Has been cancelled
checks / validate mocks (pull_request) Has been cancelled
checks / validate pre-commit-hooks file (pull_request) Has been cancelled
to 26a4ce1e34
Some checks failed
issue-labels / release-notes (pull_request_target) Successful in 6s
cascade / debug (pull_request_target) Has been skipped
cascade / end-to-end (pull_request_target) Successful in 6s
cascade / forgejo (pull_request_target) Successful in 24s
checks / Build Forgejo Runner (pull_request) Failing after 2m12s
checks / validate pre-commit-hooks file (pull_request) Successful in 2m13s
checks / Build unsupported platforms (pull_request) Has been skipped
checks / Run integration tests with Docker (docker-latest) (pull_request) Has been skipped
checks / runner exec tests (pull_request) Has been skipped
checks / Run integration tests with Podman (pull_request) Has been skipped
checks / Run integration tests with Docker (docker-stable) (pull_request) Has been skipped
checks / validate mocks (pull_request) Successful in 2m58s
Integration tests for the release process / release-simulation (pull_request) Successful in 7m52s
2026-04-03 12:36:17 +00:00
Compare
Author
Contributor

@aahlenst wrote in #1472 (comment):

Thank you for you interest in making Forgejo Runner better. We currently do not accept new back-ends for Forgejo Runner, see forgejo/forgejo-actions-feature-requests#4 (comment) and forgejo/forgejo-actions-feature-requests#4 (comment) for the reasoning and what has to happen before new back-ends could be added.

New features without a previous design discussion are a tough sell, too. They usually happen in https://code.forgejo.org/forgejo/forgejo-actions-feature-requests.

Are you aware of https://codeberg.org/forgejo/discussions/issues/66, especially https://codeberg.org/forgejo/discussions/issues/66#issuecomment-9829238?

And while we're at it, there's also Forgejo's AI Agreement, just in case.

Thank you for your quick reply! I also think that adding many backend would make it complicated to contribute and QA the actions. Meanwhile missing kubernetes native support is a pity and hurt adoptability.

I was aware of issue 66 that's why i did this work. about this the code is outdate and use an old version of the runner v9 and has many memory leaks and race condition that didn't make it suitable for production usage.

hopefully you can reconsider adding at least k8s backend until you can work out on a plugin-style.

AI usage was limited to research, no code was generated appart from auto complete.

about your community fork: i agree this might be a good solution in the meantime. the code will live there and mirror to this instance.

@aahlenst wrote in https://code.forgejo.org/forgejo/runner/pulls/1472#issuecomment-83258: > Thank you for you interest in making Forgejo Runner better. We currently do not accept new back-ends for Forgejo Runner, see forgejo/forgejo-actions-feature-requests#4 (comment) and forgejo/forgejo-actions-feature-requests#4 (comment) for the reasoning and what has to happen before new back-ends could be added. > > New features without a previous design discussion are a tough sell, too. They usually happen in https://code.forgejo.org/forgejo/forgejo-actions-feature-requests. > > Are you aware of https://codeberg.org/forgejo/discussions/issues/66, especially https://codeberg.org/forgejo/discussions/issues/66#issuecomment-9829238? > > And while we're at it, there's also [Forgejo's AI Agreement](https://codeberg.org/forgejo/governance/src/commit/540ed55e040466e1c043a0e65ea17abc9835a7ae/AIAgreement.md), just in case. Thank you for your quick reply! I also think that adding many backend would make it complicated to contribute and QA the actions. Meanwhile missing kubernetes native support is a pity and hurt adoptability. I was aware of issue 66 that's why i did this work. [about this](https://codeberg.org/forgejo/discussions/issues/66#issuecomment-9829238) the code is outdate and use an old version of the runner v9 and has many memory leaks and race condition that didn't make it suitable for production usage. hopefully you can reconsider adding at least k8s backend until you can work out on a plugin-style. AI usage was limited to research, no code was generated appart from auto complete. about your community fork: i agree this might be a good solution in the meantime. the code will live [there](https://git.erwanleboucher.dev/eleboucher/runner) and mirror to this instance.
Member

@eleboucher wrote in #1472 (comment):

hopefully you can reconsider adding at least k8s backend until you can work out on a plugin-style.

As already said, it needs a design discussion, time for community feedback, and the willingness to help shape the plug-in architecture. Merging a new feature is the last step that can happen once we're reasonable confident that we have built the right thing.

Would you like to do that? That would be terrific.

@eleboucher wrote in https://code.forgejo.org/forgejo/runner/pulls/1472#issuecomment-83261: > hopefully you can reconsider adding at least k8s backend until you can work out on a plugin-style. As already said, it needs a design discussion, time for community feedback, and the willingness to help shape the plug-in architecture. Merging a new feature is the last step that can happen once we're reasonable confident that we have built the right thing. Would you like to do that? That would be terrific.
Author
Contributor

@aahlenst wrote in #1472 (comment):

@eleboucher wrote in #1472 (comment):

hopefully you can reconsider adding at least k8s backend until you can work out on a plugin-style.

As already said, it needs a design discussion, time for community feedback, and the willingness to help shape the plug-in architecture. Merging a new feature is the last step that can happen once we're reasonable confident that we have built the right thing.

Would you like to do that? That would be terrific.

Yes that's something that i can work on!

@aahlenst wrote in https://code.forgejo.org/forgejo/runner/pulls/1472#issuecomment-83265: > @eleboucher wrote in #1472 (comment): > > > hopefully you can reconsider adding at least k8s backend until you can work out on a plugin-style. > > As already said, it needs a design discussion, time for community feedback, and the willingness to help shape the plug-in architecture. Merging a new feature is the last step that can happen once we're reasonable confident that we have built the right thing. > > Would you like to do that? That would be terrific. Yes that's something that i can work on!
Member

@eleboucher wrote in #1472 (comment):

Yes that's something that i can work on!

Splendid! But before you start, wait for @mfenniak to chime in and greenlight the endeavour.

My proposal would be:

  • Prepare your fork so that other people can try it and provide feedback. Post it in https://codeberg.org/forgejo/discussions/issues/66 to gather feedback.
  • Open an issue in https://code.forgejo.org/forgejo/forgejo-actions-feature-requests that proposes a plug-in architecture. You do not have to come up with plan or a concrete proposal. But you've already developed the Kubernetes integration. So you probably know which extension points you would need, what fits well and what does not. Listing that would be very helpful. If you want to develop a plan for how a plug-in architecture could work, even better.

In that scenario, Forgejo Runner would not be concerned with the design of the Kubernetes-native Runner plug-in itself. From my point of view, no design discussion would then be necessary.

@eleboucher wrote in https://code.forgejo.org/forgejo/runner/pulls/1472#issuecomment-83266: > Yes that's something that i can work on! Splendid! But before you start, wait for @mfenniak to chime in and greenlight the endeavour. My proposal would be: * Prepare your fork so that other people can try it and provide feedback. Post it in https://codeberg.org/forgejo/discussions/issues/66 to gather feedback. * Open an issue in https://code.forgejo.org/forgejo/forgejo-actions-feature-requests that proposes a plug-in architecture. You do not have to come up with plan or a concrete proposal. But you've already developed the Kubernetes integration. So you probably know which extension points you would need, what fits well and what does not. Listing that would be very helpful. If you want to develop a plan for how a plug-in architecture could work, even better. In that scenario, Forgejo Runner would not be concerned with the design of the Kubernetes-native Runner plug-in itself. From my point of view, no design discussion would then be necessary.
Owner

Yes, I'd be interested in discussions about a plugin architecture for these backends, and if we can align on a design I'd be happy to merge a plugin system. We can take the details to a different discussion, but they key design goals for me are:

  • The maintenance, documentation, and support burdens for an additional backend ends up being external to the Forgejo project.
  • And, the scope of understanding required for working on the Forgejo Runner is constrained. It's already a project that requires a lot of esoteric knowledge to work on, and I don't want to add in "and we need maintainers who understand k8s deeply".
Yes, I'd be interested in discussions about a plugin architecture for these backends, and if we can align on a design I'd be happy to merge a plugin system. We can take the details to a different discussion, but they key design goals for me are: - The maintenance, documentation, and support burdens for an additional backend ends up being external to the Forgejo project. - And, the scope of understanding required for working on the Forgejo Runner is constrained. It's already a project that requires a lot of esoteric knowledge to work on, and I don't want to add in "and we need maintainers who understand k8s deeply".
Author
Contributor

@aahlenst @mfenniak Hey thanks for the feedbacks, i submitted the fork to the community https://codeberg.org/forgejo/discussions/issues/66#issuecomment-12615426 and i'm also testing it with my home-ops community as well. Regarding the ADR i made a quick pass on it and made the feature request forgejo/forgejo-actions-feature-requests#107 even though i'm more drawn to the second option to be closer like tekton, i guess the first option is what you had in mind

@aahlenst @mfenniak Hey thanks for the feedbacks, i submitted the fork to the community https://codeberg.org/forgejo/discussions/issues/66#issuecomment-12615426 and i'm also testing it with my home-ops community as well. Regarding the ADR i made a quick pass on it and made the feature request https://code.forgejo.org/forgejo/forgejo-actions-feature-requests/issues/107 even though i'm more drawn to the second option to be closer like tekton, i guess the first option is what you had in mind
Some checks failed
issue-labels / release-notes (pull_request_target) Successful in 6s
cascade / debug (pull_request_target) Has been skipped
Required
Details
cascade / end-to-end (pull_request_target) Successful in 6s
Required
Details
cascade / forgejo (pull_request_target) Successful in 24s
Required
Details
checks / Build Forgejo Runner (pull_request) Failing after 2m12s
Required
Details
checks / validate pre-commit-hooks file (pull_request) Successful in 2m13s
checks / Build unsupported platforms (pull_request) Has been skipped
checks / Run integration tests with Docker (docker-latest) (pull_request) Has been skipped
Required
Details
checks / runner exec tests (pull_request) Has been skipped
Required
Details
checks / Run integration tests with Podman (pull_request) Has been skipped
Required
Details
checks / Run integration tests with Docker (docker-stable) (pull_request) Has been skipped
Required
Details
checks / validate mocks (pull_request) Successful in 2m58s
Integration tests for the release process / release-simulation (pull_request) Successful in 7m52s
This pull request has changes conflicting with the target branch.
  • act/container/docker/extensions_test.go
  • act/container/executions_environment.go
  • act/container/host_environment_test.go
  • act/runner/action.go
  • act/runner/job_executor.go
  • act/runner/run_context.go
  • act/runner/step_docker.go
  • go.mod
  • go.sum
  • internal/pkg/labels/labels.go
View command line instructions

Manual merge helper

Use this merge commit message when completing the merge manually.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u feat/k8s-backend:eleboucher-feat/k8s-backend
git switch eleboucher-feat/k8s-backend
Sign in to join this conversation.
No reviewers
No milestone
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
forgejo/runner!1472
No description provided.