Commit ffd47bca authored by julienmancuso's avatar julienmancuso Committed by GitHub
Browse files

fix: fix helm chart deployment (#172)

parent 2cca070c
...@@ -22,6 +22,7 @@ mypy ...@@ -22,6 +22,7 @@ mypy
numpy numpy
opentelemetry-api opentelemetry-api
opentelemetry-sdk opentelemetry-sdk
pip==25.0.1
pre-commit pre-commit
protobuf==5.27.3 protobuf==5.27.3
pydantic==2.7.1 pydantic==2.7.1
......
...@@ -7,10 +7,13 @@ This is a proof of concept for a Helm chart to deploy services defined in a bent ...@@ -7,10 +7,13 @@ This is a proof of concept for a Helm chart to deploy services defined in a bent
### Prerequisites ### Prerequisites
- make sure dynamo cli is installed - make sure dynamo cli is installed
- make sure you have a docker image registry to which you can push and pull from k8s cluster
- set the imagePullSecrets in the values.yaml file
### Install the Helm chart ### Install the Helm chart
```bash ```bash
./deploy.sh <docker_registry> <k8s_namespace> <bento_name> <path_to_bento_directory> export DYNAMO_IMAGE=<dynamo_docker_image_name>
# example./deploy.sh nvcr.io/nvidian/nim-llm-dev my-namespace my-helm-poc ../deploy/compoundai/sdk/examples/basic_service ./deploy.sh <docker_registry> <k8s_namespace> <path_to_dynamo_directory> <dynamo_identifier>
# example : ./deploy.sh nvcr.io/nvidian/nim-llm-dev my-namespace ../deploy/dynamo/sdk/examples/hello_world/ hello_world:Frontend
``` ```
\ No newline at end of file
...@@ -16,29 +16,31 @@ ...@@ -16,29 +16,31 @@
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: poc-{{ .name | lower }} name: {{ $.Release.Name }}-{{ .name | lower }}
labels: labels:
app: {{ .name | lower }} app: {{ $.Release.Name }}-{{ .name | lower }}
spec: spec:
replicas: 1 replicas: {{ .config.workers | default 1 }}
selector: selector:
matchLabels: matchLabels:
app: poc-{{ .name | lower }} app: {{ $.Release.Name }}-{{ .name | lower }}
template: template:
metadata: metadata:
labels: labels:
app: poc-{{ .name | lower }} app: {{ $.Release.Name }}-{{ .name | lower }}
spec: spec:
# pull secrets # pull secrets
imagePullSecrets: imagePullSecrets:
- name: yatai-regcred {{- range $.Values.imagePullSecrets }}
- name: {{ .name }}
{{- end }}
securityContext: securityContext:
runAsUser: 0 runAsUser: 0
containers: containers:
- name: poc-{{ .name | lower }} - name: {{ $.Release.Name }}-{{ .name | lower }}
image: {{ $.Values.image }} image: {{ $.Values.image }}
args: args:
- uv run compoundai start --service-name {{ .name }} - uv run dynamo start --service-name {{ .name }} src.{{ $.Values.dynamoIdentifier }}
command: command:
- sh - sh
- -c - -c
...@@ -50,11 +52,11 @@ spec: ...@@ -50,11 +52,11 @@ spec:
env: env:
- name: TRAFFIC_TIMEOUT - name: TRAFFIC_TIMEOUT
value: "{{ .config.traffic.timeout }}" value: "{{ .config.traffic.timeout }}"
{{- if and .config.nova .config.nova.enabled }} {{- if and .config.dynamo .config.dynamo.enabled }}
- name: NOVA_NAMESPACE - name: DYNAMO_NAMESPACE
value: "{{ .config.nova.namespace }}" value: "{{ .config.dynamo.namespace }}"
- name: NOVA_NAME - name: DYNAMO_NAME
value: "{{ .config.nova.name }}" value: "{{ .config.dynamo.name }}"
{{- end }} {{- end }}
{{- if .config.workers }} {{- if .config.workers }}
- name: WORKERS - name: WORKERS
...@@ -62,9 +64,13 @@ spec: ...@@ -62,9 +64,13 @@ spec:
{{- end }} {{- end }}
- name: PORT - name: PORT
value: "3000" value: "3000"
{{- if $.Values.natsAddr }}
- name: NATS_SERVER - name: NATS_SERVER
value: nats://my-nats:4222 value: {{ $.Values.natsAddr }}
{{- end }}
{{- if $.Values.etcdAddr }}
- name: ETCD_ENDPOINTS - name: ETCD_ENDPOINTS
value: etcd:2379 value: {{ $.Values.etcdAddr }}
{{- end }}
--- ---
{{- end }} {{- end }}
...@@ -16,10 +16,10 @@ ...@@ -16,10 +16,10 @@
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: {{ .name | lower }} name: {{ $.Release.Name }}-{{ .name | lower }}
spec: spec:
selector: selector:
app: {{ .name | lower }} app: {{ $.Release.Name }}-{{ .name | lower }}
ports: ports:
- protocol: TCP - protocol: TCP
port: 80 port: 80
......
# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
imagePullSecrets:
- name: yatai-regcred
- name: nvcrimagepullsecret
- name: gitlab-imagepull
natsAddr: nats://dynamo-platform-nats:4222
etcdAddr: dynamo-platform-etcd:2379
...@@ -18,26 +18,28 @@ ...@@ -18,26 +18,28 @@
set -euo pipefail set -euo pipefail
# Validate input parameters # Validate input parameters
if [ "$#" -ne 4 ]; then if [ "$#" -ne 4 ]; then
echo "Usage: $0 <DOCKER_REGISTRY> <NAMESPACE> <BENTO_NAME> <BENTO_DIRECTORY>" echo "Usage: $0 <DOCKER_REGISTRY> <NAMESPACE> <DYNAMO_DIRECTORY> <DYNAMO_IDENTIFIER>"
exit 1 exit 1
fi fi
DOCKER_REGISTRY=$1 DOCKER_REGISTRY=$1
NAMESPACE=$2 NAMESPACE=$2
BENTO_NAME=$3 DYNAMO_DIRECTORY=$3
BENTO_DIRECTORY=$4 DYNAMO_IDENTIFIER=$4
# Check if any of the inputs are empty # Check if any of the inputs are empty
if [[ -z "$DOCKER_REGISTRY" || -z "$NAMESPACE" || -z "$BENTO_NAME" || -z "$BENTO_DIRECTORY" ]]; then if [[ -z "$DOCKER_REGISTRY" || -z "$NAMESPACE" || -z "$DYNAMO_IDENTIFIER" || -z "$DYNAMO_DIRECTORY" ]]; then
echo "Error: All input parameters (DOCKER_REGISTRY, NAMESPACE, BENTO_NAME, BENTO_DIRECTORY) must be non-empty." echo "Error: All input parameters (DOCKER_REGISTRY, NAMESPACE, DYNAMO_IDENTIFIER, DYNAMO_DIRECTORY) must be non-empty."
exit 1 exit 1
fi fi
# Check if the specified directory exists # Check if the specified directory exists
if [ ! -d "$BENTO_DIRECTORY" ]; then if [ ! -d "$DYNAMO_DIRECTORY" ]; then
echo "Error: Directory $BENTO_DIRECTORY does not exist." echo "Error: Directory $DYNAMO_DIRECTORY does not exist."
exit 1 exit 1
fi fi
...@@ -45,20 +47,21 @@ echo "Logging into Docker registry: $DOCKER_REGISTRY" ...@@ -45,20 +47,21 @@ echo "Logging into Docker registry: $DOCKER_REGISTRY"
docker login "$DOCKER_REGISTRY" docker login "$DOCKER_REGISTRY"
# Change to the specified directory # Change to the specified directory
cd "$BENTO_DIRECTORY" cd "$DYNAMO_DIRECTORY"
# Update the bentofile.yaml with the new BENTO_NAME
echo "Updating bentofile.yaml with name: $BENTO_NAME"
yq eval ".name = \"$BENTO_NAME\"" -i bentofile.yaml
# Build the Bento container # Build the Bento container
echo "Building Bento image for $BENTO_NAME..." echo "Building Bento image for $DYNAMO_IDENTIFIER..."
DOCKER_DEFAULT_PLATFORM=linux/amd64 uv run dynamo build --containerize DOCKER_DEFAULT_PLATFORM=linux/amd64 uv run dynamo build --containerize $DYNAMO_IDENTIFIER
# Extract the module and the bento name
DYNAMO_MODULE=$(echo "$DYNAMO_IDENTIFIER" | awk -F':' '{print $1}' | tr '[:upper:]' '[:lower:]')
DYNAMO_NAME=$(echo "$DYNAMO_IDENTIFIER" | awk -F':' '{print $2}' | tr '[:upper:]' '[:lower:]')
# Find the built image # Find the built image
docker_image=$(docker images --format "{{.Repository}}:{{.Tag}} {{.CreatedAt}}" | grep "^$BENTO_NAME:" | sort -r | head -n 1 | awk '{print $1}') docker_image=$(docker images --format "{{.Repository}}:{{.Tag}} {{.CreatedAt}}" | grep "^$DYNAMO_NAME:" | sort -r -k2,3 | head -n 1 | awk '{print $1}')
if [[ -z "$docker_image" ]]; then if [[ -z "$docker_image" ]]; then
echo "Failed to find the built image for $BENTO_NAME" echo "Failed to find the built image for $DYNAMO_NAME"
exit 1 exit 1
fi fi
...@@ -66,7 +69,7 @@ fi ...@@ -66,7 +69,7 @@ fi
docker_sha=$(echo "$docker_image" | awk -F':' '{print $2}') docker_sha=$(echo "$docker_image" | awk -F':' '{print $2}')
echo "Found Docker image: $docker_image" echo "Found Docker image: $docker_image"
echo "Docker SHA (bento-version): $docker_sha" echo "Docker SHA: $docker_sha"
# Tag the image for the registry # Tag the image for the registry
docker_tag_for_registry="$DOCKER_REGISTRY/$docker_image" docker_tag_for_registry="$DOCKER_REGISTRY/$docker_image"
...@@ -79,6 +82,7 @@ docker push "$docker_tag_for_registry" ...@@ -79,6 +82,7 @@ docker push "$docker_tag_for_registry"
cd - cd -
# Install the Helm chart with the correct bento-version (SHA) # Install the Helm chart with the correct tag (SHA)
echo "Installing Helm chart with image: $docker_tag_for_registry and bento-version: $docker_sha" echo "Installing Helm chart with image: $docker_tag_for_registry"
helm install "$BENTO_NAME" ./poc -f ~/bentoml/bentos/"$BENTO_NAME"/"$docker_sha"/bento.yaml --set image="$docker_tag_for_registry" -n "$NAMESPACE" HELM_RELEASE="${DYNAMO_MODULE//_/\-}"
helm upgrade -i "$HELM_RELEASE" ./chart -f ~/bentoml/bentos/"$DYNAMO_NAME"/"$docker_sha"/bento.yaml --set image="$docker_tag_for_registry" --set dynamoIdentifier="$DYNAMO_IDENTIFIER" -n "$NAMESPACE"
...@@ -17,7 +17,7 @@ from __future__ import annotations ...@@ -17,7 +17,7 @@ from __future__ import annotations
import json import json
import os import os
from collections import defaultdict from collections import defaultdict
from dataclasses import dataclass from dataclasses import asdict, dataclass
from typing import Any, Dict, List, Optional, Set, Tuple, TypeVar, Union from typing import Any, Dict, List, Optional, Set, Tuple, TypeVar, Union
from _bentoml_sdk import Service, ServiceConfig from _bentoml_sdk import Service, ServiceConfig
...@@ -95,6 +95,10 @@ class DynamoService(Service[T]): ...@@ -95,6 +95,10 @@ class DynamoService(Service[T]):
if self._dynamo_config.name is None: if self._dynamo_config.name is None:
self._dynamo_config.name = inner.__name__ self._dynamo_config.name = inner.__name__
# Add dynamo configuration to the service config
# this allows for the config to be part of the service in bento.yaml
self.config["dynamo"] = asdict(self._dynamo_config)
# Register Dynamo endpoints # Register Dynamo endpoints
self._dynamo_endpoints: Dict[str, DynamoEndpoint] = {} self._dynamo_endpoints: Dict[str, DynamoEndpoint] = {}
for field in dir(inner): for field in dir(inner):
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
from pydantic import BaseModel from pydantic import BaseModel
from dynamo.sdk import api, depends, dynamo_endpoint, service from dynamo.sdk import DYNAMO_IMAGE, api, depends, dynamo_endpoint, service
""" """
Pipeline Architecture: Pipeline Architecture:
...@@ -55,6 +55,7 @@ class ResponseType(BaseModel): ...@@ -55,6 +55,7 @@ class ResponseType(BaseModel):
"namespace": "inference", "namespace": "inference",
}, },
workers=3, workers=3,
image=DYNAMO_IMAGE,
) )
class Backend: class Backend:
def __init__(self) -> None: def __init__(self) -> None:
...@@ -74,6 +75,7 @@ class Backend: ...@@ -74,6 +75,7 @@ class Backend:
resources={"cpu": "2"}, resources={"cpu": "2"},
traffic={"timeout": 30}, traffic={"timeout": 30},
dynamo={"enabled": True, "namespace": "inference"}, dynamo={"enabled": True, "namespace": "inference"},
image=DYNAMO_IMAGE,
) )
class Middle: class Middle:
backend = depends(Backend) backend = depends(Backend)
...@@ -93,7 +95,11 @@ class Middle: ...@@ -93,7 +95,11 @@ class Middle:
yield f"Middle: {response}" yield f"Middle: {response}"
@service(resources={"cpu": "1"}, traffic={"timeout": 60}) # Regular HTTP API @service(
resources={"cpu": "1"},
traffic={"timeout": 60},
image=DYNAMO_IMAGE,
) # Regular HTTP API
class Frontend: class Frontend:
middle = depends(Middle) middle = depends(Middle)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment