feat(dev): add lightweight KFP local dev cluster via k3d#753
feat(dev): add lightweight KFP local dev cluster via k3d#753cordeirops wants to merge 3 commits intokubeflow:mainfrom
Conversation
Introduce a k3d-based local development cluster as a low-resource
alternative to running minikube + KFP for contributors who only need
to work on Kale's frontend or backend.
k3d (k3s in Docker) uses ~512 MB of cluster overhead compared to ~2 GB
for minikube, bringing the total footprint for KFP down to ~2.5 GB vs
~4–6 GB with the previous approach. No Kubernetes knowledge is required
beyond installing Docker and kubectl.
Changes:
- Add scripts/kfp-dev-setup.sh: idempotent setup script that installs
k3d if missing, creates a cluster, deploys KFP v2.16 via the official
platform-agnostic kustomize manifests, waits for all pods to be Ready,
and starts a background port-forward with PID tracking
- Add five Makefile targets under a new "KFP Local Cluster" section:
make kfp-dev-setup # first-time cluster creation (~5 min)
make kfp-dev-start # daily: start cluster + port-forward to :8080
make kfp-dev-stop # pause cluster, preserves all pipeline data
make kfp-dev-delete # wipe cluster entirely
make kfp-dev-status # inspect k3d and KFP pod status
- Update clean target to remove the port-forward PID file
After kfp-dev-start, the KFP UI and API are available at
http://localhost:8080, compatible with the existing kfp-run target.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Pedro Sbaraini Cordeiro <pedro.sbarainicordeiro@gmail.com>
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
ada333
left a comment
There was a problem hiding this comment.
Hi, @cordeirops I really like this idea - thank you for making this PR!
I left a few suggestions.
|
|
||
| deploy_kfp() { | ||
| # Idempotent: if the kubeflow namespace already has the ML pipeline CRD, skip | ||
| if kubectl get namespace kubeflow >/dev/null 2>&1 && \ |
There was a problem hiding this comment.
I would do this differently so KFP can be upgraded on existing cluster without the need to delete it - or maybe a new function like upgrade_kfp can be added?
| if k3d cluster list 2>/dev/null | grep -q "^${CLUSTER_NAME}[[:space:]]"; then | ||
| warn "Cluster '${CLUSTER_NAME}' already exists — skipping creation." | ||
| info "Starting cluster in case it was stopped..." | ||
| k3d cluster start "${CLUSTER_NAME}" |
There was a problem hiding this comment.
before this we should switch kubectl context - something like
kubectl config use-context k3d-kale-kfp
| @bash scripts/kfp-dev-setup.sh "$(KFP_CLUSTER_NAME)" "$(KFP_PIPELINE_VERSION)" "$(KFP_LOCAL_PORT)" "$(KFP_PID_FILE)" | ||
|
|
||
| kfp-dev-start: ## Start existing cluster and port-forward KFP UI to localhost:8080 | ||
| @printf "$(BLUE)Starting k3d cluster '$(KFP_CLUSTER_NAME)'...\n$(NC)" |
There was a problem hiding this comment.
also here: kubectl config use-context k3d-kale-kfp
|
|
||
| kfp-dev-status: ## Show cluster and KFP pod status | ||
| @printf "$(BLUE)k3d clusters:\n$(NC)" | ||
| @k3d cluster list 2>/dev/null || printf "$(YELLOW)k3d not installed\n$(NC)" |
There was a problem hiding this comment.
also here: kubectl config use-context k3d-kale-kfp
- Switch kubectl context to k3d-{cluster} after cluster start/create
to ensure all subsequent kubectl commands target the correct cluster,
regardless of the active context before the script runs.
- Extract shared manifest-apply logic into _apply_kfp_manifests() and
introduce upgrade_kfp() alongside the existing deploy_kfp(). The
deploy function skips if KFP is already present; the upgrade function
always re-applies the manifests, allowing in-place version bumps
without deleting the cluster and losing experiment/run history.
- Add make kfp-dev-upgrade target (accepts KFP_PIPELINE_VERSION=X.Y.Z)
to expose the upgrade path from the Makefile.
- Add kubectl context switch to kfp-dev-start Makefile target for
consistency with the setup script.
Signed-off-by: Pedro Sbaraini Cordeiro <pedro.sbarainicordeiro@gmail.com>
|
Thanks for the thorough review, @ada333! I've addressed all three suggestions in the latest commit (933ff5b). Changes made1. Added an explicit context switch in both places flagged:
2. KFP upgrade without deleting the cluster Refactored
A new # Upgrade to a newer KFP version on an existing cluster
make kfp-dev-upgrade KFP_PIPELINE_VERSION=2.17.0Let me know if anything else needs adjusting! |
Signed-off-by: Pedro Sbaraini Cordeiro <pedro.sbarainicordeiro@gmail.com>
The The same workflow passed on PR #754 which ran earlier the same day. This is a known flaky behaviour in CI environments when the runner is under resource pressure. I've pushed an empty commit to re-trigger the workflow. |
Summary
Running a full Kubeflow Pipelines stack for local development currently requires minikube (or equivalent),
kubectl port-forward, and enough memory to host both the Kubernetes control plane (~2 GB) and the KFP services (~2 GB). This makes it impractical for contributors with resource-constrained machines or those who only need to work on Kale's frontend or backend — not on actual pipeline execution.This PR introduces a k3d-based local development cluster as a lightweight, one-command alternative.
k3d runs k3s (a certified, minimal Kubernetes distribution) inside Docker containers. Its control plane uses an embedded SQLite store instead of etcd, reducing cluster overhead from ~2 GB (minikube) to ~512 MB, bringing the total footprint for a full KFP stack down to approximately 2.5 GB.
Changes
scripts/kfp-dev-setup.sh(new)An idempotent Bash script that handles the full first-time setup:
dockerandkubectlare availablek3dautomatically via its official install script if not presentkale-kfp(Traefik ingress disabled to save memory)platform-agnostickustomize manifests fromgithub.com/kubeflow/pipelinesReadystatekubectl port-forwardin the background, tracking its PID in.kfp-dev-pf.pidfor clean teardownThe script is safe to re-run — it skips cluster creation and KFP deployment if they already exist.
Makefile(updated)Five new targets under a dedicated "KFP Local Cluster" section:
make kfp-dev-setupmake kfp-dev-startlocalhost:8080make kfp-dev-stopmake kfp-dev-deletemake kfp-dev-statusAll targets are configurable via Makefile variables (
KFP_CLUSTER_NAME,KFP_PIPELINE_VERSION,KFP_LOCAL_PORT).The
cleantarget is updated to also remove the port-forward PID file.Developer workflow
Requirements
kubectl(available viabrew install kubectlor bundled with Docker Desktop)kfp-dev-setupif not presentResource comparison