feat: improve Kubernetes worker lifecycle visibility (#3553)

This commit is contained in:
Carlos Florêncio
2026-09-10 11:05:05 +01:00
committed by GitHub
parent 796bf5853f
commit 2858109308
59 changed files with 4364 additions and 262 deletions
+27
View File
@@ -0,0 +1,27 @@
apiVersion: v1
kind: PodTemplate
template:
spec:
automountServiceAccountToken: false
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: kandev-agent
image: ghcr.io/kdlbs/kandev-worker@sha256:REPLACE_WITH_MINIMAL_DIGEST
imagePullPolicy: IfNotPresent
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
memory: 2Gi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
+34
View File
@@ -0,0 +1,34 @@
apiVersion: v1
kind: PodTemplate
template:
spec:
automountServiceAccountToken: false
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: kandev-agent
image: ghcr.io/kdlbs/kandev-worker@sha256:REPLACE_WITH_NODE_PNPM_DIGEST
imagePullPolicy: IfNotPresent
env:
- name: NPM_CONFIG_PREFIX
value: /workspace/.npm-global
- name: PNPM_HOME
value: /workspace/.pnpm
- name: PATH
value: /workspace/.pnpm:/workspace/.npm-global/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
memory: 2Gi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
+30
View File
@@ -0,0 +1,30 @@
apiVersion: v1
kind: PodTemplate
template:
spec:
automountServiceAccountToken: false
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: kandev-agent
image: ghcr.io/kdlbs/kandev-worker@sha256:REPLACE_WITH_PYTHON_DIGEST
imagePullPolicy: IfNotPresent
env:
- name: PIP_CACHE_DIR
value: /workspace/.cache/pip
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
memory: 2Gi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
+37
View File
@@ -0,0 +1,37 @@
# Kandev worker image recipes.
#
# These images are task-session inputs, not control-plane images. Kandev still
# owns the command, helper, credentials, runtime volume, and workspace mount.
ARG BASE_IMAGE=ghcr.io/kdlbs/kandev:0.93.0@sha256:1a3c98e62bb3ab20141695b6a6b6fdcd058480dd2ef42a89277724b95afc6884
FROM ${BASE_IMAGE} AS base
USER root
# Keep runtime installs and caches on the Kandev workspace. The executor mounts
# /workspace after image start, so these directories are created in the image
# only to document the expected ownership and to support image smoke tests.
RUN mkdir -p /workspace/.npm-global /workspace/.pnpm /workspace/.pnpm-store /workspace/.cache/pip \
&& chown -R 1000:1000 /workspace
ENV NPM_CONFIG_PREFIX=/workspace/.npm-global \
PNPM_HOME=/workspace/.pnpm \
PIP_CACHE_DIR=/workspace/.cache/pip \
PATH=/workspace/.pnpm:/workspace/.npm-global/bin:$PATH
FROM base AS minimal
USER 1000
FROM base AS node-pnpm
ARG PNPM_VERSION=9.15.9
USER root
RUN npm install --global --prefix /usr/local "pnpm@${PNPM_VERSION}" \
&& pnpm --version
USER 1000
FROM base AS python
USER 1000
+76
View File
@@ -0,0 +1,76 @@
# Kubernetes worker images
These recipes prepare the main container for a Kandev Kubernetes task session.
They do not start a session by themselves. Kandev adds the command, agentctl
helper, credentials, runtime files, and workspace mounts during launch.
## Targets and pins
Build the targets from the repository root with the immutable base and pnpm
inputs in pins.env.
| Target | Added or verified tools | Runtime paths |
|---|---|---|
| minimal | Node 24, npm, Python 3, venv, Git, and the POSIX tools from the published Kandev base | npm prefix /workspace/.npm-global, pnpm home /workspace/.pnpm, Python cache /workspace/.cache/pip |
| node-pnpm | pnpm 9.15.9 installed under /usr/local | npm globals use /workspace/.npm-global; pnpm uses /workspace/.pnpm and /workspace/.pnpm-store |
| python | Python 3 and venv from the published Kandev base | Python virtual environments and pip cache use /workspace |
The current pin is the multi-platform index for
ghcr.io/kdlbs/kandev:0.93.0:
sha256:1a3c98e62bb3ab20141695b6a6b6fdcd058480dd2ef42a89277724b95afc6884.
The image build and smoke command below is explicitly linux/amd64. A build
for another architecture does not establish Kubernetes lifecycle support for it.
~~~bash
bash scripts/test-kubernetes-worker-images.sh --check
bash scripts/test-kubernetes-worker-images.sh --smoke --platform linux/amd64
~~~
The smoke command builds each target with a unique local tag, runs as UID 1000,
uses a disposable Docker volume, performs a local Git commit, and checks the
target-specific toolchain. It removes only those tags and volumes when it exits.
It does not publish images.
## Use a target in a profile
Copy one of the strict PodTemplate examples from k8s/presets into the existing
Kubernetes executor profile. Replace its image marker with the immutable digest
of the image you built and pushed to your registry. Keep main_container
kandev-agent and set the profile platform to linux/amd64 for the evidence
covered here.
Each example starts with these profile fields:
~~~text
platform: linux/amd64
main_container: kandev-agent
workspace.mode: managed_pvc
workspace.size: 10Gi
workspace.access_modes: ["ReadWriteOnce"]
~~~
Use workspace.mode: empty_dir for disposable work, or
workspace.mode: existing_claim with an administrator-provisioned claim. The
managed PVC preserves the workspace across ordinary Stop and Resume. Archive or
Delete can remove a managed workspace through the existing task lifecycle.
The templates request 250m CPU and 512Mi memory, and limit memory to 2Gi.
These are starting values, not usage measurements. They run the main container
as UID 1000 with a non-root Pod security context, disable service-account token
automount, drop all Linux capabilities, and disable privilege escalation.
The templates deliberately omit Kandev-owned fields. Do not add commands,
arguments, working directories, reserved mounts, ports, restart policy, HOME,
or KANDEV_* environment keys. The existing profile validator rejects those
conflicts before a cluster write.
## Registry substitution
Build and push each target with your registry's immutable digest, then replace
only the image value in the selected PodTemplate. For a local Kind test, the
test fixture may use imagePullPolicy: Never and a locally loaded tag. That
fixture-only tag is not a production pin.
The recipes contain no credentials, repository content, host paths, or Docker
socket mounts. Registry access, Pod admission, storage policy, and outbound
connectivity remain administrator responsibilities.
+5
View File
@@ -0,0 +1,5 @@
# Inputs for the reproducible worker recipes. Keep the multi-platform index
# digest here. The initial lifecycle evidence is linux/amd64.
BASE_IMAGE=ghcr.io/kdlbs/kandev:0.93.0@sha256:1a3c98e62bb3ab20141695b6a6b6fdcd058480dd2ef42a89277724b95afc6884
PNPM_VERSION=9.15.9
PLATFORM=linux/amd64