Technical Documentation: SeldonIO/seldon-core
ℹ️ Provenance: Multi-Tier Ingestion · CodeWiki Reference
Overview (`README.md`)
Deploy Modular, Data-centric AI applications at scale
💡 About
Seldon Core 2 is an MLOps and LLMOps framework for deploying, managing and scaling AI systems in Kubernetes - from singular models, to modular and data-centric applications. With Core 2 you can deploy in a standardized way across a wide range of model types, on-prem or in any cloud, and production-ready out of the box.
To reach out to Seldon regarding commercial use, visit our website.
📚 Documentation
The Seldon Core 2 Docs can be found here. For most specific sections, see here:
🧩 Features
- Pipelines: Deploy composable AI applications, leveraging Kafka for realtime data streaming between components
- Autoscaling for models and application components based on native or custom logic
- Multi-Model Serving: Save infrastructure costs by consolidating multiple models on shared inference servers
- Overcommit: Deploy more models than available memory allows, saving infrastructure costs for unused models
- Experiments: Route data between candidate models or pipelines, with support for A/B tests and shadow deployments
- Custom Components: Implement custom logic, drift & outlier detection, LLMs and more through plug-and-play integrate with the rest of Seldon's ecosytem of ML/AI products!
🔬 Research
These features are influenced by our position paper on the next generation of ML model serving frameworks:
👉 Desiderata for next generation of ML model serving
📜 License
Seldon is distributed under the terms of the The Business Source License. A complete version of the license is available in the LICENSE file in this repository. Any contribution made to this project will be licensed under the Business Source License.
Overview (`ansible/README.md`)
Ansible Installation
The Ansible installation of a Seldon Core and associated ecosystem is meant for **dev/testing** purposes.
For production use cases follow [Helm installation](https://docs.seldon.io/projects/seldon-core/en/v2/contents/getting-started/kubernetes-installation/helm.html).Installing Ansible
Provided Ansible playbooks and roles depends
on kubernetes.core Ansible Collection for performing kubectl
and helm operations.
Check Ansible [documentation] for further information.
We provide a make target to install Ansible together with dependencies and any required collections.
Run the following from the ansible directory:
make install_deps_stableWe have tested provided instructions on Python 3.8 - 3.11 with following version of Python libraries
| Python | Ansible | Docker | Kubernetes |
|---|---|---|---|
| 3.8 | 6.7.0 | 6.0.1 | 26.1.0 |
| 3.9 | 7.2.0 | 6.0.1 | 26.1.0 |
| 3.10 | 7.2.0 | 6.0.1 | 26.1.0 |
| 3.11 | 7.2.0 | 6.0.1 | 26.1.0 |
and kubernetes.core collection in version 2.4.0.
Once installed you can use the following Playbooks that you will find
in Ansible folder of Seldon Core 2 repository.
You also need to have installed kubectl CLI.
Installing Seldon Core 2 using Ansible
One-liner local kind install (from scratch)
If you simply want to install into a fresh local kind
k8s cluster, the seldon-all playbook allows you to do so with a single command:
ansible-playbook playbooks/seldon-all.yamlThis will create a Kind cluster and install ecosystem dependencies (kafka,
prometheus, opentelemetry, jager) as well as all the seldon-specific components.
The seldon components are installed using helm-charts from the current git
checkout (../k8s/helm-charts/).
Internally this runs, in order, the following playbooks (described in more detail
in the sections below):
- kind-cluster.yaml
- setup-ecosystem.yaml
- setup-seldon.yaml
You may pass any of the additonal variables which are configurable for those playbooks
to seldon-all. See the Customizing Ansible Instalation section for details.
For example:
ansible-playbook playbooks/seldon-all.yaml -e seldon_mesh_namespace=my-seldon-mesh -e install_prometheus=no -e @playbooks/vars/set-custom-images.yamlRunning the playbooks individually, as described in the sections below, will give you
more control over what gets run and when (for example, if you want to install into an
existing k8s cluster).
Create Kind Cluster
It is recommended to first install Seldon inside Kind cluster.
This allow to test and trial the installation in isolated environment that is easy to remove.
ansible-playbook playbooks/kind-cluster.yamlSetup Ecosystem
Seldon runs by default in seldon-mesh namespace and a Jaeger pod and and OpenTelemetry collector are installed in the
chosen namespace. Run the following:
ansible-playbook playbooks/setup-ecosystem.yamlThe most common change will be to install in another namespace with:
ansible-playbook playbooks/setup-ecosystem.yaml -e seldon_mesh_namespace=<mynamespace>Install Seldon Core 2
Run the following from the ansible/ folder:
ansible-playbook playbooks/setup-seldon.yamlIf you have changed the namespace you wish to use you will need to run with:
ansible-playbook playbooks/setup-seldon.yaml -e seldon_mesh_namespace=<mynamespace>Customizing Ansible Installation
Ecosystem configuration options
The ecosystem setup can be parametrized by providing extra Ansible variables, e.g. using -e flag to ansible-playbook
command.
For example run the following from the ansible/ folder:
ansible-playbook playbooks/setup-ecosystem.yaml -e full_install=no -e install_kafka=yeswill only install Kafka when setting up the ecosystem.
| type | default | comment | |
|---|---|---|---|
| seldon_mesh_namespace | string | seldon-mesh | namespace to install Seldon Core 2 |
| seldon_kafka_namespace | string | seldon-mesh | namespace to install Kafka Cluster for Seldon Core 2 |
| full_install | bool | yes | enables full ecosystem installation |
| install_kafka | bool | {{ full_install }} |
installs Strimzi Kafka Operator |
| install_prometheus | bool | {{ full_install }} |
installs Prometheus Operator |
| install_grafana | bool | {{ full_install }} |
installs Grafana Operator |
| install_certmanager | bool | {{ full_install }} |
installs Cert Manager |
| install_jaeger | bool | {{ full_install }} |
installs Jaeger |
| install_opentelemetry | bool | {{ full_install }} |
installs OpenTelemetry |
| configure_kafka | bool | {{ install_kafka }} |
configures Kafka Cluster for Seldon Core 2 |
| configure_prometheus | bool | {{ install_prometheus }} |
configure Prometheus using Seldon Core 2 specific resources |
| configure_jaeger | bool | {{ install_jaeger }} |
configure Jaeger using Seldon Core 2 specific resources |
| configure_opentelemetry | bool | {{ install_opentelemetry }} |
configure OpenTelemetry using Seldon Core 2 specific resources |
| install_schema_registry | bool | false |
installs Schema Registry |
| install_clickhouse | bool | false |
installs ClickHouse and OpenTelemetry |
Seldon Core 2 configuration options
| type | default | comment | |
|---|---|---|---|
| seldon_kafka_namespace | string | seldon-mesh | namespace to install Kafka |
| seldon_mesh_namespace | string | seldon-mesh | namespace to install Seldon |
| seldon_crds_namespace | string | default | namespace to install Seldon CRDs |
| full_install | bool | yes | enables full ecosystem installation |
| install_crds | bool | {{ full_install }} |
installs Seldon CRDs |
| install_components | bool | {{ full_install }} |
install Seldon components |
| install_servers | bool | {{ full_install }} |
install Seldon servers |
Custom Seldon images and private registries
By default, the container images used in the install are the ones defined by the helm
charts (referring to images publicly available on dockerhub).
If you need to customize the images (i.e pull from private registry, pull given
tag), create a custom images config file following the example inplaybooks/vars/set-custom-images.yaml and run with:
ansible-playbook playbooks/setup-seldon.yaml -e @<path-to-custom-images-config.yaml>If, instead of pulling images from an external repository you want to build certain components
locally, please read README.dev.md
Private registries
When using private registries, access needs to be authenticated (typically, via a
service account key), and the k8s cluster will need to have access to a secret holding
this key to be able to pull images.
The setup-seldon.yaml playbook will create the required k8s secrets inside the
cluster if it is provided with an auth file in dockerconfigjson format. You provide
the path to this file by cusomizing the custom_image_pull_secrets.dockerconfigjson
variable and define the secret name via custom_image_pull_secrets.name in the custom
images config file (the one passed to the playbook via -e @file).
By default, docker creates the dockerconfigjson auth file in ~/.docker/config.json
after passing the service-account key to docker login.
The docker login command would look like this (key in json format):
cat registry-sa-key.json | docker login -u _json_key --password-stdin <registry-url>or, for keys in base64 format:
cat registry-sa-key | docker login -u _json_key_base64 --password-stdin <registry-url>Saving helm-chart customisations
Because the additional custom images config file (starting from theplaybooks/vars/set-custom-images.yaml example) overrides values in the helm-charts
available in the repo, there's also a playbook option of saving those overrides as a
separate values file, which could be used if deploying manually via helm.
This is controlled via two variables:
| type | default | comment | |
|---|---|---|---|
| save_helm_components_overrides | bool | false | enable saving helm values overrides |
| save_helm_components_overrides_file | string | ~/seldon_helm_comp_values.yaml | path/filename for saving overrides |
You can either pass those within the custom images config file or directly when running the
playbook. For example, for just saving the helm-chart overrides (without installing seldon
components), you would run:
ansible-playbook playbooks/setup-seldon.yaml -e full_install=no -e save_helm_components_overrides=yes -e @<path-to-custom-images-config.yaml>Please note that when deploying outside ansible via helm using this saved overrides file,
and using private registries, you will have to manually create the service-account key
secret with the same name as the one defined in your custom image config file undercustom_image_pull_secrets.name.
Uninstall
To fully remove the Ansible installation delete the created Kind cluster
kind delete cluster --name seldonThis will stop and delete the Kind cluster freeing all of the resources taken by the dev/trial installation.
You may want to also remove cache resources used for the installation with
rm -rf ~/.cache/seldon/If you used Ansible to install Seldon Core 2 and its ecosystem into K8s cluster other than Kind you need to manually
remove all the components.
Overview (`docs-gb/README.md`)
Discover Seldon Core 2, a Kubernetes-native MLOps framework for deploying ML and LLM systems at scale. Features flexible architecture, standardized workflows, and enhanced observability.
Production-ready ML Serving Framework
Seldon Core 2 is a Kubernetes-native framework for deploying and managing machine learning (ML) and Large Language Model (LLM) systems at scale. Its data-centric approach and modular architecture enable seamless handling of simple models to complex ML applications across on-premise, hybrid, and multi-cloud environments while ensuring flexibility, standardization, observability, and cost efficiency.
**Flexibility: Real-time, your way**
Seldon Core 2 offers a platform-agnostic, flexible framework for seamless deployment of different types of ML models across on-premise, cloud, and hybrid environments. Its adaptive architecture enables customizable applications, future-proofing MLOps or LLMOps by scaling deployments as data and applications evolve. The modular design enhances resource-efficiency, allowing dynamic scaling, component reuse, and optimized resource allocation. This ensures long-term scalability, operational efficiency, and adaptability to changing demands.
**Standardization: Consistency across workflows**
Seldon Core 2 enforces best practices for ML deployment, ensuring consistency, reliability, and efficiency across the entire lifecycle. By automating key deployment steps, it removes operational bottlenecks, enabling faster rollouts and allowing teams to focus on high-value tasks.
With a "learn once, deploy anywhere" approach, Seldon Core 2 standardizes model deployment across on-premise, cloud, and hybrid environments, reducing risk and improving productivity. Its unified execution framework supports conventional, foundational, and LLM models, streamlining deployment and enabling seamless scalability. It also enhances collaboration between MLOps Engineers, Data Scientists, and Software Engineers by providing a customizable framework that fosters knowledge sharing, innovation, and the adoption of new data science capabilities.
**Enhanced Observability**
Observability in Seldon Core 2 enables real-time monitoring, analysis, and performance tracking of ML systems, covering data pipelines, models, and deployment environments. Its customizable framework combines operational and data science monitoring, ensuring teams have the key metrics needed for maintenance and decision-making.
Seldon simplifies operational monitoring, allowing real-time ML or LLM deployments to expand across organizations while supporting complex, mission-critical use cases. A data-centric approach ensures all prediction data is auditable, maintaining explainability, compliance, and trust in AI-driven decisions.
**Optimization: Modularity to maximize resource efficiency**
Seldon Core 2 is built for scalability, efficiency, and cost-effective ML operations, enabling you to deploy only the necessary components while maintaining agility and high performance. Its modular architecture ensures that resources are optimized, infrastructure is consolidated, and deployments remain adaptable to evolving business needs.
Scaling for Efficiency: scaling infrastructure dynamically based on demand, auto-scaling for real-time use cases while scaling to zero for on-demand workloads, preserving deployment state for seamless reactivation. By eliminating redundancy and optimizing deployments, it balances cost efficiency and performance, ensuring reliable inference at any scale.
Consolidated Serving Infrastructure: maximizes resource utilization with multi-model serving (MMS) and overcommit, reducing compute overhead while ensuring efficient, reliable inference.
Extendability & Modular Adaptation: integrates with LLMs, Alibi, and other modules, enabling on-demand ML expansion. Its modular design ensures scalable AI, maximizing value extraction, agility, and cost efficiency.
Reusability for Cost Optimization: provides predictable, fixed pricing, enabling cost-effective scaling and innovation while ensuring financial transparency and flexibility.
Next Steps
- Explore our other Solutions
- Learn about the feature of Seldon Core 2
- Join our Slack Community for updates or for answers to any questions
Overview (`hodometer/README.md`)
Hodometer
Hodometer collects and publishes anonymous usage metrics for Seldon Core 2.
Usage
The metrics collected by Hodometer are used to understand how people interact with Seldon Core.
This includes how many Seldon Core clusters there are and how features are used.
See below for the metrics we collect.
Enabling full metrics collection allows Seldon to best understand what users want.
However, you can reduce the level of information provided by changing the collection level.
Which metrics are covered by which level is documented below.
Alternatively, you can opt out entirely by simply not installing Hodometer, or by removing your existing installation of it.
This does not affect your usage of the software in any way.
Installation
TODO
Metrics
There are three levels of metrics that can be enabled:
- Cluster-level -- basic information about the installation
- Resource-level -- high-level details about which Seldon Core 2 resources are used
- Feature-level -- more detailed information about how resources are used
The set of metrics available at each level is:
| Metric name | Level | Format | Notes |
|---|---|---|---|
cluster_id |
cluster | UUID | A random identifier for this cluster for de-duplication |
seldon_core_version |
cluster | Version number | E.g. 1.2.3 |
is_global_installation |
cluster | Boolean | Whether installation is global or namespaced |
is_kubernetes |
cluster | Boolean | Whether or not the installation is in Kubernetes |
kubernetes_version |
cluster | Version number | Kubernetes server version, if inside Kubernetes |
node_count |
cluster | Integer | Number of nodes in the cluster, if inside Kubernetes |
model_count |
resource | Integer | Number of Model resources |
pipeline_count |
resource | Integer | Number of Pipeline resources |
experiment_count |
resource | Integer | Number of Experiment resources |
server_count |
resource | Integer | Number of Server resources |
server_replica_count |
resource | Integer | Total number of Server resource replicas |
multimodel_enabled_count |
feature | Integer | Number of Server resources with multi-model serving enabled |
overcommit_enabled_count |
feature | Integer | Number of Server resources with overcommitting enabled |
gpu_enabled_count |
feature | Integer | Number of Server resources with GPUs attached |
inference_server_name |
feature | String | Name of inference server, e.g. MLServer or Triton |
server_cpu_cores_sum |
feature | Float | Total of CPU limits across all Server resource replicas, in cores |
server_memory_gb_sum |
feature | Float | Total of memory limits across all Server resource replicas, in GiB |
Privacy
We aim to not collect any sensitive or identifying information.
For example, we do not collect IP addresses, machine names, or company information.
If you are concerned about any of the information being collected, please raise an issue or PR, or contact Seldon directly.
Overview (`k8s/README.md`)
The generation of helm charts and yaml manifests relies on kubebuilder-generated manifests in
../operator/config/[files].If you have modified CRD definitions in the operator (
../operator/apis/mlops/v1alpha1/*and
dependencies), you must first runmake manifestsin the operator directory to update the manifests.
Only then you should runmake createin this directory.Never modify files in
../operator/config/[files]manually. These files are generated by
kubebuilder. Instead, modify the CRD definitions in the operator code
Overview (`operator/README.md`)
Creation
This operator was built with Kubebuilder
Version: main.version{KubeBuilderVersion:"3.2.0", KubernetesVendor:"1.22.1", GitCommit:"b7a730c84495122a14a0faff95e9e9615fffbfc5", BuildDate:"2021-10-29T18:32:16Z", GoOs:"linux", GoArch:"amd64"}Steps to recreate scaffolding
go mod init github.com/seldonio/seldon-core/operator/v2
kubebuilder init --domain seldon.io
kubebuilder edit --multigroup=true
kubebuilder create api --group mlops --version v1alpha1 --kind Model --resource --controller
kubebuilder create api --group mlops --version v1alpha1 --kind Server --resource --controller
kubebuilder create api --group mlops --version v1alpha1 --kind Pipeline --resource --controller
kubebuilder create api --group mlops --version v1alpha1 --kind Explainer --resource --controllerOverview (`prometheus/README.md`)
Prometheus
Install
We recommend install kube-prometheus that provides an all-in-one package with the Prometheus operator.
kubectl apply --server-side -f manifests/setup
until kubectl get servicemonitors --all-namespaces ; do date; sleep 1; echo ""; done
kubectl apply -f manifests/RBAC
You will need to modify the default RBAC installed by kube-prometheus as described here.
kubectl apply -f rbac/cr.yamlMonitors
We use a PodMonitor for scrapping agent metrics. The envoy and server monitors are there for completeness but not present needed.
kubectl apply -f monitorsIncludes:
- Agent pod monitor. Monitors the metrics port of server inference pods.
- Server pod monitor. Monitors the server-metrics port of server inference pods.
- Envoy service monitor. Monitors the Envoy proxies.
- Pipeline gateway pod monitor. Monitors the metrics port of pipeline gateway pods.
Pod monitors were chosen as ports for metrics are not exposed at service level as we do not have a top level service for server replicas but 1 headless service per replica. Future discussions could reference this.
Reference
Access the dashboards
- Access to dashboards is explained here
TODO
- Provide Ansible installation
Overview (`samples/README.md`)
Samples
Various example notebooks.
Requirements
- a seldon cli
- jupyter notebook
- jq
Artefacts
All (Python) artefacts are versioned by their respective version of Triton and
MLServer used at the time of training (e.g.gs://seldon-models/scv2/samples/mlserver_1.3.5/iris-sklearn).
To re-generate them, you can call the following Makefile targets:
$ make train-all upload-allThe new version of the artefacts will get uploaded to GCS, using the version of
Triton and MLServer specified on scheduler/Makefile.
The upload-all target will also replace all previous references to versioned
artefacts in the notebooks.
Overview (`scheduler/README.md`)
Seldon Envoy XDS Server
Development Setup
The scheduler and its associated control-plane components in Seldon Core 2 are intended to run both in and out of Kubernetes.
While it is possible to run all the individual components locally as plain, OS-level processes (see below), the recommended approach is to use Docker Compose to ensure isolation and reproducibility.
Docker Compose
Installation
Ensure that you are using a version of Docker Compose ("Compose") compatible with the 3.9+ file format.
You can install directly by following the official instructions.
Alternatively, there are asdf plugins for Compose which you can choose from:
asdf plugin-list-all | grep dockerYou may also want to install shell completion, if it has not been installed for you.
See the official documentation.
Full control plane
There are Makefile targets to start and stop a minimal Seldon Core 2 setup.
You need to choose whether to run with MLServer or Triton as the inference server, but otherwise the setups are almost identical.
To get started:
make start-all-mlserver
# OR
make start-all-tritonand once finished, you can spin down the services with:
make stop-all-mlserver
# OR
make stop-all-tritonExamples
It is possible to interact with and even start or stop individual services when using Compose.
A collection of examples are given below.
NOTE You need to specify the project (
-p) and the appropriate manifest and environment files when interacting directly with services start via the Makefile targets.
Compose allows multiple manifests to be specified, with the latter ones able to override configuration from the earlier ones.
This greatly reduces duplication between the MLServer and Triton setups at the cost of an extra command-line argument.
Check running services
$ docker-compose -f all-base.yaml -f all-mlserver.yaml --env-file env.all -p scv2_mlserver ps
Name Command State Ports
-------------------------------------------------------------------------------------------------------------------------------------------------------------
scv2_mlserver_agent_1 /bin/agent --log-level deb ... Up 0.0.0.0:8090->8090/tcp,:::8090->8090/tcp, 0.0.0.0:8091->8091/tcp,:::8091->8091/tcp
scv2_mlserver_envoy_1 /docker-entrypoint.sh /bin ... Up 10000/tcp, 0.0.0.0:9000->9000/tcp,:::9000->9000/tcp,
0.0.0.0:9003->9003/tcp,:::9003->9003/tcp
scv2_mlserver_rclone_1 rclone rcd --rc-no-auth -- ... Up 0.0.0.0:5572->5572/tcp,:::5572->5572/tcp
scv2_mlserver_scheduler_1 /bin/scheduler Up 0.0.0.0:9002->9002/tcp,:::9002->9002/tcp, 0.0.0.0:9004->9004/tcp,:::9004->9004/tcp,
0.0.0.0:9005->9005/tcp,:::9005->9005/tcp
scv2_mlserver_server_1 mlserver start /mnt/models Up 0.0.0.0:8080->8080/tcp,:::8080->8080/tcp, 0.0.0.0:8081->8081/tcp,:::8081->8081/tcpCheck logs
$ docker-compose -f all-base.yaml -f all-mlserver.yaml --env-file env.all -p scv2_mlserver logs agent | tail
agent_1 | time="2022-02-04T12:14:03Z" level=info msg="Calling Rclone server: /rc/noop with {\"foo\":\"bar\"}" Source=RCloneClient
agent_1 | time="2022-02-04T12:14:03Z" level=error msg="Rclone not ready" Name=Client error="Post \"http://0.0.0.0:5572/rc/noop\": dial tcp 0.0.0.0:5572: connect: connection refused" func=waitReady
...Restart a service
The argument to the restart command is the name of the service in the manifest, e.g. server.
$ docker-compose -f all-base.yaml -f all-mlserver.yaml --env-file env.all -p scv2_mlserver restart server
Restarting scv2_mlserver_server_1 ... doneStart a single service
Note that this example does not specify a project, so Compose defaults to the parent directory's name.
This example also does not specify -f all-mlserver.yaml as the Rclone configuration is defined in all-base.yaml and is completely independent of the inference server in use.
We can override values from env.all to specify the repository and tag for the Rclone image.
$ RCLONE_IMAGE_AND_TAG=seldonio/seldon-reclone:latest docker-compose -f all-base.yaml --env-file env.all run -d rclone
Building rclone
Step 1/3 : FROM rclone/rclone:1.56.2
1.56.2: Pulling from rclone/rclone
a0d0a0d46f8b: Already exists
...
Creating scheduler_rclone_run ... done
scheduler_rclone_run_4379d7918894Inspect environment variables in a container
It can be useful to see what environment variables have been set in a container, as these do not show up in the command column of ps commands.
The below shows a way of inspecting these values for a container called scv2_mlserver_agent_1:
$ docker inspect -f '{{ range $i, $v := .Config.Env }}{{ $v }}{{ println }}{{ end }}' scv2_mlserver_agent_1
SELDON_OVERCOMMIT_PERCENTAGE=0
SELDON_SERVER_HTTP_PORT=8090
SELDON_SERVER_GRPC_PORT=8091
SELDON_DEBUG_GRPC_PORT=7777
SELDON_SCHEDULER_HOST=0.0.0.0
SELDON_SCHEDULER_PORT=9005
MEMORY_REQUEST=1000000
SELDON_SERVER_TYPE=mlserver
SELDON_SERVER_CAPABILITIES=sklearn,xgboost
PATH=/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
GOLANG_VERSION=1.17.6
GOPATH=/goCheck specific details for running containers
The default view of docker-compose ps is limited, in that it does not have all the same configuration values as the equivalent docker command.
It can also be very dense for a split-screen or smaller screen view.
The below provides an example on customising the display:
$ docker ps --format 'table {{ .Image }}\t{{ .Names }}\t{{ .Status }}\t{{ .Command }}' --no-trunc
IMAGE NAMES STATUS COMMAND
seldonio/seldon-envoy-local:latest scv2_mlserver_envoy_1 Up 2 hours "/docker-entrypoint.sh /bin/sh -c '/usr/local/bin/envoy -c /etc/envoy.yaml'"
seldonio/seldon-rclone:latest scv2_mlserver_rclone_1 Up 2 hours "rclone rcd --rc-no-auth --config=/rclone/rclone.conf --rc-addr=0.0.0.0:5572 --verbose"
seldonio/mlserver:1.0.0.rc1 scv2_mlserver_server_1 Up 10 minutes "mlserver start /mnt/models"
registry:2 kind-registry Up 7 hours "/entrypoint.sh /etc/docker/registry/config.yml"gRPC compile
Install protoc.
protoc --version
libprotoc 3.18.0Install go grpc plugins
$ go install google.golang.org/protobuf/cmd/[email protected]
$ go install google.golang.org/grpc/cmd/[email protected]Local Envoy Install
Install or download envoy.
Tested with:
envoy --version
envoy version: a2a1e3eed4214a38608ec223859fcfa8fb679b14/1.19.1/Clean/RELEASE/BoringSSLMlServer
pip install mlserverLocal Test
make buildFollow steps in local test notebook
K8S Test
make kind-image-install-allFollow steps in k8s test notebook
Docs
Overview (`docs-gb/apis/README.md`)
APIs
Seldon provides APIs for management and inference.
- API for inference
- Scheduler API for management (Advanced)
- Internal APIs (Reference)
Overview (`docs-gb/architecture/README.md`)
Learn about the Seldon Core 2 microservice architecture, control plane and data plane components, and how these services work to provide a scalable, fault-tolerant ML model serving and management.
Architecture
Seldon Core 2 uses a microservice architecture where each service has limited and well-defined responsibilities working together to orchestrate scalable and fault-tolerant ML serving and management. These components communicate internally using gRPC and they can be scaled independently. Seldon Core 2 services can be split into two categories:
- Control Plane services are responsible for managing the operations and configurations of your ML models and workflows. This includes functionality to instantiate new inference servers, load models, update new versions of models, configure model experiments and pipelines, and expose endpoints that may receive inference requests. The main control plane component is the Scheduler that is responsible for managing the loading and unloading of resources (models, pipelines, experiments) onto the respective components.
- Data Plane services are responsible for managing the flow of data between components or models. Core 2 supports REST and gRPC payloads that follow the Open Inference Protocol (OIP). The main data plane service is Envoy, which acts as a single ingress for all data plane load and routes data to the relevant servers internally (e.g. Seldon MLServer or NVidia Triton pods).
{% hint style="info" %}
Note: Because Core 2 architecture separates control plane and data plane responsibilities, when control plane services are down (e.g. the Scheduler), data plane inference can still be served. In this manner the system is more resilient to failures. For example, an outage of control plane services does not impact the ability of the system to respond to end user traffic. Core 2 can be provisioned to be highly available on the data plane path.
{% endhint %}
The current set of services used in Seldon Core 2 is shown below. Following the diagram, we will describe each control plane and data plan service.
.png>)
Control Plane
Scheduler
This service manages the loading and unloading of Models, Pipelines and Experiments on the relevant micro services. It is also responsible for matching Models with available Servers in a way that optimises infrastructure use. In the current design we can only have one instance of the Scheduler as its internal state is persisted on disk.
When the Scheduler (re)starts there is a synchronisation flow to coordinate the startup process and to attempt to wait for expected Model Servers to connect before proceeding with control plane operations. This is important so that ongoing data plane operations are not interrupted. This then introduces a delay on any control plane operations until the process has finished (including control plan resources status updates). This synchronisation process has a timeout, which has a default of 10 minutes. It can be changed by setting helm seldon-core-v2-components value scheduler.schedulerReadyTimeoutSeconds.
Agent
This service manages the loading and unloading of models on a server and access to the server over REST/gRPC. It acts as a reverse proxy to connect end users with the actual Model Servers. In this way the system collects stats and metrics about data plane inferences that helps with observability and scaling.
Controller
We also provide a Kubernetes Operator to allow Kubernetes usage. This is implemented in the Controller Manager microservice, which manages CRD reconciliation with Scheduler. Currently Core 2 supports one instance of the Controller.
{% hint style="info" %}
Note: All services besides the Controller are Kubernetes agnostic and can run locally, e.g. on Docker Compose.
{% endhint %}
Data Plane
Pipeline Gateway
This service handles REST/gRPC calls to Pipelines. It translates between synchronous requests to Kafka operations, producing a message on the relevant input topic for a Pipeline and consuming from the output topic to return inference results back to the users.
Model Gateway
This service handles the flow of data from models to inference requests on servers and passes on the responses via Kafka.
Dataflow Engine
This service handles the flow of data between components in a pipeline, using Kafka Streams. It enables Core 2 to chain and join Models together to provide complex Pipelines.
Envoy
Envoy acts as the request proxy for Seldon Core 2, routing traffic to the appropriate inference servers and handling load balancing across available replicas. Envoy configuration of Seldon Core 2 uses weighted least-request load balancing, which dynamically distributes traffic based on both replica weights and current load, helping ensure efficient and stable request routing.
Dataflow Architecture and Pipelines
To support the movement towards data centric machine learning Seldon Core 2 follows a dataflow paradigm. By taking a decentralized route that focuses on the flow of data, users can have more flexibility and insight as they build and manage complex AI applications in production. This contrasts with more centralized orchestration approaches where data is secondary.
.png>)
Kafka
Kafka is used as the backbone for Pipelines allowing decentralized, synchronous and asynchronous usage. This enables Models to be connected together into arbitrary directed acyclic graphs. Models can be reused in different Pipelines. The flow of data between models is handled by the dataflow engine using Kafka Streams.
.png>)
By focusing on the data we allow users to join various flows together using stream joining concepts as shown below.
.png>)
We support several types of joins:
- inner joins, where all inputs need to be present for a transaction to join the tensors passed through the Pipeline;
- outer joins, where only a subset needs to be available during the join window
- triggers, in which data flows need to wait until records on one or more trigger data flows appear. The data in these triggers is not passed onwards from the join.
These techniques allow users to create complex pipeline flows of data between machine learning components.
More discussion on the data flow view of machine learning and its effect on v2 design can be found here.
Overview (`docs-gb/cli/README.md`)
CLI
Seldon provides a CLI to allow easy management and testing of Model, Experiment, and Pipeline resources.
At present this needs to be built by hand from the operator folder.
make build-seldon # for linux/macOS amd64
make build-seldon-arm # for macOS ARMThen place the bin/seldon executable in your path.
Environment Variables and Services
The CLI talks to 3 backend services on default endpoints:
- The Seldon Core 2 Scheduler: default 0.0.0.0:9004
- The Seldon Core inference endpoint: default 0.0.0.0:9000
- The Seldon Kafka broker: default: 0.0.0.0:9092
These defaults will be correct when Seldon Core 2 is installed locally as per the docs. For Kubernetes, you will need to change these by defining environment variables.
:language: golang
:start-after: // Defaults
:end-before: // Help statementsKubernetes Usage
Inference Service
For a default install into the seldon-mesh namespace if you have exposed the inference svc as a loadbalancer you will find it at:
kubectl get svc seldon-mesh -n seldon-mesh -o jsonpath='{.status.loadBalancer.ingress[0].ip}'Use above IP at port 80:
export SELDON_INFER_HOST=<ip>:80Scheduler Service
For a default install into the seldon-mesh namespace if you have exposed the scheduler svc as a loadbalancer you will find it at:
kubectl get svc seldon-scheduler -n seldon-mesh -o jsonpath='{.status.loadBalancer.ingress[0].ip}'Use above IP at port 9004:
export SELDON_SCHEDULE_HOST=<ip>:9004Kafka Broker
The Kafka broker will depend on how you have installed Kafka into your Kubernetes cluster. Find the broker IP and use:
export SELDON_KAFKA_BROKER=<ip>:<port>Config file
You can create a config file to manage connections to running Seldon Core 2 installs. The settings will override any environment variable settings.
The definition is shown below:
:language: golang
:start-after: // start config struct
:end-before: // end config structAn example below shows an example where we connect via TLS to the Seldon scheduler using our scheduler client certificate:
{
"controlplane":{
"schedulerHost": "seldon-scheduler.svc:9044",
"tls"; true,
"keyPath": "/home/certs/seldon-scheduler-client/tls.key",
"crtPath": "/home/certs/seldon-scheduler-client/tls.crt",
"caPath": "/home/certs/seldon-scheduler-client/ca.crt"
}
}To manage config files and activate them you can use the CLI command seldon config which has subcommands to list, add, remove, activate and decative configs.
For example:
$ seldon config list
config path active
------ ---- ------
kind-sasl /home/work/seldon/cli/config-sasl.json *
$ seldon config deactivate kind-sasl
$ seldon config list
config path active
------ ---- ------
kind-sasl /home/work/seldon/cli/config-sasl.json
$ seldon config add gcp-scv2 ~/seldon/cli/gcp.json
$ seldon config list
config path active
------ ---- ------
gcp-scv2 /home/work/seldon/cli/gcp.json
kind-sasl /home/work/seldon/cli/config-sasl.json
$ seldon config activate gcp-scv2
$ seldon config list
config path active
------ ---- ------
gcp-scv2 /home/work/seldon/cli/gcp.json *
kind-sasl /home/work/seldon/cli/config-sasl.json
$ seldon config list kind-sasl
{
"controlplane": {
"schedulerHost": "172.19.255.2:9004"
},
"kafka": {
"bootstrap": "172.19.255.3:9093",
"caPath": "/home/work/gcp/scv2/certs/seldon-cluster-ca-cert/ca.crt"
}
}TLS Certificates for Local Use
For running with Kubernetes TLS connections on the control and/or data plane, certificates will need to be downloaded locally. We provide an example script which will download certificates from a Kubernetes secret and store them in a folder. It can be found in hack/download-k8s-certs.sh and takes 2 or 3 arguments:
./download-k8s-certs.sh <namespace> <secret> [<folder>]e.g.:
./download-k8s-certs.sh seldon-mesh seldon-scheduler-clientOverview (`docs-gb/concepts/README.md`)
Learn how Seldon Core is different from a centralized orchestrator to a data flow architecture, enabling more efficient ML model deployment through stream processing and improved data handling.
Concepts
In the context of machine learning and Seldon Core 2, concepts provide a framework for understanding key functionalities, architectures, and workflows within the system. Some of the key concepts in Seldon Core 2 are:
Data-Centric MLOps
Data-centricity is an approach that puts the management, integrity, and flow of data at the core of machine learning deployment. Rather than focusing solely on models, this approach ensures that data quality, consistency, and adaptability drive successful ML operations. In Seldon Core 2, data-centricity is embedded in every stage of the inference workflow.
| Key Principle | Description |
|---|---|
| Flexible Workflows | Core 2 supports adaptable and scalable data pathways, accommodating various use cases and experiments. This ensures ML pipelines remain agile, allowing you to evolve the inference logic as requirements change.. |
| Real-Time Data Streaming | Integrated data streaming capabilities allow you to view, store, manage, and process data in real time. This enhances responsiveness and decision-making, ensuring models work with the most up-to-date data for accurate predictions. |
| Standardized Processing | Core 2 promotes reusable and consistent data transformation and routing mechanisms. Standardized processing ensures data integrity and uniformity across applications, reducing errors and inconsistencies. |
| Comprehensive Monitoring | Detailed metrics and logs provide real-time visibility into data integrity, transformations, and flow. This enables effective oversight and maintenance, allowing teams to detect anomalies, drifts, or inefficiencies early. |
Why Data-Centricity Matters?
By adopting a data-centric approach, Seldon Core 2 enables:
- More reliable and high-quality predictions by ensuring clean, well-structured data.
- Scalable and future-proof ML deployments through standardized data management.
- Efficient monitoring and maintenance, reducing risks related to model drift and inconsistencies.
With data-centricity as a core principle, Seldon Core 2 ensures end-to-end control over ML workflows, enabling you to maximize model performance and reliability in production environments.
Open Inference Protocol in Seldon Core 2
The Open Inference Protocol (OIP) defines a standard way for inference servers and clients to communicate in Seldon Core 2. Its goal is to enable interoperability, flexibility, and consistency across different model-serving runtimes. It exposes the Health API, Metadata API, and the Inference API.
Some of the features of Open Inference Protocol includes:
- Transport Agnostic: Servers can implement HTTP/REST or gRPC protocols.
- Runtime Awareness: Use the
protocolVersionfield in your runtime YAML or consult the supported runtimes table to verify compatibility.
By adopting OIP, Seldon Core 2 promotes a consistent experience across a diverse set of model deployments.
Components in Seldon Core 2
Components are the building blocks of an inference graph, processing data at various stages of the ML inference pipeline. They provide reusable, standardized interfaces, making it easier to maintain and update workflows without disrupting the entire system. Components include ML models, data processors, routers, and supplementary services.
Types of Components
| Component Type | Description |
|---|---|
| Data Processors | Transform, filter, or aggregate data to ensure consistent, repeatable pre-processing. |
| Data Routers | Dynamically route data to different paths based on predefined rules for A/B testing, experimentation, or conditional logic. |
| Models | Perform inference tasks, including classification, regression, and Large Language Models (LLMs), hosted internally or via external APIs. |
| Supplementary Data Services | External services like vector databases that enable models to access embeddings and extended functionality. |
| Drift/Outlier Detectors & Explainers | Monitor model predictions for drift, anomalies, and explainability insights, ensuring transparency and performance tracking. |
By modularizing inference workflows, components allow you to scale, experiment, and optimize ML deployments efficiently while ensuring data consistency and reliability.
Pipelines
In a model serving platform like Seldon Core 2, a pipeline refers to an orchestrated sequence of models and components that work together to serve more complex AI applications. These pipelines allow you to connect models, routers, transformers, and other inference components, with Kafka used to stream data between them. Each component in the pipeline is modular and independently managed—meaning it can be scaled, configured, and updated separately based on its specific input and output requirements.
This use of "pipeline" is distinct from how the term is used in MLOps for CI/CD pipelines, which automate workflows for building, testing, and deploying models. In contrast, Core 2 pipelines operate at runtime and focus on the live composition and orchestration of inference systems in production.
Servers
In Core 2, servers are responsible for hosting and serving machine learning models, handling inference requests, and ensuring scalability, efficiency, and observability in production. Core 2 supports multiple inference servers, including MLServer, and NVIDIA Triton Inference Server, enabling flexible and optimized model deployments.
MLServer: A lightweight, extensible inference server designed to work with multiple ML frameworks, including scikit-learn, XGBoost, TensorFlow, and PyTorch. It supports custom Python models and integrates well with MLOps workflows. It is built for *General-purpose model serving, custom model wrappers, multi-framework support.
Experiments
In Seldon Core 2, experiments enable controlled A/B testing, model comparisons, and performance evaluations by defining an HTTP traffic split between different models or inference pipelines. This allows organizations to test multiple versions of a model in production while managing risk and ensuring continuous improvements.
| Experiment Type | Description |
|---|---|
| Traffic Splitting | Distributes inference requests across different models or pipelines based on predefined percentage splits. This enables A/B testing and comparison of multiple model versions. For example, Canary deployment of the models. |
| Mirror Testing | Sends a percentage of the traffic to a mirror model or pipeline without affecting the response returned to users. This allows evaluation of new models without impacting production workflows. For example, Shadow deployment of the models. |
Some of the advantages of using Experiments:
- A/B Testing & Model comparison: Compare different models under real-world conditions without full deployment.
- Risk-Free model validation: Test a new model or pipeline in parallel without affecting live predictions.
- Performance monitoring: Assess latency, accuracy, and reliability before a full rollout.
- Continuous improvement: Make data-driven deployment decisions based on real-time model performance.
Overview (`docs-gb/development/README.md`)
Development
Development Requirements
- Go 1.17+ with glibc development libraries installed.
- e.g. for Ubuntu systems:
sudo apt-get install libc6-dev
- e.g. for Ubuntu systems:
- Java JDK 17+ and Kotlin 1.6.10+
- Kubebuilder V2
- Docker and docker-compose
- Helm
- Kustomize
- Ansible
Testing resources
- Kind
- k6
- unix utils: jq, curl, grpcurl
Release Process
Releases are carried out via Github.
Overview (`docs-gb/examples/README.md`)
Examples
Workflows
Seldon inference is built from atomic Model components. Models as shown here cover a wide range of artifacts including:
- Core machine learning models, e.g. a PyTorch model.
- Feature transformations that might be built with custom python code.
- Drift detectors.
- Outlier detectors.
- Explainers
- Adversarial detectors.
A typical workflow for a production machine learning setup might be as follows:
- You create a Tensorflow model for your core application use case and test this model in isolation to validate.
- You create SKLearn feature transformation component before your model to convert the input into the correct form for your model. You also create Drift and Outlier detectors using Seldon's open source Alibi-detect library and test these in isolation.
- You join these components together into a Pipeline for the final production setup.
These steps are shown in the diagram below:
.png>)
Examples & Tutorials
This section will provide some examples to allow operations with Seldon to be tested so you can run your own models, experiments, pipelines and explainers.
Getting Started Examples
Models
Pipelines
Explainers
Servers
Experiments
Making Inference Requests
- Inference examples
- Tritonclient examples
- Batch Inference examples (kubernetes)
- Batch Inference examples (local)
Misc
Further Kubernetes Examples
Advanced Examples
- Huggingface speech to sentiment with explanations pipeline
- Production image classifier with drift and outlier monitoring
- Production income classifier with drift, outlier and explanations
- Conditional pipeline with pandas query model
- Kubernetes Server with PVC
Overview (`docs-gb/getting-started/README.md`)
Getting Started
{% hint style="info" %}
Note: Some dependencies may require that the (virtual) machines on which you deploy, support the SSE4.2
instruction set or x86-64-v2 microarchitecture. If lscpu | grep sse4_2 does not return anything on
your machine, your CPU is not compatible, and you may need to update the (virtual) host's CPU.
{% endhint %}
Seldon Core can be installed either with Docker Compose or with Kubernetes:
Once installed:
- Try the existing examples.
- Train and deploy your own model artifact.
Core Concepts
There are three core resources you will use:
- Models - for deploying single machine learning models, custom transformation
logic, drift detectors and outliers detectors. - Pipelines - for connecting together flows of data transformations between Models
with a synchronous path and multiple asynchronous paths. - Experiments - for testing new versions of models
By default the standard installation will deploy MLServer and Triton inference servers which provide
support for a wide range of machine learning model artifacts including Tensorflow models, PyTorch models,
SKlearn models, XGBoost models, ONNX models, TensorRT models, custom python models and many more. For
advanced use, the creation of new inference servers is manged by two resources:
- Servers - for deploying sets of replicas of core inference servers (MLServer or Triton by default).
- ServerConfigs - for defining server configurations including custom servers.
API for Inference
Once deployed models can be called using the Seldon V2 inference protocol. This
protocol created by Seldon, NVIDIA and the KServe projects is supported by MLServer and Triton inference
servers amingst others and allows REST and gRPC calls to your model.
Your model is exposed via our internal Envoy gateway. If you wish to expose your models in Kubernetes
outside the cluster you are free to use any Service Mesh or Ingress technology. Various examples are provided
for service mesh integration.
Inference Metrics
Metrics are exposed for scraping by Prometheus. For Kubernetes we provide example instructions for using kube-prometheus.
Pipeline requirements
Pipelines are built upon Kafka streaming technology.
Overview (`docs-gb/installation/README.md`)
keywords:
- Seldon Core
- MLOps
- Kubernetes
- Docker Compose
- installation guide
- Helm charts
- machine learning deployment
Learn how to install Seldon Core 2 in various environments - from local
development with Docker Compose to production-grade Kubernetes clusters.
Installation Overview
Seldon Core 2 can be installed in various setups to suit different stages of the development lifecycle. The most common modes include:
Local Environment
Ideal for development and testing purposes, a local setup allows for quick iteration and experimentation with minimal overhead. Common tools include:
- Docker Compose:
Simplifies deployment by orchestrating Seldon Core components and dependencies in Docker containers. Suitable for environments without Kubernetes, providing a lightweight alternative. - Kind (Kubernetes IN Docker):
Runs a Kubernetes cluster inside Docker, offering a realistic testing environment.
Ideal for experimenting with Kubernetes-native features.
Production Environment
Designed for high-availability and scalable deployments, a production setup ensures security, reliability, and resource efficiency. Typical tools and setups include:
- Managed Kubernetes Clusters:
Platforms like GKE (Google Kubernetes Engine), EKS (Amazon Elastic Kubernetes Service), and AKS (Azure Kubernetes Service) provide managed Kubernetes solutions.
Suitable for enterprises requiring scalability and cloud integration. - On-Premises Kubernetes Clusters:
For organizations with strict compliance or data sovereignty requirements.
Can be deployed on platforms like OpenShift or custom Kubernetes setups.
By selecting the appropriate installation mode—whether it's Docker Compose for simplicity, Kind for local Kubernetes experimentation, or production-grade Kubernetes for scalability—you can effectively leverage Seldon Core 2 to meet your specific needs.
Helm Charts
| Name of the Helm Chart | Description |
|---|---|
seldon-core-v2-crds |
Cluster-wide installation of custom resources. |
seldon-core-v2-setup |
Installation of the manager to manage resources in the namespace or cluster-wide. This also installs default SeldonConfig and ServerConfig resources, allowing Runtimes and Servers to be installed on demand. |
seldon-core-v2-runtime |
Installs a SeldonRuntime custom resource that creates the core components in a namespace. |
seldon-core-v2-servers |
Installs Server custom resources providing example core servers to load models. |
For more information, see the published Helm charts.
For the description of (some) values that can be configured for these charts, see this Helm parameters section.
Seldon Core 2 Dependencies
Here is a list of components that Seldon Core 2 requires, along with the minimum and maximum supported versions:
| Component | Minimum Version | Maximum Version | Notes |
|---|---|---|---|
| Kubernetes | 1.27 | 1.33.0 | Required |
| Envoy* | 1.32.2 | 1.32.2 | Required. (Included in Core 2 installation) |
| Rclone* | 1.68.2 | 1.69.0 | Required. (Included in Core 2 installation) |
| Kafka | 3.4 | 3.8 | Recommended (only required for operating Seldon Core 2 dataflow Pipelines) |
| Prometheus | 2.0 | 2.x | Optional |
| Grafana | 10.0 | *** | Optional (no hard limit on the maximum version to be used) |
| Prometheus-adapter | 0.12 | 0.12 | Optional |
| Opentelemetry Collector | 0.68 | *** | Optional (no hard limit on the maximum version to be used) |
Notes:
- Envoy and Rclone: These components are included as part of the Seldon Core 2 Docker images. You are not required to install them separately but must be aware of the configuration options supported by these versions.
- Kafka: Only required for operating Seldon Core 2 dataflow Pipelines. If not needed, you should avoid installing
seldon-modelgateway,seldon-pipelinegateway, andseldon-dataflow-engine. - Maximum Versions marked with
***indicates no hard limit on the version that can be used.
Get started
| Learning environment | Install Seldon Core 2 in Docker Compose, or Kind | learning-environment | ||
| Production environment | Install Seldon Core 2 in a Managed Kubernetes cluster, or On-Premises Kubernetes cluster | production-environment |
Overview (`docs-gb/kubernetes/README.md`)
Kubernetes
Kubernetes provides the core platform for production use. However, the architecture in
agnostic to the underlying cluster technology as shown by the
local Docker installation.
Overview (`docs-gb/metrics/README.md`)
Metrics
There are two kinds of metrics present in Seldon Core 2:
Operational metrics describe the performance of components in the system. Some examples of common operational
considerations are memory consumption and CPU usage, request latency and throughput, and cache utilisation rates.
Generally speaking, these are the metrics system administrators, operations teams, and engineers will be interested in.
Usage metrics describe the system at a higher and less dynamic level. Some examples include the number of deployed
servers and models, and component versions. These are not typically metrics that engineers need insight into, but
may be relevant to platform providers and operations teams.
Overview (`docs-gb/models/README.md`)
Models
Models provide the atomic building blocks of Seldon. They represents machine learning models,
drift detectors, outlier detectors, explainers, feature transformations, and more complex routing
models such as multi-armed bandits.
- Seldon can handle a wide range of inference artifacts
- Artifacts can be stored on any of the 40 or more cloud storage technologies as well as from
local (mounted) folder as discussed here.
Kubernetes Example
A Kubernetes yaml example is shown below for a SKLearn model for iris classification:
# samples/models/sklearn-iris-gs.yaml
apiVersion: mlops.seldon.io/v1alpha1
kind: Model
metadata:
name: iris
spec:
storageUri: "gs://seldon-models/scv2/samples/mlserver_1.5.0/iris-sklearn"
requirements:
- sklearn
memory: 100KiIts Kubernetes spec has two core requirements
- A
storageUrispecifying the location of the artifact. This can be any rclone URI specification. - A
requirementslist which provides tags that need to be matched by the Server that can run
this artifact type. By default when you install Seldon we provide a set of Servers that cover a
range of artifact types.
GRPC Example
You can also load models directly over the scheduler grpc service. An example is shown below use grpcurl tool:
!grpcurl -d '{"model":{ \
"meta":{"name":"iris"},\
"modelSpec":{"uri":"gs://seldon-models/mlserver/iris",\
"requirements":["sklearn"],\
"memoryBytes":500},\
"deploymentSpec":{"replicas":1}}}' \
-plaintext \
-import-path ../../apis \
-proto apis/mlops/scheduler/scheduler.proto 0.0.0.0:9004 seldon.mlops.scheduler.Scheduler/LoadModelThe proto buffer definitions for the scheduler are outlined here.
Multi-model Serving with Overcommit
Multi-model serving is an architecture pattern where one ML inference server hosts multiple models
at the same time. It is a feature provided out of the box by Nvidia Triton and Seldon MLServer.
Multi-model serving reduces infrastructure hardware requirements (e.g. expensive GPUs) which enables
the deployment of a large number of models while making it efficient to operate the system at scale.
Seldon Core 2 leverages multi-model serving by design and it is the default option for deploying
models. The system will find an appropriate server to load the model onto based on requirements that
the user defines in the Model deployment definition.
Moreover, in many cases demand patterns allow for further Overcommit of resources. Seldon Core 2
is able to register more models than what can be served by the provisioned (memory) infrastructure
and will swap models dynamically according to least used without adding significant latency overheads
to inference workload.
See Multi-model serving for more information.
Autoscaling of Models
See here for discussion of autoscaling of models.
Scheduling of Models onto Servers
See here for details on how Core 2 schedules Models onto Servers.
Overview (`docs-gb/operational-monitoring/README.md`)
Operational Monitoring
Seldon Core 2 provides robust tools for tracking the performance and health of machine learning models in production.
Monitoring
- Real-Time metrics: collects and displays real-time metrics from deployed models, such as response times, error rates, and resource usage.
- Model performance tracking: monitors key performance indicators (KPIs) like accuracy, drift detection, and model degradation over time.
- Custom metrics: allows you to define and track custom metrics specific to their models and use cases.
- Visualization: Provides dashboards and visualizations to easily observe the status and performance of models.
There are two kinds of metrics present in Seldon Core 2 that you can monitor:
Operational metrics describe the performance of components in the system. Some examples of common operational considerations are memory consumption and CPU usage, request latency and throughput, and cache utilisation rates. Generally speaking, these are the metrics system administrators, operations teams, and engineers will be interested in.
Usage metrics describe the system at a higher and less dynamic level. Some examples include the number of deployed servers and models, and component versions. These are not typically metrics that engineers need insight into, but may be relevant to platform providers and operations teams.
Overview (`docs-gb/performance-tuning/readme.md`)
Introduction
In MLOps, system performance can be defined as how efficiently and effectively an ML model or application operates in a production environment. It is typically measured across several key dimensions, such as latency, throughput, scalability, and resource-efficiency. These factors are deeply connected: changes in configuration often result in tradeoffs, and should be carefully considered. Specifically, latency, throughput and resource usage can all impact each other, and the approach to optimizing system performance depends on the desired balance of these outcomes in order to ensure a positive end-user experience, while also minimising infrastructure costs.
High Level Approach
There are many different levers that can be considered to tune performance for ML systems deployed with Core 2, across infrastructure, models, inference execution, and the related configurations exposed by Core 2. When reasoning about the performance of an ML-based system deployed using Seldon, we recommend breaking down the problem by first understanding and tuning the performance of deployed Models, and then subsequently considering more complex Pipelines composed of those models (if applicable). For both models and pipelines, it is important to run tests to understand baseline performance characteristics, before making efforts to tune these through changes to models, infrastructure, or inference configurations. The recommended approach can be broken down as follows:
Models
- Load testing to understand latency and throughput behaviour for one model replica
- Tuning performance for models. This can be done via changes to:
- Infrastructure - choosing the right hardware, and configurations in Core related to CPUs, GPUs and memory.
- Models - optimizing model artefacts in how they are structured, configured, stored. This can include model pruning, quantization, consideration of different model frameworks, and making sure that the model can achieve a high utilisation of the allocated resources.
- Inference - the way in which inference is executed. This can include the choice of communication protocols (REST, gRPC), payload configuration, batching, and efficient execution of concurrent requests.
**Pipelines**
- Testing Pipelines to identify the critical path based on performance of underlying models
- Core 2 Configuration to optimize data-processing through pipelines
- Scalability of Pipelines to understand how Core 2 components scale with the number of deployed pipelines and models
Overview (`docs-gb/scaling/README.md`)
This page provides an overview of the appraoches to achieving autoscaling with Core 2.
Autoscaling
Autoscaling in Seldon Core 2
Seldon Core 2 provides multiple approaches to scaling your machine learning deployments, allowing you to optimize resource utilization and handle varying workloads efficiently. In Core 2, we separate out Models and Servers, and Servers can have multiple Models loaded on them (Multi-Model Serving). Given this, setting up autoscaling requires defining the logic by which you want to scale your Models and then configuring the autoscaling of Servers such that they autoscale in a coordinated way. The following steps can be followed to set up autoscaling based on specific requirements:
- Identify metrics that you want to scale Models on. There are a couple of different options here:
- Core 2 natively supports scaling based on Inference Lag, meaning the difference between incoming and outgoing requests for a model in a given period of time. This is done by configuring
minReplicasormaxReplicasin the Model CRDs and making sure you configure the Core 2 install with theautoscaling.autoscalingModelEnabledhelm value set totrue(default isfalse). - Users can expose custom or Kubernetes-native metrics, and then target the scaling of models based on those metrics by using
HorizontalPodAutoscaler. This requires exposing the right metrics, using the monitoring tool of your choice (e.g. Prometheus).
- Core 2 natively supports scaling based on Inference Lag, meaning the difference between incoming and outgoing requests for a model in a given period of time. This is done by configuring
Once the approach for Model scaling is implemented, Server scaling needs to be configured.
- Implement Server Scaling by either:
- Enabling Autoscaling of Servers based on Model needs. This is managed by Seldon's scheduler, and is enabled by setting
minReplicasandmaxReplicasin the Server Custom Resource and making sure you configure the Core 2 install with theautoscaling.autoscalingServerEnabledhelm value set totrue(the default) - If Models and Servers are to have a one-to-one mapping (no Multi-Model Serving) then users can also define scaling of Servers using an HPA manifest that matches the HPA applied to the associated Models. This approach is outlined here. This approach will only work with custom metrics, as Kubernetes does not allow mutliple HPAs to target the same metrics from Kubernetes directly.
- Enabling Autoscaling of Servers based on Model needs. This is managed by Seldon's scheduler, and is enabled by setting
Based on the requirements above, one of the following three options for coordinated autoscaling of Models and Servers can be chosen:
| Scaling Approach | Scaling Metric | Multi-Model Serving | Pros | Cons |
|---|---|---|---|---|
| Seldon Core Autoscaling | Inference lag | ✅ | - Simplest Implementation- One metric across models | - Model scale down only when no inference traffic exists to that model |
| Model Autoscaling with HPA | User-defined (HPA) | ✅ | - Custom scaling metric | - Requires Metrics store integration (e.g. Prometheus)- Potentially suboptimal Server packing on scale down |
| Model and Server Autoscaling with HPA | User-defined (HPA) | ❌ | - Coordinated Model and Server scaling | - Requires Metrics store integration (e.g. Prometheus)- No Multi-Model Serving |
Alternatively, the following decision-tree showcases the approaches we recommend based on users' requirements:
Scaling Seldon Services
When running Core 2 at scale, it is important to understand the scaling behaviour of Seldon's services as well as the scaling of the Models and Servers themselves. This is outlined in the Scaling Core Services page.
Overview (`kafka/strimzi/README.md`)
Strimzi Kafka
Seldon Core 2 requires Kafka to implement data-centric inference Pipelines.
To install Kafka for testing purposed in your k8s cluster, we recommend to use Strimzi Operator.
This page discuss how to install Strimzi Operator and create Kafka cluster for trial, dev, or testing purposes.
For production grade installation consult [Strimzi documentation](https://strimzi.io/documentation/) or use one of managed solutions mentioned [here](./index.md).You can install and configure Strimzi using either Helm charts or our Ansible playbooks, both documented below.
Helm
The installation of a Kafka cluster requires the Strimzi Kafka operator installed in the same namespace.
This allows to directly use the mTLS certificates created by Strimzi Operator.
One option to install the Strimzi operator is via Helm.
Note that we are using here KRaft instead of Zookeeper for Kafka.
You can enable featureGates during Helm installation via:
helm upgrade --install strimzi-kafka-operator \
strimzi/strimzi-kafka-operator \
--namespace seldon-mesh --create-namespace \Use with caution!
Currently Kraft installation of Strimzi is not production ready.
See Strimzi [documentation](https://strimzi.io/docs/operators/0.35.0/deploying.html#ref-operator-use-kraft-feature-gate-str) and related GitHub [issue](https://github.com/strimzi/strimzi-kafka-operator/issues/5615) for further details.Create Kafka cluster in seldon-mesh namespace
helm upgrade seldon-core-v2-kafka kafka/strimzi -n seldon-mesh --installNote that a specific strimzi operator version is associated with a subset of supported Kafka versions.
Ansible
We provide automation around the installation of a Kafka cluster for Seldon Core 2 to help with development and testing use cases.
You can follow the steps defined here to install Kafka via ansible.
You can use our Ansible playbooks to install only Strimzi Operator and Kafka cluster by setting extra Ansible vars:
ansible-playbook playbooks/setup-ecosystem.yaml -e full_install=no -e install_kafka=yesNotes
- You can check kafka-examples for more details.
- As we are using KRaft, use Kafka version 3.3 or above.
- For security settings check here.
Overview (`scheduler/data-flow/README.md`)
Inference Graph Data Flow - Kafka Streams
About
The data-flow engine is built on top of Kafka Streams.
It implements the operations required to propagate information throughout an inference pipeline in Seldon Core 2.
These operations include multi-way joins, or fan-ins, and conversion of inference v2 response types to request types.
The core idea of asynchronous data flows is that they offer:
- buffering during periods of bursty traffic, e.g. for black-box explainers
- dynamic reconfiguration of pipelines to incorporate advanced monitoring components, e.g. drift detectors
- replay of messages
- auditability
Developer setup
You will need:
- JDK 17+
- Kotlin 1.6.10+
JDK
You can install JDK versions using:
To install with asdf, run:
asdf plugin-add java
asdf list-all java | less # See available options
ASDF_JAVA_VERSION=graalvm-22.0.0.2+java17 # Or your chosen JDK, `zulu-17.32.13` should also work
asdf install java $ASDF_JAVA_VERSION
asdf global java $ASDF_JAVA_VERSIONGraalVM offers strong performance through intelligent inlining and optimisations.
Zulu is stable, well supported too, and has performant GC behaviour.
Other options, such as Coretto, AdoptOpenJDK, and plain old Oracle OpenJDK also exist.
Kotlin
You can install a Kotlin SDK using asdf or sdkman.
Alternatively, you can simply let Gradle do the work... Read on.
Gradle
There is a Gradle wrapper included in this repository: ./gradlew.
You can install the necessary build and compilation dependencies by running the build target:
$ ./gradlew build
BUILD SUCCESSFUL in 536ms
6 actionable tasks: 6 up-to-dateYou can also run lint check and formatting using ktlint, which are also available as make targets i.e. make lint and make format.
$ ./gradlew ktlintCheck
$ ./gradlew ktlintFormatAfter a successful run, they generate reports in build/reports/ktlint.
Unsupported class file major version
If you see an error like the below, your Gradle version is not high enough:
_BuildScript_' Unsupported class file major version 61The use of JDK 17 requires Gradle 7.3+.
The default in this project is Gradle 7.4, specified in ./gradle/wrapper/gradle-wrapper.properties.
Check the compatibility matrix for a new enough version
for your Java and Kotlin SDK versions.
You can then update the version in distributionUrl under ./gradle/wrapper/gradle-wrapper.properties.
If you run ./gradlew build again, it should download new dependencies and progress.
If you are in JetBrains IDEA, you will need to close and re-open the project, as it gets confused.
Invalid target release
If you see an error like the below, then there are a few things to check:
> Task :compileJava FAILED
...
Execution failed for task ':compileJava'.
> invalid target release: 17It could be that your Gradle version is too old to recognise JDK 17+.
In this case, refer to the above section for Unsupported class file major version.
Alternatively, it could be that your JDK version is too low or that Gradle is failing to detect it.
Ensure you have installed a suitable JDK version, then run the below to check which toolchains Gradle is aware of:
$ ./gradlew -q javaToolchainsThe output should look similar to the below:
+ Options
| Auto-detection: Enabled
| Auto-download: Enabled
+ GraalVM Community JDK 17.0.2+8-jvmci-22.0-b05
| Location: <home>/.asdf/installs/java/graalvm-22.0.0.2+java17
| Language Version: 17
| Vendor: GraalVM Community
| Architecture: amd64
| Is JDK: true
| Detected by: Current JVM
+ Zulu JDK 17.0.2+8-LTS
| Location: <home>/.asdf/installs/java/zulu-17.32.13
| Language Version: 17
| Vendor: Zulu
| Architecture: amd64
| Is JDK: true
| Detected by: asdf-vmIf the expected JDK is not present, check that it is available in your PATH.
If it is present, check the allowed versions and vendors for java.toolchain or kotlin.jvmToolchain in build.gradle.kts.
Ensure your chosen JDK is compatible with these settings.
Unknown JVM target version
If you see an error like the below, your Kotlin version is not high enough.
Task :compileKotlin FAILED
e: Unknown JVM target version: 17Check for a newer version and update the version in build.gradle.kts:
plugins {
...
kotlin("jvm") version "X.X.X"
}gRPC protocol buffers
Rather than the effort of setting up a Gradle plugin, it is straightforward to use protoc directly.
The steps for Kotlin are documented here.
You will need both the Java and Kotlin extensions for protoc, available at:
- https://repo1.maven.org/maven2/io/grpc/protoc-gen-grpc-kotlin/
- https://repo1.maven.org/maven2/io/grpc/protoc-gen-grpc-java/
If running manually, the command will look like:
cd $(git rev-parse --show-toplevel)/apis/mlops/chainer
protoc \
--proto_path=. \
--plugin=protoc-gen-grpc-java=<path to protoc-gen-grpc-java> \
--java_out=./kotlin \
--grpc-java_out=./kotlin \
--plugin=protoc-gen-grpckt=<path to protoc-gen-grpc-kotlin.sh> \
--kotlin_out=./kotlin \
--grpckt_out=./kotlin \
chainer.protoOverview (`service-meshes/ambassador/README.md`)
Ambassador Notebook Example
Assumes
- You have installed emissary as per their docs
Tested with
emissary-ingress-7.3.2 insatlled via helm
INGRESS_IP=!kubectl get svc emissary-ingress -n emissary -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
INGRESS_IP=INGRESS_IP[0]
import os
os.environ['INGRESS_IP'] = INGRESS_IP
INGRESS_IP'172.21.255.1'Ambassador Single Model Example
!kustomize build config/single-modelapiVersion: getambassador.io/v3alpha1
kind: Host
metadata:
name: wildcard
namespace: seldon-mesh
spec:
hostname: '*'
requestPolicy:
insecure:
action: Route
---
apiVersion: getambassador.io/v3alpha1
kind: Listener
metadata:
name: emissary-ingress-listener-8080
namespace: seldon-mesh
spec:
hostBinding:
namespace:
from: ALL
port: 8080
protocol: HTTP
securityModel: INSECURE
---
apiVersion: getambassador.io/v3alpha1
kind: Mapping
metadata:
name: iris-grpc
namespace: seldon-mesh
spec:
add_request_headers:
seldon-model:
value: iris
grpc: true
hostname: '*'
prefix: /inference.GRPCInferenceService
rewrite: ""
service: seldon-mesh:80
---
apiVersion: getambassador.io/v3alpha1
kind: Mapping
metadata:
name: iris-http
namespace: seldon-mesh
spec:
add_request_headers:
seldon-model:
value: iris
hostname: '*'
prefix: /v2/
rewrite: ""
service: seldon-mesh:80
---
apiVersion: mlops.seldon.io/v1alpha1
kind: Model
metadata:
name: iris
namespace: seldon-mesh
spec:
requirements:
- sklearn
storageUri: gs://seldon-models/mlserver/iris!kustomize build config/single-model | kubectl apply --validate=false -f -host.getambassador.io/wildcard created
listener.getambassador.io/emissary-ingress-listener-8080 created
mapping.getambassador.io/iris-grpc created
mapping.getambassador.io/iris-http created
model.mlops.seldon.io/iris created!kubectl wait --for condition=ready --timeout=300s model --all -n seldon-meshmodel.mlops.seldon.io/iris condition met!curl -v http://${INGRESS_IP}/v2/models/iris/infer -H "Content-Type: application/json"\
-d '{"inputs": [{"name": "predict", "shape": [1, 4], "datatype": "FP32", "data": [[1, 2, 3, 4]]}]}'* Trying 172.21.255.1...
* Connected to 172.21.255.1 (172.21.255.1) port 80 (#0)
> POST /v2/models/iris/infer HTTP/1.1
> Host: 172.21.255.1
> User-Agent: curl/7.47.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 94
>
* upload completely sent off: 94 out of 94 bytes
< HTTP/1.1 200 OK
< content-length: 196
< content-type: application/json
< date: Sat, 16 Apr 2022 15:45:43 GMT
< server: envoy
< x-envoy-upstream-service-time: 792
< seldon-route: iris_1
<
* Connection #0 to host 172.21.255.1 left intact
{"model_name":"iris_1","model_version":"1","id":"72ac79f5-b355-4be3-b8c5-2ebedaa39f60","parameters":null,"outputs":[{"name":"predict","shape":[1],"datatype":"INT64","parameters":null,"data":[2]}]}!grpcurl -d '{"model_name":"iris","inputs":[{"name":"input","contents":{"fp32_contents":[1,2,3,4]},"datatype":"FP32","shape":[1,4]}]}' \
-plaintext \
-import-path ../../apis \
-proto ../../apis/mlops/v2_dataplane/v2_dataplane.proto \
${INGRESS_IP}:80 inference.GRPCInferenceService/ModelInfer{
"modelName": "iris_1",
"modelVersion": "1",
"outputs": [
{
"name": "predict",
"datatype": "INT64",
"shape": [
"1"
],
"contents": {
"int64Contents": [
"2"
]
}
}
]
}!kustomize build config/single-model | kubectl delete -f -host.getambassador.io "wildcard" deleted
listener.getambassador.io "emissary-ingress-listener-8080" deleted
mapping.getambassador.io "iris-grpc" deleted
mapping.getambassador.io "iris-http" deleted
model.mlops.seldon.io "iris" deletedTraffic Split Two Models
Currently not working due to this issue
!kustomize build config/traffic-splitapiVersion: getambassador.io/v3alpha1
kind: Host
metadata:
name: wildcard
namespace: seldon-mesh
spec:
hostname: '*'
requestPolicy:
insecure:
action: Route
---
apiVersion: getambassador.io/v3alpha1
kind: Listener
metadata:
name: emissary-ingress-listener-8080
namespace: seldon-mesh
spec:
hostBinding:
namespace:
from: ALL
port: 8080
protocol: HTTP
securityModel: INSECURE
---
apiVersion: getambassador.io/v3alpha1
kind: Mapping
metadata:
name: iris1-grpc
namespace: seldon-mesh
spec:
add_request_headers:
seldon-model:
value: iris1
grpc: true
hostname: '*'
prefix: /inference.GRPCInferenceService
rewrite: ""
service: seldon-mesh:80
---
apiVersion: getambassador.io/v3alpha1
kind: Mapping
metadata:
name: iris1-http
namespace: seldon-mesh
spec:
add_request_headers:
seldon-model:
value: iris1
add_response_headers:
seldon_model:
value: iris1
hostname: '*'
prefix: /v2
rewrite: ""
service: seldon-mesh:80
---
apiVersion: getambassador.io/v3alpha1
kind: Mapping
metadata:
name: iris2-grpc
namespace: seldon-mesh
spec:
add_request_headers:
seldon-model:
value: iris2
grpc: true
hostname: '*'
prefix: /inference.GRPCInferenceService
rewrite: ""
service: seldon-mesh:80
weight: 50
---
apiVersion: getambassador.io/v3alpha1
kind: Mapping
metadata:
name: iris2-http
namespace: seldon-mesh
spec:
add_request_headers:
seldon-model:
value: iris2
add_response_headers:
seldon_model:
value: iris2
hostname: '*'
prefix: /v2
rewrite: ""
service: seldon-mesh:80
weight: 50
---
apiVersion: mlops.seldon.io/v1alpha1
kind: Model
metadata:
name: iris1
namespace: seldon-mesh
spec:
requirements:
- sklearn
storageUri: gs://seldon-models/mlserver/iris
---
apiVersion: mlops.seldon.io/v1alpha1
kind: Model
metadata:
name: iris2
namespace: seldon-mesh
spec:
requirements:
- sklearn
storageUri: gs://seldon-models/mlserver/iris!kustomize build config/traffic-split | kubectl apply -f -host.getambassador.io/wildcard created
listener.getambassador.io/emissary-ingress-listener-8080 created
mapping.getambassador.io/iris1-grpc created
mapping.getambassador.io/iris1-http created
mapping.getambassador.io/iris2-grpc created
mapping.getambassador.io/iris2-http created
model.mlops.seldon.io/iris1 created
model.mlops.seldon.io/iris2 created!kubectl wait --for condition=ready --timeout=300s model --all -n seldon-meshmodel.mlops.seldon.io/iris1 condition met
model.mlops.seldon.io/iris2 condition met!curl -v http://${INGRESS_IP}/v2/models/iris/infer -H "Content-Type: application/json" \
-d '{"inputs": [{"name": "predict", "shape": [1, 4], "datatype": "FP32", "data": [[1, 2, 3, 4]]}]}'* Trying 172.21.255.1...
* Connected to 172.21.255.1 (172.21.255.1) port 80 (#0)
> POST /v2/models/iris/infer HTTP/1.1
> Host: 172.21.255.1
> User-Agent: curl/7.47.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 94
>
* upload completely sent off: 94 out of 94 bytes
< HTTP/1.1 200 OK
< content-length: 197
< content-type: application/json
< date: Sat, 16 Apr 2022 15:46:17 GMT
< server: envoy
< x-envoy-upstream-service-time: 920
< seldon-route: iris2_1
< seldon_model: iris2
<
* Connection #0 to host 172.21.255.1 left intact
{"model_name":"iris2_1","model_version":"1","id":"ed521c32-cd85-4cb8-90eb-7c896803f271","parameters":null,"outputs":[{"name":"predict","shape":[1],"datatype":"INT64","parameters":null,"data":[2]}]}!grpcurl -d '{"model_name":"iris1","inputs":[{"name":"input","contents":{"fp32_contents":[1,2,3,4]},"datatype":"FP32","shape":[1,4]}]}' \
-plaintext \
-import-path ../../apis \
-proto ../../apis/mlops/v2_dataplane/v2_dataplane.proto \
${INGRESS_IP}:80 inference.GRPCInferenceService/ModelInfer{
"modelName": "iris2_1",
"modelVersion": "1",
"outputs": [
{
"name": "predict",
"datatype": "INT64",
"shape": [
"1"
],
"contents": {
"int64Contents": [
"2"
]
}
}
]
}!kustomize build config/traffic-split | kubectl delete -f -host.getambassador.io "wildcard" deleted
listener.getambassador.io "emissary-ingress-listener-8080" deleted
mapping.getambassador.io "iris1-grpc" deleted
mapping.getambassador.io "iris1-http" deleted
mapping.getambassador.io "iris2-grpc" deleted
mapping.getambassador.io "iris2-http" deleted
model.mlops.seldon.io "iris1" deleted
model.mlops.seldon.io "iris2" deletedOverview (`service-meshes/istio/README.md`)
Istio Notebook Examples
Assumes
- You have installed istio as per their docs
- You have exposed the ingressgateway as an external loadbalancer
tested with:
istioctl version
1.13.2
istioctl install --set profile=demo -yINGRESS_IP=!kubectl get svc istio-ingressgateway -n istio-system -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
INGRESS_IP=INGRESS_IP[0]
import os
os.environ['INGRESS_IP'] = INGRESS_IP
INGRESS_IP'172.21.255.1'Istio Single Model Example
!kustomize build config/single-modelapiVersion: mlops.seldon.io/v1alpha1
kind: Model
metadata:
name: iris
namespace: seldon-mesh
spec:
requirements:
- sklearn
storageUri: gs://seldon-models/mlserver/iris
---
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: seldon-gateway
namespace: seldon-mesh
spec:
selector:
app: istio-ingressgateway
istio: ingressgateway
servers:
- hosts:
- '*'
port:
name: http
number: 80
protocol: HTTP
- hosts:
- '*'
port:
name: https
number: 443
protocol: HTTPS
tls:
mode: SIMPLE
privateKey: /etc/istio/ingressgateway-certs/tls.key
serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: iris-route
namespace: seldon-mesh
spec:
gateways:
- istio-system/seldon-gateway
hosts:
- '*'
http:
- match:
- uri:
prefix: /v2
name: iris-http
route:
- destination:
host: seldon-mesh.seldon-mesh.svc.cluster.local
headers:
request:
set:
seldon-model: iris
- match:
- uri:
prefix: /inference.GRPCInferenceService
name: iris-grpc
route:
- destination:
host: seldon-mesh.seldon-mesh.svc.cluster.local
headers:
request:
set:
seldon-model: iris!kustomize build config/single-model | kubectl apply -f -model.mlops.seldon.io/iris unchanged
gateway.networking.istio.io/seldon-gateway unchanged
virtualservice.networking.istio.io/iris-route configured!kubectl wait --for condition=ready --timeout=300s model --all -n seldon-meshmodel.mlops.seldon.io/iris condition met!curl -v http://${INGRESS_IP}/v2/models/iris/infer -H "Content-Type: application/json" \
-d '{"inputs": [{"name": "predict", "shape": [1, 4], "datatype": "FP32", "data": [[1, 2, 3, 4]]}]}'* Trying 172.21.255.1...
* Connected to 172.21.255.1 (172.21.255.1) port 80 (#0)
> POST /v2/models/iris/infer HTTP/1.1
> Host: 172.21.255.1
> User-Agent: curl/7.47.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 94
>
* upload completely sent off: 94 out of 94 bytes
< HTTP/1.1 200 OK
< content-length: 196
< content-type: application/json
< date: Sat, 16 Apr 2022 15:34:11 GMT
< server: istio-envoy
< x-envoy-upstream-service-time: 802
< seldon-route: iris_1
<
* Connection #0 to host 172.21.255.1 left intact
{"model_name":"iris_1","model_version":"1","id":"83520c4a-c7f1-4363-9bfd-60c5d8ee2dc5","parameters":null,"outputs":[{"name":"predict","shape":[1],"datatype":"INT64","parameters":null,"data":[2]}]}!grpcurl -d '{"model_name":"iris","inputs":[{"name":"input","contents":{"fp32_contents":[1,2,3,4]},"datatype":"FP32","shape":[1,4]}]}' \
-plaintext \
-import-path ../../apis \
-proto ../../apis/mlops/v2_dataplane/v2_dataplane.proto \
${INGRESS_IP}:80 inference.GRPCInferenceService/ModelInfer{
"modelName": "iris_1",
"modelVersion": "1",
"outputs": [
{
"name": "predict",
"datatype": "INT64",
"shape": [
"1"
],
"contents": {
"int64Contents": [
"2"
]
}
}
]
}!kustomize build config/single-model | kubectl delete -f -model.mlops.seldon.io "iris" deleted
gateway.networking.istio.io "seldon-gateway" deleted
virtualservice.networking.istio.io "iris-route" deletedTraffic Split Two Models
!kustomize build config/traffic-splitapiVersion: mlops.seldon.io/v1alpha1
kind: Model
metadata:
name: iris1
namespace: seldon-mesh
spec:
requirements:
- sklearn
storageUri: gs://seldon-models/mlserver/iris
---
apiVersion: mlops.seldon.io/v1alpha1
kind: Model
metadata:
name: iris2
namespace: seldon-mesh
spec:
requirements:
- sklearn
storageUri: gs://seldon-models/mlserver/iris
---
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: seldon-gateway
namespace: seldon-mesh
spec:
selector:
app: istio-ingressgateway
istio: ingressgateway
servers:
- hosts:
- '*'
port:
name: http
number: 80
protocol: HTTP
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: iris-route
namespace: seldon-mesh
spec:
gateways:
- seldon-gateway
hosts:
- '*'
http:
- match:
- uri:
prefix: /v2/models/iris
name: iris-http
route:
- destination:
host: seldon-mesh.seldon-mesh.svc.cluster.local
headers:
request:
set:
seldon-model: iris1
weight: 50
- destination:
host: seldon-mesh.seldon-mesh.svc.cluster.local
headers:
request:
set:
seldon-model: iris2
weight: 50
- match:
- uri:
prefix: /inference.GRPCInferenceService
name: iris-grpc
route:
- destination:
host: seldon-mesh.seldon-mesh.svc.cluster.local
headers:
request:
set:
seldon-model: iris1
weight: 50
- destination:
host: seldon-mesh.seldon-mesh.svc.cluster.local
headers:
request:
set:
seldon-model: iris2
weight: 50!kustomize build config/traffic-split | kubectl apply -f -model.mlops.seldon.io/iris1 created
model.mlops.seldon.io/iris2 created
gateway.networking.istio.io/seldon-gateway created
virtualservice.networking.istio.io/iris-route created!kubectl wait --for condition=ready --timeout=300s model --all -n seldon-meshmodel.mlops.seldon.io/iris1 condition met
model.mlops.seldon.io/iris2 condition met!curl -v http://${INGRESS_IP}/v2/models/iris/infer -H "Content-Type: application/json" \
-d '{"inputs": [{"name": "predict", "shape": [1, 4], "datatype": "FP32", "data": [[1, 2, 3, 4]]}]}'* Trying 172.21.255.1...
* Connected to 172.21.255.1 (172.21.255.1) port 80 (#0)
> POST /v2/models/iris/infer HTTP/1.1
> Host: 172.21.255.1
> User-Agent: curl/7.47.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 94
>
* upload completely sent off: 94 out of 94 bytes
< HTTP/1.1 200 OK
< content-length: 197
< content-type: application/json
< date: Sat, 16 Apr 2022 15:35:01 GMT
< server: istio-envoy
< x-envoy-upstream-service-time: 801
< seldon-route: iris1_1
<
* Connection #0 to host 172.21.255.1 left intact
{"model_name":"iris1_1","model_version":"1","id":"b54e6d8c-d253-4bb9-bb64-02c2ee49e89f","parameters":null,"outputs":[{"name":"predict","shape":[1],"datatype":"INT64","parameters":null,"data":[2]}]}!grpcurl -d '{"model_name":"iris1","inputs":[{"name":"input","contents":{"fp32_contents":[1,2,3,4]},"datatype":"FP32","shape":[1,4]}]}' \
-plaintext \
-import-path ../../apis \
-proto ../../apis/mlops/v2_dataplane/v2_dataplane.proto \
${INGRESS_IP}:80 inference.GRPCInferenceService/ModelInfer{
"modelName": "iris1_1",
"modelVersion": "1",
"outputs": [
{
"name": "predict",
"datatype": "INT64",
"shape": [
"1"
],
"contents": {
"int64Contents": [
"2"
]
}
}
]
}!kustomize build config/traffic-split | kubectl delete -f -model.mlops.seldon.io "iris1" deleted
model.mlops.seldon.io "iris2" deleted
gateway.networking.istio.io "seldon-gateway" deleted
virtualservice.networking.istio.io "iris-route" deletedOverview (`service-meshes/traefik/README.md`)
Traefik Examples
Assumes
- You have installed Traefik as per their docs into namespace traefik-v2
Tested with traefik-10.19.4
INGRESS_IP=!kubectl get svc traefik -n traefik-v2 -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
INGRESS_IP=INGRESS_IP[0]
import os
os.environ['INGRESS_IP'] = INGRESS_IP
INGRESS_IP'172.21.255.1'Traefik Single Model Example
!kustomize build config/single-modelapiVersion: v1
kind: Service
metadata:
name: myapps
namespace: seldon-mesh
spec:
ports:
- name: web
port: 80
protocol: TCP
selector:
app: traefik-ingress-lb
type: LoadBalancer
---
apiVersion: mlops.seldon.io/v1alpha1
kind: Model
metadata:
name: iris
namespace: seldon-mesh
spec:
requirements:
- sklearn
storageUri: gs://seldon-models/mlserver/iris
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: iris
namespace: seldon-mesh
spec:
entryPoints:
- web
routes:
- kind: Rule
match: PathPrefix(`/`)
middlewares:
- name: iris-header
services:
- name: seldon-mesh
port: 80
scheme: h2c
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: iris-header
namespace: seldon-mesh
spec:
headers:
customRequestHeaders:
seldon-model: iris!kustomize build config/single-model | kubectl apply -f -service/myapps created
model.mlops.seldon.io/iris created
ingressroute.traefik.containo.us/iris created
middleware.traefik.containo.us/iris-header created!kubectl wait --for condition=ready --timeout=300s model --all -n seldon-meshmodel.mlops.seldon.io/iris condition met!curl -v http://${INGRESS_IP}/v2/models/iris/infer -H "Content-Type: application/json" \
-d '{"inputs": [{"name": "predict", "shape": [1, 4], "datatype": "FP32", "data": [[1, 2, 3, 4]]}]}'* Trying 172.21.255.1...
* Connected to 172.21.255.1 (172.21.255.1) port 80 (#0)
> POST /v2/models/iris/infer HTTP/1.1
> Host: 172.21.255.1
> User-Agent: curl/7.47.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 94
>
* upload completely sent off: 94 out of 94 bytes
< HTTP/1.1 200 OK
< Content-Length: 196
< Content-Type: application/json
< Date: Sat, 16 Apr 2022 15:53:27 GMT
< Seldon-Route: iris_1
< Server: envoy
< X-Envoy-Upstream-Service-Time: 895
<
* Connection #0 to host 172.21.255.1 left intact
{"model_name":"iris_1","model_version":"1","id":"0dccf477-78fa-4a11-92ff-4d7e4f1cdda8","parameters":null,"outputs":[{"name":"predict","shape":[1],"datatype":"INT64","parameters":null,"data":[2]}]}!grpcurl -d '{"model_name":"iris","inputs":[{"name":"input","contents":{"fp32_contents":[1,2,3,4]},"datatype":"FP32","shape":[1,4]}]}' \
-plaintext \
-import-path ../../apis \
-proto ../../apis/mlops/v2_dataplane/v2_dataplane.proto \
${INGRESS_IP}:80 inference.GRPCInferenceService/ModelInfer{
"modelName": "iris_1",
"modelVersion": "1",
"outputs": [
{
"name": "predict",
"datatype": "INT64",
"shape": [
"1"
],
"contents": {
"int64Contents": [
"2"
]
}
}
]
}!kustomize build config/single-model | kubectl delete -f -service "myapps" deleted
model.mlops.seldon.io "iris" deleted
ingressroute.traefik.containo.us "iris" deleted
middleware.traefik.containo.us "iris-header" deletedOverview (`tests/k6/README.md`)
K6 Load Testing
Available environment variables can be found in components/settings.js
Setup
- Install k6 (load driver)
- link
- Alternatively you can build a docker image that includes k6 via:
make docker-build
- (Optional) Install kube api
make xk6-install, remember to use the local folder k6 binary if kube apis are required - Local testing
- Deploy the system using docker compose via:
make deploy-local
- Deploy the system using docker compose via:
Examples
- run tfsimple model
- output http debug to file log.txt
- Only load models and infer (no unload)
- run 500 model loads with 10 concurrent VUs
INFER_HTTP_ITERATIONS=10 SKIP_UNLOAD_MODEL=1 MODEL_TYPE="tfsimple" k6 run -u 10 -i 500 --http-debug --log-output=stdout scenarios/load_predict_unload.js > log.txtFor isolated agent test:
- start seldon-core with host networking via:
make -C scheduler start-all-host - hit mlserver directly
SCHEDULER_ENDPOINT=0.0.0.0:9004 ENVOY="false" INFER_GRPC_ENDPOINT=0.0.0.0:8081 INFER_HTTP_ENDPOINT=http://0.0.0.0:8080 INFER_HTTP_ITERATIONS=1 INFER_GRPC_ITERATIONS=1 MODEL_TYPE="iris" MAX_NUM_MODELS=10 k6 run -u 1 -i 10 --http-debug scenarios/infer_constant_rate.js- hit agent reverse proxy, just change the ports for the inference endpoints
SCHEDULER_ENDPOINT=0.0.0.0:9004 ENVOY="false" INFER_GRPC_ENDPOINT=0.0.0.0:9998 INFER_HTTP_ENDPOINT=http://0.0.0.0:9999 INFER_HTTP_ITERATIONS=1 INFER_GRPC_ITERATIONS=1 MODEL_TYPE="iris" MAX_NUM_MODELS=10 k6 run -u 1 -i 10 --http-debug scenarios/infer_constant_rate.jsNote: check ports in scheduler/env.all
For k8s you will need to update the default endpoints to the services exposed, e.g.
MODEL_TYPE="tfsimple" SCHEDULER_ENDPOINT=172.18.255.4:9004 INFER_GRPC_ENDPOINT=172.18.255.3:80 INFER_HTTP_ENDPOINT=http://172.18.255.3 k6 run -u 5 -i 50 scenarios/load_predict_unload.jsConstant Throughput Test
Run against model name iris which is of type iris against a envoy http ip as given.
MODEL_NAME="iris" MODEL_TYPE="iris" INFER_HTTP_ENDPOINT="http://172.31.255.9" k6 run scenarios/model_constant_rate.jsRun locally but with grpc
INFER_TYPE="grpc" MODEL_TYPE="iris" k6 run scenarios/model_constant_rate.jsNote: there are more scenarios in scenarios and models in components/model.js
Overview (`apis/mlops/agent/README.md`)
Agent Service
- Allow scheduler to ask agent to load or unload a model.
- Allow agent to tell scheduler a model has been loaded or unloaded.
Overview (`apis/mlops/scheduler/README.md`)
Scheduler Service
- Allow a model server to be added with given replica endpoints
- Allow a model server to be removed
- Allow a model to be started on a server
- Allow a model to be removed
Overview (`docs-gb/apis/inference/README.md`)
A comprehensive guide to Seldon's Open Inference Protocol API specification for standardized inference server implementations.
Inference
Learn about the API specification implemented in all Seldon inference servers. The specification ensures consistency and interoperability across different inference server implementations.
Seldon inference servers must respect the following API specification.
In future, Seldon may provide extensions for use with Pipelines, Experiments and Explainers.
Overview (`docs-gb/apis/internal/README.md`)
Internal APIs
Seldon provides some internal gRPC services it uses to manage components.
Overview (`docs-gb/getting-started/kubernetes-installation/README.md`)
Kubernetes Installation
Prerequisites
- Ensure that the version of the Kubernetes cluster meets the requirement listed below. You can create a KinD cluster on your local computer for testing with Ansible.
- Install the ecosystem components using Ansible.
Core 2 Dependencies
Here is a list of components that Seldon Core 2 depends on, with minimum and maximum supported versions.
| Component | Minimum Version | Maximum Version | Notes |
|---|---|---|---|
| Kubernetes | 1.27 | 1.31 | Required |
Envoy* |
1.32.2 | 1.32.2 | Required |
Rclone* |
1.68.2 | 1.68.2 | Required |
Kafka** |
3.4 | 3.8 | Recommended |
| Prometheus | 2.0 | 2.x | Optional |
| Grafana | 10.0 | *** |
Optional |
| Prometheus-adapter | 0.12 | 0.12 | Optional |
| Opentelemetry Collector | 0.68 | *** |
Optional |
* These components are shipped as part of Seldon Core 2 docker images set, users should not install them separately but they need to be aware of the configuration options that are supported by these versions.** Kafka is only required to operate Seldon Core 2 dataflow Pipelines. If not required then users should not install seldon-modelgateway, seldon-pipelinegateway, and seldon-dataflow-engine.*** Not hard limit on the maximum version to be used.
Install Ecosystem Components
You also need to install our ecosystem components. For this we provide directions for Ansible to install these.
| Component | Summary |
|---|---|
| Kafka | Required for inference Pipeline usage. |
| Prometheus | (Optional) Exposes metrics. |
| Grafana | (Optional) UI for metrics. |
| OpenTelemetry | (Optional) Exposes tracing. |
| Jaeger | (Optional) UI for traces. |
Install
To install Seldon Core 2 from the source repository, you can choose one of the following methods:
The Kubernetes operator that is installed runs in namespaced mode so any resources you create
need to be in the same namespace as you installed into.
Kustomize
Seldon recommends installing Seldon Core 2 using Helm or Ansible. If you prefer to use Kustomize, you can base your configuration on the raw YAML files you generate in the k8s/yaml folder. Alternatively, you can follow the steps in the k8s/Makefile, which demonstrates how to build the YAML files from the Kustomize bases.
Operations
Overview (`docs-gb/installation/advanced-configurations/README.md`)
Advanced Configurations
Overview (`docs-gb/installation/helm/README.md`)
Helm Configuration Options
Seldon Core 2 provides a highly configurable deployment framework that allows you to fine-tune various components using Helm configuration options. These options offer control over deployment behavior, resource management, logging, autoscaling, and model lifecycle policies to optimize the performance and scalability of machine learning deployments.
This section details the key Helm configuration parameters for Envoy, Autoscaling, Server Prestop, and Model Control Plane, ensuring that you can customize deployment workflows and enhance operational efficiency.
- Envoy: Manage pre-stop behaviors and configure access logging to track request-level interactions.
- Autoscaling (Experimental): Fine-tune dynamic scaling policies for efficient resource allocation based on real-time inference workloads.
- Servers: Define grace periods for controlled shutdowns and optimize model control plane parameters for efficient model loading, unloading, and error handling.
- Logging: Define log levels for the different components of the system.
Envoy
Prestop
| Key | Chart | Description | Default |
|---|---|---|---|
envoy.preStopSleepPeriodSeconds |
components | Sleep after calling prestop command. | 30 |
envoy.terminationGracePeriodSeconds |
components | Grace period to wait for prestop to finish for Envoy pods. | 120 |
Access Log
| Key | Chart | Description | Default |
|---|---|---|---|
envoy.enableAccesslog |
components | Whether to enable logging of requests. | true |
envoy.accesslogPath |
components | Path on disk to store logfile. This is only used when enableAccesslog is set. |
/tmp/envoy-accesslog.txt |
envoy.includeSuccessfulRequests |
components | Whether to including successful requests. If set to false, then only failed requests are logged. This is only used when enableAccesslog is set. |
false |
Autoscaling
Native autoscaling (experimental)
| Key | Chart | Description | Default |
|---|---|---|---|
autoscaling.autoscalingModelEnabled |
components | Enable native autoscaling for Models. This is orthogonal to external autoscaling services e.g. HPA. | false |
autoscaling.autoscalingServerEnabled |
components | Enable native autoscaling for Models. This is orthogonal to external autoscaling services e.g. HPA. | true |
agent.scalingStatsPeriodSeconds |
components | Sampling rate for metrics used for autoscaling. | 20 |
agent.modelInferenceLagThreshold |
components | Queue lag threshold to trigger scaling up of a model replica. | 30 |
agent.modelInactiveSecondsThreshold |
components | Period with no activity after which to trigger scaling down of a model replica. | 600 |
autoscaling.serverPackingEnabled |
components | Whether packing of models onto fewer servers is enabled. | false |
autoscaling.serverPackingPercentage |
components | Percentage of events where packing is allowed. Higher values represent more aggressive packing. This is only used when serverPackingEnabled is set. Range is from 0.0 to 1.0 |
0.0 |
Server
Prestop
| Key | Chart | Description | Default |
|---|---|---|---|
serverConfig.terminationGracePeriodSeconds |
components | Grace period to wait for prestop process to finish for this particular Server pod. | 120 |
Model Control Plane
| Key | Chart | Description | Default |
|---|---|---|---|
agent.overcommitPercentage |
components | Overcommit percentage (of memory) allowed. Range is from 0 to 100 | 10 |
agent.maxLoadElapsedTimeMinutes |
components | Max time allowed for one model load command for a model on a particular server replica to take. Lower values allow errors to be exposed faster. | 120 |
agent.maxLoadRetryCount |
components | Max number of retries for unsuccessful load command for a model on a particular server replica. Lower values allow control plane commands to fail faster. | 5 |
agent.maxUnloadElapsedTimeMinutes |
components | Max time allowed for one model unload command for a model on a particular server replica to take. Lower values allow errors to be exposed faster. | 15 |
agent.maxUnloadRetryCount |
components | Max number of retries for unsuccessful unload command for a model on a particular server replica. Lower values allow control plane commands to fail faster. | 5 |
agent.unloadGracePeriodSeconds |
components | A period guarding against race conditions between Envoy actually applying the cluster change to remove a route and before proceeding with the model replica unloading command. | 2 |
Logging
Component Log Level
| Key | Chart | Description | Default |
|---|---|---|---|
logging.logLevel |
components | Components wide settings for logging level, if individual component levels are not set. Options are: debug, info, error. | info |
controller.logLevel |
components | check zap log level here | |
dataflow.logLevel |
components | check klogging level here | |
dataflow.logLevelKafka |
components | check klogging level here | |
scheduler.logLevel |
components | check logrus log level here | |
modelgateway.logLevel |
components | check logrus log level here | |
pipelinegateway.logLevel |
components | check logrus log level here | |
hodometer.logLevel |
components | check logrus log level here | |
serverConfig.rclone.logLevel |
components | check rclone log-level here |
|
serverConfig.agent.logLevel |
components | check logrus log level here |
Notes:
- We set kafka client library log level from the log level that is passed to the component, which could be different to the level expected by
librdkafka(syslog level). In this case we attempt to map the log level value to the best match.
Overview (`docs-gb/installation/learning-environment/README.md`)
Learning Environment
You can install Seldon Core 2 on your local computer that is running a Kubernetes cluster using kind.
Seldon publishes the Helm charts that are required to install Seldon Core 2. For more information about the Helm charts and the related dependencies,see Helm charts and Dependencies.
{% hint style="info" %}
Note: These instructions guide you through installing Seldon Core 2 on a local Kubernetes cluster, focusing on ease of learning. Ensure your kind cluster is running on hardware with at least 32GB of RAM and a load balancer such as MetalLB is configured.
{% endhint %}
Prerequisites
- Install a Kubernetes cluster that is running version 1.27 or later.
- Install kubectl, the Kubernetes command-line tool.
- Install Helm, the package manager for Kubernetes or Ansible, the automation tool used for provisioning, configuration management, and application deployment.
{% hint style="info" %}
Note: Ansible automates provisioning, configuration management, and handles all dependencies required for Seldon Core 2.
With Helm, you need to configure and manage the dependencies yourself.
{% endhint %}
Installing Seldon Core 2
{% tabs %}
{% tab title="Helm" %}
Create a namespace to contain the main components of Seldon Core 2. For example, create the
seldon-meshnamespace.bashkubectl create ns seldon-mesh || echo "Namespace seldon-mesh already exists"Add and update the Helm charts,
seldon-charts, to the repository.bashhelm repo add seldon-charts https://seldonio.github.io/helm-charts/ helm repo update seldon-chartsInstall Custom resource definitions for Seldon Core 2.
bashhelm upgrade seldon-core-v2-crds seldon-charts/seldon-core-v2-crds \ --namespace default \ --installInstall Seldon Core 2 operator in the
seldon-meshnamespace.bashhelm upgrade seldon-core-v2-setup seldon-charts/seldon-core-v2-setup \ --namespace seldon-mesh --set controller.clusterwide=true \ --installThis configuration installs the Seldon Core 2 operator across an entire Kubernetes cluster. To perform cluster-wide operations, create
ClusterRolesand ensure your user has the necessary permissions during deployment. With cluster-wide operations, you can createSeldonRuntimesin any namespace.You can configure the installation to deploy the Seldon Core 2 operator in a specific namespace so that it control resources in the provided namespace. To do this, set
controller.clusterwidetofalse.Install Seldon Core 2 runtimes in the
seldon-meshnamespace.bashhelm upgrade seldon-core-v2-runtime seldon-charts/seldon-core-v2-runtime \ --namespace seldon-mesh \ --installInstall Seldon Core 2 servers in the
seldon-meshnamespace. Two example servers namedmlserver-0, andtriton-0are installed so that you can load the models to these servers after installation.bashhelm upgrade seldon-core-v2-servers seldon-charts/seldon-core-v2-servers \ --namespace seldon-mesh \ --installCheck Seldon Core 2 operator, runtimes, servers, and CRDS are installed in the
seldon-meshnamespace. It might take a couple of minutes for all the Pods to be ready. To check the status of the Pods in real time use this command:kubectl get pods -w -n seldon-mesh.bashkubectl get pods -n seldon-meshThe output should be similar to this:
textNAME READY STATUS RESTARTS AGE hodometer-749d7c6875-4d4vw 1/1 Running 0 4m33s mlserver-0 3/3 Running 0 4m10s seldon-dataflow-engine-7b98c76d67-v2ztq 0/1 CrashLoopBackOff 5 (49s ago) 4m33s seldon-envoy-bb99f6c6b-4mpjd 1/1 Running 0 4m33s seldon-modelgateway-5c76c7695b-bhfj5 1/1 Running 0 4m34s seldon-pipelinegateway-584c7d95c-bs8c9 1/1 Running 0 4m34s seldon-scheduler-0 1/1 Running 0 4m34s seldon-v2-controller-manager-5dd676c7b7-xq5sm 1/1 Running 0 4m52s triton-0 2/3 Running 0 4m10s
{% hint style="info" %}
Note: Pods with names starting with seldon-dataflow-engine, seldon-pipelinegateway, and seldon-modelgateway may generate log errors until they successfully connect to Kafka. This occurs because Kafka is not yet fully integrated with Seldon Core 2.
{% endhint %}
{% endtab %}
{% tab title="Ansible" %}
{% hint style="info" %}
Note: For more information about configurations, see the supported versions of Python libraries, and customization options
{% endhint %}
You can install Seldon Core 2 and its components using Ansible in one of the following methods:
Single command
To install Seldon Core 2 into a new local kind Kubernetes cluster, you can use the seldon-all playbook with a single command:
ansible-playbook playbooks/seldon-all.yamlThis creates a kind cluster and installs ecosystem dependencies such kafka,
Prometheus, OpenTelemetry, and Jaeger as well as all the seldon-specific components.
The seldon components are installed using helm-charts from the current git
checkout (../k8s/helm-charts/).
Internally this runs, in order, the following playbooks:
- kind-cluster.yaml
- setup-ecosystem.yaml
- setup-seldon.yaml
You may pass any of the additonal variables which are configurable for those playbooks to seldon-all.
For example:
ansible-playbook playbooks/seldon-all.yaml -e seldon_mesh_namespace=my-seldon-mesh -e install_prometheus=no -e @playbooks/vars/set-custom-images.yamlRunning the playbooks individually gives you more control over what and when it runs. For example, if you want to install into an existing k8s cluster.
Multiple commands
Create a kind cluster.
bashansible-playbook playbooks/kind-cluster.yamlSetup ecosystem.
bashansible-playbook playbooks/setup-ecosystem.yamlSeldon runs by default in the
seldon-meshnamespace and a Jaeger pod and OpenTelemetry collector are installed in the namespace.
To install in a different<mynamespace>namespace:bashansible-playbook playbooks/setup-ecosystem.yaml -e seldon_mesh_namespace=<mynamespace>Install Seldon Core 2 in the
ansible/folder.bashansible-playbook playbooks/setup-seldon.yamlTo install in a different namespace,
<mynamespace>.bashansible-playbook playbooks/setup-seldon.yaml -e seldon_mesh_namespace=<mynamespace>
{% endtab %}
{% endtabs %}
Next Steps
If you installed Seldon Core 2 using Helm, you need to complete the installation of other components in the following order:
Overview (`docs-gb/installation/production-environment/README.md`)
Prerequisites
- Set up and connect to a Kubernetes cluster running version 1.27 or later. For instructions on connecting to your Kubernetes cluster, refer to the documentation provided by your cloud provider.
- Install kubectl, the Kubernetes command-line tool.
- Install Helm, the package manager for Kubernetes.
To use Seldon Core 2 in a production environment:
Seldon publishes the Helm charts that are required to install Seldon Core 2. For more information about the Helm charts and the related dependencies, see Helm charts and Dependencies.
Creating Namespaces
Create a namespace to contain the main components of Seldon Core 2. For example, create the namespace
seldon-mesh:bashkubectl create ns seldon-mesh || echo "Namespace seldon-mesh already exists"Create a namespace to contain the components related to monitoring. For example, create the namespace
seldon-monitoring:bashkubectl create ns seldon-monitoring || echo "Namespace seldon-monitoring already exists"
Installing Seldon Core 2
Add and update the Helm charts
seldon-chartsto the repository.bashhelm repo add seldon-charts https://seldonio.github.io/helm-charts/ helm repo update seldon-chartsInstall custom resource definitions for Seldon Core 2.
bashhelm upgrade seldon-core-v2-crds seldon-charts/seldon-core-v2-crds \ --namespace default \ --installInstall Seldon Core 2 operator in the
seldon-meshnamespace.bashhelm upgrade seldon-core-v2-setup seldon-charts/seldon-core-v2-setup \ --namespace seldon-mesh --set controller.clusterwide=true \ --installThis configuration installs the Seldon Core 2 operator across an entire Kubernetes cluster. To perform cluster-wide operations, create
ClusterRolesand ensure your user has the necessary permissions during deployment. With cluster-wide operations, you can createSeldonRuntimesin any namespace.With cluster-wide installation, you can specify the namespaces to watch by setting
controller.watchNamespacesto a comma-separated list of namespaces (e.g.,{ns1, ns2}). This allows the Seldon Core 2 operator to monitor and manage resources in those namespaces.You can also install multiple operators in different namespaces, and configure them to watch a disjoint set of namespaces. For example, you can install two operators in
op-ns1andop-ns2, and configure them to watchns1, ns2andns3, ns4, respectively, using the following commands:bashfor ns in op-ns1 op-ns2 ns1 ns2 ns3 ns4; do kubectl create ns "$ns"; doneWe now install the first operator in
op-ns1and configure it to watchns1andns2:bashhelm upgrade seldon-core-v2-setup seldon-charts/seldon-core-v2-setup \ --namespace op-ns1 \ --set controller.clusterwide=true \ --set "controller.watchNamespaces={ns1,ns2}" \ --installNext, we install the second operator in
op-ns2and configure it to watchns3andns4:bashhelm upgrade seldon-core-v2-setup seldon-charts/seldon-core-v2-setup \ --namespace op-ns2 \ --set controller.clusterwide=true \ --set "controller.watchNamespaces={ns3,ns4}" \ --set controller.skipClusterRoleCreation=true \ --installNote that the second operator is installed with
skipClusterRoleCreation=trueto avoid re-creating theClusterRoleandClusterRoleBindingthat were created by the first operator.Finally, you can configure the installation to deploy the Seldon Core 2 operator in a specific namespace so that it control resources in the provided namespace. To do this, set
controller.clusterwidetofalse.Install Seldon Core 2 runtimes in the namespace
seldon-mesh.bashhelm upgrade seldon-core-v2-runtime seldon-charts/seldon-core-v2-runtime \ --namespace seldon-mesh \ --installInstall Seldon Core 2 servers in the namespace
seldon-mesh. Two example servers namedmlserver-0, andtriton-0are installed so that you can load the models to these servers after installation.bashhelm upgrade seldon-core-v2-servers seldon-charts/seldon-core-v2-servers \ --namespace seldon-mesh \ --installCheck Seldon Core 2 operator, runtimes, servers, and CRDS are installed in the namespace
seldon-mesh:bashkubectl get pods -n seldon-meshThe output should be similar to this:
textNAME READY STATUS RESTARTS AGE hodometer-749d7c6875-4d4vw 1/1 Running 0 4m33s mlserver-0 3/3 Running 0 4m10s seldon-dataflow-engine-7b98c76d67-v2ztq 0/1 CrashLoopBackOff 5 (49s ago) 4m33s seldon-envoy-bb99f6c6b-4mpjd 1/1 Running 0 4m33s seldon-modelgateway-5c76c7695b-bhfj5 1/1 Running 0 4m34s seldon-pipelinegateway-584c7d95c-bs8c9 1/1 Running 0 4m34s seldon-scheduler-0 1/1 Running 0 4m34s seldon-v2-controller-manager-5dd676c7b7-xq5sm 1/1 Running 0 4m52s triton-0 2/3 Running 0 4m10s
{% hint style="info" %}
Note: Pods with names starting with seldon-dataflow-engine, seldon-pipelinegateway, and seldon-modelgateway may generate log errors until they successfully connect to Kafka. This occurs because Kafka is not yet fully integrated with Seldon Core 2.
{% endhint %}
Next steps
You can integrate Seldon Core 2 with Kafka that is self-hosted or a managed Kafka.
Additional Resources
Overview (`docs-gb/kubernetes/confluent/README.md`)
Confluent
Seldon Core 2 leverages Kafka for implementing data-centric inference Pipelines. This also means that Core 2 users have the ability of integrating with other products from the Kafka ecosystem, such as Schema Registry, Connect or ksqlDB in order to build custom data streaming, processing and logging solutions for machine learning workflows.
Overview (`docs-gb/kubernetes/resources/README.md`)
Resources
For Kubernetes usage we provide a set of custom resources for interacting with Seldon.
- SeldonRuntime - for installing Seldon in a particular namespace.
- Servers - for deploying sets of replicas of core inference servers (MLServer or Triton).
- Models - for deploying single machine learning models, custom transformation logic, drift detectors, outliers detectors and explainers.
- Experiments - for testing new versions of models.
- Pipelines - for connecting together flows of data between models.
Advanced Customization
SeldonConfig and ServerConfig define the core installation configuration and machine learning inference server
configuration for Seldon. Normally, you would not need to customize these but this may be required for
your particular custom installation within your organisation.
- ServerConfigs - for defining new types of inference server that can
be reference by a Server resource. - SeldonConfig - for defining how seldon is installed
Overview (`docs-gb/kubernetes/service-meshes/README.md`)
Service Meshes
The Seldon models and pipelines are exposed via a single service endpoint in the install
namespace called seldon-mesh. All models, pipelines and experiments can be reached via
this single Service endpoint by setting appropriate headers on the inference REST/gRPC
request. By this means Seldon is agnostic to any service mesh you may wish to use in your
organisation. We provide some example integrations for some example service meshes below
(alphabetical order):
We welcome help to extend these to other service meshes.
Overview (`docs-gb/models/parameterized-models/README.md`)
Parameterized Models
The Model specification allows parameters to be passed to the loaded model to allow customization. For example:
# samples/models/choice1.yaml
apiVersion: mlops.seldon.io/v1alpha1
kind: Model
metadata:
name: choice-is-one
spec:
storageUri: "gs://seldon-models/scv2/examples/pandasquery"
requirements:
- mlserver
- python
parameters:
- name: query
value: "choice == 1"This capability is only available for MLServer custom model runtimes. The named keys and
values will be added to the model-settings.json file for the provided model in theparameters.extra Dict. MLServer models are able to read these values in their load method.
Example Parameterized Models
Overview (`docs-gb/performance-tuning/models/README.md`)
Model Performance Tuning
This section covers various aspects of optimizing model performance in Seldon Core 2, from initial load testing to infrastructure setup and inference optimization. Each subsection provides detailed guidance on different aspects of model performance tuning:
[Load Testing](load-testing.md)
Learn how to conduct effective load testing to understand your model's performance characteristics:
- Determining load saturation points
- Understanding closed-loop vs. open-loop testing
- Determining the right number of replicas based on your configuration (model, infrastructure, etc.)
- Setting up reproducible test environments
- Interpreting test results for autoscaling configuration
[Inference](inference.md)
Explore different approaches to optimize inference performance:
- Choosing between gRPC and REST protocols
- Implementing adaptive batching
- Optimizing input dimensions
- Configuring parallel processing with workers
- Understanding CPU vs. GPU utilization
- Optimizing your model artefact
[Infrastructure Setup](infrastructure-setup.md)
Understand how to configure the underlying infrastructure for optimal model performance:
- Choosing between CPU and GPU deployments
- Setting appropriate CPU specifications
- Configuring thread affinity
- Managing memory allocation
- Optimizing resource utilization
Each of these aspects plays a crucial role in achieving optimal model performance. We recommend starting with load testing to establish a baseline, then using the insights gained to inform your infrastructure setup and inference optimization strategies.
Overview (`docs-gb/performance-tuning/pipelines/README.md`)
Pipeline Performance Tuning
This section covers various aspects of optimizing pipeline performance in Seldon Core 2, from testing methodologies to Core 2 configuration. Each subsection provides detailed guidance on different aspects of pipeline performance tuning:
[Testing Pipelines](testing-pipelines.md)
Learn how to effectively test and optimize pipeline performance:
- Understanding pipeline latency components
- Identifying and reducing bottlenecks
- Balancing model replicas and resources
[Core 2 Configuration](core-2-configuration.md)
Explore how to configure Core 2 components for optimal pipeline performance:
- Understanding Core 2 data processing components
- Optimizing Kafka integration
- Configuring Core 2 services
[Scalability of Pipelines](scalability-pipelines.md)
Understand how Core 2 components scale with the number of deployed pipelines and models:
- Dynamic scaling of dataflow engine, model gateway, and pipeline gateway
- Loading and unloading of models and pipelines
- Assignment of pipelines and models to replicas
Each of these aspects plays a crucial role in achieving optimal pipeline performance. We recommend starting with testing individual models in your pipeline, then using those insights to inform your Core 2 configuration and overall pipeline optimization strategies.
Overview (`docs-gb/user-guide/data-science-monitoring/README.md`)
Data Science Monitoring
Overview (`docs-gb/user-guide/inference/README.md`)
Inference
Overview (`docs-gb/user-guide/v2/README.md`)
Open Inference Protocol
This page describes a predict/inference API independent of any
specific ML/DL framework and model server. These APIs are
able to support both easy-to-use and high-performance use cases.
By implementing this protocol both
inference clients and servers will increase their utility and
portability by being able to operate seamlessly on platforms that have
standardized around this API. This protocol is endorsed by NVIDIA
Triton Inference Server, TensorFlow Serving, and ONNX Runtime
Server. It is sometimes referred to by its old name "V2 Inference Protocol".
For an inference server to be compliant with this protocol the server
must implement all APIs described below, except where an optional
feature is explicitly noted. A compliant inference server may choose
to implement either or both of the HTTP/REST API and the GRPC API.
The protocol supports an extension mechanism as a required part of the
API, but this document does not propose any specific extensions. Any
specific extensions will be proposed separately.
HTTP/REST
A compliant server must implement the health, metadata, and inference
APIs described in this section.
The HTTP/REST API uses JSON because it is widely supported and
language independent. In all JSON schemas shown in this document
$number, $string, $boolean, $object and $array refer to the
fundamental JSON types. #optional indicates an optional JSON field.
All strings in all contexts are case-sensitive.
For Seldon a server must recognize the following URLs. The
versions portion of the URL is shown as optional to allow
implementations that don’t support versioning or for cases when the
user does not want to specify a specific model version (in which case
the server will choose a version based on its own policies).
Health:
GET v2/health/live
GET v2/health/ready
GET v2/models/${MODEL_NAME}[/versions/${MODEL_VERSION}]/readyServer Metadata:
GET v2Model Metadata:
GET v2/models/${MODEL_NAME}[/versions/${MODEL_VERSION}]Inference:
POST v2/models/${MODEL_NAME}[/versions/${MODEL_VERSION}]/inferHealth
A health request is made with an HTTP GET to a health endpoint. The
HTTP response status code indicates a boolean result for the health
request. A 200 status code indicates true and a 4xx status code
indicates false. The HTTP response body should be empty. There are
three health APIs.
Server Live
The “server live” API indicates if the inference server is able to
receive and respond to metadata and inference requests. The “server
live” API can be used directly to implement the Kubernetes
livenessProbe.
Server Ready
The “server ready” health API indicates if all the models are ready
for inferencing. The “server ready” health API can be used directly to
implement the Kubernetes readinessProbe.
Model Ready
The “model ready” health API indicates if a specific model is ready
for inferencing. The model name and (optionally) version must be
available in the URL. If a version is not provided the server may
choose a version based on its own policies.
Server Metadata
The server metadata endpoint provides information about the server. A
server metadata request is made with an HTTP GET to a server metadata
endpoint. In the corresponding response the HTTP body contains theServer Metadata Response JSON Object
or theServer Metadata Response JSON Error Object.
Server Metadata Response JSON Object
A successful server metadata request is indicated by a 200 HTTP status
code. The server metadata response object, identified as$metadata_server_response, is returned in the HTTP body.
$metadata_server_response =
{
"name" : $string,
"version" : $string,
"extensions" : [ $string, ... ]
}- “name” : A descriptive name for the server.
- "version" : The server version.
- “extensions” : The extensions supported by the server. Currently no
standard extensions are defined. Individual inference servers may
define and document their own extensions.
Server Metadata Response JSON Error Object
A failed server metadata request must be indicated by an HTTP error
status (typically 400). The HTTP body must contain the$metadata_server_error_response object.
$metadata_server_error_response =
{
"error": $string
}- “error” : The descriptive message for the error.
Model Metadata
The per-model metadata endpoint provides information about a model. A
model metadata request is made with an HTTP GET to a model metadata
endpoint. In the corresponding response the HTTP body contains theModel Metadata Response JSON Object
or theModel Metadata Response JSON Error Object.
The model name and (optionally) version must be available in the
URL. If a version is not provided the server may choose a version
based on its own policies or return an error.
Model Metadata Response JSON Object
A successful model metadata request is indicated by a 200 HTTP status
code. The metadata response object, identified as$metadata_model_response, is returned in the HTTP body for every
successful model metadata request.
$metadata_model_response =
{
"name" : $string,
"versions" : [ $string, ... ] #optional,
"platform" : $string,
"inputs" : [ $metadata_tensor, ... ],
"outputs" : [ $metadata_tensor, ... ]
}- “name” : The name of the model.
- "versions" : The model versions that may be explicitly requested via
the appropriate endpoint. Optional for servers that don’t support
versions. Optional for models that don’t allow a version to be
explicitly requested. - “platform” : The framework/backend for the model. SeePlatforms.
- “inputs” : The inputs required by the model.
- “outputs” : The outputs produced by the model.
Each model input and output tensors’ metadata is described with a$metadata_tensor object.
$metadata_tensor =
{
"name" : $string,
"datatype" : $string,
"shape" : [ $number, ... ]
}- “name” : The name of the tensor.
- "datatype" : The data-type of the tensor elements as defined inTensor Data Types.
- "shape" : The shape of the tensor. Variable-size dimensions are
specified as -1.
Model Metadata Response JSON Error Object
A failed model metadata request must be indicated by an HTTP error
status (typically 400). The HTTP body must contain the$metadata_model_error_response object.
$metadata_model_error_response =
{
"error": $string
}- “error” : The descriptive message for the error.
Inference
An inference request is made with an HTTP POST to an inference
endpoint. In the request the HTTP body contains theInference Request JSON Object. In
the corresponding response the HTTP body contains theInference Response JSON Object orInference Response JSON Error Object. SeeInference Request Examples for some
example HTTP/REST requests and responses.
Inference Request JSON Object
The inference request object, identified as $inference_request, is
required in the HTTP body of the POST request. The model name and
(optionally) version must be available in the URL. If a version is not
provided the server may choose a version based on its own policies or
return an error.
$inference_request =
{
"id" : $string #optional,
"parameters" : $parameters #optional,
"inputs" : [ $request_input, ... ],
"outputs" : [ $request_output, ... ] #optional
}id: An identifier for this request. Optional, but if specified
this identifier must be returned in the response.parameters: An object containing zero or more parameters for this
inference request expressed as key/value pairs. SeeParameters for more information.inputs: The input tensors. Each input is described using the$request_inputschema defined in Request Input.outputs: The output tensors requested for this inference. Each
requested output is described using the$request_outputschema
defined in Request Output. Optional, if not
specified all outputs produced by the model will be returned using
default$request_outputsettings.
Request Input
The $request_input JSON describes an input to the model. If the
input is batched, the shape and data must represent the full shape and
contents of the entire batch.
$request_input =
{
"name" : $string,
"shape" : [ $number, ... ],
"datatype" : $string,
"parameters" : $parameters #optional,
"data" : $tensor_data
}"name": The name of the input tensor."shape": The shape of the input tensor. Each dimension must be an
integer representable as an unsigned 64-bit integer value."datatype": The data-type of the input tensor elements as defined
in Tensor Data Types."parameters": An object containing zero or more parameters for this
input expressed as key/value pairs. See Parameters
for more information.“data”: The contents of the tensor. See Tensor Data
for more information.
Request Output
The $request_output JSON is used to request which output tensors
should be returned from the model.
$request_output =
{
"name" : $string,
"parameters" : $parameters #optional,
}"name": The name of the output tensor."parameters": An object containing zero or more parameters for this
output expressed as key/value pairs. See Parameters
for more information.
Inference Response JSON Object
A successful inference request is indicated by a 200 HTTP status
code. The inference response object, identified as$inference_response, is returned in the HTTP body.
$inference_response =
{
"model_name" : $string,
"model_version" : $string #optional,
"id" : $string,
"parameters" : $parameters #optional,
"outputs" : [ $response_output, ... ]
}"model_name": The name of the model used for inference."model_version": The specific model version used for
inference. Inference servers that do not implement versioning should
not provide this field in the response."id": The "id" identifier given in the request, if any."parameters": An object containing zero or more parameters for this
response expressed as key/value pairs. See Parameters
for more information."outputs": The output tensors. Each output is described using the$response_outputschema defined inResponse Output.
Response Output
The $response_output JSON describes an output from the model. If the
output is batched, the shape and data represents the full shape of the
entire batch.
$response_output =
{
"name" : $string,
"shape" : [ $number, ... ],
"datatype" : $string,
"parameters" : $parameters #optional,
"data" : $tensor_data
}"name": The name of the output tensor."shape": The shape of the output tensor. Each dimension must be an
integer representable as an unsigned 64-bit integer value."datatype": The data-type of the output tensor elements as defined
in Tensor Data Types."parameters": An object containing zero or more parameters for this
input expressed as key/value pairs. See Parameters
for more information.“data”: The contents of the tensor. See Tensor Data
for more information.
Inference Response JSON Error Object
A failed inference request must be indicated by an HTTP error status
(typically 400). The HTTP body must contain the$inference_error_response object.
$inference_error_response =
{
"error": <error message string>
}“error”: The descriptive message for the error.
Inference Request Examples
The following example shows an inference request to a model with two
inputs and one output. The HTTP Content-Length header gives the size
of the JSON object.
POST /v2/models/mymodel/infer HTTP/1.1
Host: localhost:8000
Content-Type: application/json
Content-Length: <xx>
{
"id" : "42",
"inputs" : [
{
"name" : "input0",
"shape" : [ 2, 2 ],
"datatype" : "UINT32",
"data" : [ 1, 2, 3, 4 ]
},
{
"name" : "input1",
"shape" : [ 3 ],
"datatype" : "BOOL",
"data" : [ true ]
}
],
"outputs" : [
{
"name" : "output0"
}
]
}For the above request the inference server must return the “output0”
output tensor. Assuming the model returns a [ 3, 2 ] tensor of data
type FP32 the following response would be returned.
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: <yy>
{
"id" : "42"
"outputs" : [
{
"name" : "output0",
"shape" : [ 3, 2 ],
"datatype" : "FP32",
"data" : [ 1.0, 1.1, 2.0, 2.1, 3.0, 3.1 ]
}
]
}Parameters
The $parameters JSON describes zero or more “name”/”value” pairs,
where the “name” is the name of the parameter and the “value” is a$string, $number, or $boolean.
$parameters =
{
$parameter, ...
}
$parameter = $string : $string | $number | $booleanCurrently no parameters are defined. As required a future proposal may
define one or more standard parameters to allow portable functionality
across different inference servers. A server can implement
server-specific parameters to provide non-standard capabilities.
Tensor Data
Tensor data must be presented in row-major order of the tensor
elements. Element values must be given in "linear" order without any
stride or padding between elements. Tensor elements may be presented
in their nature multi-dimensional representation, or as a flattened
one-dimensional representation.
Tensor data given explicitly is provided in a JSON array. Each element
of the array may be an integer, floating-point number, string or
boolean value. The server can decide to coerce each element to the
required type or return an error if an unexpected value is
received. Note that fp16 is problematic to communicate explicitly
since there is not a standard fp16 representation across backends nor
typically the programmatic support to create the fp16 representation
for a JSON number.
For example, the 2-dimensional matrix:
[ 1 2
4 5 ]Can be represented in its natural format as:
"data" : [ [ 1, 2 ], [ 4, 5 ] ]Or in a flattened one-dimensional representation:
"data" : [ 1, 2, 4, 5 ]GRPC
The GRPC API closely follows the concepts defined in theHTTP/REST API. A compliant server must implement the
health, metadata, and inference APIs described in this section.
All strings in all contexts are case-sensitive.
The GRPC definition of the service is:
//
// Inference Server GRPC endpoints.
//
service GRPCInferenceService
{
// Check liveness of the inference server.
rpc ServerLive(ServerLiveRequest) returns (ServerLiveResponse) {}
// Check readiness of the inference server.
rpc ServerReady(ServerReadyRequest) returns (ServerReadyResponse) {}
// Check readiness of a model in the inference server.
rpc ModelReady(ModelReadyRequest) returns (ModelReadyResponse) {}
// Get server metadata.
rpc ServerMetadata(ServerMetadataRequest) returns (ServerMetadataResponse) {}
// Get model metadata.
rpc ModelMetadata(ModelMetadataRequest) returns (ModelMetadataResponse) {}
// Perform inference using a specific model.
rpc ModelInfer(ModelInferRequest) returns (ModelInferResponse) {}
}Health
A health request is made using the ServerLive, ServerReady, or
ModelReady endpoint. For each of these endpoints errors are indicated
by the google.rpc.Status returned for the request. The OK code
indicates success and other codes indicate failure.
Server Live
The ServerLive API indicates if the inference server is able to
receive and respond to metadata and inference requests. The request
and response messages for ServerLive are:
message ServerLiveRequest {}
message ServerLiveResponse
{
// True if the inference server is live, false if not live.
bool live = 1;
}Server Ready
The ServerReady API indicates if the server is ready for
inferencing. The request and response messages for ServerReady are:
message ServerReadyRequest {}
message ServerReadyResponse
{
// True if the inference server is ready, false if not ready.
bool ready = 1;
}Model Ready
The ModelReady API indicates if a specific model is ready for
inferencing. The request and response messages for ModelReady are:
message ModelReadyRequest
{
// The name of the model to check for readiness.
string name = 1;
// The version of the model to check for readiness. If not given the
// server will choose a version based on the model and internal policy.
string version = 2;
}
message ModelReadyResponse
{
// True if the model is ready, false if not ready.
bool ready = 1;
}Server Metadata
The ServerMetadata API provides information about the server. Errors
are indicated by the google.rpc.Status returned for the request. The
OK code indicates success and other codes indicate failure. The
request and response messages for ServerMetadata are:
message ServerMetadataRequest {}
message ServerMetadataResponse
{
// The server name.
string name = 1;
// The server version.
string version = 2;
// The extensions supported by the server.
repeated string extensions = 3;
}Model Metadata
The per-model metadata API provides information about a model. Errors
are indicated by the google.rpc.Status returned for the request. The
OK code indicates success and other codes indicate failure. The
request and response messages for ModelMetadata are:
message ModelMetadataRequest
{
// The name of the model.
string name = 1;
// The version of the model to check for readiness. If not given the
// server will choose a version based on the model and internal policy.
string version = 2;
}
message ModelMetadataResponse
{
// Metadata for a tensor.
message TensorMetadata
{
// The tensor name.
string name = 1;
// The tensor data type.
string datatype = 2;
// The tensor shape. A variable-size dimension is represented
// by a -1 value.
repeated int64 shape = 3;
}
// The model name.
string name = 1;
// The versions of the model available on the server.
repeated string versions = 2;
// The model's platform. See Platforms.
string platform = 3;
// The model's inputs.
repeated TensorMetadata inputs = 4;
// The model's outputs.
repeated TensorMetadata outputs = 5;
}Inference
The ModelInfer API performs inference using the specified
model. Errors are indicated by the google.rpc.Status returned for the
request. The OK code indicates success and other codes indicate
failure. The request and response messages for ModelInfer are:
/* Detailed source-code truncated for AI context efficiency. */Parameters
The Parameters message describes a “name”/”value” pair, where the“name” is the name of the parameter and the “value” is a boolean,
integer, or string corresponding to the parameter.
Currently no parameters are defined. As required a future proposal may
define one or more standard parameters to allow portable functionality
across different inference servers. A server can implement
server-specific parameters to provide non-standard capabilities.
//
// An inference parameter value.
//
message InferParameter
{
// The parameter value can be a string, an int64, a boolean
// or a message specific to a predefined parameter.
oneof parameter_choice
{
// A boolean parameter value.
bool bool_param = 1;
// An int64 parameter value.
int64 int64_param = 2;
// A string parameter value.
string string_param = 3;
}
}Tensor Data
In all representations tensor data must be flattened to a
one-dimensional, row-major order of the tensor elements. Element
values must be given in "linear" order without any stride or padding
between elements.
Using a "raw" representation of tensors withModelInferRequest::raw_input_contents andModelInferResponse::raw_output_contents will typically allow higher
performance due to the way protobuf allocation and reuse interacts
with GRPC. For example, see issue here.
An alternative to the "raw" representation is to use
InferTensorContents to represent the tensor data in a format that
matches the tensor's data type.
/* Detailed source-code truncated for AI context efficiency. */Platforms
A platform is a string indicating a DL/ML framework or
backend. Platform is returned as part of the response to aModel Metadata request but is information only. The
proposed inference APIs are generic relative to the DL/ML framework
used by a model and so a client does not need to know the platform of
a given model to use the API. Platform names use the format“_<format>”. The following platform names are allowed:
tensorrt_plan: A TensorRT model encoded as a serialized engine or“plan”.tensorflow_graphdef: A TensorFlow model encoded as a GraphDef.tensorflow_savedmodel: A TensorFlow model encoded as a SavedModel.onnx_onnxv1: A ONNX model encoded for ONNX Runtime.pytorch_torchscript: A PyTorch model encoded as TorchScript.mxnet_mxnetAn MXNet modelcaffe2_netdef: A Caffe2 model encoded as a NetDef.
Tensor Data Types
Tensor data types are shown in the following table along with the size
of each type, in bytes.
| Data Type | Size (bytes) |
|---|---|
| BOOL | 1 |
| UINT8 | 1 |
| UINT16 | 2 |
| UINT32 | 4 |
| UINT64 | 8 |
| INT8 | 1 |
| INT16 | 2 |
| INT32 | 4 |
| INT64 | 8 |
| FP16 | 2 |
| FP32 | 4 |
| FP64 | 8 |
| BYTES | Variable (max 232) |
References
This document is based on the KServe original created during the lifetime of the KFServing project in Kubeflow by its various contributors including Seldon, NVIDIA, IBM, Bloomberg and others.
Overview (`k8s/kustomize/helm-components-sc/README.md`)
Custom Resource Patching
To allow kustomize to do a strategic patch operation on our Custom Resources we need to give it the open api spec otherwise it will default to a normal patch and overwrite.
- Dowload openapi spec by installing the CRDs on a cluster and running
kustomize openapi fetch > crds-schema.json - As we use a custom podSpec the extensions needed in the OpenApi spec are not added. Also maybe dependong on this . Edit the areas you want strategic merge by adding extension settings, e.g. for containers keyd on
name:text"x-kubernetes-patch-merge-key": "name", "x-kubernetes-patch-strategy": "merge",
Overview (`docs-gb/getting-started/kubernetes-installation/security/README.md`)
Security
Seldon can be run with secure control plane and data plane operations. There are three areas of concern:
The various communication points between services are shown in the diagram below:
.jpg>)
Control Plane
TLS control plane activation is switched on and off via the environment variable: CONTROL_PLANE_SECURITY_PROTOCOL whose values can be PLAINTEXT or SSL.
Certificates will be loaded and used for the control plane gRPC services. The secrets or folders will be watched for updates (on certificate renewal) and automatically loaded again.
Helm Control Plane Install
When installing seldon-core-v2-setup you can set the secret names for your certificates. If using cert-manager example discussed below this would be as follows:
helm install seldon-v2 k8s/helm-charts/seldon-core-v2-setup/ -n seldon-mesh \
--set security.controlplane.protocol=SSLKafka
Kafka secure activation is switched on and off via the environment variable: KAFKA_SECURITY_PROTOCOL whose values can be PLAINTEXT, SSL or SASL_SSL.
Examples are shown below:
- mTLS Strimzi example
- mTLS AWS MSK example
- SASL PLAIN with Confluent Cloud example
- SASL PLAIN with Azure Event Hub example
- SASL SCRAM with Strimzi example
- SASL SCRAM with AWS MSK example
- SASL OAUTH with Confluent Cloud example
Data Plane
TLS Data plane activation is switched on and off via the environment variable: ENVOY_SECURITY_PROTOCOL whose values can be PLAINTEXT or SSL.
When activated this ensures TLS is used to communicate to Envoy via the xDS server as well as using the SDS service to send cretificates to envoy to use for upstream and downstream networking. Downstream is the external access to Seldon and upstream is the path from Envoy to the model servers or pipeline gateway.
Helm Data Plane Install
When installing seldon-core-v2-setup you can set data plane operations to TLS as below. This assumes the secrets installed by the helm chart at the end of this section.
helm install seldon-v2 k8s/helm-charts/seldon-core-v2-setup/ -n seldon-mesh --set security.envoy.protocol=SSLThe above uses default secret names defined for the certificates installed. You can change the names of the required certificate secrets as shown in a longer configuration below (again using the default names for illustration).
For this we use the following updated Helm values (k8s/samples/values-tls-dataplane-example.yaml):
security:
controlplane:
protocol: PLAINTEXT
ssl:
server:
secret: seldon-controlplane-server
clientValidationSecret: seldon-controlplane-client
client:
secret: seldon-controlplane-client
serverValidationSecret: seldon-controlplane-server
envoy:
protocol: SSL
ssl:
upstream:
server:
secret: seldon-upstream-server
clientValidationSecret: seldon-upstream-client
client:
secret: seldon-upstream-client
serverValidationSecret: seldon-upstream-server
downstream:
client:
serverValidationSecret: seldon-downstream-server
server:
secret: seldon-downstream-serverWe use Envoy internally to direct traffic and in Envoy's terminology upstream is for internal model servers called from Envoy while the downstream server is the entrypoint server running in Envoy to receive grpc and REST calls. The above settings ensure mTLS for internal "upstream" traffic while provides a standard SSL non-mTLS entrpoint.
To use the above with the seldon CLI you would need a custom config file as follow:
{
"dataplane": {
"tls": true,
"skipSSLVerify": true
}
}We skip SSL Verify as these are internal self-signed certificates. For production use you would change this to the correct DNS name you are exposing the Seldon entrypoint.
Cetificate Providers
The installer/cluster controller for Seldon needs to provide the certificates. As part of Seldon we provide an example set of certificate issuers and certificates using cert-manager.
Helm
You can install Certificates into the desired namespace, here we use seldon-mesh as an example.
helm install seldon-v2-certs k8s/helm-charts/seldon-core-v2-certs/ -n seldon-meshOverview (`docs-gb/installation/production-environment/kafka/README.md`)
Kafka Setup
Kafka is a component in the Seldon Core 2 ecosystem, that provides scalable, reliable, and flexible communication for machine learning deployments. It serves as a strong backbone for building complex inference pipelines, managing high-throughput asynchronous predictions, and seamlessly integrating with event-driven systems—key features needed for contemporary enterprise-grade ML platforms.
An inference request is a request sent to a machine learning model to make a prediction or inference based on input data. It is a core concept in deploying machine learning models in production, where models serve predictions to users or systems in real-time or batch mode.
To explore this feature of Seldon Core 2, you need to integrate with Kafka. Integrate Kafka through managed cloud services or by deploying it directly within a Kubernetes cluster.
{% hint style="info" %}
Note: Kafka is an external component outside of the main Seldon stack. Therefore, it is the cluster administrator's responsibility to administrate and manage the Kafka instance used by Seldon. For production installation it is highly recommended to use managed Kafka instance.
{% endhint %}
- Securing Kafka provides more information about the encrytion and authentication.
- Configuration examples provides the steps to configure some of the managed Kafka services.
Self-hosted Kafka
Seldon Core 2 requires Kafka to implement data-centric inference Pipelines. To install Kafka for testing purposed in your Kubernetes cluster, use Strimzi Operator. For more information, see Self Hosted Kafka
Overview (`docs-gb/user-guide/v2/rest/README.md`)
REST
Source Index (`docs/source/index.md`)
Home
:maxdepth: 4
:titlesonly:
:includehidden:
contents/about/index
contents/getting-started/index
contents/tutorials/index
contents/servers/index
contents/models/index
contents/explainers/index
contents/drift/index
contents/outlier/index
contents/experiments/index
contents/pipelines/index
contents/inference/index
contents/kubernetes/index
contents/examples/index
contents/cli/index
contents/apis/index
contents/architecture/index
contents/faqs/index
contents/metrics/index
contents/performance-tests/index
contents/upgrading/index
contents/development/indexSource Contents About Index (`docs/source/contents/about/index.md`)
About
Seldon V2 APIs provide a state of the art solution for machine learning inference which can be run locally on a laptop as well as on Kubernetes for production.
:width: 100%Features
- A single platform for inference of wide range of standard and custom artifacts.
- Deploy locally in Docker during development and testing of models.
- Deploy at scale on Kubernetes for production.
- Deploy single models to multi-step pipelines.
- Save infrastructure costs by deploying multiple models transparently in inference servers.
- Overcommit on resources to deploy more models than available memory.
- Dynamically extended models with pipelines with a data-centric perspective backed by Kafka.
- Explain individual models and pipelines with state of the art explanation techniques.
- Deploy drift and outlier detectors alongside models.
- Kubernetes Service mesh agnostic - use the service mesh of your choice.
Core features and comparison to Seldon Core V1 APIs
Our V2 APIs separate out core tasks into separate resources allowing users to get started fast with deploying a Model and the progressing to more complex Pipelines, Explanations and Experiments.
Multi-model serving
Seldon transparently will provision your model onto the correct inference server.
By packing multiple models onto a smaller set of servers users can save infrastructure costs and efficiently utilize their models.
By allowing over-commit users can provision model models that available memory resources by allowing Seldon to transparently unload models that are not in use.
Inference Servers
Seldon V2 supports any V2 protocol inference server. At present we include Seldon's MLServer and NVIDIA's Triton inference server automatically on install. These servers cover a wide range of artifacts including custom python models.
Service Mesh Agnostic
Seldon Core 2 can be integrated with any Kubernetes service mesh. There are current examples with istio, Ambassador and Traefic.
Publication
These features are influenced by our position paper on the next generation of ML model serving frameworks:
Title: Desiderata for next generation of ML model serving
Workshop: Challenges in deploying and monitoring ML systems workshop - NeurIPS 2022
Source Contents Apis Index (`docs/source/contents/apis/index.md`)
APIs
Seldon provides APIs for management and inference.
- API for inference
- Scheduler API for management (Advanced)
- Internal APIs (Reference)
:maxdepth: 1
:hidden:
inference/index.md
scheduler/index.md
internal/index.mdSource Contents Architecture Index (`docs/source/contents/architecture/index.md`)
Architecture
The current set of components used in Seldon Core 2 is shown below:
The core components are:
- Scheduler : manages the load and unload of models, pipelines, explainers and experiments.
- Pipeline gateway : handles REST/gRPC calls to pipelines.
- Dataflow engine : handles the flow of data between components in a pipeline.
- Model gateway : handles the flow of data from models to inference requests on servers and passes on the responses.
- Agent : manages the loading and unloading of models on a server and access to the server over REST/gRPC.
- Envoy : manages the proxying of requests to the correct servers including load balancing.
All the above are Kubernetes agnostic and can run locally, e.g. on Docker Compose.
We also provide a Kubernetes Operator to allow Kubernetes usage.
Kafka is used as the backbone for Pipelines allowing a decentralized, synchronous and asynchronous usage.
Kafka
Kafka is used as the backbone for allowing Pipelines of Models to be connected together into arbitrary directed acyclic graphs. Models can be reused in different Pipelines. The flow of data between models is handled by the dataflow engine using KStreams.
Dataflow Architecture
Seldon V2 follows a dataflow design paradigm and it's part of the current movement for data centric machine learning. By taking a decentralized route that focuses on the flow of data users can have more flexibility and insight in building complex applications containing machine learning and traditional components. This contrasts with a more centralized orchestration more traditional in service orientated architectures.
By focusing on the data we allow users to join various flows together using stream joining concepts as shown below.
We support several types of joins:
- inner joins, where all inputs need to be present for a transaction to join the tensors passed through the Pipeline;
- outer joins, where only a subset needs to be available during the join window
- triggers, in which data flows need to wait until records on one or more trigger data flows appear. The data in these triggers is not passed onwards from the join.
These techniques allow users to create complex pipeline flows of data between machine learning components.
More discussion on the data flow view of machine learning and its effect on v2 design can be found here.
:maxdepth: 1
:hidden:
dataflow.mdSource Contents Cli Index (`docs/source/contents/cli/index.md`)
CLI
Seldon provides a CLI to allow easy management and testing of Model, Experiment, and Pipeline resources.
At present this needs to be built by hand from the operator folder.
make build-seldon # for linux/macOS amd64
make build-seldon-arm # for macOS ARMThen place the bin/seldon executable in your path.
Environment Variables and Services
The CLI talks to 3 backend services on default endpoints:
- The Seldon Core 2 Scheduler: default 0.0.0.0:9004
- The Seldon Core inference endpoint: default 0.0.0.0:9000
- The Seldon Kafka broker: default: 0.0.0.0:9092
These defaults will be correct when Seldon Core 2 is installed locally as per the docs. For Kubernetes, you will need to change these by defining environment variables.
:language: golang
:start-after: // Defaults
:end-before: // Help statementsKubernetes Usage
Inference Service
For a default install into the seldon-mesh namespace if you have exposed the inference svc as a loadbalancer you will find it at:
kubectl get svc seldon-mesh -n seldon-mesh -o jsonpath='{.status.loadBalancer.ingress[0].ip}'Use above IP at port 80:
export SELDON_INFER_HOST=<ip>:80Scheduler Service
For a default install into the seldon-mesh namespace if you have exposed the scheduler svc as a loadbalancer you will find it at:
kubectl get svc seldon-scheduler -n seldon-mesh -o jsonpath='{.status.loadBalancer.ingress[0].ip}'Use above IP at port 9004:
export SELDON_SCHEDULE_HOST=<ip>:9004Kafka Broker
The Kafka broker will depend on how you have installed Kafka into your Kubernetes cluster. Find the broker IP and use:
export SELDON_KAFKA_BROKER=<ip>:<port>Config file
You can create a config file to manage connections to running Seldon Core 2 installs. The settings will override any environment variable settings.
The definition is shown below:
:language: golang
:start-after: // start config struct
:end-before: // end config structAn example below shows an example where we connect via TLS to the Seldon scheduler using our scheduler client certificate:
{
"controlplane":{
"schedulerHost": "seldon-scheduler.svc:9044",
"tls"; true,
"keyPath": "/home/certs/seldon-scheduler-client/tls.key",
"crtPath": "/home/certs/seldon-scheduler-client/tls.crt",
"caPath": "/home/certs/seldon-scheduler-client/ca.crt"
}
}To manage config files and activate them you can use the CLI command seldon config which has subcommands to list, add, remove, activate and decative configs.
For example:
$ seldon config list
config path active
------ ---- ------
kind-sasl /home/work/seldon/cli/config-sasl.json *
$ seldon config deactivate kind-sasl
$ seldon config list
config path active
------ ---- ------
kind-sasl /home/work/seldon/cli/config-sasl.json
$ seldon config add gcp-scv2 ~/seldon/cli/gcp.json
$ seldon config list
config path active
------ ---- ------
gcp-scv2 /home/work/seldon/cli/gcp.json
kind-sasl /home/work/seldon/cli/config-sasl.json
$ seldon config activate gcp-scv2
$ seldon config list
config path active
------ ---- ------
gcp-scv2 /home/work/seldon/cli/gcp.json *
kind-sasl /home/work/seldon/cli/config-sasl.json
$ seldon config list kind-sasl
{
"controlplane": {
"schedulerHost": "172.19.255.2:9004"
},
"kafka": {
"bootstrap": "172.19.255.3:9093",
"caPath": "/home/work/gcp/scv2/certs/seldon-cluster-ca-cert/ca.crt"
}
}TLS Certificates for Local Use
For running with Kubernetes TLS connections on the control and/or data plane, certificates will need to be downloaded locally. We provide an example script which will download certificates from a Kubernetes secret and store them in a folder. It can be found in hack/download-k8s-certs.sh and takes 2 or 3 arguments:
./download-k8s-certs.sh <namespace> <secret> [<folder>]e.g.:
./download-k8s-certs.sh seldon-mesh seldon-scheduler-client:maxdepth: 1
:hidden:
docs/seldon.md
docs/seldon_config.md
docs/seldon_model.md
docs/seldon_experiment.md
docs/seldon_pipeline.md
docs/seldon_server.md
docs/seldon_config_activate.md
docs/seldon_config_add.md
docs/seldon_config_deactivate.md
docs/seldon_config_list.md
docs/seldon_config_remove.md
docs/seldon_model_infer.md
docs/seldon_model_load.md
docs/seldon_model_status.md
docs/seldon_model_unload.md
docs/seldon_experiment_start.md
docs/seldon_experiment_status.md
docs/seldon_experiment_stop.md
docs/seldon_pipeline_infer.md
docs/seldon_pipeline_load.md
docs/seldon_pipeline_status.md
docs/seldon_pipeline_unload.md
docs/seldon_pipeline_inspect.md
docs/seldon_server_status.mdSource Contents Development Index (`docs/source/contents/development/index.md`)
Development
Development Requirements
- Go 1.17+ with glibc development libraries installed.
- e.g. for Ubuntu systems:
sudo apt-get install libc6-dev
- e.g. for Ubuntu systems:
- Java JDK 17+ and Kotlin 1.6.10+
- Kubebuilder V2
- Docker and docker-compose
- Helm
- Kustomize
- Ansible
Testing resources
- Kind
- k6
- unix utils: jq, curl, grpcurl
Release Process
Releases are carried out via Github.
:maxdepth: 1
:hidden:
release/index.md
licenses.mdSource Contents Drift Index (`docs/source/contents/drift/index.md`)
Drift Detection
Drift detection models are treated as any other Model. You can run any saved Alibi-Detect drift detection model by adding the requirement alibi-detect.
An example drift detection model from the CIFAR10 image classification example is shown below:
:language: yamlUsually you would run these models in an asynchronous part of a Pipeline, i.e. they are not connected to the output of the Pipeline which defines the synchronous path. For example, the CIFAR-10 image detection example uses a pipeline as shown below:
:language: yamlNote how the cifar10-drift model is not part of the path to the outputs. Drift alerts can be read from the Kafka topic of the model.
Examples
- CIFAR10 image classification with drift detector
- Tabular income classification model with drift detector
Source Contents Examples Index (`docs/source/contents/examples/index.md`)
Examples
This section will provide some examples to allow operations with Seldon to be tested so you can run your own models, experiments, pipelines and explainers.
Getting Started Examples
Models
Pipelines
Explainers
Servers
Experiments
Making Inference Requests
- Inference examples
- Tritonclient examples
- Batch Inference examples (kubernetes)
- Batch Inference examples (local)
Misc
Further Kubernetes Examples
Advanced Examples
- Huggingface speech to sentiment with explanations pipeline
- Production image classifier with drift and outlier monitoring
- Production income classifier with drift, outlier and explanations
- Conditional pipeline with pandas query model
- Kubernetes Server with PVC
:maxdepth: 1
:hidden:
local-examples.md
k8s-examples.md
huggingface.md
model-zoo.md
multi-version.md
pipeline-examples.md
pipeline-to-pipeline.md
explainer-examples.md
local-experiments.md
experiment-versions.md
inference.md
tritonclient-examples.md
pipeline-ready-and-metadata.md
speech-to-sentiment.md
cifar10.md
income.md
pandasquery.md
k8s-pvc.mdSource Contents Experiments Index (`docs/source/contents/experiments/index.md`)
Experiments
An Experiment defines an http traffic split between Models or Pipelines.
Experiments also allow a mirror model or pipeline to be tested where some percentage of the traffic to the main model is sent to the mirror but the result is not returned.
Further details are given here.
Source Contents Explainers Index (`docs/source/contents/explainers/index.md`)
Explainers
Explainers are Model resources with some extra settings. They allow a range of explainers from the Alibi-Explain library to be run on MLServer.
An example Anchors explainer definitions is shown below.
:language: yamlThe key additions are:
type: This must be one of the supported Alibi Explainer types supported by the Alibi Explain runtime in MLServer.modelRef: The model name for black box explainers.pipelineRef: The pipeline name for black box explainers.
Only one of modelRef and pipelineRef is allowed.
Pipeline Explanations
Blackbox explainers can explain a Pipeline as well as a model. An example from the Huggingface sentiment demo is show below.
:language: yamlExamples
- Tabular income classification model with Anchor Tabular black box model explainer
- Huggingface Sentiment model with Anchor Text black box pipeline explainer
- Anchor Text movies sentiment explainer
Source Contents Faqs Index (`docs/source/contents/faqs/index.md`)
FAQs
Should I use Core 1 or Core 2?
We strongly recommend using Seldon Core 2 for all new and production deployments. Core 1 is now in maintenance mode — it is no longer actively developed, and future improvements will be focused exclusively on Core 2. Core 2 is already being supported for production use by our enterprise-scale customers.
Seldon Core 2 introduces a more modern, scalable, and flexible architecture designed for production-grade machine learning systems. Key advantages include:
- Data-centric ML pipelines with native support for streaming data via Kafka, enabling real-time inference and observability.
- Multi-Model Serving and resource overcommit strategies that improve infrastructure efficiency and model utilization.
Can Seldon Core 2 be used with Seldon Core 1
The two projects are able to be run side by side. Existing users of Seldon Core can update to deploy their models using Seldon Core 2 as needed to take advantage of the new functionality. Both will be supported.
Can I do payload logging in Seldon Core 2?
By default, the input and output of every step in a pipeline (as well as the pipeline itself) is logged in Kafka.
From there it's up to you what to do with the data.
You could use something like Kafka Connect to stream the logs to a datastore of your choice.
Note that there is no automatic request logging for models being accessed directly over REST or gRPC.
Requests need to be sent via pipelines to be recorded in Kafka.
Source Contents Getting Started Index (`docs/source/contents/getting-started/index.md`)
Getting Started
Some dependencies may require that the (virtual) machines on which you deploy, support the SSE4.2 instruction set or x86-64-v2 microarchitecture. If `lscpu | grep sse4_2` does not return anything on your machine, your CPU is not compatible, and you may need to update the (virtual) host's CPU.Seldon Core can be installed either with Docker Compose or with Kubernetes:
Once installed:
- Try the existing examples.
- Train and deploy your own model artifact.
Core Concepts
There are three core resources you will use:
- Models - for deploying single machine learning models, custom transformation logic, drift detectors and outliers detectors.
- Pipelines - for connecting together flows of data transformations between Models with a synchronous path and multiple asynchronous paths.
- Experiments - for testing new versions of models
By default the standard installation will deploy MLServer and Triton inference servers which provide support for a wide range of machine learning model artifacts including Tensorflow models, PyTorch models, SKlearn models, XGBoost models, ONNX models, TensorRT models, custom python models and many more. For advanced use, the creation of new inference servers is manged by two resources:
- Servers - for deploying sets of replicas of core inference servers (MLServer or Triton by default).
- ServerConfigs - for defining server configurations including custom servers.
API for Inference
Once deployed models can be called using the Seldon V2 inference protocol. This protocol created by Seldon, NVIDIA and the KServe projects is supported by MLServer and Triton inference servers amingst others and allows REST and gRPC calls to your model.
Your model is exposed via our internal Envoy gateway. If you wish to expose your models in Kubernetes outside the cluster you are free to use any Service Mesh or Ingress technology. Various examples are provided for service mesh integration.
Inference Metrics
Metrics are exposed for scraping by Prometheus. For Kubernetes we provide example instructions for using kube-prometheus.
Pipeline requirements
Pipelines are built upon Kafka streaming technology.
:maxdepth: 1
:hidden:
docker-installation/index.md
kubernetes-installation/index.md
configuration/index.md
cli.mdSource Contents Inference Index (`docs/source/contents/inference/index.md`)
Inference
This section will discuss how to make inference calls against your Seldon models or pipelines.
You can make synchronous inference requests via REST or gRPC or asynchronous requests via Kafka topics.
The content of your request should be an inference v2 protocol payload:
- REST payloads will generally be in the JSON v2 protocol format.
- gRPC and Kafka payloads must be in the Protobuf v2 protocol format.
Synchronous Requests
For making synchronous requests, the process will generally be:
- Find the appropriate service endpoint (IP address and port) for accessing the installation of Seldon Core 2.
- Determine the appropriate headers/metadata for the request.
- Make requests via REST or gRPC.
Find the Seldon Service Endpoint
````{tab} Docker Compose
In the default Docker Compose setup, container ports are accessible from the host machine.
This means you can use `localhost` or `0.0.0.0` as the hostname.
The default port for sending inference requests to the Seldon system is `9000`.
This is controlled by the `ENVOY_DATA_PORT` environment variable for Compose.
Putting this together, you can send inference requests to `0.0.0.0:9000`.
````
````{tab} Kubernetes
In Kubernetes, Seldon creates a single `Service` called `seldon-mesh` in the namespace it is installed into.
By default, this namespace is also called `seldon-mesh`.
If this `Service` is exposed via a load balancer, the appropriate address and port can be found via:
```bash
kubectl get svc seldon-mesh -n seldon-mesh -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
```
If you are not using a `LoadBalancer` for the `seldon-mesh` `Service`, you can still send inference requests.
For development and testing purposes, you can port-forward the `Service` locally using the below.
Inference requests can then be sent to `localhost:8080`.
```
kubectl port-forward svc/seldon-mesh -n seldon-mesh 8080:80
```
If you are using a service mesh like Istio or Ambassador, you will need to use the IP address of the service mesh ingress and determine the appropriate port.
````Make Inference Requests
Let us imagine making inference requests to a model called iris.
This iris model has the following schema, which can be set in a model-settings.json file for MLServer:
{
"name": "iris",
"implementation": "mlserver_sklearn.SKLearnModel",
"inputs": [
{
"name": "predict",
"datatype": "FP32",
"shape": [-1, 4]
}
],
"outputs": [
{
"name": "predict",
"datatype": "INT64",
"shape": [-1, 1]
}
],
"parameters": {
"version": "1"
}
}Examples are given below for some common tools for making requests.
````{group-tab} Seldon CLI
An example `seldon` request might look like this:
```
seldon model infer iris \
'{"inputs": [{"name": "predict", "shape": [1, 4], "datatype": "FP32", "data": [[1, 2, 3, 4]]}]}'
```
The default inference mode is REST, but you can also send gRPC requests like this:
```
seldon model infer iris \
--inference-mode grpc \
'{"model_name":"iris","inputs":[{"name":"input","contents":{"fp32_contents":[1,2,3,4]},"datatype":"FP32","shape":[1,4]}]}'
```
````
````{group-tab} cURL
An example `curl` request might look like this:
```
curl -v http://0.0.0.0:9000/v2/models/iris/infer \
-H "Content-Type: application/json" \
-d '{"inputs": [{"name": "predict", "shape": [1, 4], "datatype": "FP32", "data": [[1, 2, 3, 4]]}]}'
```
````
````{group-tab} grpcurl
An example `grpcurl` request might look like this:
```
grpcurl \
-d '{"model_name":"iris","inputs":[{"name":"input","contents":{"fp32_contents":[1,2,3,4]},"datatype":"FP32","shape":[1,4]}]}' \
-plaintext \
-import-path apis \
-proto apis/mlops/v2_dataplane/v2_dataplane.proto \
0.0.0.0:9000 inference.GRPCInferenceService/ModelInfer
```
The above request was run from the project root folder allowing reference to the Protobuf manifests defined in the `apis/` folder.
````
````{group-tab} Python tritonclient
You can use the Python [tritonclient](https://github.com/triton-inference-server/client) package to send inference requests.
A short, self-contained example is:
```python
import tritonclient.http as httpclient
import numpy as np
client = httpclient.InferenceServerClient(
url="localhost:8080",
verbose=False,
)
inputs = [httpclient.InferInput("predict", (1, 4), "FP64")]
inputs[0].set_data_from_numpy(
np.array([[1, 2, 3, 4]]).astype("float64"),
binary_data=False,
)
result = client.infer("iris", inputs)
print("result is:", result.as_numpy("predict"))
```
````For pipelines, a synchronous request is possible if the pipeline has an `outputs` section defined in its spec.Request Routing
Seldon Routes
Seldon needs to determine where to route requests to, as models and pipelines might have the same name.
There are two ways of doing this: header-based routing (preferred) and path-based routing.
````{tab} Headers
Seldon can route requests to the correct endpoint via headers in HTTP calls, both for REST (HTTP/1.1) and gRPC (HTTP/2).
Use the `Seldon-Model` header as follows:
* For models, use the model name as the value.
For example, to send requests to a model named `foo` use the header `Seldon-Model: foo`.
* For pipelines, use the pipeline name followed by `.pipeline` as the value.
For example, to send requests to a pipeline named `foo` use the header `Seldon-Model: foo.pipeline`.
The `seldon` CLI is aware of these rules and can be used to easily send requests to your deployed resources.
See the [examples](../examples/index) and the [Seldon CLI docs](../cli/index.md) for more information.
````
````{tab} Paths
The inference v2 protocol is only aware of models, thus has no concept of pipelines.
Seldon works around this limitation by introducing _virtual_ endpoints for pipelines.
Virtual means that Seldon understands them, but other v2 protocol-compatible components like inference servers do not.
Use the following rules for paths to route to models and pipelines:
* For models, use the path prefix `/v2/models/{model name}`.
This is normal usage of the inference v2 protocol.
* For pipelines, you can use the path prefix `/v2/pipelines/{pipeline name}`.
Otherwise calling pipelines looks just like the inference v2 protocol for models.
Do **not** use any suffix for the pipeline name as you would for routing headers.
* For pipelines, you can also use the path prefix `/v2/models/{pipeline name}.pipeline`.
Again, this form looks just like the inference v2 protocol for models.
````Extending our examples from above, the requests may look like the below when using header-based routing.
````{group-tab} Seldon CLI
No changes are required as the `seldon` CLI already understands how to set the appropriate gRPC and REST headers.
````
````{group-tab} cURL
Note the header in the last line:
```{code-block}
:emphasize-lines: 4
curl -v http://0.0.0.0:9000/v2/models/iris/infer \
-H "Content-Type: application/json" \
-d '{"inputs": [{"name": "predict", "shape": [1, 4], "datatype": "FP32", "data": [[1, 2, 3, 4]]}]}' \
-H "Seldon-Model: iris"
```
````
````{group-tab} grpcurl
Note the `rpc-header` flag in the penultimate line:
```{code-block}
:emphasize-lines: 6
grpcurl \
-d '{"model_name":"iris","inputs":[{"name":"input","contents":{"fp32_contents":[1,2,3,4]},"datatype":"FP32","shape":[1,4]}]}' \
-plaintext \
-import-path apis \
-proto apis/mlops/v2_dataplane/v2_dataplane.proto \
-rpc-header seldon-model:iris \
0.0.0.0:9000 inference.GRPCInferenceService/ModelInfer
```
````
````{group-tab} Python tritonclient
Note the `headers` dictionary in the `client.infer()` call:
```{code-block}
:emphasize-lines: 18
import tritonclient.http as httpclient
import numpy as np
client = httpclient.InferenceServerClient(
url="localhost:8080",
verbose=False,
)
inputs = [httpclient.InferInput("predict", (1, 4), "FP64")]
inputs[0].set_data_from_numpy(
np.array([[1, 2, 3, 4]]).astype("float64"),
binary_data=False,
)
result = client.infer(
"iris",
inputs,
headers={"Seldon-Model": "iris"},
)
print("result is:", result.as_numpy("predict"))
```
````Ingress Routes
If you are using an ingress controller to make inference requests with Seldon, you will need to configure the routing rules correctly.
There are many ways to do this, but custom path prefixes will not work with gRPC.
This is because gRPC determines the path based on the Protobuf definition.
Some gRPC implementations permit manipulating paths when sending requests, but this is by no means universal.
If you want to expose your inference endpoints via gRPC and REST in a consistent way, you should use virtual hosts, subdomains, or headers.
The downside of using only paths is that you cannot differentiate between different installations of Seldon Core 2 or between traffic to Seldon and any other inference endpoints you may have exposed via the same ingress.
You might want to use a mixture of these methods; the choice is yours.
````{tab} Virtual Hosts
Virtual hosts are a way of differentiating between logical services accessed via the same physical machine(s).
Virtual hosts are defined by the `Host` header for [HTTP/1](https://www.rfc-editor.org/rfc/rfc7230#section-5.4) and the `:authority` pseudo-header for [HTTP/2](https://www.rfc-editor.org/rfc/rfc9113.html#section-8.3.1).
These represent the same thing, and the HTTP/2 specification defines how to translate these when converting between protocol versions.
Many tools and libraries treat these headers as special and have particular ways of handling them.
Some common ones are given below:
* The `seldon` CLI has an `--authority` flag which applies to both REST and gRPC inference calls.
* `curl` accepts `Host` as a normal header.
* `grpcurl` has an `-authority` flag.
* In Go, the standard library's `http.Request` struct has a `Host` field and ignores attempts to set this value via headers.
* In Python, the `requests` library accepts the host as a normal header.
Be sure to check the documentation for how to set this with your preferred tools and languages.
````
````{tab} Subdomains
Subdomain names constitute a part of the overall host name.
As such, specifying a subdomain name for requests will involve setting the appropriate host in the URI.
For example, you may expose inference services in the namespaces `seldon-1` and `seldon-2` as in the following snippets:
```
curl https://seldon-1.example.com/v2/models/iris/infer ...
seldon model infer --inference-host https://seldon-2.example.com/v2/models/iris/infer ...
```
Many popular ingresses support subdomain-based routing, including Istio and Nginx.
Please refer to the documentation for your ingress of choice for further information.
````
````{tab} Headers
Many ingress controllers and service meshes support routing on headers.
You can use whatever headers you prefer, so long as they do not conflict with any Seldon relies upon.
Many tools and libraries support adding custom headers to requests.
Some common ones are given below:
* The `seldon` CLI accepts headers using the `--header` flag, which can be specified multiple times.
* `curl` accepts headers using the `-H` or `--header` flags.
* `grpcurl` accepts headers using the `-H` flag, which can be specified multiple times.
````
````{tab} Paths
It is possible to route on paths by using well-known path prefixes defined by the inference v2 protocol.
For gRPC, the full path (or "method") for an inference call is:
```
/inference.GRPCInferenceService/ModelInfer
```
This corresponds to the package (`inference`), service (`GRPCInferenceService`), and RPC name (`ModelInfer`) in the Protobuf definition of the inference v2 protocol.
You could use an exact match or a regex like `.*inference.*` to match this path, for example.
````Asynchronous Requests
The Seldon architecture uses Kafka and therefore asynchronous requests can be sent by pushing inference v2 protocol payloads to the appropriate topic.
Topics have the following form:
seldon.<namespace>.<model|pipeline>.<name>.<inputs|outputs>If writing to a pipeline topic, you will need to include a Kafka header with the key `pipeline` and the value being the name of the pipeline.Model Inference
For a local install if you have a model iris, you would be able to send a prediction request by pushing to the topic: seldon.default.model.iris.inputs.
The response will appear on seldon.default.model.iris.outputs.
For a Kubernetes install in seldon-mesh if you have a model iris, you would be able to send a prediction request by pushing to the topic: seldon.seldon-mesh.model.iris.inputs.
The response will appear on seldon.seldon-mesh.model.iris.outputs.
Pipeline Inference
For a local install if you have a pipeline mypipeline, you would be able to send a prediction request by pushing to the topic: seldon.default.pipeline.mypipeline.inputs. The response will appear on seldon.default.pipeline.mypipeline.outputs.
For a Kubernetes install in seldon-mesh if you have a pipeline mypipeline, you would be able to send a prediction request by pushing to the topic: seldon.seldon-mesh.pipeline.mypipeline.inputs. The response will appear on seldon.seldon-mesh.pipeline.mypipeline.outputs.
Pipeline Metadata
It may be useful to send metadata alongside your inference.
If using Kafka directly as described above, you can attach Kafka metadata to your request, which will be passed around the graph.
When making synchronous requests to your pipeline with REST or gRPC you can also do this.
- For REST requests add HTTP headers prefixed with
X- - For gRPC requests add metadata with keys starting with
X-
You can also do this with the Seldon CLI by setting headers with the --header argument (and also showing response headers with the --show-headers argument)
seldon pipeline infer --show-headers --header X-foo=bar tfsimples \
'{"inputs":[{"name":"INPUT0","data":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16],"datatype":"INT32","shape":[1,16]},{"name":"INPUT1","data":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16],"datatype":"INT32","shape":[1,16]}]}'For pipeline inference, the response also contains a x-pipeline-version header, indicating which version of pipeline it ran inference with.
Request IDs
For both model and pipeline requests the response will contain a x-request-id response header. For pipeline requests this can be used to inspect the pipeline steps via the CLI, e.g.:
seldon pipeline inspect tfsimples --request-id carjjolvqj3j2pfbut10 --offset 10The --offset parameter specifies how many messages (from the latest) you want to search to find your request. If not specified the last request will be shown.
x-request-id will also appear in tracing spans.
If x-request-id is passed in by the caller then this will be used. It is the caller's responsibility to ensure it is unique.
The IDs generated are XIDs.
Source Contents Kubernetes Index (`docs/source/contents/kubernetes/index.md`)
Kubernetes
Kubernetes provides the core platform for production use. However, the architecture in agnostic to the underlying cluster technology as shown by the local Docker installation.
:maxdepth: 1
:hidden:
kafka/index.md
resources/index.md
storage-secrets/index.md
metrics/index.md
tracing/index.md
service-meshes/index.md
scaling/index.md
autoscaling/index.mdSource Contents Metrics Index (`docs/source/contents/metrics/index.md`)
Metrics
There are two kinds of metrics present in Seldon Core 2:
Operational metrics describe the performance of components in the system.
Examples of common operational considerations are memory consumption and CPU usage, request latency and throughput, and cache utilisation rates.
Generally speaking, these are the metrics system administrators, operations teams, and engineers will be interested in.
Usage metrics describe the system at a higher and less dynamic level.
Examples include the number of deployed servers and models, and component versions.
These are not typically metrics that engineers need insight into, but may be relevant to platform providers and operations teams.
:maxdepth: 1
:hidden:
operational.md
usage.mdSource Contents Models Index (`docs/source/contents/models/index.md`)
Models
Models provide the atomic building blocks of Seldon. They represents machine learning models, drift detectors, outlier detectors, explainers, feature transformations, and more complex routing models such as multi-armed bandits.
- Seldon can handle a wide range of inference artifacts
- Artifacts can be stored on any of the 40 or more cloud storage technologies as well as from local (mounted) folder as discussed here.
Kubernetes Example
A Kubernetes yaml example is shown below for a SKLearn model for iris classification:
:language: yamlIts Kubernetes spec has two core requirements
- A
storageUrispecifying the location of the artifact. This can be any rclone URI specification. - A
requirementslist which provides tags that need to be matched by the Server that can run this artifact type. By default when you install Seldon we provide a set of Servers that cover a range of artifact types.
GRPC Example
You can also load models directly over the scheduler grpc service. An example is shown below use grpcurl tool:
!grpcurl -d '{"model":{ \
"meta":{"name":"iris"},\
"modelSpec":{"uri":"gs://seldon-models/mlserver/iris",\
"requirements":["sklearn"],\
"memoryBytes":500},\
"deploymentSpec":{"replicas":1}}}' \
-plaintext \
-import-path ../../apis \
-proto apis/mlops/scheduler/scheduler.proto 0.0.0.0:9004 seldon.mlops.scheduler.Scheduler/LoadModelThe proto buffer definitions for the scheduler are outlined here.
:maxdepth: 1
:hidden:
inference-artifacts/index.md
rclone/index.md
parameterized-models/index.mdMulti-model Serving with Overcommit
Multi-model serving is an architecture pattern where one ML inference server hosts multiple models at the same time. It is a feature provided out of the box by Nvidia Triton and Seldon MLServer. Multi-model serving reduces infrastructure hardware requirements (e.g. expensive GPUs) which enables the deployment of a large number of models while making it efficient to operate the system at scale.
Seldon Core 2 leverages multi-model serving by design and it is the default option for deploying models. The system will find an appropriate server to load the model onto based on requirements that the user defines in the Model deployment definition.
Moreover, in many cases demand patterns allow for further Overcommit of resources. Seldon Core 2 is able to register more models than what can be served by the provisioned (memory) infrastructure and will swap models dynamically according to least used without adding significant latency overheads to inference workload.
See Multi-model serving for more information.
Autoscaling of Models
See here for discussion of autoscaling of models.
Source Contents Outlier Index (`docs/source/contents/outlier/index.md`)
Outlier Detection
Outlier detection models are treated as any other Model. You can run any saved Alibi-Detect outlier detection model by adding the requirement alibi-detect.
An example outlier detection model from the CIFAR10 image classification example is shown below:
:language: yamlExamples
- CIFAR10 image classification with outlier detector
- Tabular income classification model with outlier detector
Source Contents Performance Tests Index (`docs/source/contents/performance-tests/index.md`)
Performance tests
This section describes how a user can run performance tests to understand the limits of a particular SCv2 deployment.
The base directly is tests/k6
Driver
k6 is used to drive requests for load, unload and infer workloads. It is recommended that the load test is run within the same cluster that has SCv2 installed as it requires internal access to some of the services that are not automatically exposed to the outside world. Furthermore having the driver withthin the same cluster minimises link latency to SCv2 entrypoint; therefore infer latencies are more representatives of actual overheads of the system.
Tests
- Envoy
Tests synchronous inference requests via envoy
To run: make deploy-envoy-test
- Agent
Tests inference requests direct to a specific agent, defaults to triton-0 or mlserver-0
To run: make deploy-rproxy-test pr make deploy-rproxy-mlserver-test
- Server
Tests inference requests direct to a specific server (bypassing agent), defaults to triton-0 or mlserver-0
to run: make deploy-server-test or deploy-server-mlserver-test
- Pipeline gateway (HTTP-Kafka gateway)
Tests inference requests to one-node pipeline HTTP and GPRC requests
To run: make deploy-kpipeline-test
- Model gateway (Kafka-HTTP gateway)
Tests inference requests to a model via kafka
To run: deploy-kmodel-test
Results
One way to look at results is to look at the log of the pod that executed the kubernetes job.
Results can also be persisted to a gs bucket, a service account k6-sa-key in the same namespace is required,
Users can also look at the metrics that are exposed in prometheus while the test is underway
Building k6 image
In the case a user is modifying the actual scenario of the test:
export DOCKERHUB_USERNAME=mydockerhubaccount- build the k6 image via
make build-push - in the same shell environment, deploying jobs will use this custome built docker image
Modifying tests
Users can modify settings of the tests in tests/k6/configs/k8s/base/k6.yaml. This will apply to all subsequent tests that are deployed using the above process.
Settings
Some settings that can be changed
- k6 args{literalinclude} ../../../../tests/k6/configs/k8s/base/k6.yaml
:language: yaml :start-after: args :end-before: env
for a full list, check k6 args
- Environment variables{literalinclude} ../../../../tests/k6/configs/k8s/base/k6.yaml
:language: yaml :start-after: SCHEDULER_ENDPOINT}:9004 :end-before: GOOGLE_APPLICATION_CREDENTIALS- for
MODEL_TYPE, choose from:
{literalinclude} ../../../../tests/k6/components/model.js:language: javascript :end-before: const models - for
Source Contents Pipelines Index (`docs/source/contents/pipelines/index.md`)
Pipelines
Pipelines allow models to be connected into flows of data transformations. This allows more complex machine learning pipelines to be created with multiple models, feature transformations and monitoring components such as drift and outlier detectors.
Creating Pipelines
The simplest way to create Pipelines is by defining them with the Pipeline resource we provide for Kubernetes. This format is accepted by our Kubernetes implementation but also locally via our seldon CLI.
Internally in both cases Pipelines are created via our Scheduler API. Advanced users could submit Pipelines directly using this gRPC service.
An example that chains two models together is shown below:
apiVersion: mlops.seldon.io/v1alpha1
kind: Pipeline
metadata:
name: chain
namespace: seldon-mesh
spec:
steps:
- name: model1
- name: model2
inputs:
- model1
output:
steps:
- model2stepsallow you to specify the models you want to combine into a pipeline. Each step name will correspond to a model of the same name. These models will need to have been deployed and available for the Pipeline to function, however Pipelines can be deployed before or at the same time you deploy the underlying models.steps.inputsallow you to specify the inputs to this step.outputs.stepsallow you to specify the output of the Pipeline. A pipeline can have multiple paths include flows of data that do not reach the output, e.g. Drift detection steps. However, if you wish to call your Pipeline in a synchronous manner via REST/gRPC then an output must be present so the Pipeline can be treated as a function.
Expressing input data sources
Model step inputs are defined with a dot notation of the form:
<stepName>|<pipelineName>.<inputs|outputs>.<tensorName>Inputs with just a step name will be assumed to be step.outputs.
The default payloads for Pipelines is the V2 protocol which requires named tensors as inputs and outputs from a model. If you require just certain tensors from a model you can reference those in the inputs, e.g. mymodel.outputs.t1 will reference the tensor t1 from the model mymodel.
For the specification of the V2 protocol.
Chain
The simplest Pipeline chains models together: the output of one model goes into the input of the next. This will work out of the box if the output tensor names from a model match the input tensor names for the one being chained to. If they do not then the tensorMap construct presently needs to be used to define the mapping explicitly, e.g. see below for a simple chained pipeline of two tfsimple example models:
:language: yaml:caption: "*A simple chain of two models.*"
:align: center
flowchart LR
classDef pipeIO fill:#F6E083
subgraph input
INPUT0:::pipeIO
INPUT1:::pipeIO
end
INPUT0 --> TF1(tfsimple1)
INPUT1 --> TF1
TF1 --->|OUTPUT0: INPUT0| TF2(tfsimple2)
TF1 --->|OUTPUT1: INPUT1| TF2
subgraph output
OUTPUT0:::pipeIO
OUTPUT1:::pipeIO
end
TF2 --> OUTPUT0
TF2 --> OUTPUT1In the above we rename tensor OUTPUT0 to INPUT0 and OUTPUT1 to INPUT1. This allows these models to be chained together. The shape and data-type of the tensors needs to match as well.
This example can be found in the pipeline-examples examples.
Join
Joining allows us to combine outputs from multiple steps as input to a new step.
:language: yaml:caption: "*Joining the outputs of two models into a third model. The dashed lines signify model outputs that are not captured in the output of the pipeline.*"
:align: center
flowchart LR
classDef pipeIO fill:#F6E083
classDef hidden fill:#ffffff,stroke:#ffffff
subgraph input
INPUT0:::pipeIO
INPUT1:::pipeIO
end
INPUT0 --> TF1(tfsimple1)
INPUT1 --> TF1
INPUT0 --> TF2(tfsimple2)
INPUT1 --> TF2
TF1 -.-> |OUTPUT1| tf1( ):::hidden
TF1 --> |OUTPUT0: INPUT0| TF3(tfsimple3)
TF2 -.-> |OUTPUT0| tf2( ):::hidden
TF2 --> |OUTPUT1: INPUT1| TF3
subgraph output
OUTPUT0:::pipeIO
OUTPUT1:::pipeIO
end
TF3 --> OUTPUT0
TF3 --> OUTPUT1Here we pass the pipeline inputs to two models and then take one output tensor from each and pass to the final model. We use the same tensorMap technique to rename tensors as disucssed in the previous section.
Joins can have a join type which can be specified with inputsJoinType and can take the values:
inner: require all inputs to be available to join.outer: wait forjoinWindowMsto join any inputs. Ignoring any inputs that have not sent any data at that point. This will mean this step of the pipeline is guaranteed to have a latency of at leastjoinWindowMs.any: Wait for any of the specified data sources.
This example can be found in the pipeline-examples examples.
Conditional Logic
Pipelines can create conditional flows via various methods. We will discuss each in turn.
Model routing via tensors
The simplest way is to create a model that outputs different named tensors based on its decision. This way downstream steps can be dependant on different expected tensors. An example is shown below:
:language: yaml:caption: "*Pipeline with a conditional output model. The model **conditional** only outputs one of the two tensors, so only one path through the graph (red or blue) is taken by a single request*"
:align: center
flowchart LR
classDef pipeIO fill:#F6E083
classDef join fill:#CEE741;
subgraph input
INPUT0:::pipeIO
CHOICE:::pipeIO
INPUT0:::pipeIO
INPUT1:::pipeIO
end
CHOICE --> conditional
INPUT0 --> conditional
INPUT1 --> conditional
conditional --> |OUTPUT0: INPUT| add10
conditional --> |OUTPUT1: INPUT| mul10
add10 --> |OUTPUT| any(any):::join
mul10 --> |OUTPUT| any
subgraph output
OUTPUT(OUTPUT):::pipeIO
end
any --> OUTPUT
linkStyle 3 stroke:blue,color:blue;
linkStyle 5 stroke:blue,color:blue;
linkStyle 4 stroke:red,color:red;
linkStyle 6 stroke:red,color:red;In the above we have a step conditional that either outputs a tensor named OUTPUT0 or a tensor named OUTPUT1. The mul10 step depends on an output in OUTPUT0 while the add10 step depends on an output from OUTPUT1.
Note, we also have a final Pipeline output step that does an any join on these two models essentially outputting fron the pipeline whichever data arrives from either model. This type of Pipeline can be used for Multi-Armed bandit solutions where you want to route traffic dynamically.
This example can be found in the pipeline-examples examples.
Errors
Its also possible to abort pipelines when an error is produced to in effect create a condition. This is illustrated below:
:language: yamlThis Pipeline runs normally or throws an error based on whether the input tensors have certain values.
This example can be found in the pipeline-examples examples.
Triggers
Sometimes you want to run a step if an output is received from a previous step but not to send the data from that step to the model. This is illustrated below:
:language: yaml:caption: "*A pipeline with a single trigger. The model **tfsimple3** only runs if the model **check** returns a tensor named `OUTPUT`. The green edge signifies that this is a trigger and not an additional input to **tfsimple3**. The dashed lines signify model outputs that are not captured in the output of the pipeline.*"
:align: center
flowchart LR
classDef pipeIO fill:#F6E083
classDef hidden fill:#ffffff,stroke:#ffffff
subgraph input
INPUT0:::pipeIO
INPUT1:::pipeIO
end
INPUT0 --> TF1(tfsimple1)
INPUT1 --> TF1
INPUT0 --> TF2(tfsimple2)
INPUT1 --> TF2
TF1 -.-> |OUTPUT1| tf1( ):::hidden
TF1 --> |OUTPUT0: INPUT| check
TF1 --> |OUTPUT0: INPUT0| TF3(tfsimple3)
TF2 --> |OUTPUT1: INPUT1| TF3
TF2 -.-> |OUTPUT0| tf2( ):::hidden
check --o |OUTPUT| TF3
linkStyle 9 stroke:#CEE741,color:black;
subgraph output
OUTPUT0:::pipeIO
OUTPUT1:::pipeIO
end
TF3 --> OUTPUT0
TF3 --> OUTPUT1In this example the last step tfsimple3 runs only if there are outputs from tfsimple1 and tfsimple2 but also data from the check step. However, if the step tfsimple3 is run it only receives the join of data from tfsimple1 and tfsimple2.
This example can be found in the pipeline-examples examples.
Trigger Joins
You can also define multiple triggers which need to happen based on a particulr join type. For example:
:language: yaml:caption: "*A pipeline with multiple triggers and a trigger join of type `any`. The pipeline has four inputs, but three of these are optional (signified by the dashed borders).*"
:align: center
flowchart LR
classDef pipeIO fill:#F6E083
classDef pipeIOopt fill:#F6E083,stroke-dasharray: 5 5;
classDef trigger fill:#CEE741;
classDef hidden fill:#ffffff,stroke:#ffffff
classDef join fill:#CEE741;
subgraph input
ok1:::pipeIOopt
ok2:::pipeIOopt
INPUT:::pipeIO
ok3:::pipeIOopt
end
ok1 --o any
ok2 --o any
any((any)):::trigger --o mul10
linkStyle 0 stroke:#CEE741,color:green;
linkStyle 1 stroke:#CEE741,color:green;
linkStyle 2 stroke:#CEE741,color:green;
INPUT --> mul10
INPUT --> add10
ok3 --o add10
linkStyle 5 stroke:#CEE741,color:green;
subgraph output
OUTPUT:::pipeIO
end
mul10 -->|OUTPUT| anyOut(any):::join
add10 --> |OUTPUT| anyOut
anyOut --> OUTPUTHere the mul10 step is run if data is seen on the pipeline inputs in the ok1 or ok2 tensors based on the any join type. If data is seen on ok3 then the add10 step is run.
If we changed the triggersJoinType for mul10 to inner then both ok1 and ok2 would need to appear before mul10 is run.
Pipeline Inputs
Pipelines by default can be accessed synchronously via http/grpc or asynchronously via the Kafka topic created for them. However, it's also possible to create a pipeline to take input from one or more other pipelines by specifying an input section. If for example we already have the tfsimple pipeline shown below:
:language: yamlWe can create another pipeline which takes its input from this pipeline, as shown below:
:language: yaml:caption: "*A pipeline taking as input the output of another pipeline.*"
:align: center
flowchart LR
classDef pipeIO fill:#F6E083
subgraph tfsimple.inputs
INPUT0:::pipeIO
INPUT1:::pipeIO
end
INPUT0 --> TF1(tfsimple1)
INPUT1 --> TF1
subgraph tfsimple.outputs
OUTPUT0:::pipeIO
OUTPUT1:::pipeIO
end
TF1 --> OUTPUT0
TF1 --> OUTPUT1
subgraph tfsimple-extended.inputs
INPUT10(INPUT0):::pipeIO
INPUT11(INPUT1):::pipeIO
end
OUTPUT0 --> INPUT10
OUTPUT1 --> INPUT11
INPUT10 --> TF2(tfsimple2)
INPUT11 --> TF2
subgraph tfsimple-extended.outputs
OUTPUT10(OUTPUT0):::pipeIO
OUTPUT11(OUTPUT1):::pipeIO
end
TF2 --> OUTPUT10
TF2 --> OUTPUT11In this way pipelines can be built to extend existing running pipelines to allow extensibility and sharing of data flows.
The spec follows the same spec for a step except that references to other pipelines are contained in the externalInputs section which takes the form of pipeline or pipeline.step references:
.(inputs|outputs).<tensorName>.(step).<stepName>.<tensorName>
Tensor names are optional and only needed if you want to take just one tensor from an input or output.
There is also an externalTriggers section which allows triggers from other pipelines.
Further examples can be found in the pipeline-to-pipeline examples.
Present caveats:
- Circular dependencies are not presently detected.
- Pipeline status is local to each pipeline.
Data Centric Implementation
Internally Pipelines are implemented using Kafka. Each input and output to a pipeline step has an associated Kafka topic. This has many advantages and allows auditing, replay and debugging easier as data is preserved from every step in your pipeline.
Tracing allows you to monitor the processing latency of your pipelines.
As each request to a pipelines moves through the steps its data will appear in input and output topics. This allows a full audit of every transformation to be carried out.
Source Contents Servers Index (`docs/source/contents/servers/index.md`)
Servers
By default Seldon installs two server farms using MLServer and Triton with 1 replica each. Models are scheduled onto servers based on the server's resources and whether the capabilities of the server matches the requirements specified in the Model request. For example:
:language: yamlThis model specifies the requirement sklearn
There is a default capabilities for each server as follows:
- MLServer{literalinclude} ../../../../operator/config/serverconfigs/mlserver.yaml
:language: yaml :start-after: SELDON_SERVER_CAPABILITIES :end-before: SELDON_OVERCOMMIT_PERCENTAGE - Triton{literalinclude} ../../../../operator/config/serverconfigs/triton.yaml
:language: yaml :start-after: SELDON_SERVER_CAPABILITIES :end-before: SELDON_OVERCOMMIT_PERCENTAGE
Custom Capabilities
Servers can be defined with a capabilities field to indicate custom configurations (e.g. Python dependencies). For instance:
:language: yamlThese capabilities override the ones from the serverConfig: mlserver. A model that takes advantage of this is shown below:
:language: yamlThis above model will be matched with the previous custom server mlserver-134.
Servers can also be set up with the extraCapabilities that add to existing capabilities from the referenced ServerConfig. For instance:
:language: yamlThis server, mlserver-extra, inherits a default set of capabilities via serverConfig: mlserver.
These defaults are discussed above.
The extraCapabilities are appended to these to create a single list of capabilities for this server.
Models can then specify requirements to select a server that satisfies those requirements as follows.
:language: yamlThe capabilities field takes precedence over the extraCapabilities field.
For some examples see here.
Autoscaling of Servers
Within docker we don't support this but for Kubernetes see here
Source Contents Tutorials Index (`docs/source/contents/tutorials/index.md`)
Workflow and Tutorials
Workflow
Seldon inference is built from atomic Model components. Models as shown here cover a wide range of artifacts including:
- Core machine learning models, e.g. a Tensorflow model.
- Feature transformations that might be built with custom python code.
- Drift detectors.
- Outlier detectors.
- Explainers
- Adversarial detectors.
A typical workflow for a production machine learning setup might be as follows:
- You create a Tensorflow model for your core application use case and test this model in isolation to validate.
- You create SKLearn feature transformation component before your model to convert the input into the correct form for your model. You also create Drift and Outlier detectors using Seldon's open source Alibi-detect library and test these in isolation.
- You join these components together into a Pipeline for the final production setup.
These steps are shown in the diagram below:
Worked Examples
See our selection of examples.
Source Contents Upgrading Index (`docs/source/contents/upgrading/index.md`)
Upgrading
Upgrading from 2.6 - 2.7
All pods provisioned through the operator i.e. SeldonRuntime and Server resources now have the label app.kubernetes.io/name for identifying the pods.
Previously, the labelling has been inconsistent across different versions of Seldon Core 2, with mixture of app and app.kubernetes.io/name used.
If using the Prometheus operator ("Kube Prometheus"), please apply the v2.7.0 manifests for Seldon Core 2 according to the metrics documentation.
Note that these manifests need to be adjusted to discover metrics endpoints based on the existing setup.
If previous pod monitors had namespaceSelector fields set, these should be copied over and applied to the new manifests.
If namespaces do not matter, cluster-wide metrics endpoint discovery can be setup by modifying the namespaceSelector field in the pod monitors:
spec:
namespaceSelector:
any: trueUpgrading from 2.5 - 2.6
Release 2.6 brings with it new custom resources SeldonConfig and SeldonRuntime, which provide a new way to install Seldon Core 2 in Kubernetes. Upgrading in the same namespace will cause downtime while the pods are being recreated. Alternatively users can have an external service mesh or other means to be used over multiple namespaces to bring up the system in a new namespace and redeploy models before switch traffic between them.
If the new 2.6 charts are used to upgrade in an existing namespace models will eventually be redeloyed but there will be service downtime as the core components are redeployed.
Source Contents Apis Inference Index (`docs/source/contents/apis/inference/index.md`)
Inference API
Seldon inference servers must respect the following API specification.
In future, Seldon may provide extensions for use with Pipelines, Experiments and Explainers.
:maxdepth: 1
:hidden:
v2.mdSource Contents Apis Internal Index (`docs/source/contents/apis/internal/index.md`)
Internal APIs
Seldon provides some internal gRPC services it uses to manage components.
:maxdepth: 1
:hidden:
agent.md
chainer.mdSource Contents Apis Scheduler Index (`docs/source/contents/apis/scheduler/index.md`)
Scheduler API
The Seldon scheduler API provides a gRPC service to allow Models, Servers, Experiments, and Pipelines to be managed. In Kubernetes the manager deployed by Seldon translates Kubernetes custom resource definitions into calls to the Seldon Scheduler.
In non-Kubernetes environments users of Seldon could create a client to directly control Seldon resources using this API.
Proto Definition
:language: protoSource Contents Development Release Index (`docs/source/contents/development/release/index.md`)
Release process
Source Contents Getting Started Configuration Index (`docs/source/contents/getting-started/configuration/index.md`)
Configuration
Seldon can be configured via various config files.
Kafka Configuration
We allow configuration of the Kafka integration. In general this configuration looks like:
:language: jsonThe top level keys are:
topicPrefix: the prefix to add to kafka topics created by SeldonconsumerGroupIdPrefix: the prefix to add to Kafka consumer group IDs created by Seldonbootstrap.servers: the global bootstrap kafka servers to useconsumer: consumer settingsproducer: producer settingsstreams: KStreams settings
For topicPrefix you can use any acceptable kafka topic characters which are a-z, A-Z, 0-9, . (dot), _ (underscore), and - (dash). We use . (dot) internally as topic naming separator so we would suggest you don't end your topic prefix with a dot for clarity. For illustration, an example topic could be seldon.default.model.mymodel.inputs where seldon is the topic prefix.
The consumerGroupIdPrefix will ensure that all consumer groups created have a given prefix.
Kubernetes
For Kubernetes this is controlled via a ConfigMap called seldon-kafka whose default values are defined in the SeldonConfig custom resource.
:language: yaml
:start-after: kafkaConfig
:end-before: serviceConfigWhen the SeldonRuntime is installed in a namespace a configMap will be created with these settings for Kafka configuration.
To customize the settings you can add and modify the Kafka configuration via Helm, for example below is a custom Helm values file that add compression for producers:
:language: yamlTo use this with the SeldonRuntime Helm chart:
helm install seldon-v2-runtime k8s/helm-charts/seldon-core-v2-runtime \
--namespace seldon-mesh \
--values k8s/samples/values-runtime-kafka-compression.yamlTopic and consumer isolation
If you use a shared Kafka cluster with other applications you may want to isolate the topic names and consumer group IDs from other users of the cluster to ensure there is no name clash. For this we provide two settings:
topicPrefix: set a prefix for all topicsconsumerGroupIdPrefix: set a prefix for all consumer groups
An example to set this in the configuration when using the helm installation is showm below for creating the default SeldonConfig:
helm upgrade --install seldon-v2 k8s/helm-charts/seldon-core-v2-setup/ -n seldon-mesh \
--set controller.clusterwide=true \
--set kafka.topicPrefix=myorg \
--set kafka.consumerGroupIdPrefix=myorgYou can find a worked example here.
You can create alternate SeldonConfigs with different values or override values for particular SeldonRuntime installs.
Tracing Configuration
We allow configuration of tracing. This file looks like:
:language: jsonThe top level keys are:
enable: whether to enable tracingotelExporterEndpoint: The host and port for the OTEL exporterotelExporterProtocol: The protocol for the OTEL exporter. Currently used for
jvm-based components only (such as dataflow-engine), becauseopentelemetry-java-instrumentation
requires a http(s) URI for the endpoint but defaults tohttp/protobufas a protocol.
Because of this, gRPC connections (over http) can only be set up by setting this option togrpcratio: The ratio of requests to trace. Takes values between 0 and 1 inclusive.
Kubernetes
For Kubernetes this is controlled via a ConfigMap call seldon-tracing whose default value is shown below:
:language: yamlNote, this ConfigMap is created via our Helm charts and there is usually no need to modify it manually.
At present Java instrumentation (for the dataflow engine) is duplicated via separate keys.
Source Contents Getting Started Docker Installation Index (`docs/source/contents/getting-started/docker-installation/index.md`)
Docker Installation
Preparation
git clone https://github.com/SeldonIO/seldon-core --branch=v2- Build Seldon CLI
- Install Docker Compose (or directly from GitHub release if not using Docker Desktop).
- Install
make. This will depend on your version of Linux, for example on Ubuntu runsudo apt-get install build-essential.
Deploy
From the project root run:
make deploy-localThis will run with latest images for the components.
Note: Triton and MLServer are large images at present (11G and 9G respectively) so will take time to download on first usage.
Run a particular version
To run a particular release set the environment variable CUSTOM_IMAGE_TAG to the desired version before running the command, e.g.:
export CUSTOM_IMAGE_TAG=0.2.0
make deploy-localGPU support
To enable GPU on servers:
- Make sure that
nvidia-container-runtimeis installed, follow link - Enable GPU:
export GPU_ENABLED=1
Local Models
To deploy with a local folder available for loading models set the environment variable LOCAL_MODEL_FOLDER to the folder, e.g.:
export LOCAL_MODEL_FOLDER=/home/seldon/models
make deploy-localThis folder will be mounted at /mnt/models. You can then specify models as shown below:
:language: yamlIf you have set the local model folder as above then this would be looking at /home/seldon/models/iris.
Tracing
The default local install will provide Jaeger tracing at http://0.0.0.0:16686/search.
Metrics
The default local install will expose Grafana at http://localhost:3000.
Undeploy
From the project root run:
make undeploy-local:maxdepth: 1
:hidden:Source Contents Getting Started Kubernetes Installation Index (`docs/source/contents/getting-started/kubernetes-installation/index.md`)
Kubernetes Installation
Prerequisites
A running Kubernetes Cluster
You will need a running Kubernetes cluster or can create a local KinD one for testing via Ansible.
Install Ecosystem Components
You will also need to install our ecosystem components. For this we provide directions for Ansible to install these.
:header-rows: 1
* - Component
- Summary
* - Kafka
- Required for inference Pipeline usage.
* - Prometheus
- (Optional) Exposes metrics.
* - Grafana
- (Optional) UI for metrics.
* - OpenTelemetry
- (Optional) Exposes tracing.
* - Jaeger
- (Optional) UI for traces.Install
To install Seldon Core 2 itself you can choose from the following. At present, all require a clone of the source repository.
- Helm Installation (recommended for production systems)
- Ansible (recommended for test / dev / trial purposes)
The Kubernetes operator that is installed runs in namespaced mode so any resources you create need to be in the same namespace as you installed into.
Kustomize
Our recommended and supported way to install is via Helm or Ansible. If you wish to use Kustomize then you can base your configuration on the raw yaml we create in the folder k8s/yaml or follow the steps in k8s/Makefile which illustrate how we build this yaml from our own Kustomize bases.
Operations
:maxdepth: 1
:hidden:
helm.md
ansible.md
security/index.mdSource Contents Kubernetes Autoscaling Index (`docs/source/contents/kubernetes/autoscaling/index.md`)
Autoscaling
Autoscaling in Seldon applies to various concerns:
- Inference servers autoscaling
- Model autoscaling
- Model memory overcommit
Inference servers autoscaling
Autoscaling of servers can be done via HorizontalPodAutoscaler (HPA).
HPA can be applied to any deployed Server resource.
In this case HPA will manage the number of server replicas in the corresponding statefulset according to utilisation metrics (e.g. CPU or memory).
For example assuming that a triton server is deployed, then the user can attach an HPA based on cpu utilisation as follows:
kubectl autoscale server triton --cpu-percent=50 --min=1 --max=5In this case, according to load, the system will add / remove server replicas to / from the triton statefulset.
It is worth considering the following points:
If HPA adds a new server replica, this new replica will be included in any future scheduling decisions.
In other words, when deploying a new model or rescheduling failed models this new replica will be considered.If HPA deletes an existing server replica, the scheduler will first attempt to drain any loaded model on this server replica before the server replica gets actually deleted. This is achieved by leveraging a
PreStophook on the server replica pod that triggers a process before receiving the termination signal. This draining process is capped byterminationGracePeriodSeconds, which the user can set (default is 2 minutes).
Therefore there should generally be minimal disruption to the inference workload during scaling.
For more details on HPA check this Kubernetes walk-through.
Autoscaling of inference servers via `seldon-scheduler` is under consideration for the roadmap. This allow for more fine grained interactions with model autoscaling.Autoscaling via HPA for both Models and Servers using custom metrics from Prometheus is possible
for the special case of single model serving (i.e. single model per server). Check the detailed
documentation [here](hpa-rps-autoscaling.md)Model autoscaling
As each model server can serve multiple models, models can scale across the available replicas of the server according to load.
Autoscaling of models is enabled if at least MinReplicas or MaxReplicas is set in the model custom resource. Then according to load the system will scale the number of Replicas within this range.
For example the following model will be deployed at first with 1 replica and it can scale up according to load.
:language: yamlNote that model autoscaling will not attempt to add extra servers if the desired number of replicas cannot be currently fulfilled by the current provisioned number of servers. This is a process left to be done by server autoscaling.
Additionally when the system autoscales, the initial model spec is not changed (e.g. the number of Replicas) and therefore the user cannot reset the number of replicas back to the initial specified value without an explicit change.
If only Replicas is specified by the user, autoscaling of models is disabled and the system will have exactly the number of replicas of this model deployed regardless of inference load.
Architecture
The model autoscaling architecture is designed such as each agent decides on which models to scale up / down according to some defined internal metrics and then sends a triggering message to the scheduler. The current metrics are collected from the data plane (inference path), representing a proxy on how loaded is a given model with fulfilling inference requests.
Agent autoscaling stats collection
Scale up logic:
The main idea is that we keep the "lag" for each model. We define the "lag" as the difference between incoming and outgoing requests in a given time period. If the lag crosses a threshold, then we trigger a model scale up event. This threshold can be defined via SELDON_MODEL_INFERENCE_LAG_THRESHOLD inference server environment variable.
Scale down logic:
For now we keep things simple and we trigger model scale down events if a model has not been used for a number of seconds. This is defined in SELDON_MODEL_INACTIVE_SECONDS_THRESHOLD inference server environment variable.
Each agent checks the above stats periodically and if any model hits the corresponding threshold, then the agent sends an event to the scheduler to request model scaling.
How often this process executes can be defined via SELDON_SCALING_STATS_PERIOD_SECONDS inference server environment variable.
Scheduler autoscaling
The scheduler will perform model autoscale if:
- The model is stable (no state change in the last 5 minutes) and available.
- The desired number of replicas is within range. Note we always have a least 1 replica of any deployed model and we rely on over commit to reduce the resources used further.
- For scaling up, there is enough capacity for the new model replica.
Model memory overcommit
Servers can hold more models than available memory if overcommit is swictched on (default yes). This allows under utilized models to be moved from inference server memory to allow for other models to take their place. Note that these evicted models are still registered and in the case future inference requests arrive, the system will reload the models back to memory before serving the requests. If traffic patterns for inference of models vary then this can allow more models than available server memory to be run on the system.
Source Contents Kubernetes Kafka Index (`docs/source/contents/kubernetes/kafka/index.md`)
Kafka
Seldon Core 2 requires Kafka to implement data-centric inference Pipelines.
See our architecture documentation to learn more on how Seldon Core 2 uses Kafka.
Kafka integration is required to enable data-centric inference pipelines feature.
It is highly advice to configure Kafka integration to take full advantage of Seldon Core 2 features.We list alternatives below.
Managed Kafka
We recommend to use managed Kafka solution for production installation.
This allow to take away all the complexity on running secure and scalable Kafka cluster away.
We currently have tested and documented integration with following managed solutions:
- Confluent Cloud (security: SASL/PLAIN)
- Confluent Cloud (security: SASL/OAUTHBEARER)
- Amazon MSK (security: mTLS)
- Amazon MSK (security: SASL/SCRAM)
- Azure Event Hub (security: SASL/PLAIN)
See our Kafka security section for configuration examples.
Self Hosted Kafka
:heading-offset: 2
:relative-docs: ..Source Contents Kubernetes Metrics Index (`docs/source/contents/kubernetes/metrics/index.md`)
Metrics
Metrics are exposed for scrapping by Prometheus.
Example Installation
We recommend to install kube-prometheus that provides an all-in-one package with the Prometheus operator.
RBAC
You will need to modify the default RBAC installed by kube-prometheus as described here.
From the prometheus folder in the project run:
kubectl apply -f rbac/cr.yamlMonitors
We use a PodMonitor for scrapping agent metrics. The envoy and server monitors are there for completeness but not presently needed.
kubectl apply -f monitorsIncludes:
- Agent pod monitor. Monitors the metrics port of server inference pods.
- Server pod monitor. Monitors the server-metrics port of inference server pods.
- Envoy service monitor. Monitors the Envoy gateway proxies.
- Pipeline gateway pod monitor. Monitors the metrics port of pipeline gateway pods.
Pod monitors were chosen as ports for metrics are not exposed at service level as we do not have a top level service for server replicas but 1 headless service per replica. Future discussions could reference this.
Example Grafana Dashboard
Check metrics for more information.
Reference
Source Contents Kubernetes Resources Index (`docs/source/contents/kubernetes/resources/index.md`)
Resources
For Kubernetes usage we provide a set of custom resources for interacting with Seldon.
- SeldonRuntime - for installing Seldon in a particular namespace.
- Servers - for deploying sets of replicas of core inference servers (MLServer or Triton).
- Models - for deploying single machine learning models, custom transformation logic, drift detectors, outliers detectors and explainers.
- Experiments - for testing new versions of models.
- Pipelines - for connecting together flows of data between models.
Advanced Customization
SeldonConfig and ServerConfig define the core installation configuration and machine learning inference server configuration for Seldon. Normally, you would not need to customize these but this may be required for your particular custom installation within your organisation.
- ServerConfigs - for defining new types of inference server that can be reference by a Server resource.
- SeldonConfig - for defining how seldon is installed
:maxdepth: 1
:hidden:
seldonruntime/index.md
model/index.md
experiment/index.md
pipeline/index.md
server/index.md
serverconfig/index.md
seldonconfig/index.mdSource Contents Kubernetes Scaling Index (`docs/source/contents/kubernetes/scaling/index.md`)
Scaling
Models
Models can be scaled by setting their replica count, e.g.
apiVersion: mlops.seldon.io/v1alpha1
kind: Model
metadata:
name: iris
spec:
storageUri: "gs://seldon-models/scv2/samples/mlserver_1.2.3/iris-sklearn"
requirements:
- sklearn
memory: 100Ki
replicas: 3Currently, the number of replicas will need not to exceed the replicas of the Server the model is scheduled to.
Servers
Servers can be scaled by setting their replica count, e.g.
apiVersion: mlops.seldon.io/v1alpha1
kind: Server
metadata:
name: mlserver
namespace: seldon
spec:
replicas: 4
serverConfig: mlserverCurrently, models scheduled to a server can only scale up to the server replica count.
Internal Components
Seldon Core 2 runs with several control and dataplane components. The scaling of these resources is discussed below:
- Pipeline gateway.
- This pipeline gateway handles REST and gRPC synchronous requests to Pipelines. It is stateless and can be scaled based on traffic demand.
- Model gateway.
- This component pulls model requests from Kafka and sends them to inference servers. It can be scaled up to the partition factor of your Kafka topics. At present we set a uniform partition factor for all topics in one installation of Seldon Core 2.
- Dataflow engine.
- The dataflow engine runs KStream topologies to manage Pipelines. It can run as multiple replicas and the scheduler will balance Pipelines to run across it with a consistent hashing load balancer. Each Pipeline is managed up to the partition factor of Kafka (presently hardwired to one).
- Scheduler.
- This manages the control plane operations. It is presently required to be one replica as it maintains internal state within a BadgerDB held on local persistent storage (stateful set in Kubernetes). Performance tests have shown this not to be a bottleneck at present.
- Kubernetes Controller.
- The Kubernetes controller manages resources updates on the cluster which it passes on to the Scheduler. It is by default one replica but has the ability to scale.
- Envoy
- Envoy replicas get their state from the scheduler for routing information and can be scaled as needed.
Future Enhancements
- Allow configuration of partition factor for data plane consistent hashing load balancer.
- Allow Model gateway and Pipeline gateway to use consistent hashing load balancer.
- Consider control plane scaling options.
Source Contents Kubernetes Service Meshes Index (`docs/source/contents/kubernetes/service-meshes/index.md`)
Service Meshes
The Seldon models and pipelines are exposed via a single service endpoint in the install namespace called seldon-mesh. All models, pipelines and experiments can be reached via this single Service endpoint by setting appropriate headers on the inference REST/gRPC request. By this means Seldon is agnostic to any service mesh you may wish to use in your organisation. We provide some example integrations for some example service meshes below (alphabetical order):
We welcome help to extend these to other service meshes.
:maxdepth: 1
:hidden:
ambassador/index.md
istio/index.md
traefik/index.mdSource Contents Kubernetes Storage Secrets Index (`docs/source/contents/kubernetes/storage-secrets/index.md`)
Storage Secrets
Inference artifacts referenced by Models can be stored in any of the storage backends supported by Rclone.
This includes local filesystems, AWS S3, and Google Cloud Storage (GCS), among others.
Configuration is provided out-of-the-box for public GCS buckets, which enables the use of Seldon-provided models like in the below example:
:language: yamlThis configuration is provided by the Kubernetes Secret seldon-rclone-gs-public.
It is made available to Servers as a preloaded secret.
You can define and use your own storage configurations in exactly the same way.
Configuration Format
To define a new storage configuration, you need the following details:
- Remote name
- Remote type
- Provider parameters
A remote is what Rclone calls a storage location.
The type defines what protocol Rclone should use to talk to this remote.
A provider is a particular implementation for that storage type.
Some storage types have multiple providers, such as s3 having AWS S3 itself, MinIO, Ceph, and so on.
The remote name is your choice.
The prefix you use for models in spec.storageUri must be the same as this remote name.
The remote type is one of the values supported by Rclone.
For example, for AWS S3 it is s3 and for Dropbox it is dropbox.
The provider parameters depend entirely on the remote type and the specific provider you are using.
Please check the Rclone documentation for the appropriate provider.
Note that Rclone docs for storage types call the parameters properties and provide both config and env var formats--you need to use the config format.
For example, the GCS parameter --gcs-client-id described here should be used as client_id.
For reference, this format is described in the Rclone documentation.
Note that we do not support the use of opts discussed in that section.
Kubernetes Secrets
Kubernetes Secrets are used to store Rclone configurations, or storage secrets, for use by Servers.
Each Secret should contain exactly one Rclone configuration.
A Server can use storage secrets in one of two ways:
- It can dynamically load a secret specified by a Model in its
.spec.secretName - It can use global configurations made available via preloaded secrets
The name of a Secret is entirely your choice, as is the name of the data key in that Secret.
All that matters is that there is a single data key and that its value is in the format described above.
It is possible to use preloaded secrets for some Models and dynamically loaded secrets for others.Preloaded Secrets
Rather than Models always having to specify which secret to use, a Server can load storage secrets ahead of time.
These can then be reused across many Models.
When using a preloaded secret, the Model definition should leave .spec.secretName empty.
The protocol prefix in .spec.storageUri still needs to match the remote name specified by a storage secret.
The secrets to preload are named in a centralised ConfigMap called seldon-agent.
This ConfigMap applies to all Servers managed by the same SeldonRuntime.
By default this ConfigMap only includes seldon-rclone-gs-public, but can be extended with your own secrets as shown below:
:language: yamlThe easiest way to change this is to update your SeldonRuntime.
- If your SeldonRuntime is configured using the
seldon-core-v2-runtimeHelm chart, the corresponding value isconfig.agentConfig.rclone.configSecrets.
This can be used as shown below:yamlconfig: agentConfig: rclone: configSecrets: - my-s3 - custom-gcs - minio-in-cluster - Otherwise, if your SeldonRuntime is configured directly, you can add secrets by setting
.spec.config.agentConfig.rclone.config_secrets.
This can be used as follows:yamlapiVersion: mlops.seldon.io/v1alpha1 kind: SeldonRuntime metadata: name: seldon spec: seldonConfig: default config: agentConfig: rclone: config_secrets: - my-s3 - custom-gcs - minio-in-cluster ...
Examples
````{group-tab} S3 MinIO
Assuming you have installed MinIO in the `minio-system` namespace, a corresponding secret could be:
```{literalinclude} ../../../../../samples/auth/minio-secret.yaml
:language: yaml
```
You can then reference this in a Model with `.spec.secretName`:
```{literalinclude} ../../../../../samples/models/sklearn-iris-minio.yaml
:language: yaml
```
````
````{group-tab} Google Cloud Storage
[GCS](https://rclone.org/googlecloudstorage/) can use [service accounts](https://cloud.google.com/iam/docs/service-accounts) for access.
You can generate the credentials for a service account using the [gcloud CLI](https://cloud.google.com/sdk/gcloud/reference/iam/service-accounts/keys/create):
```bash
gcloud iam service-accounts keys create \
gcloud-application-credentials.json \
--iam-account [SERVICE-ACCOUNT--NAME]@[PROJECT-ID].iam.gserviceaccount.com
```
The contents of `gcloud-application-credentials.json` can be put into a secret:
```yaml
apiVersion: v1
kind: Secret
metadata:
name: gcs-bucket
type: Opaque
stringData:
gcs: |
type: gcs
name: gcs
parameters:
service_account_credentials: '<gcloud-application-credentials.json>'
```
You can then reference this in a Model with `.spec.secretName`:
```yaml
apiVersion: mlops.seldon.io/v1alpha1
kind: Model
metadata:
name: mymodel
spec:
storageUri: "gcs://my-bucket/my-path/my-pytorch-model"
secretName: "gcs-bucket"
requirements:
- pytorch
```
````Source Contents Kubernetes Tracing Index (`docs/source/contents/kubernetes/tracing/index.md`)
Tracing
We support Open Telemetry tracing. By default all components will attempt to send OLTP events to seldon-collector.seldon-mesh:4317 which will export to Jaeger at simplest-collector.seldon-mesh:4317.
The components can be installed from the tracing/k8s folder. In future an Ansible playbook will be created. This installs a Open Telemetry collector and a simple Jaeger install with a service that can be port forwarded to at simplest.seldon-mesh:16686.
An example Jaeger trace is show below:
Source Contents Models Inference Artifacts Index (`docs/source/contents/models/inference-artifacts/index.md`)
Inference Artifacts
To run your model inside Seldon you must supply an inference artifact that can be downloaded and run on one of MLServer or Triton inference servers. We list artifacts below by alphabetical order below.
:header-rows: 1
* - Type
- Server
- Tag
- Example
* - Alibi-Detect
- MLServer
- `alibi-detect`
- [example](../../examples/cifar10.md)
* - Alibi-Explain
- MLServer
- `alibi-explain`
- [example](../../examples/explainer-examples.md)
* - DALI
- Triton
- `dali`
- TBC
* - Huggingface
- MLServer
- `huggingface`
- [example](../../examples/huggingface.md)
* - LightGBM
- MLServer
- `lightgbm`
- [example](../../examples/model-zoo.md#lightgbm-model)
* - MLFlow
- MLServer
- `mlflow`
- [example](../../examples/model-zoo.md#mlflow-wine-model)
* - ONNX
- Triton
- `onnx`
- [example](../../examples/model-zoo.md#onnx-mnist-model)
* - OpenVino
- Triton
- `openvino`
- TBC
* - Custom Python
- MLServer
- `python, mlserver`
- [example](../../examples/pandasquery.md)
* - Custom Python
- Triton
- `python, triton`
- [example](https://github.com/SeldonIO/triton-python-examples)
* - PyTorch
- Triton
- `pytorch`
- [example](../../examples/model-zoo.md#pytorch-mnist-model)
* - SKLearn
- MLServer
- `sklearn`
- [example](../../examples/income.md)
* - Spark Mlib
- MLServer
- `spark-mlib`
- TBC
* - Tensorflow
- Triton
- `tensorflow`
- [example](../../examples/cifar10.md)
* - TensorRT
- Triton
- `tensorrt`
- TBC
* - Triton FIL
- Triton
- `fil`
- TBC
* - XGBoost
- MLServer
- `xgboost`
- [example](../../examples/model-zoo.md#xgboost-model)Saving Model artifacts
For many machine learning artifacts you can simply save them to a folder and load them into Seldon Core 2. Details are given below as well as a link to creating a custom model settings file if needed.
/* Detailed source-code truncated for AI context efficiency. */Custom MLServer Model Settings
For MLServer targeted models you can create a model-settings.json file to help MLServer load your model and place this alongside your artifact. See the MLServer project for details.
Custom Triton Configuration
For Triton inference server models you can create a configuration config.pbtxt file alongside your artifact.
Notes
- The
tagfield represents the tag you need to add to therequirementspart of the Model spec for your artifact to be loaded on a compatible server. e.g. for an sklearn model:{literalinclude} ../../../../../samples/models/sklearn-iris-gs.yaml:language: yaml
Source Contents Models Parameterized Models Index (`docs/source/contents/models/parameterized-models/index.md`)
Parameterized Models
The Model specification allows parameters to be passed to the loaded model to allow customization. For example:
:language: yamlThis capability is only available for MLServer custom model runtimes. The named keys and values will be added to the model-settings.json file for the provided model in theparameters.extra Dict. MLServer models are able to read these values in their load method.
Example Parameterized Models
:maxdepth: 1
:hidden:
pandasquery.mdSource Contents Models Rclone Index (`docs/source/contents/models/rclone/index.md`)
Rclone
We utilize Rclone to copy model artifacts from a storage location to the model servers. This allows users to take advantage of Rclones support for over 40 cloud storage backends including Amazon S3, Google Storage and many others.
For local storage while developing see here.
For authorization needed for cloud storage when running on Kubernetes see here.
Source Contents Getting Started Kubernetes Installation Security Index (`docs/source/contents/getting-started/kubernetes-installation/security/index.md`)
Security
Seldon can be run with secure control plane and data plane operations. There are three areas of concern:
The various communication points between services are shown in the diagram below:
Control Plane
TLS control plane activation is switched on and off via the environment variable: CONTROL_PLANE_SECURITY_PROTOCOL whose values can be PLAINTEXT or SSL.
Certificates will be loaded and used for the control plane gRPC services. The secrets or folders will be watched for updates (on certificate renewal) and automatically loaded again.
Helm Control Plane Install
When installing seldon-core-v2-setup you can set the secret names for your certificates. If using cert-manager example discussed below this would be as follows:
helm install seldon-v2 k8s/helm-charts/seldon-core-v2-setup/ -n seldon-mesh \
--set security.controlplane.protocol=SSLKafka
Kafka secure activation is switched on and off via the environment variable: KAFKA_SECURITY_PROTOCOL whose values can be PLAINTEXT, SSL or SASL_SSL.
Examples are shown below:
- mTLS Strimzi example
- mTLS AWS MSK example
- SASL PLAIN with Confluent Cloud example
- SASL PLAIN with Azure Event Hub example
- SASL SCRAM with Strimzi example
- SASL SCRAM with AWS MSK example
- SASL OAUTH with Confluent Cloud example
Data Plane
TLS Data plane activation is switched on and off via the environment variable: ENVOY_SECURITY_PROTOCOL whose values can be PLAINTEXT or SSL.
When activated this ensures TLS is used to communicate to Envoy via the xDS server as well as using the SDS service to send cretificates to envoy to use for upstream and downstream networking. Downstream is the external access to Seldon and upstream is the path from Envoy to the model servers or pipeline gateway.
Helm Data Plane Install
When installing seldon-core-v2-setup you can set data plane operations to TLS as below. This assumes the secrets installed by the helm chart at the end of this section.
helm install seldon-v2 k8s/helm-charts/seldon-core-v2-setup/ -n seldon-mesh --set security.envoy.protocol=SSLThe above uses default secret names defined for the certificates installed. You can change the names of the required certificate secrets as shown in a longer configuration below (again using the default names for illustration).
For this we use the following updated Helm values (k8s/samples/values-tls-dataplane-example.yaml):
:language: yamlWe use Envoy internally to direct traffic and in Envoy's terminology upstream is for internal model servers called from Envoy while the downstream server is the entrypoint server running in Envoy to receive grpc and REST calls. The above settings ensure mTLS for internal "upstream" traffic while provides a standard SSL non-mTLS entrpoint.
To use the above with the seldon CLI you would need a custom config file as follow:
{
"dataplane": {
"tls": true,
"skipSSLVerify": true
}
}We skip SSL Verify as these are internal self-signed certificates. For production use you would change this to the correct DNS name you are exposing the Seldon entrypoint.
Cetificate Providers
The installer/cluster controller for Seldon needs to provide the certificates. As part of Seldon we provide an example set of certificate issuers and certificates using cert-manager.
Helm
You can install Certificates into the desired namespace, here we use seldon-mesh as an example.
helm install seldon-v2-certs k8s/helm-charts/seldon-core-v2-certs/ -n seldon-mesh:maxdepth: 1
:hidden:
strimzi-mtls.md
strimzi-sasl.md
confluent-sasl.md
confluent-oauth.md
azure-event-hub-sasl.md
aws-msk-sasl.md
aws-msk-mtls.md
reference.mdSource Contents Kubernetes Resources Experiment Index (`docs/source/contents/kubernetes/resources/experiment/index.md`)
Experiment
An Experiment defines a traffic split between Models or Pipelines. This allows new versions of models and pipelines to be tested.
An experiment spec has three sections:
candidates(required) : a set of candidate models to split traffic.default(optional) : an existing candidate who endpoint should be modified to split traffic as defined by the candidates.- Each candidate has a traffic weight. The percentage of traffic will be this weight divided by the sum of traffic weights.
mirror(optional) : a single model to mirror traffic to the candidates. Responses from this model will not be returned to the caller.
An example experiment with a defaultModel is shown below:
:language: yamlThis defines a split of 50% traffic between two models iris and iris2. In this case we want to expose this traffic split on the existing endpoint created for the iris model. This allows us to test new versions of models (in this case iris2) on an existing endpoint (in this case iris). The default key defines the model whose endpoint we want to change. The experiment will become active when both underplying models are in Ready status.
An experiment over two separate models which exposes a new API endpoint is shown below:
:language: yamlTo call the endpoint add the header seldon-model: <experiment-name>.experiment in this case: seldon-model: experiment-iris.experiment. For example with curl:
curl http://${MESH_IP}/v2/models/experiment-iris/infer \
-H "Content-Type: application/json" \
-H "seldon-model: experiment-iris.experiment" \
-d '{"inputs": [{"name": "predict", "shape": [1, 4], "datatype": "FP32", "data": [[1, 2, 3, 4]]}]}'For examples see the local experiments notebook.
Pipeline Experiments
Running an experiment between some pipelines is very similar. The difference is resourceType: pipeline needs to be defined and in this case the candidates or mirrors will refer to pipelines. An example is shown below:
:language: yamlFor an example see the local experiments notebook.
Mirror Experiments
A mirror can be added easily for model or pipeline experiments. An example model mirror experiment is shown below:
:language: yamlFor an example see the local experiments notebook.
An example pipeline mirror experiment is shown below:
:language: yamlFor an example see the local experiments notebook.
Sticky Sessions
To allow cohorts to get consistent views in an experiment each inference request passes back a response header x-seldon-route which can be passed in future requests to an experiment to bypass the random traffic splits and get a prediction from the sequence of models and pipelines used in the initial request.
Note: you must pass the normal seldon-model header along with the x-seldon-route header.
This is illustrated in the local experiments notebook.
Caveats:
- Note the models used will be the same but not necessarily the same replica instances. This means at present this will not work for stateful models that need to go to the same model replica instance.
Service Meshes
As an alternative you can choose to run experiments at the service mesh level if you use one of the popular service meshes that allow header based routing in traffic splits. For further discussion see here.
Source Contents Kubernetes Resources Model Index (`docs/source/contents/kubernetes/resources/model/index.md`)
Model
A Model is the core atomic building block. It specifies a machine learning artifact that will be loaded onto one of the running Servers. A model could be a standard machine learning inference component such as
- a Tensorflow model, PyTorch model or SKLearn model.
- an inference transformation component such as a SKLearn pipeline or a piece of custom python logic.
a monitoring component such as an outlier detector or drift detector. - An alibi-explain model explainer
An example is shown below for a SKLearn model for iris classification:
:language: yamlIts Kubernetes spec has two core requirements
- A
storageUrispecifying the location of the artifact. This can be any rclone URI specification. - A
requirementslist which provides tags that need to be matched by the Server that can run this artifact type. By default when you install Seldon we provide a set of Servers that cover a range of artifact types.
Source Contents Kubernetes Resources Pipeline Index (`docs/source/contents/kubernetes/resources/pipeline/index.md`)
Pipeline
Pipelines allow one to connect flows of inference data transformed by Model components. A directed acyclic graph (DAG) of steps can be defined to join Models together. Each Model will need to be capable of receiving a V2 inference request and respond with a V2 inference response. An example Pipeline is shown below:
:language: yamlThe steps list shows three models: tfsimple1, tfsimple2 and tfsimple3. These three models each take two tensors called INPUT0 and INPUT1 of integers. The models produce two outputs OUTPUT0 (the sum of the inputs) and OUTPUT1 (subtraction of the second input from the first).
tfsimple1 and tfsimple2 take as inputs the input to the Pipeline: the default assumption when no explicit inputs are defined. tfsimple3 takes one V2 tensor input from each of the outputs of tfsimple1 and tfsimple2. As the outputs of tfsimple1 and tfsimple2 have tensors named OUTPUT0 and OUTPUT1 their names need to be changed to respect the expected input tensors and this is done with a tensorMap component providing this tensor renaming. This is only required if your models can not be directly chained together.
The output of the Pipeline is the output from the tfsimple3 model.
Detailed Specification
The full GoLang specification for a Pipeline is shown below:
:language: golang
:start-after: // PipelineSpec
:end-before: // PipelineStatusSource Contents Kubernetes Resources Seldonconfig Index (`docs/source/contents/kubernetes/resources/seldonconfig/index.md`)
Seldon Config
This section is for advanced usage where you want to define how seldon is installed in each namespace.The SeldonConfig resource defines the core installation components installed by Seldon. If you wish to install Seldon, you can use the SeldonRuntime resource which allows easy overriding of some parts defined in this specification. In general, we advise core DevOps to use the default SeldonConfig or customize it for their usage. Individual installation of Seldon can then use the SeldonRuntime with a few overrides for special customisation needed in that namespace.
The specification contains core PodSpecs for each core component and a section for general configuration including the ConfigMaps that are created for the Agent (rclone defaults), Kafka and Tracing (open telemetry).
:language: golang
:start-after: // SeldonConfigSpec
:end-before: // SeldonConfigStatusSome of these values can be overridden on a per namespace basis via the SeldonRuntime resource.
The default configuration is shown below.
:language: yamlSource Contents Kubernetes Resources Seldonruntime Index (`docs/source/contents/kubernetes/resources/seldonruntime/index.md`)
Seldon Runtime
The SeldonRuntime resource is used to create an instance of Seldon installed in a particular namespace.
:language: golang
:start-after: // SeldonRuntimeSpec
:end-before: // SeldonRuntimeStatusFor the definition of SeldonConfiguration above see the SeldonConfig resource.
The specification above contains overrides for the chosen SeldonConfig.
To override the PodSpec for a given component, the overrides field needs to specify the component name and the PodSpec needs to specify the container name, along with fields to override.
For instance, the following overrides the resource limits for cpu and memory in the hodometer component in the seldon-mesh namespace, while using values specified in the seldonConfig elsewhere (e.g. default).
apiVersion: mlops.seldon.io/v1alpha1
kind: SeldonRuntime
metadata:
name: seldon
namespace: seldon-mesh
spec:
overrides:
- name: hodometer
podSpec:
containers:
- name: hodometer
resources:
limits:
memory: 64Mi
cpu: 20m
seldonConfig: defaultAs a minimal use you should just define the SeldonConfig to use as a base for this install, for example to install in the seldon-mesh namespace with the SeldonConfig named default:
apiVersion: mlops.seldon.io/v1alpha1
kind: SeldonRuntime
metadata:
name: seldon
namespace: seldon-mesh
spec:
seldonConfig: defaultThe helm chart seldon-core-v2-runtime allows easy creation of this resource and associated default Servers for an installation of Seldon in a particular namespace.
SeldonConfig Update Propagation
When a SeldonConfig resource changes any SeldonRuntime resources that reference the changed SeldonConfig will also be updated immediately. If this behaviour is not desired you can set spec.disableAutoUpdate in the SeldonRuntime resource for it not be be updated immediately but only when it changes or any owned resource changes.
Source Contents Kubernetes Resources Server Index (`docs/source/contents/kubernetes/resources/server/index.md`)
Server
The default installation will provide two initial servers: one MLServer and one Triton. You only need to define additional servers for advanced use cases.A Server defines an inference server onto which models will be placed for inference. By default on installation two server StatefulSets will be deployed one MlServer and one Triton. An example Server definition is shown below:
:language: yamlThe main requirement is a reference to a ServerConfig resource in this case mlserver.
Detailed Specs
:language: golang
:start-after: // ServerSpec
:end-before: // ServerStatusCustom Servers
One can easily utilize a custom image with the existing ServerConfigs. For example, the following defines an MLServer server with a custom image:
:language: yamlThis server can then be targeted by a particular model by specifying this server name when creating the model, for example:
:language: yamlServer with PVC
One can also create a Server definition to add a persistent volume to your server. This can be used to allow models to be loaded directly from the persistent volume.
:language: yamlThe server can be targeted by a model whose artifact is on the persistent volume as shown below.
:language: yamlA fully worked example for this can be found here.
An alternative would be to create your own ServerConfig for more complex use cases or you want to standardise the Server definition in one place.
Source Contents Kubernetes Resources Serverconfig Index (`docs/source/contents/kubernetes/resources/serverconfig/index.md`)
Server Config
This section is for advanced usage where you want to define new types of inference servers.Server configurations define how to create an inference server. By default one is provided for Seldon MLServer and one for NVIDIA Triton Inference Server. Both these servers support the V2 inference protocol which is a requirement for all inference servers. They define how the Kubernetes ReplicaSet is defined which includes the Seldon Agent reverse proxy as well as an Rclone server for downloading artifacts for the server. The Kustomize ServerConfig for MlServer is shown below:
:language: yamlSource Contents Kubernetes Service Meshes Ambassador Index (`docs/source/contents/kubernetes/service-meshes/ambassador/index.md`)
Ambassador
Ambassador provides service mesh and ingress products. Our examples here are based on the Emissary ingress.
We will run through some examples as shown in the notebook service-meshes/ambassador/ambassador.ipynb
Single Model
- Seldon Iris classifier model
- Default Ambassador Host and Listener
- Ambassador Mappings for REST and gRPC endpoints
:language: yamlTraffic Split
Traffic splitting does not presently work due to this [issue](https://github.com/emissary-ingress/emissary/issues/4062). We recommend you use a Seldon Experiment instead.Seldon provides an Experiment resource for service mesh agnostic traffic splitting but if you wish to control this via Ambassador and example is shown below to split traffic between two models.
:language: yamlSource Contents Kubernetes Service Meshes Istio Index (`docs/source/contents/kubernetes/service-meshes/istio/index.md`)
Istio
Istio provides a service mesh and ingress solution.
We will run through some examples as shown in the notebook service-meshes/istio/istio.ipynb
Single Model
- A Seldon Iris Model
- An istio Gateway
- An instio VirtualService to expose REST and gRPC
:language: yamlTraffic Split
- Two Iris Models
- An istio Gateway
- An istio VirtualService with traffic split
:language: yamlSource Contents Kubernetes Service Meshes Traefik Index (`docs/source/contents/kubernetes/service-meshes/traefik/index.md`)
Traefik
Traefik provides a service mesh and ingress solution.
We will run through some examples as shown in the notebook service-meshes/traefik/traefik.ipynb
Single Model
- A Seldon Iris Model
- Traefik Service
- Traefik IngressRoute
- Traefik Middleware for adding a header
:language: yamlTraffic Split
Traffic splitting does not presently work due to this [issue](https://github.com/emissary-ingress/emissary/issues/4062). We recommend you use a Seldon Experiment instead.Requirements Docs (`docs/requirements-docs.txt`)
jupyter-book==0.6.5
linkify-it-py==1.0.1
myst-parser==1.0.0
Sphinx==6.2.1
sphinx-autobuild==2021.3.14
sphinx-copybutton==0.5.0
sphinx-jinja2-compat==0.2.0
sphinx-material==0.0.32
sphinx-notfound-page==0.7.1
sphinx-panels==0.4.1
sphinx-tabs==3.4.1
sphinx-togglebutton==0.3.0
sphinx-toolbox==3.2.0
sphinxcontrib-applehelp==1.0.2
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==2.0.1
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-mermaid==0.8.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.5
sphinxcontrib-youtube==1.2.0
Scheduler Docs Design (`scheduler/docs/design.md`)
Design
- Operator
- Calls scheduler with load/unload model requests
- Agent
- Runs on each server pod. On start calls scheduler to inform of new server replica with given capabilities, memory.
- Handles load requests:
- Tell Rclone server to download artifacts
- Tell server to load/unload model
- Scheduler
- Assigns models to server replicas
- Manages gRPC connections to:
- Agent to load/unload models assigned to a replica
- Envoy to update routing to replicas for models
- Server
- V2 compatible ML server
- Rclone
- Rclone server to download artifacts onto local PVC
- DB
- State of truth store for model->server mapping
- Scaler
- Handles possble:
- Scale to zero
- Scale from zero
- Payload logging
- Handles possble:
Agent-Scheduler design
Requirements:
- Handle server updates, e.g. user changes server configuration (more memory, different image with capabilities (sklearn, alibi etc))
- Handle server failures
Due to above current design:
- Agent calls scheduler on startup, when pod is ready, and informs scheduler of new replica (if any, there may be 0 replicas) with a server with given capabilities
- Scheduler tells agent of model(s) to load
- Scheduler handles loss of gRPC connection by rescheduling models (if possible)
- Scheduler reschedules failed scheduling models when replicas restart
Scheduler design
Requirements:
- Handle core state of truth for model->server mapping
- Update via a "scheduling algorithm"
- Handle syncing of Envoy and Agents when model->server changes
- Handle running as multiple pods with remote DB storage
gRPC Services
Model Replica State
A model state can be in a set of states.
const (
ModelStateUnknown ModelState = iota
ModelProgressing
ModelAvailable
ModelFailed
ModelTerminating
ModelTerminated
ModelTerminateFailed
ScheduleFailed
ModelScaledDown
)And the underlying model replicas can be in a set of states.
const (
ModelReplicaStateUnknown ModelReplicaState = iota
LoadRequested
Loading
Loaded
LoadFailed
UnloadEnvoyRequested
UnloadRequested
Unloading
Unloaded
UnloadFailed
Available
LoadedUnavailable
Draining
)The idea is the core scheduler, the scheduler-agent server and the scheduler-envoy can in theory all work independently with the later two syncing when a model state changes.
Scheduler
Loading
- Scheduler gprc receives load model RPC
- Scheduler assigns model to 1 or more replicas updating the core model->server state
- Model replica state it set to
LoadRequestedand Model state is set toModelProgressing
- Model replica state it set to
Unloading
- Scheduler gprc receives unload model RPC
- Scheduler removes model replicas updating the core model->server state
- Model replica state it set to
UnloadEnvoyRequestedand Model state is set toModelTerminating
- Model replica state it set to
Scheduler-Agent
When it syncs
Loading
- Agent-server sees model replica is
LoadRequested- A load request to agent for desired replicas and changes state to
Loading - When model is loaded agent sends Event update to scheduler and scheduler sets state to
Loaded
- A load request to agent for desired replicas and changes state to
Unloading
- Agent-server sees model replica is
UnloadRequested- An unload request to agent for desired replicas and changes state to
Unloading - When model is unloaded agent sends Event update to scheduler and scheduler sets state to
Unloaded
- An unload request to agent for desired replicas and changes state to
Scheduler-Envoy
- Envoy syncs and updates mapping for any models it sees that have state
Loadedto beAvailableand removes any whose state is notLoaded - Envoy sets all model replicas marked as
UnloadEnvoyRequestedtoUnloadRequested, which would trigger Agent-server model replica unload
Below a diagram of the interaction of creating a new Model
/* Detailed source-code truncated for AI context efficiency. */Source Contents Architecture Dataflow (`docs/source/contents/architecture/dataflow.md`)
Data flow design paradigm in Seldon Core
Seldon Core 2 is designed around data flow paradigm. Here we will explain what that means and some of the rationals behind this choice.
Seldon Core v1
Initial release of Seldon Core introduced a concept of an inference graph, which can be thought of as a sequence of operations that happen to the inference request. Here is how it may look like:
In reality though this was not how Seldon Core v1 is implemented. Instead, Seldon deployment consists of a range of independent services that host models, transformations, detectors and explainers, and a central orchestrator that knows the inference graph topology and makes service calls in the correct order, passing data between requests and responses as necessary. Here is how the picture looks under the hood:
While this is a convenient way of implementing evaluation graph with microservices, it has a few problems. Orchestrator becomes a bottleneck and a single point of failure. It also hides all the data transformations that need to happen to translate one service's response to another service's request. Data tracing and lineage becomes difficult. All in all, while Seldon platform is all about processing data, under-the-hood implementation was still focused on order of operations and not on data itself.
Data flow
The realisation of this disparity led to a new approach towards inference graph evaluation in v2, based on the data flow paradigm. Data flow is a well known concept in software engineering, known from 1960s. In contrast to services, that model programs as a control flow, focusing on the order of operations, data flow proposes to model software systems as a series of connections that modify incoming data, focusing on data flowing through the system. A particular flavor of data flow paradigm used by v2 is known as flow-based programming, FBP. FBP defines software applications as a set of processes which exchange data via connections that are external to those processes. Connections are made via named ports, which promotes data coupling between components of the system.
Data flow design makes data in software the top priority. That is one of the key messages of the so called "data-centric AI" idea, which is becoming increasingly popular within the ML community. Data is a key component of a successful ML project. Data needs to be discovered, described, cleaned, understood, monitored and verified. Consequently, there is a growing demand for data-centric platforms and solutions. Making Seldon Core data-centric was one of the key goals of the v2 design.
Seldon Core 2
In the context of Seldon Core application of FBP design approach means that the evaluation implementation is done the same way inferece graph. So instead of routing everything through a centralized orchestrator the evaluation happens in the same graph-like manner:
As far as implementation goes, Seldon Core 2 runs on Kafka. Inference request is put onto a pipeline input topic, which triggers an evaluation. Each part of the inference graph is a service running in its own container fronted by a model gateway. Model gateway listens to a corresponding input Kafka topic, reads data from it, calls the service and puts the received response to an output Kafka topic. There is also a pipeline gateway that allows to interact with Seldon Core in synchronous manner.
This approach gives SCv2 several important features. Firstly, Seldon Core natively supports both synchronous and asynchronous modes of operation. Asynchronicity is achieved via streaming: input data can be sent to an input topic in Kafka, and after the evaluation the output topic will contain the inference result. For those looking to use it in the v1 style, a service API is provided.
Secondly, there is no single point of failure. Even if one or more nodes in the graph go down, the data will still be sitting on the streams waiting to be processed, and the evaluation resumes whenever the failed node comes back up.
Thirdly, data flow means intermediate data can be accessed at any arbitrary step of the graph, inspected and collected as necessary. Data lineage is possible throughout, which opens up opportunities for advanced monitoring and explainability use cases. This is a key feature for effective error surfacing in production environments as it allows:
- Adding context from different parts of the graph to better understand a particular output
- Reducing false positive rates of alerts as different slices of the data can be investigated
- Enabling reproducing of results as fined-grained lineage of computation and associated data transformation are tracked by design
Finally, inference graph can now be extended with adding new nodes at arbitrary places, all without affecting the pipeline execution. This kind of flexibility was not possible with v1. This also allows multiple pipelines to share common nodes and therefore optimising resources usage.
References
More details and information on data-centric AI and data flow paradigm can be found in these resources:
- Data-centric AI Resource Hub: https://datacentricai.org/
- Stanford MLSys seminar "What can Data-Centric AI Learn from Data and ML Engineering?": https://www.youtube.com/watch?v=cqDgxP8DcJA
- A paper that explores data flow in ML deployment context: https://arxiv.org/abs/2204.12781
- Introduction to flow based programming from its creator J.P. Morrison: https://jpaulm.github.io/fbp/index.html
- Pathways: Asynchronous Distributed Dataflow for ML (research work from Google on the design and implementation of data flow based orchestration layer for accelerators): https://arxiv.org/abs/2203.12533
- Better understanding of data requires tracking its history and context: https://queue.acm.org/detail.cfm?id=2602651
Source Contents Development Licenses (`docs/source/contents/development/licenses.md`)
3rd part license generation
We use the following tools and processes for generationg 3rd party licenses.
Go Modules
Install tools
For Go modules we use a fork of Kubeflow's testing repo with some fixes.
Clone and update to this branch.
git clone https://github.com/SeldonIO/kubeflow-testing -b seldon-updateGo to go-license-tools folder:
cd kubeflow-testing/py/kubeflow/testing/go-license-tools/Install
python setup.py installGeneration
Run make update-3rd-party-licenses in top level folder.
Source Contents Examples Batch Examples K8s (`docs/source/contents/examples/batch-examples-k8s.md`)
Batch Inference Examples
Requires mlserver to be installed.
Deprecated: The MLServer CLI `infer` feature is experimental and will be removed in future work.pip install mlserver:relative-images:Source Contents Examples Batch Examples Local (`docs/source/contents/examples/batch-examples-local.md`)
Local Batch Inference Example
This example runs you through a series of batch inference requests made to both models and pipelines running on Seldon Core locally.
Deprecated: The MLServer CLI `infer` feature is experimental and will be removed in future work.Setup
If you haven't already, you'll need to clone the Seldon Core repository and run it locally before you run through this example.
By default, the CLI will expect your inference endpoint to be at `0.0.0.0:9000`. If you have customized this, you'll need to [redirect the CLI](../cli/index).Deploy Models and Pipelines
First, let's jump in to the samples folder where we'll find some sample models and pipelines we can use:
cd samples/Deploy the Iris Model
Let's take a look at a sample model before we deploy it:
cat models/sklearn-iris-gs.yamlapiVersion: mlops.seldon.io/v1alpha1
kind: Model
metadata:
name: iris
spec:
storageUri: "gs://seldon-models/mlserver/iris"
requirements:
- sklearn
memory: 100KiThe above manifest will deploy a simple sci-kit learn model based on the iris dataset.
Let's now deploy that model using the Seldon CLI:
seldon model load -f models/sklearn-iris-gs.yamlDeploy the Iris Pipeline
Now that we've deployed our iris model, let's create a pipeline around the model.
cat pipelines/iris.yamlapiVersion: mlops.seldon.io/v1alpha1
kind: Pipeline
metadata:
name: iris-pipeline
spec:
steps:
- name: iris
output:
steps:
- irisWe see that this pipeline only has one step, which is to call the iris model we deployed earlier. We can create the pipeline by running:
seldon pipeline load -f pipelines/iris.yamlDeploy the Tensorflow Model
To demonstrate batch inference requests to different types of models, we'll also deploy a simple tensorflow model:
cat models/tfsimple1.yamlapiVersion: mlops.seldon.io/v1alpha1
kind: Model
metadata:
name: tfsimple1
spec:
storageUri: "gs://seldon-models/triton/simple"
requirements:
- tensorflow
memory: 100KiThe tensorflow model takes two arrays as inputs and returns two arrays as outputs. The first output is the addition of the two inputs and the second output is the value of (first input - second input).
Let's deploy the model:
seldon model load -f models/tfsimple1.yamlDeploy the Tensorflow Pipeline
Just as we did for the scikit-learn model, we'll deploy a simple pipeline for our tensorflow model:
Inspect the pipeline manifest:
cat pipelines/tfsimple.yamlapiVersion: mlops.seldon.io/v1alpha1
kind: Pipeline
metadata:
name: tfsimple
spec:
steps:
- name: tfsimple1
output:
steps:
- tfsimple1and deploy it:
seldon pipeline load -f pipelines/tfsimple.yamlCheck Model and Pipeline Status
Once we've deployed a model or pipeline to Seldon Core, we can list them and check their status by running:
seldon model listand
seldon pipeline listYour models and pieplines should be showing a state of ModelAvailable and PipelineReady respectively.
Test Predictions
Before we run a large batch job of predictions through our models and pipelines, let's quickly check that they work with a single standalone inference request. We can do this using the seldon model infer command.
Scikit-learn Model
seldon model infer iris '{"inputs": [{"name": "predict", "shape": [1, 4], "datatype": "FP32", "data": [[1, 2, 3, 4]]}]}' | jq{
"model_name": "iris_1",
"model_version": "1",
"id": "a67233c2-2f8c-4fbc-a87e-4e4d3d034c9f",
"parameters": {
"content_type": null,
"headers": null
},
"outputs": [
{
"name": "predict",
"shape": [
1
],
"datatype": "INT64",
"parameters": null,
"data": [
2
]
}
]
}The preidiction request body needs to be an Open Inference Protocol compatible payload and also match the expected inputs for the model you've deployed. In this case, the iris model expects data of shape [1, 4] and of type FP32.
You'll notice that the prediction results for this request come back on outputs[0].data.
Scikit-learn Pipeline
seldon pipeline infer iris-pipeline '{"inputs": [{"name": "predict", "shape": [1, 4], "datatype": "FP32", "data": [[1, 2, 3, 4]]}]}' | jq{
"model_name": "",
"outputs": [
{
"data": [
2
],
"name": "predict",
"shape": [
1
],
"datatype": "INT64"
}
]
}Tensorflow Model
seldon model infer tfsimple1 '{"outputs":[{"name":"OUTPUT0"}], "inputs":[{"name":"INPUT0","data":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16],"datatype":"INT32","shape":[1,16]},{"name":"INPUT1","data":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16],"datatype":"INT32","shape":[1,16]}]}' | jq{
"model_name": "tfsimple1_1",
"model_version": "1",
"outputs": [
{
"name": "OUTPUT0",
"datatype": "INT32",
"shape": [
1,
16
],
"data": [
2,
4,
6,
8,
10,
12,
14,
16,
18,
20,
22,
24,
26,
28,
30,
32
]
}
]
}You'll notice that the inputs for our tensorflow model look different from the ones we sent to the iris model. This time, we're sending two arrays of shape [1,16]. When sending an inference request, we can optionally chose which outputs we want back by including an {"outputs":...} object.
Tensorflow Pipeline
seldon pipeline infer tfsimple '"inputs":[{"name":"INPUT0","data":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16],"datatype":"INT32","shape":[1,16]},{"name":"INPUT1","data":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16],"datatype":"INT32","shape":[1,16]}]}' | jq{
"model_name": "",
"outputs": [
{
"data": [
2,
4,
6,
8,
10,
12,
14,
16,
18,
20,
22,
24,
26,
28,
30,
32
],
"name": "OUTPUT0",
"shape": [
1,
16
],
"datatype": "INT32"
},
{
"data": [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
"name": "OUTPUT1",
"shape": [
1,
16
],
"datatype": "INT32"
}
]
}Running the Scikit-Learn Batch Job
In the samples folder there is a batch request input file: batch-inputs/iris-input.txt. It contains 100 input payloads for our iris model. Let's take a look at the first line in that file:
cat batch-inputs/iris-input.txt | head -n 1 | jq{
"inputs": [
{
"name": "predict",
"data": [
0.38606369295833043,
0.006894049558299753,
0.6104082981607108,
0.3958954239450676
],
"datatype": "FP64",
"shape": [
1,
4
]
}
]
}To run a batch inference job we'll use the MLServer CLI. If you don't already have it installed you can install it using:
pip install mlserverIris Model
The inference job can be executed by running the following command:
mlserver infer -u localhost:9000 -m iris -i batch-inputs/iris-input.txt -o /tmp/iris-output.txt --workers 52023-01-22 18:24:17,272 [mlserver] INFO - Using asyncio event-loop policy: uvloop
2023-01-22 18:24:17,273 [mlserver] INFO - server url: localhost:9000
2023-01-22 18:24:17,273 [mlserver] INFO - model name: iris
2023-01-22 18:24:17,273 [mlserver] INFO - request headers: {}
2023-01-22 18:24:17,273 [mlserver] INFO - input file path: batch-inputs/iris-input.txt
2023-01-22 18:24:17,273 [mlserver] INFO - output file path: /tmp/iris-output.txt
2023-01-22 18:24:17,273 [mlserver] INFO - workers: 5
2023-01-22 18:24:17,273 [mlserver] INFO - retries: 3
2023-01-22 18:24:17,273 [mlserver] INFO - batch interval: 0.0
2023-01-22 18:24:17,274 [mlserver] INFO - batch jitter: 0.0
2023-01-22 18:24:17,274 [mlserver] INFO - connection timeout: 60
2023-01-22 18:24:17,274 [mlserver] INFO - micro-batch size: 1
2023-01-22 18:24:17,420 [mlserver] INFO - Finalizer: processed instances: 100
2023-01-22 18:24:17,421 [mlserver] INFO - Total processed instances: 100
2023-01-22 18:24:17,421 [mlserver] INFO - Time taken: 0.15 secondsThe mlserver batch component will take your input file batch-inputs/iris-input.txt, distribute those payloads across 5 different workers (--workers 5), collect the responses and write them to a file /tmp/iris-output.txt. For a full set of options check out the MLServer CLI Reference.
Checking the Output
We can check the inference responses by looking at the contents of the output file:
cat /tmp/iris-output.txt | head -n 1 | jqIris Pipeline
We can run the same batch job for our iris pipeline and store the outputs in a different file:
mlserver infer -u localhost:9000 -m iris-pipeline.pipeline -i batch-inputs/iris-input.txt -o /tmp/iris-pipeline-output.txt --workers 52023-01-22 18:25:18,651 [mlserver] INFO - Using asyncio event-loop policy: uvloop
2023-01-22 18:25:18,653 [mlserver] INFO - server url: localhost:9000
2023-01-22 18:25:18,653 [mlserver] INFO - model name: iris-pipeline.pipeline
2023-01-22 18:25:18,653 [mlserver] INFO - request headers: {}
2023-01-22 18:25:18,653 [mlserver] INFO - input file path: batch-inputs/iris-input.txt
2023-01-22 18:25:18,653 [mlserver] INFO - output file path: /tmp/iris-pipeline-output.txt
2023-01-22 18:25:18,653 [mlserver] INFO - workers: 5
2023-01-22 18:25:18,653 [mlserver] INFO - retries: 3
2023-01-22 18:25:18,653 [mlserver] INFO - batch interval: 0.0
2023-01-22 18:25:18,653 [mlserver] INFO - batch jitter: 0.0
2023-01-22 18:25:18,653 [mlserver] INFO - connection timeout: 60
2023-01-22 18:25:18,653 [mlserver] INFO - micro-batch size: 1
2023-01-22 18:25:18,963 [mlserver] INFO - Finalizer: processed instances: 100
2023-01-22 18:25:18,963 [mlserver] INFO - Total processed instances: 100
2023-01-22 18:25:18,963 [mlserver] INFO - Time taken: 0.31 secondsChecking the Output
We can check the inference responses by looking at the contents of the output file:
cat /tmp/iris-pipeline-output.txt | head -n 1 | jqRunning the Tensorflow Batch Job
The samples folder contains an example batch input for the tensorflow model, just as it did for the scikit-learn model. You can find it at batch-inputs/tfsimple-input.txt. Let's take a look at the first inference request in the file:
cat batch-inputs/tfsimple-input.txt | head -n 1 | jq{
"inputs": [
{
"name": "INPUT0",
"data": [
75,
39,
9,
44,
32,
97,
99,
40,
13,
27,
25,
36,
18,
77,
62,
60
],
"datatype": "INT32",
"shape": [
1,
16
]
},
{
"name": "INPUT1",
"data": [
39,
7,
14,
58,
13,
88,
98,
66,
97,
57,
49,
3,
49,
63,
37,
12
],
"datatype": "INT32",
"shape": [
1,
16
]
}
]
}Tensorflow Model
As before, we can run the inference batch job using the mlserver infer command:
mlserver infer -u localhost:9000 -m tfsimple1 -i batch-inputs/tfsimple-input.txt -o /tmp/tfsimple-output.txt --workers 102023-01-23 14:56:10,870 [mlserver] INFO - Using asyncio event-loop policy: uvloop
2023-01-23 14:56:10,872 [mlserver] INFO - server url: localhost:9000
2023-01-23 14:56:10,872 [mlserver] INFO - model name: tfsimple1
2023-01-23 14:56:10,872 [mlserver] INFO - request headers: {}
2023-01-23 14:56:10,872 [mlserver] INFO - input file path: batch-inputs/tfsimple-input.txt
2023-01-23 14:56:10,872 [mlserver] INFO - output file path: /tmp/tfsimple-output.txt
2023-01-23 14:56:10,872 [mlserver] INFO - workers: 10
2023-01-23 14:56:10,872 [mlserver] INFO - retries: 3
2023-01-23 14:56:10,872 [mlserver] INFO - batch interval: 0.0
2023-01-23 14:56:10,872 [mlserver] INFO - batch jitter: 0.0
2023-01-23 14:56:10,872 [mlserver] INFO - connection timeout: 60
2023-01-23 14:56:10,872 [mlserver] INFO - micro-batch size: 1
2023-01-23 14:56:11,077 [mlserver] INFO - Finalizer: processed instances: 100
2023-01-23 14:56:11,077 [mlserver] INFO - Total processed instances: 100
2023-01-23 14:56:11,078 [mlserver] INFO - Time taken: 0.21 secondsChecking the Output
We can check the inference responses by looking at the contents of the output file:
cat /tmp/tfsimple-output.txt | head -n 1 | jqYou should get the following response:
{
"model_name": "tfsimple1_1",
"model_version": "1",
"id": "54e6c237-8356-4c3c-96b5-2dca4596dbe9",
"parameters": {
"batch_index": 0,
"inference_id": "54e6c237-8356-4c3c-96b5-2dca4596dbe9"
},
"outputs": [
{
"name": "OUTPUT0",
"shape": [
1,
16
],
"datatype": "INT32",
"parameters": {},
"data": [
114,
46,
23,
102,
45,
185,
197,
106,
110,
84,
74,
39,
67,
140,
99,
72
]
},
{
"name": "OUTPUT1",
"shape": [
1,
16
],
"datatype": "INT32",
"parameters": {},
"data": [
36,
32,
-5,
-14,
19,
9,
1,
-26,
-84,
-30,
-24,
33,
-31,
14,
25,
48
]
}
]
}Tensorflow Pipeline
mlserver infer -u localhost:9000 -m tfsimple1 -i batch-inputs/tfsimple-input.txt -o /tmp/tfsimple-pipeline-output.txt --workers 102023-01-23 14:56:10,870 [mlserver] INFO - Using asyncio event-loop policy: uvloop
2023-01-23 14:56:10,872 [mlserver] INFO - server url: localhost:9000
2023-01-23 14:56:10,872 [mlserver] INFO - model name: tfsimple1
2023-01-23 14:56:10,872 [mlserver] INFO - request headers: {}
2023-01-23 14:56:10,872 [mlserver] INFO - input file path: batch-inputs/tfsimple-input.txt
2023-01-23 14:56:10,872 [mlserver] INFO - output file path: /tmp/tfsimple-pipeline-output.txt
2023-01-23 14:56:10,872 [mlserver] INFO - workers: 10
2023-01-23 14:56:10,872 [mlserver] INFO - retries: 3
2023-01-23 14:56:10,872 [mlserver] INFO - batch interval: 0.0
2023-01-23 14:56:10,872 [mlserver] INFO - batch jitter: 0.0
2023-01-23 14:56:10,872 [mlserver] INFO - connection timeout: 60
2023-01-23 14:56:10,872 [mlserver] INFO - micro-batch size: 1
2023-01-23 14:56:11,077 [mlserver] INFO - Finalizer: processed instances: 100
2023-01-23 14:56:11,077 [mlserver] INFO - Total processed instances: 100
2023-01-23 14:56:11,078 [mlserver] INFO - Time taken: 0.25 secondsChecking the Output
We can check the inference responses by looking at the contents of the output file:
cat /tmp/tfsimple-pipeline-output.txt | head -n 1 | jqCleaning Up
Now that we've run our batch examples, let's remove the models and pipelines we created:
seldon model unload irisseldon model unload tfsimple1seldon pipeline unload iris-pipelineseldon pipeline unload tfsimpleAnd finally let's spin down our local instance of Seldon Core:
cd ../ && make undeploy-localSource Contents Examples Cifar10 (`docs/source/contents/examples/cifar10.md`)
Production Image Classifier
Run these examples from the samples/examples/image_classifier folder.
:relative-images:Source Contents Examples Custom Servers (`docs/source/contents/examples/custom-servers.md`)
Custom Servers
Run these examples from the samples folder.
Source Contents Examples Experiment Versions (`docs/source/contents/examples/experiment-versions.md`)
Experiments Versions
Run these examples from the samples folder.
Source Contents Examples Explainer Examples (`docs/source/contents/examples/explainer-examples.md`)
Explainer Examples
Run these examples from the samples folder.
Source Contents Examples Huggingface (`docs/source/contents/examples/huggingface.md`)
Huggingface Models
Run these examples from the samples folder.
Source Contents Examples Income (`docs/source/contents/examples/income.md`)
Production Income Classifier with Drift, Outlier and Explanations
Run these examples from the samples/examples/income_classifier folder.
Source Contents Examples Inference (`docs/source/contents/examples/inference.md`)
Inference Examples
Run these examples from the samples folder.
Source Contents Examples K8s Clusterwide (`docs/source/contents/examples/k8s-clusterwide.md`)
Kubernetes Clusterwide Example
Run these examples from the samples folder.
Source Contents Examples K8s Examples (`docs/source/contents/examples/k8s-examples.md`)
Kubernetes Examples
Run these examples from the samples folder.
Source Contents Examples K8s Pvc (`docs/source/contents/examples/k8s-pvc.md`)
Kubernetes Server with PVC
Source Contents Examples Local Examples (`docs/source/contents/examples/local-examples.md`)
Local Examples
Run these examples from the samples folder.
Source Contents Examples Local Experiments (`docs/source/contents/examples/local-experiments.md`)
Local Experiments
Run these examples from the samples folder.
Source Contents Examples Local Overcommit Examples (`docs/source/contents/examples/local-overcommit-examples.md`)
Local Multi-model Serving with Overcommit Examples
Run these examples from the samples folder.
Source Contents Examples Model Zoo (`docs/source/contents/examples/model-zoo.md`)
Model Zoo
Run these examples from the samples folder.
Source Contents Examples Multi Version (`docs/source/contents/examples/multi-version.md`)
Artifact Versions
Run these examples from the samples folder.
Source Contents Examples Pandasquery (`docs/source/contents/examples/pandasquery.md`)
Conditional Pipeline with Pandas Query Model
The model is defined as an MLServer custom runtime and allows the user to pass in a custom pandas query as a parameter defined at model creation to be used to filter the data passed to the model.
:language: pythonSource Contents Examples Pipeline Examples (`docs/source/contents/examples/pipeline-examples.md`)
Pipeline Examples
Run these examples from the samples folder.
Source Contents Examples Pipeline Ready And Metadata (`docs/source/contents/examples/pipeline-ready-and-metadata.md`)
Pipeline Readiness
Run these examples from the samples folder.
Source Contents Examples Pipeline To Pipeline (`docs/source/contents/examples/pipeline-to-pipeline.md`)
Pipeline to Pipeline Examples
Run these examples from the samples folder.
:relative-images:Source Contents Examples Speech To Sentiment (`docs/source/contents/examples/speech-to-sentiment.md`)
Huggingface speech to sentiment pipeline
Run these examples from the samples/examples/huggingface folder.
:relative-images:Source Contents Examples Tritonclient Examples (`docs/source/contents/examples/tritonclient-examples.md`)
Tritonclient Examples with Seldon Core 2
To install tritonclient
pip install tritonclient[all]:relative-images:Source Contents Getting Started Cli (`docs/source/contents/getting-started/cli.md`)
Seldon CLI
Seldon Core 2 can be managed via a CLI tool.
Download Linux Binary
Download from a recent release from https://github.com/SeldonIO/seldon-core/releases.
It is dynamically linked and will require and *nix architecture and glibc 2.25+.
mv seldon-linux-amd64 seldon
chmod u+x seldonAdd to your PATH.
Local build (requires Go)
git clone https://github.com/SeldonIO/seldon-core --branch=v2
cd seldon-core/operator
make build-seldonAdd <project-root>/operator/bin to your PATH.
Local macOS ARM build (requires Go and librdkafka)
# install dependencies
brew install go librdkafkagit clone https://github.com/SeldonIO/seldon-core --branch=v2
cd seldon-core/operator
make build-seldon-armAdd <project-root>/operator/bin to your PATH.
Source Contents Metrics Local Metrics Test (`docs/source/contents/metrics/local-metrics-test.md`)
Local Metrics
Run these examples from the samples folder.
Source Contents Metrics Operational (`docs/source/contents/metrics/operational.md`)
Operational Metrics
While the system is running we collect metrics via Prometheus that allow users to observe different aspects of SCv2 with regards to throughout, latency, memory, CPU etc.
This is in addition to the standard Kubernetes metrics that are scraped by Prometheus.
There is a Grafana dashboard (referenced below) that provides an overview of the system.
List of SCv2 metrics
The list of SCv2 metrics that we are compiling is as follows.
For the agent that sits next to the inference servers:
:language: golang
:start-after: // Docs Start Metrics
:end-before: // Docs End MetricsFor the pipeline gateway that handles requests to pipelines:
:language: golang
:start-after: // Docs Start Metrics
:end-before: // Docs End MetricsMany of these metrics are model and pipeline level counters and gauges.
We also aggregate some of these metrics to speed up the display of graphs. We don't presently store per-model histogram metrics for performance reasons. However, we do presently store per-pipeline histogram metrics.
This is experimental and these metrics are bound to change to reflect the trends we want to capture as we get more information about the usage of the system.
Grafana dashboard
We have a prebuilt Grafana dashboard that makes use of many of the metrics that we expose.
Local Use
Grafana and Prometheus are available when you run Seldon locally.
You will be able to connect to the Grafana dashboard at http://localhost:3000.
Prometheus will be available at http://localhost:9090.
Kubernetes Installation
Download the dashboard from SCv2 dashboard and import it in Grafana, making sure that the data source is pointing to the correct Prometheus store.
Find more information on how to import the dashboard here.
Local Metrics Examples
An example to show raw metrics that Prometheus will scrape.
:maxdepth: 1
:hidden:
local-metrics-test.mdSource Contents Metrics Usage (`docs/source/contents/metrics/usage.md`)
Usage Metrics
There are various interesting system metrics about how Seldon Core 2 is used.
These metrics can be recorded anonymously and sent to Seldon by a lightweight, optional, stand-alone component called Hodometer.
When provided, these metrics will be used to understand the adoption of Seldon Core 2 and how people interact with it.
For example, knowing how many clusters Seldon Core 2 is running on, if it is used in Kubernetes or for local development, and how many people are benefitting from features like multi-model serving.
Architecture
Hodometer is not an integral part of Seldon Core 2, but rather an independent component which connects to the public APIs of the Seldon Core 2 scheduler.
If deployed in Kubernetes, it will also try to request some basic information from the Kubernetes API.
Recorded metrics are sent to Seldon and, optionally, to any additional endpoints you define.
Privacy
Hodometer was explicitly designed with privacy of user information and transparency of implementation in mind.
It does not record any sensitive or identifying information.
For example, it has no knowledge of IP addresses, model names, or user information.
All information sent to Seldon is anonymised with a completely random cluster identifier.
Hodometer supports different information levels, so you have full control over what metrics are provided to Seldon, if any.
For transparency, the implementation is fully open-source and designed to be easy to read.
The full source code is available here, with metrics defined in code here.
See below for an equivalent table of metrics.
Performance
Metrics are collected as periodic snapshots a few times per day.
They are lightweight to collect, coming mostly from the Seldon Core 2 scheduler, and are heavily aggregated.
As such, they should have minimal impact on CPU, memory, and network consumption.
Hodometer does not store anything it records, so does not have any persistent storage.
As a result, it should not be considered a replacement for tools like Prometheus.
Configuration
Metrics levels
Hodometer supports 3 different metrics levels:
| Level | Description |
|---|---|
| Cluster | Basic information about the Seldon Core 2 installation |
| Resource | High-level information about which Seldon Core 2 resources are used |
| Feature | More detailed information about how resources are used and whether or not certain feature flags are enabled |
Alternatively, usage metrics can be completely disabled.
To do so, simply remove any existing deployment of Hodometer or disable it in the installation for your environment, discussed below.
Options
The following environment variables control the behaviour of Hodometer, regardless of the environment it is installed in.
| Flag | Format | Example | Description |
|---|---|---|---|
METRICS_LEVEL |
string | feature | Level of detail for recorded metrics; one of feature, resource, or cluster |
EXTRA_PUBLISH_URLS |
comma-separated list of URLs | http://my-endpoint-1:8000,http://my-endpoint-2:8000 | Additional endpoints to publish metrics to |
SCHEDULER_HOST |
string | seldon-scheduler | Hostname for Seldon Core 2 scheduler |
SCHEDULER_PORT |
integer | 9004 | Port for Seldon Core 2 scheduler |
LOG_LEVEL |
string | info | Level of detail for application logs |
Kubernetes
Hodometer is installed as a separate deployment, by default in the same namespace as the rest of the Seldon components.
````{group-tab} Helm
If you install Seldon Core 2 by [Helm chart](../getting-started/kubernetes-installation/helm.md), there are values corresponding to the key environment variables discussed [above](#options).
These Helm values and their equivalents are provided below:
| Helm value | Environment variable |
| --- | --- |
| `hodometer.metricsLevel` | `METRICS_LEVEL` |
| `hodometer.extraPublishUrls` | `EXTRA_PUBLISH_URLS` |
| `hodometer.logLevel` | `LOG_LEVEL` |
If you do not want usage metrics to be recorded, you can disable Hodometer via the `hodometer.disable` Helm value when installing the runtime Helm chart.
The following command disables collection of usage metrics in fresh installations and also serves to remove Hodometer from an existing installation:
```bash
helm install seldon-v2-runtime k8s/helm-charts/seldon-core-v2-runtime \
--namespace seldon-mesh \
--set hodometer.disable=true
```
```{note}
It is a good practice to set Helm values in values file.
These can be applied by using the `-f <filename>` switch when running Helm.
```
````Docker Compose
The Compose setup provides a pre-configured and opinionated, yet still flexible, approach to using Seldon Core 2.
Hodometer is defined as a service called hodometer in the Docker Compose manifest.
It is automatically enabled when running as per the installation instructions.
You can disable Hodometer in Docker Compose by removing the corresponding service from the base manifest.
Alternatively, you can gate it behind a profile.
If the service is already running, you can stop it directly using docker-compose stop ....
Configuration can be provided by environment variables when running make or directly invoking docker-compose.
The available variables are defined in the Docker Compose environment file, prefixed with HODOMETER_.
Extra publish URLs
Hodometer can be instructed to publish metrics not only to Seldon, but also to any extra endpoints you specify.
This is controlled by the EXTRA_PUBLISH_URLS environment variable, which expects a comma-separated list of HTTP-compatible URLs.
You might choose to use this for your own usage monitoring.
For example, you could capture these metrics and expose them to Prometheus or another monitoring system using your own service.
Metrics are recorded in MixPanel-compatible format, which employs a highly flexible JSON schema.
For an example of how to define your own metrics listener, see the receiver Go package in the hodometer sub-project.
List of metrics
:start-after:
:end-before:Source Contents Apis Inference V2 (`docs/source/contents/apis/inference/v2.md`)
Open Inference Protocol
This page describes a predict/inference API independent of any
specific ML/DL framework and model server. These APIs are
able to support both easy-to-use and high-performance use cases.
By implementing this protocol both
inference clients and servers will increase their utility and
portability by being able to operate seamlessly on platforms that have
standardized around this API. This protocol is endorsed by NVIDIA
Triton Inference Server, TensorFlow Serving, and ONNX Runtime
Server. It is sometimes referred to by its old name "V2 Inference Protocol".
For an inference server to be compliant with this protocol the server
must implement all APIs described below, except where an optional
feature is explicitly noted. A compliant inference server may choose
to implement either or both of the HTTP/REST API and the GRPC API.
The protocol supports an extension mechanism as a required part of the
API, but this document does not propose any specific extensions. Any
specific extensions will be proposed separately.
HTTP/REST
A compliant server must implement the health, metadata, and inference
APIs described in this section.
The HTTP/REST API uses JSON because it is widely supported and
language independent. In all JSON schemas shown in this document
$number, $string, $boolean, $object and $array refer to the
fundamental JSON types. #optional indicates an optional JSON field.
All strings in all contexts are case-sensitive.
For Seldon a server must recognize the following URLs. The
versions portion of the URL is shown as optional to allow
implementations that don’t support versioning or for cases when the
user does not want to specify a specific model version (in which case
the server will choose a version based on its own policies).
Health:
GET v2/health/live
GET v2/health/ready
GET v2/models/${MODEL_NAME}[/versions/${MODEL_VERSION}]/readyServer Metadata:
GET v2Model Metadata:
GET v2/models/${MODEL_NAME}[/versions/${MODEL_VERSION}]Inference:
POST v2/models/${MODEL_NAME}[/versions/${MODEL_VERSION}]/inferHealth
A health request is made with an HTTP GET to a health endpoint. The
HTTP response status code indicates a boolean result for the health
request. A 200 status code indicates true and a 4xx status code
indicates false. The HTTP response body should be empty. There are
three health APIs.
Server Live
The “server live” API indicates if the inference server is able to
receive and respond to metadata and inference requests. The “server
live” API can be used directly to implement the Kubernetes
livenessProbe.
Server Ready
The “server ready” health API indicates if all the models are ready
for inferencing. The “server ready” health API can be used directly to
implement the Kubernetes readinessProbe.
Model Ready
The “model ready” health API indicates if a specific model is ready
for inferencing. The model name and (optionally) version must be
available in the URL. If a version is not provided the server may
choose a version based on its own policies.
Server Metadata
The server metadata endpoint provides information about the server. A
server metadata request is made with an HTTP GET to a server metadata
endpoint. In the corresponding response the HTTP body contains the
Server Metadata Response JSON Object
or the
Server Metadata Response JSON Error Object.
Server Metadata Response JSON Object
A successful server metadata request is indicated by a 200 HTTP status
code. The server metadata response object, identified as
$metadata_server_response, is returned in the HTTP body.
$metadata_server_response =
{
"name" : $string,
"version" : $string,
"extensions" : [ $string, ... ]
}- “name” : A descriptive name for the server.
- "version" : The server version.
- “extensions” : The extensions supported by the server. Currently no
standard extensions are defined. Individual inference servers may
define and document their own extensions.
Server Metadata Response JSON Error Object
A failed server metadata request must be indicated by an HTTP error
status (typically 400). The HTTP body must contain the
$metadata_server_error_response object.
$metadata_server_error_response =
{
"error": $string
}- “error” : The descriptive message for the error.
Model Metadata
The per-model metadata endpoint provides information about a model. A
model metadata request is made with an HTTP GET to a model metadata
endpoint. In the corresponding response the HTTP body contains the
Model Metadata Response JSON Object
or the
Model Metadata Response JSON Error Object.
The model name and (optionally) version must be available in the
URL. If a version is not provided the server may choose a version
based on its own policies or return an error.
Model Metadata Response JSON Object
A successful model metadata request is indicated by a 200 HTTP status
code. The metadata response object, identified as
$metadata_model_response, is returned in the HTTP body for every
successful model metadata request.
$metadata_model_response =
{
"name" : $string,
"versions" : [ $string, ... ] #optional,
"platform" : $string,
"inputs" : [ $metadata_tensor, ... ],
"outputs" : [ $metadata_tensor, ... ]
}- “name” : The name of the model.
- "versions" : The model versions that may be explicitly requested via
the appropriate endpoint. Optional for servers that don’t support
versions. Optional for models that don’t allow a version to be
explicitly requested. - “platform” : The framework/backend for the model. See
Platforms. - “inputs” : The inputs required by the model.
- “outputs” : The outputs produced by the model.
Each model input and output tensors’ metadata is described with a
$metadata_tensor object.
$metadata_tensor =
{
"name" : $string,
"datatype" : $string,
"shape" : [ $number, ... ]
}- “name” : The name of the tensor.
- "datatype" : The data-type of the tensor elements as defined in
Tensor Data Types. - "shape" : The shape of the tensor. Variable-size dimensions are
specified as -1.
Model Metadata Response JSON Error Object
A failed model metadata request must be indicated by an HTTP error
status (typically 400). The HTTP body must contain the
$metadata_model_error_response object.
$metadata_model_error_response =
{
"error": $string
}- “error” : The descriptive message for the error.
Inference
An inference request is made with an HTTP POST to an inference
endpoint. In the request the HTTP body contains the
Inference Request JSON Object. In
the corresponding response the HTTP body contains the
Inference Response JSON Object or
Inference Response JSON Error Object. See
Inference Request Examples for some
example HTTP/REST requests and responses.
Inference Request JSON Object
The inference request object, identified as $inference_request, is
required in the HTTP body of the POST request. The model name and
(optionally) version must be available in the URL. If a version is not
provided the server may choose a version based on its own policies or
return an error.
$inference_request =
{
"id" : $string #optional,
"parameters" : $parameters #optional,
"inputs" : [ $request_input, ... ],
"outputs" : [ $request_output, ... ] #optional
}- "id" : An identifier for this request. Optional, but if specified
this identifier must be returned in the response. - "parameters" : An object containing zero or more parameters for this
inference request expressed as key/value pairs. See
Parameters for more information. - "inputs" : The input tensors. Each input is described using the
$request_inputschema defined in Request Input. - "outputs" : The output tensors requested for this inference. Each
requested output is described using the$request_outputschema
defined in Request Output. Optional, if not
specified all outputs produced by the model will be returned using
default $request_output settings.
Request Input
The $request_input JSON describes an input to the model. If the
input is batched, the shape and data must represent the full shape and
contents of the entire batch.
$request_input =
{
"name" : $string,
"shape" : [ $number, ... ],
"datatype" : $string,
"parameters" : $parameters #optional,
"data" : $tensor_data
}- "name" : The name of the input tensor.
- "shape" : The shape of the input tensor. Each dimension must be an
integer representable as an unsigned 64-bit integer value. - "datatype" : The data-type of the input tensor elements as defined
in Tensor Data Types. - "parameters" : An object containing zero or more parameters for this
input expressed as key/value pairs. See Parameters
for more information. - “data”: The contents of the tensor. See Tensor Data
for more information.
Request Output
The $request_output JSON is used to request which output tensors
should be returned from the model.
$request_output =
{
"name" : $string,
"parameters" : $parameters #optional,
}- "name" : The name of the output tensor.
- "parameters" : An object containing zero or more parameters for this
output expressed as key/value pairs. See Parameters
for more information.
Inference Response JSON Object
A successful inference request is indicated by a 200 HTTP status
code. The inference response object, identified as
$inference_response, is returned in the HTTP body.
$inference_response =
{
"model_name" : $string,
"model_version" : $string #optional,
"id" : $string,
"parameters" : $parameters #optional,
"outputs" : [ $response_output, ... ]
}- "model_name" : The name of the model used for inference.
- "model_version" : The specific model version used for
inference. Inference servers that do not implement versioning should
not provide this field in the response. - "id" : The "id" identifier given in the request, if any.
- "parameters" : An object containing zero or more parameters for this
response expressed as key/value pairs. See Parameters
for more information. - "outputs" : The output tensors. Each output is described using the
$response_output schema defined in
Response Output.
Response Output
The $response_output JSON describes an output from the model. If the
output is batched, the shape and data represents the full shape of the
entire batch.
$response_output =
{
"name" : $string,
"shape" : [ $number, ... ],
"datatype" : $string,
"parameters" : $parameters #optional,
"data" : $tensor_data
}- "name" : The name of the output tensor.
- "shape" : The shape of the output tensor. Each dimension must be an
integer representable as an unsigned 64-bit integer value. - "datatype" : The data-type of the output tensor elements as defined
in Tensor Data Types. - "parameters" : An object containing zero or more parameters for this
input expressed as key/value pairs. See Parameters
for more information. - “data”: The contents of the tensor. See Tensor Data
for more information.
Inference Response JSON Error Object
A failed inference request must be indicated by an HTTP error status
(typically 400). The HTTP body must contain the
$inference_error_response object.
$inference_error_response =
{
"error": <error message string>
}- “error” : The descriptive message for the error.
Inference Request Examples
The following example shows an inference request to a model with two
inputs and one output. The HTTP Content-Length header gives the size
of the JSON object.
POST /v2/models/mymodel/infer HTTP/1.1
Host: localhost:8000
Content-Type: application/json
Content-Length: <xx>
{
"id" : "42",
"inputs" : [
{
"name" : "input0",
"shape" : [ 2, 2 ],
"datatype" : "UINT32",
"data" : [ 1, 2, 3, 4 ]
},
{
"name" : "input1",
"shape" : [ 3 ],
"datatype" : "BOOL",
"data" : [ true ]
}
],
"outputs" : [
{
"name" : "output0"
}
]
}For the above request the inference server must return the “output0”
output tensor. Assuming the model returns a [ 3, 2 ] tensor of data
type FP32 the following response would be returned.
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: <yy>
{
"id" : "42"
"outputs" : [
{
"name" : "output0",
"shape" : [ 3, 2 ],
"datatype" : "FP32",
"data" : [ 1.0, 1.1, 2.0, 2.1, 3.0, 3.1 ]
}
]
}Parameters
The $parameters JSON describes zero or more “name”/”value” pairs,
where the “name” is the name of the parameter and the “value” is a
$string, $number, or $boolean.
$parameters =
{
$parameter, ...
}
$parameter = $string : $string | $number | $booleanCurrently no parameters are defined. As required a future proposal may
define one or more standard parameters to allow portable functionality
across different inference servers. A server can implement
server-specific parameters to provide non-standard capabilities.
Tensor Data
Tensor data must be presented in row-major order of the tensor
elements. Element values must be given in "linear" order without any
stride or padding between elements. Tensor elements may be presented
in their nature multi-dimensional representation, or as a flattened
one-dimensional representation.
Tensor data given explicitly is provided in a JSON array. Each element
of the array may be an integer, floating-point number, string or
boolean value. The server can decide to coerce each element to the
required type or return an error if an unexpected value is
received. Note that fp16 is problematic to communicate explicitly
since there is not a standard fp16 representation across backends nor
typically the programmatic support to create the fp16 representation
for a JSON number.
For example, the 2-dimensional matrix:
[ 1 2
4 5 ]Can be represented in its natural format as:
"data" : [ [ 1, 2 ], [ 4, 5 ] ]Or in a flattened one-dimensional representation:
"data" : [ 1, 2, 4, 5 ]GRPC
The GRPC API closely follows the concepts defined in the
HTTP/REST API. A compliant server must implement the
health, metadata, and inference APIs described in this section.
All strings in all contexts are case-sensitive.
The GRPC definition of the service is:
//
// Inference Server GRPC endpoints.
//
service GRPCInferenceService
{
// Check liveness of the inference server.
rpc ServerLive(ServerLiveRequest) returns (ServerLiveResponse) {}
// Check readiness of the inference server.
rpc ServerReady(ServerReadyRequest) returns (ServerReadyResponse) {}
// Check readiness of a model in the inference server.
rpc ModelReady(ModelReadyRequest) returns (ModelReadyResponse) {}
// Get server metadata.
rpc ServerMetadata(ServerMetadataRequest) returns (ServerMetadataResponse) {}
// Get model metadata.
rpc ModelMetadata(ModelMetadataRequest) returns (ModelMetadataResponse) {}
// Perform inference using a specific model.
rpc ModelInfer(ModelInferRequest) returns (ModelInferResponse) {}
}Health
A health request is made using the ServerLive, ServerReady, or
ModelReady endpoint. For each of these endpoints errors are indicated
by the google.rpc.Status returned for the request. The OK code
indicates success and other codes indicate failure.
Server Live
The ServerLive API indicates if the inference server is able to
receive and respond to metadata and inference requests. The request
and response messages for ServerLive are:
message ServerLiveRequest {}
message ServerLiveResponse
{
// True if the inference server is live, false if not live.
bool live = 1;
}Server Ready
The ServerReady API indicates if the server is ready for
inferencing. The request and response messages for ServerReady are:
message ServerReadyRequest {}
message ServerReadyResponse
{
// True if the inference server is ready, false if not ready.
bool ready = 1;
}Model Ready
The ModelReady API indicates if a specific model is ready for
inferencing. The request and response messages for ModelReady are:
message ModelReadyRequest
{
// The name of the model to check for readiness.
string name = 1;
// The version of the model to check for readiness. If not given the
// server will choose a version based on the model and internal policy.
string version = 2;
}
message ModelReadyResponse
{
// True if the model is ready, false if not ready.
bool ready = 1;
}Server Metadata
The ServerMetadata API provides information about the server. Errors
are indicated by the google.rpc.Status returned for the request. The
OK code indicates success and other codes indicate failure. The
request and response messages for ServerMetadata are:
message ServerMetadataRequest {}
message ServerMetadataResponse
{
// The server name.
string name = 1;
// The server version.
string version = 2;
// The extensions supported by the server.
repeated string extensions = 3;
}Model Metadata
The per-model metadata API provides information about a model. Errors
are indicated by the google.rpc.Status returned for the request. The
OK code indicates success and other codes indicate failure. The
request and response messages for ModelMetadata are:
message ModelMetadataRequest
{
// The name of the model.
string name = 1;
// The version of the model to check for readiness. If not given the
// server will choose a version based on the model and internal policy.
string version = 2;
}
message ModelMetadataResponse
{
// Metadata for a tensor.
message TensorMetadata
{
// The tensor name.
string name = 1;
// The tensor data type.
string datatype = 2;
// The tensor shape. A variable-size dimension is represented
// by a -1 value.
repeated int64 shape = 3;
}
// The model name.
string name = 1;
// The versions of the model available on the server.
repeated string versions = 2;
// The model's platform. See Platforms.
string platform = 3;
// The model's inputs.
repeated TensorMetadata inputs = 4;
// The model's outputs.
repeated TensorMetadata outputs = 5;
}Inference
The ModelInfer API performs inference using the specified
model. Errors are indicated by the google.rpc.Status returned for the
request. The OK code indicates success and other codes indicate
failure. The request and response messages for ModelInfer are:
message ModelInferRequest
{
// An input tensor for an inference request.
message InferInputTensor
{
// The tensor name.
string name = 1;
// The tensor data type.
string datatype = 2;
// The tensor shape.
repeated int64 shape = 3;
// Optional inference input tensor parameters.
map<string, InferParameter> parameters = 4;
// The tensor contents using a data-type format. This field must
// not be specified if "raw" tensor contents are being used for
// the inference request.
InferTensorContents contents = 5;
}
// An output tensor requested for an inference request.
message InferRequestedOutputTensor
{
// The tensor name.
string name = 1;
// Optional requested output tensor parameters.
map<string, InferParameter> parameters = 2;
}
// The name of the model to use for inferencing.
string model_name = 1;
// The version of the model to use for inference. If not given the
// server will choose a version based on the model and internal policy.
string model_version = 2;
// Optional identifier for the request. If specified will be
// returned in the response.
string id = 3;
// Optional inference parameters.
map<string, InferParameter> parameters = 4;
// The input tensors for the inference.
repeated InferInputTensor inputs = 5;
// The requested output tensors for the inference. Optional, if not
// specified all outputs produced by the model will be returned.
repeated InferRequestedOutputTensor outputs = 6;
// The data contained in an input tensor can be represented in "raw"
// bytes form or in the repeated type that matches the tensor's data
// type. To use the raw representation 'raw_input_contents' must be
// initialized with data for each tensor in the same order as
// 'inputs'. For each tensor, the size of this content must match
// what is expected by the tensor's shape and data type. The raw
// data must be the flattened, one-dimensional, row-major order of
// the tensor elements without any stride or padding between the
// elements. Note that the FP16 data type must be represented as raw
// content as there is no specific data type for a 16-bit float
// type.
//
// If this field is specified then InferInputTensor::contents must
// not be specified for any input tensor.
repeated bytes raw_input_contents = 7;
}
message ModelInferResponse
{
// An output tensor returned for an inference request.
message InferOutputTensor
{
// The tensor name.
string name = 1;
// The tensor data type.
string datatype = 2;
// The tensor shape.
repeated int64 shape = 3;
// Optional output tensor parameters.
map<string, InferParameter> parameters = 4;
// The tensor contents using a data-type format. This field must
// not be specified if "raw" tensor contents are being used for
// the inference response.
InferTensorContents contents = 5;
}
// The name of the model used for inference.
string model_name = 1;
// The version of the model used for inference.
string model_version = 2;
// The id of the inference request if one was specified.
string id = 3;
// Optional inference response parameters.
map<string, InferParameter> parameters = 4;
// The output tensors holding inference results.
repeated InferOutputTensor outputs = 5;
// The data contained in an output tensor can be represented in
// "raw" bytes form or in the repeated type that matches the
// tensor's data type. To use the raw representation 'raw_output_contents'
// must be initialized with data for each tensor in the same order as
// 'outputs'. For each tensor, the size of this content must match
// what is expected by the tensor's shape and data type. The raw
// data must be the flattened, one-dimensional, row-major order of
// the tensor elements without any stride or padding between the
// elements. Note that the FP16 data type must be represented as raw
// content as there is no specific data type for a 16-bit float
// type.
//
// If this field is specified then InferOutputTensor::contents must
// not be specified for any output tensor.
repeated bytes raw_output_contents = 6;
}Parameters
The Parameters message describes a “name”/”value” pair, where the
“name” is the name of the parameter and the “value” is a boolean,
integer, or string corresponding to the parameter.
Currently no parameters are defined. As required a future proposal may
define one or more standard parameters to allow portable functionality
across different inference servers. A server can implement
server-specific parameters to provide non-standard capabilities.
//
// An inference parameter value.
//
message InferParameter
{
// The parameter value can be a string, an int64, a boolean
// or a message specific to a predefined parameter.
oneof parameter_choice
{
// A boolean parameter value.
bool bool_param = 1;
// An int64 parameter value.
int64 int64_param = 2;
// A string parameter value.
string string_param = 3;
}
}Tensor Data
In all representations tensor data must be flattened to a
one-dimensional, row-major order of the tensor elements. Element
values must be given in "linear" order without any stride or padding
between elements.
Using a "raw" representation of tensors with
ModelInferRequest::raw_input_contents and
ModelInferResponse::raw_output_contents will typically allow higher
performance due to the way protobuf allocation and reuse interacts
with GRPC. For example, see https://github.com/grpc/grpc/issues/23231.
An alternative to the "raw" representation is to use
InferTensorContents to represent the tensor data in a format that
matches the tensor's data type.
//
// The data contained in a tensor represented by the repeated type
// that matches the tensor's data type. Protobuf oneof is not used
// because oneofs cannot contain repeated fields.
//
message InferTensorContents
{
// Representation for BOOL data type. The size must match what is
// expected by the tensor's shape. The contents must be the flattened,
// one-dimensional, row-major order of the tensor elements.
repeated bool bool_contents = 1;
// Representation for INT8, INT16, and INT32 data types. The size
// must match what is expected by the tensor's shape. The contents
// must be the flattened, one-dimensional, row-major order of the
// tensor elements.
repeated int32 int_contents = 2;
// Representation for INT64 data types. The size must match what
// is expected by the tensor's shape. The contents must be the
// flattened, one-dimensional, row-major order of the tensor elements.
repeated int64 int64_contents = 3;
// Representation for UINT8, UINT16, and UINT32 data types. The size
// must match what is expected by the tensor's shape. The contents
// must be the flattened, one-dimensional, row-major order of the
// tensor elements.
repeated uint32 uint_contents = 4;
// Representation for UINT64 data types. The size must match what
// is expected by the tensor's shape. The contents must be the
// flattened, one-dimensional, row-major order of the tensor elements.
repeated uint64 uint64_contents = 5;
// Representation for FP32 data type. The size must match what is
// expected by the tensor's shape. The contents must be the flattened,
// one-dimensional, row-major order of the tensor elements.
repeated float fp32_contents = 6;
// Representation for FP64 data type. The size must match what is
// expected by the tensor's shape. The contents must be the flattened,
// one-dimensional, row-major order of the tensor elements.
repeated double fp64_contents = 7;
// Representation for BYTES data type. The size must match what is
// expected by the tensor's shape. The contents must be the flattened,
// one-dimensional, row-major order of the tensor elements.
repeated bytes bytes_contents = 8;
}Platforms
A platform is a string indicating a DL/ML framework or
backend. Platform is returned as part of the response to a
Model Metadata request but is information only. The
proposed inference APIs are generic relative to the DL/ML framework
used by a model and so a client does not need to know the platform of
a given model to use the API. Platform names use the format
“
- tensorrt_plan : A TensorRT model encoded as a serialized engine or “plan”.
- tensorflow_graphdef : A TensorFlow model encoded as a GraphDef.
- tensorflow_savedmodel : A TensorFlow model encoded as a SavedModel.
- onnx_onnxv1 : A ONNX model encoded for ONNX Runtime.
- pytorch_torchscript : A PyTorch model encoded as TorchScript.
- mxnet_mxnet: An MXNet model
- caffe2_netdef : A Caffe2 model encoded as a NetDef.
Tensor Data Types
Tensor data types are shown in the following table along with the size
of each type, in bytes.
| Data Type | Size (bytes) |
|---|---|
| BOOL | 1 |
| UINT8 | 1 |
| UINT16 | 2 |
| UINT32 | 4 |
| UINT64 | 8 |
| INT8 | 1 |
| INT16 | 2 |
| INT32 | 4 |
| INT64 | 8 |
| FP16 | 2 |
| FP32 | 4 |
| FP64 | 8 |
| BYTES | Variable (max 232) |
References
This document is based on the KServe original created during the lifetime of the KFServing project in Kubeflow by its various contributors including Seldon, NVIDIA, IBM, Bloomberg and others.
Source Contents Apis Internal Agent (`docs/source/contents/apis/internal/agent.md`)
Agent API
This API is for communication between the Seldon Scheduler and the Seldon Agent which runs next to each inference server and manages the loading and unloading of models onto the server as well as acting as a reverse proxy in the data plane for handling requests to the inference server.
Proto Definition
:language: protoSource Contents Apis Internal Chainer (`docs/source/contents/apis/internal/chainer.md`)
Chainer API
This API is for communication between the Seldon Scheduler and the Seldon dataflow component which manages pipelines.
Proto Definition
:language: protoSource Contents Cli Docs Seldon (`docs/source/contents/cli/docs/seldon.md`)
seldon
Options
-h, --help help for seldonSEE ALSO
- seldon config - manage configs
- seldon experiment - manage experiments
- seldon model - manage models
- seldon pipeline - manage pipelines
- seldon server - manage servers
Source Contents Cli Docs Seldon Config (`docs/source/contents/cli/docs/seldon_config.md`)
seldon config
manage configs
Synopsis
Manage and activate configuration files for the CLI
seldon config <subcomand> [flags]Options
-h, --help help for configSEE ALSO
- seldon -
- seldon config activate - activate config
- seldon config add - add config
- seldon config deactivate - deactivate config
- seldon config list - list configs
- seldon config remove - remove config
Source Contents Cli Docs Seldon Config Activate (`docs/source/contents/cli/docs/seldon_config_activate.md`)
seldon config activate
activate config
Synopsis
activate config
seldon config activate [flags]Options
-h, --help help for activateSEE ALSO
- seldon config - manage configs
Source Contents Cli Docs Seldon Config Add (`docs/source/contents/cli/docs/seldon_config_add.md`)
seldon config add
add config
Synopsis
add config
seldon config add [flags]Options
-h, --help help for addSEE ALSO
- seldon config - manage configs
Source Contents Cli Docs Seldon Config Deactivate (`docs/source/contents/cli/docs/seldon_config_deactivate.md`)
seldon config deactivate
deactivate config
Synopsis
deactivate config
seldon config deactivate [flags]Options
-h, --help help for deactivateSEE ALSO
- seldon config - manage configs
Source Contents Cli Docs Seldon Config List (`docs/source/contents/cli/docs/seldon_config_list.md`)
seldon config list
list configs
Synopsis
list configs
seldon config list [flags]Options
-h, --help help for listSEE ALSO
- seldon config - manage configs
Source Contents Cli Docs Seldon Config Remove (`docs/source/contents/cli/docs/seldon_config_remove.md`)
seldon config remove
remove config
Synopsis
remove config
seldon config remove [flags]Options
-h, --help help for removeSEE ALSO
- seldon config - manage configs
Source Contents Cli Docs Seldon Experiment (`docs/source/contents/cli/docs/seldon_experiment.md`)
seldon experiment
manage experiments
Synopsis
experiments allow you to test models by splitting traffic between candidates.
seldon experiment <subcomand> [flags]Options
-h, --help help for experimentSEE ALSO
- seldon -
- seldon experiment list - get list of experiments
- seldon experiment start - start an experiment
- seldon experiment status - get status for experiment
- seldon experiment stop - stop an experiment
Source Contents Cli Docs Seldon Experiment List (`docs/source/contents/cli/docs/seldon_experiment_list.md`)
seldon experiment list
get list of experiments
Synopsis
get list of experiments and whether they are active
seldon experiment list [flags]Options
--authority string authority (HTTP/2) or virtual host (HTTP/1)
-h, --help help for list
--scheduler-host string seldon scheduler host (default "0.0.0.0:9004")SEE ALSO
- seldon experiment - manage experiments
Source Contents Cli Docs Seldon Experiment Start (`docs/source/contents/cli/docs/seldon_experiment_start.md`)
seldon experiment start
start an experiment
Synopsis
start an experiment
seldon experiment start [flags]Options
--authority string authority (HTTP/2) or virtual host (HTTP/1)
-f, --file-path string experiment manifest file (YAML)
-h, --help help for start
--scheduler-host string seldon scheduler host (default "0.0.0.0:9004")
-r, --show-request show request
-o, --show-response show response (default true)SEE ALSO
- seldon experiment - manage experiments
Source Contents Cli Docs Seldon Experiment Status (`docs/source/contents/cli/docs/seldon_experiment_status.md`)
seldon experiment status
get status for experiment
Synopsis
get status for experiment
seldon experiment status <experimentName> [flags]Options
--authority string authority (HTTP/2) or virtual host (HTTP/1)
-h, --help help for status
--scheduler-host string seldon scheduler host (default "0.0.0.0:9004")
-r, --show-request show request
-o, --show-response show response (default true)
-w, --wait wait for experiment to be activeSEE ALSO
- seldon experiment - manage experiments
Source Contents Cli Docs Seldon Experiment Stop (`docs/source/contents/cli/docs/seldon_experiment_stop.md`)
seldon experiment stop
stop an experiment
Synopsis
stop an experiment
seldon experiment stop <experimentName> [flags]Options
--authority string authority (HTTP/2) or virtual host (HTTP/1)
-h, --help help for stop
--scheduler-host string seldon scheduler host (default "0.0.0.0:9004")
-r, --show-request show request
-o, --show-response show response (default true)SEE ALSO
- seldon experiment - manage experiments
Source Contents Cli Docs Seldon Model (`docs/source/contents/cli/docs/seldon_model.md`)
seldon model
manage models
Synopsis
load and unload and get status for models
seldon model <subcomand> [flags]Options
-h, --help help for modelSEE ALSO
- seldon -
- seldon model infer - run inference on a model
- seldon model list - get list of models
- seldon model load - load a model
- seldon model metadata - get model metadata
- seldon model status - get status for model
- seldon model unload - unload a model
Source Contents Cli Docs Seldon Model Infer (`docs/source/contents/cli/docs/seldon_model_infer.md`)
seldon model infer
run inference on a model
Synopsis
call a model with a given input and get a prediction
seldon model infer <modelName> (data) [flags]Options
--authority string authority (HTTP/2) or virtual host (HTTP/1)
-f, --file-path string inference payload file
--header stringArray add a header, e.g. key=value; use the flag multiple times to add more than one header
-h, --help help for infer
--inference-host string seldon inference host (default "0.0.0.0:9000")
--inference-mode string inference mode (rest or grpc) (default "rest")
-i, --iterations int how many times to run inference (default 1)
-t, --seconds int number of secs to run inference
--show-headers show request and response headers
-r, --show-request show request
-o, --show-response show response (default true)
-s, --sticky-session use sticky session from last inference (only works with experiments)SEE ALSO
- seldon model - manage models
Source Contents Cli Docs Seldon Model List (`docs/source/contents/cli/docs/seldon_model_list.md`)
seldon model list
get list of models
Synopsis
get the list of all models with their status
seldon model list [flags]Options
--authority string authority (HTTP/2) or virtual host (HTTP/1)
-h, --help help for list
--scheduler-host string seldon scheduler host (default "0.0.0.0:9004")SEE ALSO
- seldon model - manage models
Source Contents Cli Docs Seldon Model Load (`docs/source/contents/cli/docs/seldon_model_load.md`)
seldon model load
load a model
Synopsis
load a model
seldon model load [flags]Options
--authority string authority (HTTP/2) or virtual host (HTTP/1)
-f, --file-path string model manifest file (YAML)
-h, --help help for load
--scheduler-host string seldon scheduler host (default "0.0.0.0:9004")
-r, --show-request show request
-o, --show-response show response (default true)SEE ALSO
- seldon model - manage models
Source Contents Cli Docs Seldon Model Metadata (`docs/source/contents/cli/docs/seldon_model_metadata.md`)
seldon model metadata
get model metadata
Synopsis
get model metadata
seldon model metadata <modelName> [flags]Options
--authority string authority (HTTP/2) or virtual host (HTTP/1)
-h, --help help for metadata
--inference-host string seldon inference host (default "0.0.0.0:9000")SEE ALSO
- seldon model - manage models
Source Contents Cli Docs Seldon Model Status (`docs/source/contents/cli/docs/seldon_model_status.md`)
seldon model status
get status for model
Synopsis
get the status for a model
seldon model status <modelName> [flags]Options
--authority string authority (HTTP/2) or virtual host (HTTP/1)
-h, --help help for status
--scheduler-host string seldon scheduler host (default "0.0.0.0:9004")
-r, --show-request show request
-o, --show-response show response (default true)
-w, --wait string model wait conditionSEE ALSO
- seldon model - manage models
Source Contents Cli Docs Seldon Model Unload (`docs/source/contents/cli/docs/seldon_model_unload.md`)
seldon model unload
unload a model
Synopsis
unload a model
seldon model unload <modelName> [flags]Options
--authority string authority (HTTP/2) or virtual host (HTTP/1)
-h, --help help for unload
--scheduler-host string seldon scheduler host (default "0.0.0.0:9004")
-r, --show-request show request
-o, --show-response show response (default true)SEE ALSO
- seldon model - manage models
Source Contents Cli Docs Seldon Pipeline (`docs/source/contents/cli/docs/seldon_pipeline.md`)
seldon pipeline
manage pipelines
Synopsis
pipelines allow you to join models together into inference graphs.
seldon pipeline <subcomand> [flags]Options
-h, --help help for pipelineSEE ALSO
- seldon -
- seldon pipeline infer - run inference on a pipeline
- seldon pipeline inspect - inspect data in a pipeline
- seldon pipeline list - list pipelines
- seldon pipeline load - load a pipeline
- seldon pipeline status - status of a pipeline
- seldon pipeline unload - unload a pipeline
Source Contents Cli Docs Seldon Pipeline Infer (`docs/source/contents/cli/docs/seldon_pipeline_infer.md`)
seldon pipeline infer
run inference on a pipeline
Synopsis
call a pipeline with a given input and get a prediction
seldon pipeline infer (data) [flags]Options
--authority string authority (HTTP/2) or virtual host (HTTP/1)
-f, --file-path string inference payload file
--header stringArray add a header, e.g. key=value; use the flag multiple times to add more than one header
-h, --help help for infer
--inference-host string seldon inference host (default "0.0.0.0:9000")
--inference-mode string inference mode (rest or grpc) (default "rest")
-i, --iterations int how many times to run inference (default 1)
-t, --seconds int number of secs to run inference
--show-headers show request and response headers
-r, --show-request show request
-o, --show-response show response (default true)
-s, --sticky-session use sticky session from last inference (only works with experiments)SEE ALSO
- seldon pipeline - manage pipelines
Source Contents Cli Docs Seldon Pipeline Inspect (`docs/source/contents/cli/docs/seldon_pipeline_inspect.md`)
seldon pipeline inspect
inspect data in a pipeline
Synopsis
inspect data in a pipeline. Specify as pipelineName or pipelineName.(inputs|outputs) or pipelineName.stepName or pipelineName.stepName.(inputs|outputs) or pipelineName.stepName.(inputs|outputs).tensorName
seldon pipeline inspect <expression> [flags]Options
--format string inspect output format: raw or json. Default raw (default "raw")
-h, --help help for inspect
--kafka-broker string kafka broker (default "0.0.0.0:9092")
--namespace string Kubernetes namespace. Default default (default "default")
--offset int message offset to start reading from, i.e. default 1 is the last message only (default 1)
--request-id string request id to show, if not specified will be all messages in offset range
--scheduler-host string seldon scheduler host (default "0.0.0.0:9004")
--verbose display more details, such as headersSEE ALSO
- seldon pipeline - manage pipelines
Source Contents Cli Docs Seldon Pipeline List (`docs/source/contents/cli/docs/seldon_pipeline_list.md`)
seldon pipeline list
list pipelines
Synopsis
list pipelines
seldon pipeline list [flags]Options
--authority string authority (HTTP/2) or virtual host (HTTP/1)
-h, --help help for list
--scheduler-host string seldon scheduler host (default "0.0.0.0:9004")SEE ALSO
- seldon pipeline - manage pipelines
Source Contents Cli Docs Seldon Pipeline Load (`docs/source/contents/cli/docs/seldon_pipeline_load.md`)
seldon pipeline load
load a pipeline
Synopsis
load a pipeline
seldon pipeline load [flags]Options
--authority string authority (HTTP/2) or virtual host (HTTP/1)
-f, --file-path string pipeline manifest file (YAML)
-h, --help help for load
--scheduler-host string seldon scheduler host (default "0.0.0.0:9004")
-r, --show-request show request
-o, --show-response show response (default true)SEE ALSO
- seldon pipeline - manage pipelines
Source Contents Cli Docs Seldon Pipeline Status (`docs/source/contents/cli/docs/seldon_pipeline_status.md`)
seldon pipeline status
status of a pipeline
Synopsis
status of a pipeline
seldon pipeline status [flags]Options
--authority string authority (HTTP/2) or virtual host (HTTP/1)
-h, --help help for status
--scheduler-host string seldon scheduler host (default "0.0.0.0:9004")
-r, --show-request show request
-o, --show-response show response (default true)
-w, --wait string pipeline wait conditionSEE ALSO
- seldon pipeline - manage pipelines
Source Contents Cli Docs Seldon Pipeline Unload (`docs/source/contents/cli/docs/seldon_pipeline_unload.md`)
seldon pipeline unload
unload a pipeline
Synopsis
unload a pipeline
seldon pipeline unload [flags]Options
--authority string authority (HTTP/2) or virtual host (HTTP/1)
-h, --help help for unload
--scheduler-host string seldon scheduler host (default "0.0.0.0:9004")
-r, --show-request show request
-o, --show-response show response (default true)SEE ALSO
- seldon pipeline - manage pipelines
Source Contents Cli Docs Seldon Server (`docs/source/contents/cli/docs/seldon_server.md`)
seldon server
manage servers
Synopsis
get status for servers
seldon server <subcomand> [flags]Options
-h, --help help for serverSEE ALSO
- seldon -
- seldon server list - get list of servers
- seldon server status - get status for server
Source Contents Cli Docs Seldon Server List (`docs/source/contents/cli/docs/seldon_server_list.md`)
seldon server list
get list of servers
Synopsis
get the available servers, their replicas and loaded models
seldon server list [flags]Options
--authority string authority (HTTP/2) or virtual host (HTTP/1)
-h, --help help for list
--scheduler-host string seldon scheduler host (default "0.0.0.0:9004")SEE ALSO
- seldon server - manage servers
Source Contents Cli Docs Seldon Server Status (`docs/source/contents/cli/docs/seldon_server_status.md`)
seldon server status
get status for server
Synopsis
get the status for a server
seldon server status [flags]Options
--authority string authority (HTTP/2) or virtual host (HTTP/1)
-h, --help help for status
--scheduler-host string seldon scheduler host (default "0.0.0.0:9004")
-r, --show-request show request
-o, --show-response show response (default true)SEE ALSO
- seldon server - manage servers
Source Contents Getting Started Kubernetes Installation Helm (`docs/source/contents/getting-started/kubernetes-installation/helm.md`)
Helm Installation
We provide several Helm charts.
seldon-core-v2-crds: cluster wide install of custom resources.seldon-core-v2-setup: installation of the manager to manage resources in the namespace or clusterwide. This also installs default SeldonConfig and ServerConfig resources which allow Runtimes and Servers to be installed easily on demand.seldon-core-v2-runtime: this installs a SeldonRuntime custom resource which creates the core components in a namespace.seldon-core-v2-servers: this installs Server custom resources which provide example core servers to load models.seldon-core-v2-certs: a default set of certificates for TLS.
The Helm charts can be found within the k8s/helm-charts folder and they are published here
Assuming you have installed any ecosystem components: Jaeger, Prometheus, Kafka as discussed here you can follow the
following steps.
Note that for Kafka follow the steps discussed here
Add Seldon Core 2 Charts
helm repo add seldon-charts https://seldonio.github.io/helm-charts
helm repo update seldon-chartsInstall the CRDs
helm install seldon-core-v2-crds seldon-charts/seldon-core-v2-crdsInstall the Seldon Core 2 Components
You can install into any namespace. For illustration we will use seldon-mesh. This will install the core manager which will handle the key resources used by Seldon including the SeldonRuntime and Server resources.
kubectl create namespace seldon-meshhelm install seldon-core-v2 seldon-charts/seldon-core-v2-setup --namespace seldon-meshThis will install the operator namespaced so it will only control resources in the provided namespace. To allow cluster wide usage add the --set controller.clusterwide=true, e.g.
helm install seldon-core-v2 seldon-charts/seldon-core-v2-setup --namespace seldon-mesh --set controller.clusterwide=trueCluster wide operations will require ClusterRoles to be created so when deploying be aware your user will require the required permissions. With cluster wide operations you can create SeldonRuntimes in any namespace.
Install the default Seldon Core 2 Runtime
helm install seldon-v2-runtime seldon-charts/seldon-core-v2-runtime --namespace seldon-meshThis will install the core components in your desired namespace.
Install example servers
To install some MLServer and Triton servers you can either create Server resources yourself or for initial testing you can use our example Helm chart seldon-core-v2-servers:
helm install seldon-v2-servers seldon-charts/seldon-core-v2-servers --namespace seldon-meshBy default this will install 1 MLServer and 1 Triton in the desired namespace. This namespace should be the same namespace you installed a Seldon Core Runtime.
Uninstall
Remove any models, pipelines that are running.
Remove the runtime:
helm uninstall seldon-core-v2-runtime --namespace seldon-meshRemove the core components:
helm uninstall seldon-core-v2 --namespace seldon-meshRemove the CRDs
helm uninstall seldon-core-v2-crdsSource Contents Kubernetes Autoscaling Hpa Rps Autoscaling (`docs/source/contents/kubernetes/autoscaling/hpa-rps-autoscaling.md`)
Autoscaling single-model serving based on model RPS, using HorizontalPodAutoscaler
The goal is to autoscale model and server replicas based on model inference RPS. This will require:
- Having a Seldon Core 2 install that publishes metrics to prometheus (default). In the following, we will assume that prometheus is already installed and configured in the
seldon-monitoringnamespace. - Installing and configuring Prometheus Adapter, which allows prometheus queries on relevant metrics to be published as k8s custom metrics
- Configuring HPA manifests to scale Models and the corresponding Server replicas based on the custom metrics
Installing and configuring the Prometheus Adapter
The role of the Prometheus Adapter is to expose queries on metrics in prometheus as k8s custom or external metrics. Those can then be accessed by HPA in order to take scaling decisions.
To install via helm:
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install --set prometheus.url='http://seldon-monitoring-prometheus' hpa-metrics prometheus-community/prometheus-adapter -n seldon-monitoringIn the commands above, we install prometheus-adapter as a helm release named hpa-metrics in the same namespace as our prometheus install, and point to its service URL (without the port).
If running prometheus on a different port than the default 9090, you can also pass --set prometheus.port=[custom_port] You may inspect all the options available as helm values by running helm show values prometheus-community/prometheus-adapter
We now need to configure the adapter to look for the correct prometheus metrics and compute per-model RPS values. On install, the adapter has created a ConfigMap in the same namespace as itself, named [helm_release_name]-prometheus-adapter. In our case, it will be hpa-metrics-prometheus-adapter.
We want to overwrite this ConfigMap with the content below (please change the name if your helm release has a different one). The manifest contains embedded documentation, highlighting how we match the seldon_model_infer_total metric in Prometheus, compute a rate via a metricsQuery and expose this to k8s as the infer_rps metric, on a per (model, namespace) basis.
Other aggregations on per (server, namespace) and (pod, namespace) are also exposed and may be used in HPA, but we will focus on the (model, namespace) aggregation in the examples below.
You may want to modify some of the settings to match the prometheus query that you typically use for RPS metrics. For example, the metricsQuery below computes the RPS by calling rate() with a 1 minute window.
/* Detailed source-code truncated for AI context efficiency. */# kubectl get --raw
# "/apis/custom.metrics.k8s.io/v1beta1/namespaces/[NAMESPACE]/[RESOURCE_NAME]/[CR_NAME]/infer_rps"
# ```
#
# For example:
# ```
# kubectl get --raw
# "/apis/custom.metrics.k8s.io/v1beta1/namespaces/seldon-mesh/models.mlops.seldon.io/iris0/infer_rps"
# ```
#
# For the namespace resource, you can get the namespace-level aggregation of the metric with:
# ```
# kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/*/metrics/infer_rps"
# ```/* Detailed source-code truncated for AI context efficiency. */
Apply the config, and restart the prometheus adapter deployment (this restart is required so that prometheus-adapter picks up the new config):
```bash
# Apply prometheus adapter config
kubectl apply -f prometheus-adapter.config.yaml
# Restart prom-adapter pods
kubectl rollout restart deployment hpa-metrics-prometheus-adapter -n seldon-monitoringIn order to test that the prometheus adapter config works and everything is set up correctly, you can issue raw kubectl requests against the custom metrics API, as described below.
If no inference requests were issued towards any model in the Seldon install, the metrics configured above will not be available in prometheus, and thus will also not appear when checking via the commands below. Therefore, please first run some inference requests towards a sample model to ensure that the metrics are available — this is only required for the testing of the install.
Testing the prometheus-adapter install using the custom metrics API
List available metrics
kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/ | jq .Fetching model RPS metric for specific (namespace, model) pair:
kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/namespaces/seldon-mesh/models.mlops.seldon.io/irisa0/infer_rpsFetching model RPS metric aggregated at the (namespace, server) level:
kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/namespaces/seldon-mesh/servers.mlops.seldon.io/mlserver/infer_rpsFetching model RPS metric aggregated at the (namespace, pod) level:
kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/namespaces/seldon-mesh/pods/mlserver-0/infer_rpsFetching the same metric aggregated at namespace level:
kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/namespaces/*/metrics/infer_rpsConfiguring HPA manifests
For every (Model, Server) pair you want to autoscale, you need to apply 2 HPA manifests based on the same metric: one scaling the Model, the other the Server. The example below only works if the mapping between Models and Servers is 1-to-1 (i.e no multi-model serving).
Consider a model named irisa0 with the following manifest. Please note we don’t set minReplicas/maxReplicas this is in order to disable the seldon-specific autoscaling so that it doesn’t interact with HPA.
apiVersion: mlops.seldon.io/v1alpha1
kind: Model
metadata:
name: irisa0
namespace: seldon-mesh
spec:
memory: 3M
replicas: 1
requirements:
- sklearn
storageUri: gs://seldon-models/testing/iris1Let’s scale this model when it is deployed on a server named mlserver, with a target RPS per replica of 3 RPS (higher RPS would trigger scale-up, lower would trigger scale-down):
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: irisa0-model-hpa
namespace: seldon-mesh
spec:
scaleTargetRef:
apiVersion: mlops.seldon.io/v1alpha1
kind: Model
name: irisa0
minReplicas: 1
maxReplicas: 3
metrics:
- type: Object
object:
metric:
name: infer_rps
describedObject:
apiVersion: mlops.seldon.io/v1alpha1
kind: Model
name: irisa0
target:
type: AverageValue
averageValue: 3
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: mlserver-server-hpa
namespace: seldon-mesh
spec:
scaleTargetRef:
apiVersion: mlops.seldon.io/v1alpha1
kind: Server
name: mlserver
minReplicas: 1
maxReplicas: 3
metrics:
- type: Object
object:
metric:
name: infer_rps
describedObject:
apiVersion: mlops.seldon.io/v1alpha1
kind: Model
name: irisa0
target:
type: AverageValue
averageValue: 3In the two HPA manifests above, the scaling metric is exactly the same, and uses the exact same parameters: this is to ensure that both the Models and the Servers are scaled up/down at approximately the same time. Small variations in the scale-up time are expected because each HPA samples the metrics independently, at regular intervals. If a Model gets scaled up slightly before its corresponding Server, the model is currently marked with the condition ModelReady "Status: False" with a "ScheduleFailed" message until new Server replicas become available. However, the existing replicas of that model remain available and will continue to serve inference load.
In order to ensure similar scaling behaviour between Models and Servers, the number of minReplicas and maxReplicas defined in the HPA, as well as other scaling policies configured should be kept in sync across the HPA for the model and the server.
Please note that you must use a target.type of AverageValue. The value given inaverageValue is the threshold RPS per replica, and the new (scaled) number of replicas is computed by HPA according
to the following formula:
$$\texttt{targetReplicas} = \frac{\texttt{infer_rps}}{\texttt{thresholdPerReplicaRPS}}$$
Attempting other target types will not work under the current Seldon Core 2 setup, because they use the number of active Pods associated with the Model CR (i.e. the associated Server pods) in the targetReplicas computation. However, this also means that this set of pods becomes "owned" by the Model HPA. Once a pod is owned by a given HPA it is not available for other HPAs to use, so we would no longer be able to scale the Server CRs using HPA.
Advanced settings:
Filtering metrics by other labels on the prometheus metric
The prometheus metric from which the model RPS is computed has the following labels:
yamlseldon_model_infer_total{**code**="200", **container**="agent", **endpoint**="metrics", **instance**="10.244.0.39:9006", **job**="seldon-mesh/agent", **method_type**="rest", **model**="irisa0", **model_internal**="irisa0_1", **namespace**="seldon-mesh", **pod**="mlserver-0", **server**="mlserver", **server_replica**="0"}If we wanted the scaling metric to be computed based on inferences with a particular value for those metrics, we can add this in the HPA metric config, as in the example below (targeting
method_type="rest"):yamlmetrics: - type: Object object: describedObject: apiVersion: mlops.seldon.io/v1alpha1 kind: Model name: irisa0 metric: name: infer_rps selector: matchLabels: method_type: rest target: type: AverageValue averageValue: "3"Customise scale-up / scale-down rate & properties by using scaling policies as described in the HPA scaling policies docs
For more resources, please consult the HPA docs and the HPA walkthrough
Source Contents Models Mms Mms (`docs/source/contents/models/mms/mms.md`)
Multi-model Serving with Overcommit
Multi-model Serving
Multi-model serving is an architecture pattern where one ML inference server hosts multiple models at the same time. This means that, within a single instance of the server, you can serve multiple models under different paths. This is a feature provided out of the box by Nvidia Triton and Seldon MLServer, currently the two inference servers that are integrated in Seldon Core 2.
This deployment pattern allows the system to handle a large number of deployed models letting them share hardware resources allocated to inference servers (e.g GPUs). For example if a single model inference server is deployed on a one GPU node, the underlying loaded models on this inference server instance are able to effectively share this GPU. This is contrast to a single model per server deployment pattern where only one model can use the allocated GPU.
Multi-model serving is enabled by design in Seldon Core 2. Based on requirements that are specified by the user on a given Model, the Scheduler will find an appropriate model inference server instance to load the model onto.
In the below example, given that the model is tensorflow, the system will deploy the model onto a triton server instance (matching with the Server labels). Additionally as the model memory requirement is 100Ki, the system will pick the server instance that has enough (memory) capacity to host this model in parallel to other potentially existing models.
:language: yamlAll models are loaded and active on this model server. Inference requests for these models are served concurrently and the hardware resources are shared to fulfil these inference requests.
Overcommit
Overcommit allows shared servers to handle more models than can fit in memory. This is done by keeping highly utilized models in memory and evicting other ones to disk using a least-recently-used (LRU) cache mechanism. From a user perspective these models are all registered and "ready" to serve inference requests. If an inference request comes for a model that is unloaded/evicted to disk, the system will reload the model first before forwarding the request to the inference server.
Overcommit is enabled by setting SELDON_OVERCOMMIT_PERCENTAGE on shared servers; it is set by default at 10%. In other words a given model inference server instance can register models with a total memory requirement up to MEMORY_REQUEST * ( 1 + SELDON_OVERCOMMIT_PERCENTAGE / 100).
The Seldon Agent (a side car next to each model inference server deployment) is keeping track of inference requests times on the different models. These models are sorted in time ascending order and this data structure is used to evict the least recently used model in order to make room for another incoming model. This happens during two scenarios:
- A new model load request beyond the active memory capacity of the inference server.
- An incoming inference request to a registered model that is not loaded in-memory (previously evicted).
This is done seamlessly to users and specifically for reloading a model onto the inference server to respond to an inference request, the model artifact is cached on disk which allows a faster reload (no remote artifact fetch). Therefore we expect that the extra latency to reload a model during an inference request is acceptable in many cases (with a lower bound of ~100ms).
Overcommit can be disabled by setting SELDON_OVERCOMMIT_PERCENTAGE to 0 for a given shared server.
Note: currently we are using memory requirement values that are specified by the user on the Server and Model side. In the future we are looking at how to make the system automatically handle memory management.
Check notebook for a local example.
Source Contents Models Parameterized Models Pandasquery (`docs/source/contents/models/parameterized-models/pandasquery.md`)
Pandas Query Model
This model allows a Pandas query to be run in the input to select rows. An example is shown below:
:language: yamlThis invocation check filters for tensor A having value 1.
- The model also returns a tensor called
statuswhich indicates the operation run and whether it was a success. If no rows satisfy the query then just astatustensor output will be returned. - Further details on Pandas query can be found here
This model can be useful for conditional Pipelines. For example, you could have two invocations of this model:
:language: yamland
:language: yamlBy including these in a Pipeline as follows we can define conditional routes:
:language: yamlHere the mul10 model will be called if the choice-is-one model succeeds and the add10 model will be called if the choice-is-two model succeeds.
The full notebook can be found here
Source Contents Getting Started Kubernetes Installation Security Aws Msk Mtls (`docs/source/contents/getting-started/kubernetes-installation/security/aws-msk-mtls.md`)
AWS MSK mTLS
Seldon will run with AWS MSK.
At present we support mTLS authentication to MSK which can be run from a Kubernetes cluster inside or outside Amazon. If running outside your MSK cluster must have a public endpoint.
Considerations
Public Access to MSK Cluster
If you running your Kubernetes cluster outside AWS you will need to create a public accessible MSK cluster.
You will need to setup Kafka ACLs for your user where the username is the CommonName of the certificate of the client and allow full topic access. For example, to add a user with CN=myname to have full operations using the kafka-acls script with mTLS config setup as described in AWS MSK docs:
kafka-acls.sh --bootstrap-server <mTLS endpoint> --add --allow-principal User:CN=myname --operation All --topic '*' --command-config client.propertiesYou will also need to allow the connecting user to be able to perform admin tasks on the cluster so we can create topics on demand.
kafka-acls.sh --bootstrap-server <nTLS endpoint> --add --allow-principal User:CN=myname --operation All --cluster '*' --command-config client.propertiesYou will need to allow group access also.
kafka-acls.sh --bootstrap-server <mTKS endpoint> --add --allow-principal User:CN=myname --operation All --group '*' --command-config client.propertiesCreate TLS Kubernetes Secrets
Create a secret for the client certificate you created. If you followed the AWS MSK mTLS guide you will need to export your private key from the JKS keystore. The certificate and chain will be provided in PEM format when you get the certificate signed. You can use these to create a secret with:
- tls.key : PEM formatted private key
- tls.crt : PEM formatted certificate
- ca.crt : Certificate chain
kubectl create secret generic aws-msk-client --from-file=./tls.key --from-file=./tls.crt --from-file=./ca.crt -n seldon-meshCreate a secret for the broker certificate. If following the AWS MSK mTLS guide you will need to export the trusstore of Amazon into PEM format and save as ca.crt.
To extract certificates from truststore do:
keytool -importkeystore -srckeystore truststore.jks -destkeystore truststore.p12 -srcstoretype jks -deststoretype pkcs12
openssl pkcs12 -in truststore.p12 -nodes -out trust.pem
cat trust.pem | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ca.crtAdd ca.crt to a secret.
kubectl create secret generic aws-msk-broker-ca --from-file=./ca.crt -n seldon-meshExample Helm install
We provide a template you can extend in k8s/samples/values-aws-msk-kafka-mtls.yaml.tmpl:
:language: yamlCopy this and modify by adding your broker endpoints.
helm install seldon-v2 k8s/helm-charts/seldon-core-v2-setup/ -n seldon-mesh -f k8s/samples/values-aws-msk-kafka-mtls.yaml --set kafka.bootstrap=<your aws msk broker endpoints>Troubleshooting
First check AWS MSK troubleshooting.
No messages are being produced to the topics
Set the kafka config map debug setting to "all". For Helm install you can set kafka.debug=all.
If you see an error from the producer in the Pipeline gateway complaining about not enough insync replicas then the replication factor Seldon is using is less than the cluster setting for min.insync.replicas which for a default AWS MSK cluster defaults to 2. Ensure this is equal to that of the cluster. This value can be set in the Helm chart with kafka.topics.replicationFactor.
Source Contents Getting Started Kubernetes Installation Security Aws Msk Sasl (`docs/source/contents/getting-started/kubernetes-installation/security/aws-msk-sasl.md`)
AWS MSK SASL
New in Seldon Core 2.5.0
Seldon Core 2 can integrate with Amazon managed Apache Kafka (MSK). You can control access to your Amazon MSK clusters using sign-in credentials that are stored and secured using AWS Secrets Manager. Storing user credentials in Secrets Manager reduces the overhead of cluster authentication such as auditing, updating, and rotating credentials. Secrets Manager also lets you share user credentials across clusters.
Configuration of the AWS MSK instance itself is out of scope for this example.
Please follow the official [AWS documentation](https://docs.aws.amazon.com/msk/latest/developerguide/what-is-msk.html) on how to enable SASL and public access to the Kafka cluster (if required).Setting up SASL/SCRAM authentication for an Amazon MSK cluster
To setup SASL/SCRAM in an Amazon MSK cluster, please follow the guide from Amazon's Official documentation.
Do not forget to also copy the bootstrap.servers which we will use it in our configuration later below for Seldon.
Create Kubernetes Secret
Seldon Core 2 expects password to be in form of K8s secret
kubectl create secret generic aws-msk-kafka-secret -n seldon-mesh --from-literal password="<MSK SASL Password>"Configure Seldon Core 2
Configure Seldon Core 2 by setting following Helm values:
:language: yamlNote you may need to tweak replicationFactor and numPartitions to your cluster configuration.
Troubleshooting
Please check Amazon MSK Troubleshooting documentation.
Set the kafka config map debug setting to
all. For Helm install you can setkafka.debug=all.
Source Contents Getting Started Kubernetes Installation Security Azure Event Hub Sasl (`docs/source/contents/getting-started/kubernetes-installation/security/azure-event-hub-sasl.md`)
Azure Event Hub SASL Example
New in Seldon Core 2.5.0
Seldon Core 2 can integrate with Azure Event Hub via Kafka protocol.
You will need at least `Standard` tier for your Event Hub Namespace as `Basic` tier does not support Kafka protocol.Seldon Core 2 creates 2 Kafka topics for each pipeline and model plus one global topic for errors.
This means that total number of topics will be `2 x (#models + #pipelines) + 1` which will likely exceed the limit of `Standard` tier in Azure Event Hub.
You can find more information on quotas, like the number of partitions per Event Hub, [here](https://learn.microsoft.com/en-us/azure/event-hubs/event-hubs-quotas#basic-vs-standard-vs-premium-vs-dedicated-tiers).Prerequisites
To start you will need to have an Azure Event Hub Namespace.
You can create one following Azure quickstart docs.
Note that you do not need to create an Event Hub (topics) as Core 2 will require all the topics it needs automatically.
Create API Keys
To connect to Azure Event Hub provided Kafka API you need to obtain:
- Kafka Endpoint
- Connection String
You can obtain both using Azure Portal as documented here.
You should get the Connection String for a namespace level as we will need to dynamically create new topics.The Connection String should be in format of
Endpoint=sb://<namespace>.servicebus.windows.net/;SharedAccessKeyName=XXXXXX;SharedAccessKey=XXXXXXCreate Kubernetes Secret
Seldon Core 2 expects password to be in form of K8s secret
kubectl create secret generic azure-kafka-secret -n seldon-mesh --from-literal password="Endpoint=sb://<namespace>.servicebus.windows.net/;SharedAccessKeyName=XXXXXX;SharedAccessKey=XXXXXX"Configure Seldon Core 2
Configure Seldon Core 2 by setting following Helm values:
:language: yamlNote you may need to tweak replicationFactor and numPartitions to your cluster configuration. The username should read $ConnectionString and this is not a variable for you to replace.
Troubleshooting
First check Azure Event Hub troubleshooting guide.
Set the kafka config map debug setting to
all. For Helm install you can setkafka.debug=all.Verify that you did not hit quotas for topics or partitions in your Event Hub namespace.
Source Contents Getting Started Kubernetes Installation Security Confluent Oauth (`docs/source/contents/getting-started/kubernetes-installation/security/confluent-oauth.md`)
Confluent Cloud Oauth 2.0 Example
New in Seldon Core 2.7.0
Seldon Core 2 can integrate with Confluent Cloud managed Kafka.
In this example we use Oauth 2.0 security mechanism.
Configure Identity Provider in Confluent Cloud Console
In your Confluent Cloud Console go to Account & Access / Identity providers and register your Identity Provider.
See Confluent Cloud documentation for further details.
Configure Identity Pool
In your Confluent Cloud Console go to Account & Access / Identity providers and add new identity pool to your newly registered Identity Provider.
See Confluent Cloud documentation for further details.
Create Kubernetes Secret
Seldon Core 2 expects oauth credentials to be in form of K8s secret
apiVersion: v1
kind: Secret
metadata:
name: confluent-kafka-oauth
namespace: seldon-mesh
type: Opaque
stringData:
method: OIDC
client_id: <client id>
client_secret: <client secret>
token_endpoint_url: <token endpoint url>
extensions: logicalCluster=<cluster id>,identityPoolId=
scope: ""You will need following information from Confluent Cloud:
- Cluster ID:
Cluster Overview→Cluster Settings→General→Identification - Identity Pool ID:
Accounts & access→Identity providers→<specific provider details>
Client ID, client secret and token endpoint url should come from identity provider, e.g. Keycloak or Azure AD.
Configure Seldon Core 2
Configure Seldon Core 2 by setting following Helm values:
:language: yamlNote you may need to tweak replicationFactor and numPartitions to your cluster configuration.
Troubleshooting
First check Confluent Cloud documentation.
Set the kafka config map debug setting to
all. For Helm install you can setkafka.debug=all.
Source Contents Getting Started Kubernetes Installation Security Confluent Sasl (`docs/source/contents/getting-started/kubernetes-installation/security/confluent-sasl.md`)
Confluent Cloud SASL Example
New in Seldon Core 2.5.0
Seldon Core 2 can integrate with Confluent Cloud managed Kafka.
In this example we use SASL security mechanism.
Create API Keys
In your Confluent Cloud environment create new API keys.
The easiest way to obtain all required information is to head to Clients -> New client (choose e.g. Go) and generate new Kafka cluster API key from there.
This will generate for you:
Key(we use it asusername)Secret(we use it aspassword)
Do not forget to also copy the bootstrap.servers from the example config.
See Confluent Cloud documentation in case of issues.
Create Kubernetes Secret
Seldon Core 2 expects password to be in form of K8s secret
kubectl create secret generic confluent-kafka-sasl -n seldon-mesh --from-literal password="<Confluent Cloud API Secret>"Configure Seldon Core 2
Configure Seldon Core 2 by setting following Helm values:
:language: yamlNote you may need to tweak replicationFactor and numPartitions to your cluster configuration.
Troubleshooting
First check Confluent Cloud documentation.
Set the kafka config map debug setting to
all. For Helm install you can setkafka.debug=all.
Source Contents Getting Started Kubernetes Installation Security Reference (`docs/source/contents/getting-started/kubernetes-installation/security/reference.md`)
Security Settings Reference
Helm Settings
:language: yaml
:language: golang
:start-after: # Security settings
:end-before: opentelemetryEnvironment variables
Kubernetes secrets and mounted files can be used to provide the certificates in PEM format. These are controlled by environment variables for server or client depending on the component:
Control Plane
:header-rows: 1
* - EnvVar
- Value
* - CONTROL_PLANE_SECURITY_PROTOCOL
- SSL or PLAINTEXTFor a server (scheduler):
:header-rows: 1
* - EnvVar
- Value
* - CONTROL_PLANE_SERVER_TLS_SECRET_NAME
- (optional) the name of the namespaced secret which holds the certificates
* - CONTROL_PLANE_CLIENT_TLS_SECRET_NAME
- (optional) the name of the namespaced secret which holds the validation ca roots to verify the client certificate
* - CONTROL_PLANE_SERVER_TLS_KEY_LOCATION
- the path to the TLS private key
* - CONTROL_PLANE_SERVER_TLS_CRT_LOCATION
- the path to the TLS certificate
* - CONTROL_PLANE_SERVER_TLS_CA_LOCATION
- the path to the TLS CA chain for the server
* - CONTROL_PLANE_CLIENT_TLS_CA_LOCATION
- the path to the TLS CA chain for the client for mTLS verificationFor a client (agent, modelgateway, hodometer, CRD controller):
:header-rows: 1
* - EnvVar
- Value
* - CONTROL_PLANE_CLIENT_TLS_SECRET_NAME
- (optional) the name of the namespaced secret which holds the certificates
* - CONTROL_PLANE_SERVER_TLS_SECRET_NAME
- (optional) the name of the namespaced secret which holds the validation ca roots to verify the server certificate
* - CONTROL_PLANE_CLIENT_TLS_KEY_LOCATION
- the path to the TLS private key
* - CONTROL_PLANE_CLIENT_TLS_CRT_LOCATION
- the path to the TLS certificate
* - CONTROL_PLANE_CLIENT_TLS_CA_LOCATION
- the path to the TLS CA chain for the client
* - CONTROL_PLANE_SERVER_TLS_CA_LOCATION
- the path to the TLS CA chain for the server for mTLS verificationKafka
:header-rows: 1
* - EnvVar
- Value
* - KAFKA_SECURITY_PROTOCOL
- PLAINTXT, SSL, or SASL_SSL:header-rows: 1
* - EnvVar
- Value
* - KAFKA_CLIENT_TLS_SECRET_NAME
- (optional) the name of the namespaced secret which holds the Kafka client certificate
* - KAFKA_CLIENT_SERVER_TLS_KEY_LOCATION
- the path to the TLS private key
* - KAFKA_CLIENT_SERVER_TLS_CRT_LOCATION
- the path to the TLS certificate
* - KAFKA_CLIENT_SERVER_TLS_CA_LOCATION
- the path to the CA chain for the client
* - KAFKA_BROKER_TLS_SECRET_NAME
- (optional) the name of the namespaced secret which holds the validation ca roots for the kafka broker
* - KAFKA_BROKER_TLS_CA_LOCATION
- The path to the broker validatiob CA chain
* - KAFKA_CLIENT_SASL_USERNAME
- SASL username
* - KAFKA_CLIENT_SASL_SECRET_NAME
- the name of the namespaced secret which holds the SASL password
* - KAFKA_CLIENT_SASL_PASSWORD_LOCATION
- the path to the file containing the SASL passwordEnvoy
Envoy xDS server will use the control plane server and client certificates defined above.
Downstream server
:header-rows: 1
* - EnvVar
- Value
* - ENVOY_DOWNSTREAM_SERVER_TLS_SECRET_NAME
- (optional) the name of the namespaced secret which holds the certificates
* - ENVOY_DOWNSTREAM_CLIENT_TLS_SECRET_NAME
- (optional) the name of the namespaced secret which holds the validation ca roots to verify the client certificate
* - ENVOY_DOWNSTREAM_SERVER_TLS_KEY_LOCATION
- the path to the TLS private key
* - ENVOY_DOWNSTREAM_SERVER_TLS_CRT_LOCATION
- the path to the TLS certificate
* - ENVOY_DOWNSTREAM_SERVER_TLS_CA_LOCATION
- the path to the TLS CA chain for the server
* - ENVOY_DOWNSTREAM_CLIENT_TLS_CA_LOCATION
- the path to the TLS CA chain for the client for mTLS verificationDownstream client
:header-rows: 1
* - EnvVar
- Value
* - ENVOY_DOWNSTREAM_CLIENT_TLS_SECRET_NAME
- (optional) the name of the namespaced secret which holds the certificates
* - ENVOY_DOWNSTREAM_SERVER_TLS_SECRET_NAME
- (optional) the name of the namespaced secret which holds the validation ca roots to verify the server certificate
* - ENVOY_DOWNSTREAM_CLIENT_TLS_KEY_LOCATION
- the path to the TLS private key
* - ENVOY_DOWNSTREAM_CLIENT_TLS_CRT_LOCATION
- the path to the TLS certificate
* - ENVOY_DOWNSTREAM_CLIENT_TLS_CA_LOCATION
- the path to the TLS CA chain for the server
* - ENVOY_DOWNSTREAM_SERVER_TLS_CA_LOCATION
- the path to the TLS CA chain for the server for mTLS verificationUpstream server
:header-rows: 1
* - EnvVar
- Value
* - ENVOY_UPSTREAM_SERVER_TLS_SECRET_NAME
- (optional) the name of the namespaced secret which holds the certificates
* - ENVOY_UPSTREAM_CLIENT_TLS_SECRET_NAME
- (optional) the name of the namespaced secret which holds the validation ca roots to verify the client certificate
* - ENVOY_UPSTREAM_SERVER_TLS_KEY_LOCATION
- the path to the TLS private key
* - ENVOY_UPSTREAM_SERVER_TLS_CRT_LOCATION
- the path to the TLS certificate
* - ENVOY_UPSTREAM_SERVER_TLS_CA_LOCATION
- the path to the TLS CA chain for the server
* - ENVOY_UPSTREAM_CLIENT_TLS_CA_LOCATION
- the path to the TLS CA chain for the client for mTLS verificationUpstream client
:header-rows: 1
* - EnvVar
- Value
* - ENVOY_UPSTREAM_CLIENT_TLS_SECRET_NAME
- (optional) the name of the namespaced secret which holds the certificates
* - ENVOY_UPSTREAM_SERVER_TLS_SECRET_NAME
- (optional) the name of the namespaced secret which holds the validation ca roots to verify the server certificate
* - ENVOY_UPSTREAM_CLIENT_TLS_KEY_LOCATION
- the path to the TLS private key
* - ENVOY_UPSTREAM_CLIENT_TLS_CRT_LOCATION
- the path to the TLS certificate
* - ENVOY_UPSTREAM_CLIENT_TLS_CA_LOCATION
- the path to the TLS CA chain for the server
* - ENVOY_UPSTREAM_SERVER_TLS_CA_LOCATION
- the path to the TLS CA chain for the server for mTLS verificationSource Contents Getting Started Kubernetes Installation Security Strimzi Mtls (`docs/source/contents/getting-started/kubernetes-installation/security/strimzi-mtls.md`)
Strimzi mTLS Example
Cluster Setup
If you have installed Strimzi we have an example Helm chart to create a Kafka cluster for seldon and an associated user in kafka/strimzi folder. Ensure the tls is enabled with:
broker:
tls:
enabled: true
port: 9093
listenerType: internal
authentication:
type: tlsThe Ansible setup-ecosystem playbook will also install Strimzi and include a mTLS endpoint. See here.
mTLS Example
Create a Kafka User seldon in the namespace seldon was installed. This assumes Strimzi Kafka cluster is installed in the same namespace or is running with cluster wide permissions. Our Ansible scripts to setup the ecosystem will also create this user if tls is active.
:language: yamlIf you don't have this user you can install it with in your desired namespace (here seldon-mesh):
kubectl create -f k8s/samples/strimzi-example-tls-user.yaml -n seldon-meshInstall seldon with the Strimzi certificate secrets using a custom values file. This sets the secret created by Strimzi for the user created above (seldon) and targets the server certificate authority secret from the name of the cluster created on install of the Kafka cluster (seldon-cluster-ca-cert).
Configure Seldon Core 2 by setting following Helm values:
:language: yamlhelm install seldon-v2 k8s/helm-charts/seldon-core-v2-setup/ -n seldon-mesh -f k8s/samples/values-strimzi-kafka-mtls.yamlYou can now go ahead and install a SeldonRuntime in your desired install namespace (here seldon-mesh), e.g.
helm install seldon-v2-runtime ../k8s/helm-charts/seldon-core-v2-runtime -n seldon-meshSource Contents Getting Started Kubernetes Installation Security Strimzi Sasl (`docs/source/contents/getting-started/kubernetes-installation/security/strimzi-sasl.md`)
Strimzi SASL Example
Create a Strimzi Kafka cluster with SASL_SSL enabled.
This can be done with our Ansible scripts by running the following from the ansible/ folder:
ansible-playbook playbooks/setup-ecosystem.yaml -e @../k8s/samples/ansible-strimzi-kafka-sasl-scram.yaml -e strimzi_kafka_operator_feature_gates=""The referenced SASL/SCRAM YAML file looks like the below:
:language: yamlThis will use the Strimzi Helm chart provided in Core 2.
This will call the Strimzi cluster Helm chart provided by the project with overrides for the cluster authentication type and will also create a user seldon with password credentials in a Kubernetes Secret.
Install Seldon Core 2 with SASL settings using a custom values file.
This sets the secret created by Strimzi for the user created above (seldon) and targets the server certificate authority secret from the name of the cluster created on install of the Kafka cluster (seldon-cluster-ca-cert).
Configure Seldon Core 2 by setting following Helm values:
:language: yamlhelm install seldon-v2 k8s/helm-charts/seldon-core-v2-setup/ -n seldon-mesh -f k8s/samples/values-strimzi-kafka-sasl-scram.yaml--- METRICS ---
- Files Extracted: 177
- Estimated Token Budget: ~108725 tokens
- Canonical Reference: https://codewiki.google/github.com/SeldonIO/seldon-core