Development Guide
This guide provides comprehensive instructions for setting up a development environment for KServe, whether you want to contribute to the project or create a custom development setup. You'll learn how to:
- Install the required development tools and dependencies
- Deploy KServe in different configurations (serverless or raw deployment modes)
- Set up networking requirements for each deployment option
- Understand the KServe architecture and development workflow
- Build, test, and debug your KServe development environment
Prerequisites
Follow the instructions below to set up your development environment. Once you meet these requirements, you can make changes and deploy your own version of KServe!
Before submitting a PR, see also the contribution guidelines.
Install Development Tools
You must install these tools:
go
: KServe controller is written in Go and requires Go 1.24.1+.git
: For source control.ko
: For development and building container images without a Dockerfile.kubectl
: For managing Kubernetes clusters and resources.pre-commit
: Used to run checks on the codebase before committing changes.helm
: Used to install KServe and dependencies.uv
: Used to create and manage virtual environments.
Setup Your Environment
To start your environment, you'll need to set these environment variables (we
recommend adding them to your .bashrc
):
-
GOPATH
: If you don't have one, simply pick a directory and addexport GOPATH=...
-
$GOPATH/bin
onPATH
: This is so that tooling installed viago get
will work properly. -
KO_DEFAULTPLATFORMS
: If you are using M1 Mac book the value islinux/arm64
. -
KO_DOCKER_REPO
: The docker repository to which developer images should be pushed (e.g.docker.io/<username>
).Note: Set up a docker repository for pushing images. You can use any container image registry by adjusting the authentication methods and repository paths mentioned in the sections below.
If you are using Docker Hub to store your images, your KO_DOCKER_REPO
variable should be docker.io/<username>
.
Currently, Docker Hub doesn't let you create subdirs under your username.
.bashrc
example:
export GOPATH="$HOME/go"
export PATH="${PATH}:${GOPATH}/bin"
export KO_DOCKER_REPO='docker.io/<username>'
Checkout Your Fork
To check out this repository:
- Create your own fork of this repo
- Clone it to your machine:
git clone git@github.com:${YOUR_GITHUB_USERNAME}/kserve.git
cd kserve
git remote add upstream git@github.com:kserve/kserve.git
git remote set-url --push upstream no_push
Adding the upstream
remote sets you up nicely for regularly
syncing your fork.
Once you reach this point, you are ready to do a full build and deploy as described below.
Install Pre-commit Hooks
Configuring pre-commit hooks will run checks on the codebase before committing changes. This will help you catch lint errors, formatting issues, and other common problems before they reach the repository.
pre-commit install --install-hooks
Local Development and Testing
This section provides guidance on developing KServe locally and testing your changes.
Setting Up a Local Development Environment
For local development, we recommend using either:
Using kind for Development
-
Create a cluster with required features:
cat <<EOF | kind create cluster --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 31080 # exposed NodePort for ingress
hostPort: 80
- containerPort: 31443 # exposed NodePort for ingress
hostPort: 443
EOF -
Configure ko for local development:
# For local development with kind
export KO_DOCKER_REPO=kind.local
Using minikube for Development
-
Start minikube:
minikube start --driver=docker --memory=8192 --cpus=4
-
Enable the registry addon:
minikube addons enable registry
-
Configure Docker to use Minikube's daemon:
eval $(minikube docker-env)
export KO_DOCKER_REPO=localhost:5000
Installation Requirements
KServe offers two deployment modes:
- Serverless deployment requires
Knative Serving
for request-based auto-scaling, scale-to-zero, and canary rollouts - Raw deployment doesn't require Knative, suitable for generative inference workloads with stable resource allocation
For networking:
- Serverless mode: Requires Knative Serving; while Istio is recommended as the networking layer for Knative, you can use any ingress/networking solution supported by Knative (like Kourier or Contour)
- Raw deployment: Uses Gateway API or standard Kubernetes Ingress, compatible with various networking implementations
Note that the quick install script installs Istio by default for both deployment modes for convenience.
Quick Installation (Recommended for Development)
For development purposes, you can use the quick install script provided in the KServe repository:
# Clone the repository if you haven't already
git clone https://github.com/kserve/kserve.git
cd kserve
# Run the quick install script with serverless mode (installs Knative + Istio)
./hack/quick_install.sh -s
# For Raw deployment mode (without Knative, using Gateway API + Istio)
./hack/quick_install.sh -r
# To install only dependencies (without KServe)
./hack/quick_install.sh -d
# To include KEDA (Kubernetes Event-driven Autoscaling)
./hack/quick_install.sh -k
The script installs:
- Gateway API CRDs (used by both deployment modes)
- Istio (installed by default for both modes, but not strictly required)
- Cert Manager (for webhook certificates)
- Knative Operator and Serving (only when using serverless mode with
-s
flag) - Optionally KEDA for event-driven autoscaling (with
-k
flag) - Latest stable KServe CRDs and controller (configured for the selected deployment mode)
You can check the current versions used in the script by examining the environment variables at the top of the hack/quick_install.sh
file.
To uninstall everything, run:
./hack/quick_install.sh -u
Manual Installation
If you prefer manual installation, follow the instructions from the administrator guide.
Deploy KServe
Deploy KServe from Master Branch
When deploying manually, we suggest using cert manager for provisioning the certificates for the webhook server. Other solutions should also work as long as they put the certificates in the desired location.
If you don't want to install cert manager, you can set the KSERVE_ENABLE_SELF_SIGNED_CA
environment variable to true. KSERVE_ENABLE_SELF_SIGNED_CA
will execute a script to create a self-signed CA and patch it to the webhook config.
export KSERVE_ENABLE_SELF_SIGNED_CA=true
After that, you can run the following command to deploy KServe
. You can skip the above step if cert manager is already installed.
make deploy
You can change CPU and memory limits when deploying KServe
.
export KSERVE_CONTROLLER_CPU_LIMIT=<cpu_limit>
export KSERVE_CONTROLLER_MEMORY_LIMIT=<memory_limit>
make deploy
$ kubectl get pods -n kserve -l control-plane=kserve-controller-manager
NAME READY STATUS RESTARTS AGE
kserve-controller-manager-0 2/2 Running 0 13m
By default, it installs to the kserve
namespace with the published controller manager image from the master branch.
Deploy KServe with Your Own Version
Whether you used the quick install script or deployed manually, when you want to test your local code changes, you'll need to rebuild and redeploy the components you've modified.
Run the following command to deploy the KServe
controller and model agent with your local changes:
make deploy-dev
deploy-dev
builds the image from your local code, publishes to KO_DOCKER_REPO
, and deploys the kserve-controller-manager
and model agent
with the image digest to your cluster for testing.
Please also ensure you are logged in to KO_DOCKER_REPO
from your client machine.
Run the following command to deploy the model server with your local changes:
make deploy-dev-sklearn
make deploy-dev-huggingface
Run the following command to deploy the explainer with your local changes:
make deploy-dev-alibi
Run the following command to deploy the storage initializer with your local changes:
make deploy-dev-storageInitializer
The deploy
command publishes the image to KO_DOCKER_REPO
with the version latest
and changes the InferenceService
configmap or the respective ServingRuntime
to point to the newly built image SHA. It is recommended to first build and deploy the controller and model agent with make deploy-dev
before deploying the model server, explainer, or storage initializer using respective deploy-dev-<component>
commands.
The built image is only for development and testing purposes. The current limitation is that it changes the impacted image and resets all other images, including the
kserve-controller-manager
, to use the default ones.
Smoke Test After Deployment
Run the following command to smoke test the deployment:
kubectl apply -f https://raw.githubusercontent.com/kserve/kserve/master/docs/samples/v1beta1/tensorflow/tensorflow.yaml
You should see model serving deployment running under default or your specified namespace:
kubectl get pods -n default -l serving.kserve.io/inferenceservice=flower-sample
NAME READY STATUS RESTARTS AGE
flower-sample-default-htz8r-deployment-8fd979f9b-w2qbv 3/3 Running 0 10s
Running Unit/Integration Tests
kserver-controller-manager
has a few integration tests which require mock apiserver
and etcd; they get installed along with kubebuilder
.
To run all unit/integration tests:
make test
To run servingruntime tests:
Go to the respective runtime directory, e.g., python/huggingface
, and run:
make dev_install
pytest .
Run E2E Tests Locally
To set up from local code:
- Install KServe dependencies using the quick install script with the
-d
flag (installs dependencies only):./hack/quick_install.sh -d
- If you already have a KServe installation, undeploy it:
make undeploy
- Deploy KServe with your local changes:
make deploy-dev
Go to python/kserve
and install KServe Python SDK deps:
uv sync --group test --group dev
Then go to end to end test directory
cd test/e2e
Run kubectl create namespace kserve-ci-e2e-test
For KIND/minikube:
- Run
export KSERVE_INGRESS_HOST_PORT=localhost:8080
- In a different window run
kubectl port-forward -n istio-system svc/istio-ingressgateway 8080:80
- Note that not all tests will pass as the PyTorch test requires GPU. These will show as pending pods at the end, or you can add a marker to skip the test.
Run pytest -m <markers> > testresults.txt
. You can view the available markers by running pytest --markers
.
When running tests with Gateway API, you should provide the --networking-layer
flag to specify the networking layer. The available options are istio-gatewayapi
, envoy-gatewayapi
, and knative
.
Tests may not clean up. To re-run, first do kubectl delete namespace kserve-ci-e2e-test
, recreate the namespace, and run again.
Iterating
As you make changes to the code-base, there are special cases to be aware of:
-
If you change an input to generated code, then you must run
make manifests
. Inputs include:- API type definitions in apis/serving
- Manifests or kustomize patches stored in config.
To generate the KServe python/go clients, you should run
make generate
. -
If you want to add new dependencies, then you add the imports and the specific version of the dependency module in
go.mod
. When it encounters an import of a package not provided by any module ingo.mod
, the go command automatically looks up the module containing the package and adds it togo.mod
using the latest version. -
If you want to upgrade the go dependency, then you run the go get command e.g.,
go get golang.org/x/text
to upgrade to the latest version,go get golang.org/x/text@v0.3.0
to upgrade to a specific version. -
If you want to upgrade the python dependency, then you can add the package to the respective
pyproject.toml
and runuv lock
to update the package version.
You can run make precommit
to make sure that your code passes all the pre-commit hooks and checks before committing.
After making your changes, you can deploy KServe with your updates:
make deploy-dev
Contribute to the Code
See the guidelines for:
Releases
Please check out the documentation here to understand the release schedule and process.
Feedback
The best place to provide feedback about the KServe code is via a Github issue. See creating a Github issue for guidelines on submitting bugs and feature requests.
Common Development Issues and Solutions
Installation Issues
Knative Installation Fails
Error: failed to create resource: Invalid value: "some-namespace": must be a DNS label
- Ensure your namespace names follow Kubernetes naming conventions
- Try using the YAML installation method instead of the Knative Quickstart
- Verify you have appropriate RBAC permissions
Istio Installation Issues
Error: failed to create resource: CustomResourceDefinition.apiextensions.k8s.io "gateways.networking.istio.io" is invalid
- This can happen when installing a newer version of Istio over an older one
- Clean up the old Istio installation first:
istioctl x uninstall --purge
KServe Webhook Issues
Error: Internal error occurred: failed calling webhook "isvc.serving.kserve.io"
- Verify the webhook service is running:
kubectl get pods -n kserve
- Check cert-manager is properly installed and has generated valid certificates
- Look at controller pod logs:
kubectl logs -n kserve <controller-pod-name>
Networking Issues
Unable to Access InferenceService
- Check that your Gateway or Ingress is properly configured
- For serverless mode, verify Knative endpoints:
kubectl get ksvc -n your-namespace
- For raw mode, check Gateway resources:
kubectl get gateways,httproutes -A
- Verify network policies allow traffic to your services
Slow Cold Start in Serverless Mode
- Consider setting
minScale
in your InferenceService spec to keep a minimum number of pods ready - Check for large container images that might be slow to pull
- Review resource limits and requests
Development Workflow Issues
Local Development with ko
If ko
fails to build and deploy:
- Ensure
KO_DOCKER_REPO
is set correctly for your environment - For kind clusters, use
export KO_DOCKER_REPO=kind.local
- Check Docker daemon is running and accessible
Pre-commit Hooks Failing
- Run
pre-commit install --install-hooks
to ensure hooks are installed - Update pre-commit:
pre-commit autoupdate
- Check individual errors in the pre-commit output
Go Module Issues
go: inconsistent vendoring in ...
- Run
go mod tidy
- Ensure Go version matches the project requirements
Debugging Resources
For more detailed debugging approaches, see the debugging guide.
When troubleshooting, the KServe controller and webhook logs are invaluable:
kubectl logs -n kserve -l control-plane=kserve-controller-manager