Skip to content

Commit

Permalink
K8s local deployment and documentation updated (#1548)
Browse files Browse the repository at this point in the history
* added script to deploy a k8s cluster locally

* Updated the README

* basic documentation update

* experimental documentation updated

* updated deployment configuration

* remove failed link in docker compose

* applied tips for resources assignment

* use tox command instead
  • Loading branch information
Tansito authored Dec 13, 2024
1 parent edac72a commit 77b981a
Show file tree
Hide file tree
Showing 18 changed files with 426 additions and 578 deletions.
81 changes: 45 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
# Qiskit Serverless

Qiskit Serverless is a user-friendly tool that enables you to easily run complex quantum computing tasks.
With this software, you can execute Qiskit programs as long running jobs and distribute them across multiple CPUs, GPUs, and QPUs.
With this software, you can execute Qiskit Functions as long running jobs and distribute them across multiple CPUs, GPUs, and QPUs.
This means you can take on more complex quantum-classical programs and run them with ease.
You don't have to worry about configuration or scaling up computational resources, as Qiskit Serverless takes care of everything for you.

Expand All @@ -16,6 +16,8 @@ You don't have to worry about configuration or scaling up computational resource
### Table of Contents

1. [Quickstart](#quickstart)
1. [Using Docker](#docker)
1. [Using Kubernetes](#kubernetes)
1. Modules
1. [Client](./client)
1. [Gateway](./gateway)
Expand All @@ -29,25 +31,28 @@ You don't have to worry about configuration or scaling up computational resource
----------------------------------------------------------------------------------------------------

### Quickstart
This Quickstart section guides users to easily deploy QiskitServerless infrastructure and run a simple example.
For user convenience, this section assumes that users will deploy the infrastructure in a local environment using Docker and test examples within the deployed Jupyter notebook.
This Quickstart section guides users to easily deploy Qiskit Serverless infrastructure and run a simple example.

1. Prepare local QiskitServerless infrastructure
#### Docker
For user convenience, this section assumes that users will deploy the infrastructure in a local environment using Docker following the next steps.

1. Prepare local Qiskit Serverless infrastructure
1. Install Docker
If Docker is not installed on your system, follow the directions on the [Docker website](https://docs.docker.com/engine/install/) to install Docker on your system.
1. Install qiskit-serverless on your local system (we recommend using a [virtual environment](https://docs.python.org/3/library/venv.html)).
You can use any runtime that you prefer to run Docker on your machine: Docker Desktop, podman... If you are using a MacOS with ARM processors we highly recommend to use [Colima](https://github.com/abiosoft/colima) as your container runtime to avoid problems with that architecture.

This is a project that takes advantage of distributed computing, so it places a high demand on resources. We recommend increasing the assigned resources to these runtimes. In case of Colima for example we typically use:
```shell
pip install qiskit-serverless
colima start --cpu 4 --memory 8 --disk 100
```
Optional: install [Jupyter Lab](https://jupyter.org/)
1. Install qiskit-serverless on your local system (we recommend using a [virtual environment](https://docs.python.org/3/library/venv.html)).
```shell
pip install jupyterlab
pip install qiskit-serverless
```
1. Clone the Qiskit Serverless repository
```shell
git clone https://github.com/Qiskit/qiskit-serverless.git
```
1. Run QiskitServerless infrastructure
1. Run Qiskit Serverless infrastructure
Execute Docker Compose using the following commands.
```shell
cd qiskit-serverless/
Expand All @@ -63,43 +68,47 @@ For user convenience, this section assumes that users will deploy the infrastruc
✔ Container public-qiskit-serverless-postgres-1 Created 0.0s
✔ Container gateway Created 0.0s
✔ Container scheduler Created 0.0s
Attaching to gateway, public-qiskit-serverless-postgres-1, qs-jupyter, ray-head, scheduler
Attaching to gateway, public-qiskit-serverless-postgres-1, ray-head, scheduler
```
1. Write your first Qiskit Function following our hello-world example in the [tutorial section](https://qiskit.github.io/qiskit-serverless/getting_started/basic/01_running_program.html).

That's all!
1. Launch JupyterLab environment.
```shell
cd docs/getting_started/ # the directory with sample notebooks
jupyter lab
```
This will open the Jupyter Lab environment in your web browser.
1. Write your first example Qiskit Pattern.
In the JupyterLab, create a new file, `pattern.py`, in the `work` directory. You can include any arbitrary Python code in your program, or you can use the
[example Python file in this tutorial](https://github.com/Qiskit/qiskit-serverless/blob/main/docs/getting_started/basic/01_running_program.ipynb).

1. Run the program
In the JupyterLab, create a new notebook in the same directory as your program, and execute [the tutorial code](https://github.com/Qiskit/qiskit-serverless/blob/main/docs/getting_started/basic/01_running_program.ipynb).

You can check the job status and get the result.
#### Kubernetes
For user convenience, this section assumes that users will deploy the infrastructure in a local environment using Kind following the next steps.
```
job.status()
# 'DONE'
1. Prepare local Qiskit Serverless infrastructure
1. Install Docker
You can use any runtime that you prefer to run Docker on your machine: Docker Desktop, podman... If you are using a MacOS with ARM processors we highly recommend to use [Colima](https://github.com/abiosoft/colima) as your container runtime to avoid problems with that architecture.
job.logs()
# 2023-09-21 03:48:40,286\tINFO worker.py:1329 -- Using address 172.18.0.4:6379 set in the environment variable RAY_ADDRESS\n2023-09-21 03:48:40,286\tINFO worker.py:1458 -- Connecting to existing Ray cluster at address: 172.18.0.4:6379...\n2023-09-21 03:48:40,295\tINFO worker.py:1633 -- Connected to Ray cluster. View the dashboard at \x1b[1m\x1b[32m172.18.0.4:8265 \x1b[39m\x1b[22m\n
```
```
job.status()
# '{"quasi_dists": [{"1": 0.5071335183298108, "5": 0.4334908044837378, "7": 0.0593756771864515}, {"1": 0.9161860602334094, "5": 0.0838139397665906}, {"2": 0.4999999999999999, "3": 0.4999999999999999}]}'
```
This is a project that takes advantage of distributed computing, so it places a high demand on resources. We recommend increasing the assigned resources to these runtimes. In case of Colima for example we typically use:
```shell
colima start --cpu 4 --memory 8 --disk 100
```
1. Install Kind
To simplify the process to deploy a k8s cluster locally we use [Kind](https://kind.sigs.k8s.io/docs/user/quick-start#installation) as the main tool to create a cluster.
1. Install qiskit-serverless on your local system (we recommend using a [virtual environment](https://docs.python.org/3/library/venv.html)).
```shell
pip install qiskit-serverless
```
1. Clone the Qiskit Serverless repository
```shell
git clone https://github.com/Qiskit/qiskit-serverless.git
```
1. Run Qiskit Serverless infrastructure
Execute the script to setup the cluster
```shell
tox -e cluster-deploy
```
The creation process can take some minutes.
1. Write your first Qiskit Function following our hello-world example in the [tutorial section](https://qiskit.github.io/qiskit-serverless/getting_started/basic/01_running_program.html).
That's all!

For more detailed examples and explanations refer to the [Guide](https://qiskit.github.io/qiskit-serverless/index.html):

1. [Getting Started](https://qiskit.github.io/qiskit-serverless/getting_started/index.html#)
1. [Example Qiskit Patterns](https://qiskit.github.io/qiskit-serverless/examples/index.html)
1. [Example Qiskit Functions](https://qiskit.github.io/qiskit-serverless/examples/index.html)
1. [Infrastructure](https://qiskit.github.io/qiskit-serverless/deployment/index.html)
1. [Migrating from Qiskit Runtime programs](https://qiskit.github.io/qiskit-serverless/migration/index.html)

Expand Down
73 changes: 73 additions & 0 deletions docs/deployment/custom_function/local_cluster/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#! /bin/bash

set -ex

cat <<EOF | kind create cluster --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
image: kindest/node:v1.29.4
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
extraPortMappings:
- containerPort: 80
hostPort: 80
protocol: TCP
- containerPort: 443
hostPort: 443
protocol: TCP
EOF

kubectl label node kind-control-plane has-gpu=gpu has-cpu=cpu
kubectl apply -f https://kind.sigs.k8s.io/examples/ingress/deploy-ingress-nginx.yaml

docker build -t gateway:test -f ./gateway/Dockerfile .
kind load docker-image gateway:test
docker image rm gateway:test

docker build -t ray:test -f ./Dockerfile-ray-node .
kind load docker-image ray:test
docker image rm ray:test

cd charts/qiskit-serverless
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add kuberay https://ray-project.github.io/kuberay-helm
helm dependency build
helm install qs \
--set platform=kind \
--set nginxIngressControllerEnable=false \
--set gateway.image.repository=gateway \
--set gateway.image.tag=test \
--set gateway.application.ray.nodeImage=ray:test \
--set gateway.application.ray.proxyImage=proxy:test \
--set gateway.application.ray.cpu=1 \
--set gateway.application.debug=1 \
--set gateway.application.limits.keepClusterOnComplete=false \
--set gateway.application.authMockproviderRegistry=test \
--set gateway.application.proxy.enabled=false \
--set ingress.hosts[0].host=localhost \
--set ingress.hosts[0].paths[0].path=/ \
--set ingress.hosts[0].paths[0].pathType=Prefix \
--set ingress.hosts[0].paths[0].serviceName=gateway \
--set ingress.hosts[0].paths[0].servicePort=8000 \
.

kubectl wait \
--for=condition=ready pod \
--selector=app.kubernetes.io/name=gateway-scheduler \
--timeout=5m

kubectl wait \
--for=condition=ready pod \
--selector=app.kubernetes.io/name=gateway \
--timeout=5m

kubectl wait --namespace ingress-nginx \
--for=condition=ready pod \
--selector=app.kubernetes.io/component=controller \
--timeout=5m
23 changes: 16 additions & 7 deletions docs/deployment/deploying_custom_image_function.rst
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ and after that we need to build it:
.. code-block::
:caption: Build image
docker build -t local-provider-function -f Sample-Dockerfile .
docker build -t test-local-provider-function -f Sample-Dockerfile .
We got to our final step of function development - uploading to serverless.

Expand All @@ -80,7 +80,7 @@ For a local development you can modify `docker-compose.yaml` ray image with the
services:
ray-head:
container_name: ray-head
image: local-provider-function:latest
image: test-local-provider-function:latest
Run it:

Expand All @@ -89,6 +89,15 @@ Run it:
docker-compose up
Or if you are using kubernetes you will need to create the cluster and load the image in Kind:

.. code-block::
:caption: Run docker compose
tox -e cluster-deploy
kind load docker-image test-local-provider-function:latest
And that's everything you need to take into account if you are using the k8s approach.

Once time the local environment is running, it only remains to run the code! For that you just need to define `QiskitFunction`

with the image that you just built, give it a name and upload it:
Expand All @@ -102,20 +111,20 @@ with the image that you just built, give it a name and upload it:
serverless = ServerlessClient(
token=os.environ.get("GATEWAY_TOKEN", "awesome_token"),
host=os.environ.get("GATEWAY_HOST", "http://localhost:8000"),
# If you are using the kubernetes approach the URL must be http://localhost
)
serverless
function = QiskitFunction(
title="custom-image-function",
image="local-provider-function:latest",
image="test-local-provider-function:latest",
provider="mockprovider"
)
function_with_custom_image
function
serverless.upload(function_with_custom_image)
serverless.upload(function)
functions = {f.title: f for f in serverless.list()}
my_function = functions.get("custom-image-function")
my_function = serverless.get("custom-image-function")
my_function
job = my_function.run(test_argument_one=1, test_argument_two="two")
Expand Down
10 changes: 10 additions & 0 deletions docs/deployment/example_custom_image_function.rst
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,13 @@ Run it
docker-compose up
Or if you are using kubernetes you will need to create the cluster and load the image in Kind

.. code-block::
:caption: Run docker compose
tox -e cluster-deploy
kind load docker-image test-local-provider-function:latest
Run serverless

.. code-block::
Expand All @@ -98,6 +105,7 @@ Run serverless
serverless = ServerlessClient(
token=os.environ.get("GATEWAY_TOKEN", "awesome_token"),
host=os.environ.get("GATEWAY_HOST", "http://localhost:8000"),
# If you are using the kubernetes approach the URL must be http://localhost
)
help = """
Expand Down Expand Up @@ -132,6 +140,7 @@ List all available functions
serverless = ServerlessClient(
token=os.environ.get("GATEWAY_TOKEN", "awesome_token"),
host=os.environ.get("GATEWAY_HOST", "http://localhost:8000"),
# If you are using the kubernetes approach the URL must be http://localhost
)
my_functions = serverless.list()
Expand Down Expand Up @@ -169,6 +178,7 @@ Execute Function
serverless = ServerlessClient(
token=os.environ.get("GATEWAY_TOKEN", "awesome_token"),
host=os.environ.get("GATEWAY_HOST", "http://localhost:8000"),
# If you are using the kubernetes approach the URL must be http://localhost
)
my_function = serverless.get("custom-image-function")
Expand Down
39 changes: 33 additions & 6 deletions docs/deployment/local.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,21 @@ on your local machine straightforward. The first thing we will do is clone the r
cd /path/to/workspace/
git clone [email protected]:Qiskit/qiskit-serverless.git
Step 2: Set up Docker
Step 2: Setup Docker

To set up Qiskit Serverless on your local machine, you will need to use `docker compose`_.
To setup Qiskit Serverless on your local machine, you will need to use docker compose. As we mentioned in the `README <https://github.com/Qiskit/qiskit-serverless/blob/main/README.md>`_
you can use any runtime that you prefer to run Docker on your machine: Docker Desktop, podman...
If you are using a MacOS with ARM processors we highly recommend to use `Colima <https://github.com/abiosoft/colima>`_
as your container runtime to avoid problems with that architecture.

.. _docker compose: https://docs.docker.com/compose/
This is a project that takes advantage of distributed computing, so it places a high demand on resources. We recommend increasing the assigned resources to these runtimes.
In case of Colima for example we typically use:

Step 3: Initiate the test cluster
.. code-block::
$ colima start --cpu 4 --memory 8 --disk 100
Step 2.1: Initiate the test environment

Once you have Docker and docker compose installed, you can run the following command from the root of the
``qiskit-serverless`` repository to set up the infrastructure:
Expand All @@ -50,8 +58,27 @@ Additionally, you can include the profile `full`.
With the full profile installs all core services, including logging and
monitorying systems.

Step 3: Setup Kind

Additionally we provide you a way to deploy a k8s cluster on your local machine. This has some benefits as this is a more similar environment
to production than the docker-compose approach.

To simplify the process to deploy a k8s cluster locally we use `Kind <https://kind.sigs.k8s.io/docs/user/quick-start#installation>`_
as the main tool to create a cluster.

Step 3.1: Initiate the test cluster

To setup the cluster for testing we prepare a little script that will initialize for you all the needed resources. You can execute it
using the terminal just running the next command:

.. code-block::
$ tox -e cluster-deploy
Step 4: Run a program in the test environment

Once the containers are running, you can simulate a remote cluster with the resources on your
local machine. To create and run programs in this simulated cluster, we recommend using `Jupyter Lab <https://jupyter.org/install>`_. Refer to the :ref:`getting_started` guides
for details about running your program remotely.
local machine. Feel free to go to our tutorials in the `Getting started section <https://qiskit.github.io/qiskit-serverless/getting_started/index.html>`_
and run some of them.


Loading

0 comments on commit 77b981a

Please sign in to comment.