Skip to content

Kubernetes: precreate workingDir as nonroot when required#6322

Merged
6543 merged 3 commits into
woodpecker-ci:mainfrom
Aex12:feat/kubernetes-unprivileged-clone-step
Apr 28, 2026
Merged

Kubernetes: precreate workingDir as nonroot when required#6322
6543 merged 3 commits into
woodpecker-ci:mainfrom
Aex12:feat/kubernetes-unprivileged-clone-step

Conversation

@Aex12

@Aex12 Aex12 commented Mar 25, 2026

Copy link
Copy Markdown
Contributor

Problem

When the working directory is set to a directory that doesn't exists (for example, as plugin-git does), kubelet will pre-create it with ownership set to root:root and permissions 0755 . This makes pods running as non-root unable to write to it, causing permission errors.

Solution

Added a podInitContainer function that conditionally creates an init container to pre-create the working directory with the correct permissions before the main step container starts.

Behavior

  • If the pod runs as root (RunAsUser == 0 or unset), no init container is created. Kubelet handles directory creation automatically
  • If the working directory matches a volume mount path exactly, no init container is needed. FSGroupChangePolicy handles permissions
  • An init container is only created when the working directory is nested within a volume mount path
  • The init container uses busybox:stable-musl with minimal resource limits (5m CPU, 5Mi memory) and drops all capabilities.

Related issues and PRs

@Aex12

Aex12 commented Mar 25, 2026

Copy link
Copy Markdown
Contributor Author

Hi @6543, what do you think about this alternative approach to #6312 for allowing the clone step to run unprivileged?

This approach is more self contained to kubernetes only, so other backends remain unaffected.

This PR doesn't cover the home issue mentioned in that PR, but still improves the experience of running woodpecker workloads in unprivileged namespaces in Kubernetes.

As an example, with this PR changes (in addition to #6322 and #6307) it's possible to run the clone step completely unprivileged by setting the following agent env vars:

WOODPECKER_BACKEND_K8S_DEFAULT_SECCTX='{"runAsUser":1000,"runAsGroup":1000,"fsGroup":1000,"fsGroupChangePolicy": "OnRootMismatch"}'
WOODPECKER_BACKEND_K8S_ENFORCED_SECCTX='{"privileged":false,"runAsNonRoot":true,"allowPrivilegeEscalation":false,"seccompProfile": {"type": "RuntimeDefault"}, "capabilities": {"drop": ["ALL"]}}'

And using this workflow:

clone:
  git:
    image: docker.io/woodpeckerci/plugin-git
    settings:
      depth: 0
      home: "/tmp"

steps:
  - name: check-clone-succeeded
    image: alpine
    commands:
      - pwd
      - ls -lah

Not as convenient as if home was set to /tmp by default, as it wouldn't require additional changes to the workflow, but still a step forward in making the Kubernetes backend in unprivileged mode more convenient to use.

@Aex12 Aex12 force-pushed the feat/kubernetes-unprivileged-clone-step branch from b82ea45 to b730cca Compare March 25, 2026 01:58
@codecov

codecov Bot commented Mar 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 41.12%. Comparing base (52ed3f1) to head (cf59c3c).
⚠️ Report is 24 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6322      +/-   ##
==========================================
- Coverage   41.29%   41.12%   -0.18%     
==========================================
  Files         431      431              
  Lines       28792    28821      +29     
==========================================
- Hits        11890    11852      -38     
- Misses      15836    15899      +63     
- Partials     1066     1070       +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@6543 6543 added the enhancement improve existing features label Mar 29, 2026
Comment thread pipeline/backend/kubernetes/pod.go
Comment thread pipeline/backend/kubernetes/pod_test.go
@Aex12 Aex12 force-pushed the feat/kubernetes-unprivileged-clone-step branch from 6994e5b to 8a70a27 Compare April 1, 2026 16:56
@Aex12

Aex12 commented Apr 1, 2026

Copy link
Copy Markdown
Contributor Author

I took the opportunity to rebase from main to make merging easier

@6543 6543 enabled auto-merge (squash) April 28, 2026 15:12
@6543 6543 merged commit 85c71fb into woodpecker-ci:main Apr 28, 2026
7 checks passed
@woodpecker-bot woodpecker-bot mentioned this pull request Apr 28, 2026
1 task
@6543

6543 commented Apr 28, 2026

Copy link
Copy Markdown
Member

@Aex12 thanks for the work ... took us some time to get reviewed :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend/kubernetes enhancement improve existing features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants