From 20032798695308c4d6e874d26df38f2ea45e5864 Mon Sep 17 00:00:00 2001 From: ychangkim Date: Wed, 9 Jul 2025 14:14:38 +0900 Subject: [PATCH] nim --- charts/nim/.helmignore | 23 +++++++ charts/nim/CUSTOM-README.md | 31 +++++++++ charts/nim/Chart.yaml | 11 +++ charts/nim/custom-values.yaml | 14 ++++ charts/nim/templates/NOTES.txt | 27 ++++++++ charts/nim/templates/_helpers.tpl | 52 ++++++++++++++ charts/nim/templates/auth-secret.yaml | 12 ++++ charts/nim/templates/image-pull-secret.yaml | 14 ++++ charts/nim/templates/nimservice.yaml | 32 +++++++++ .../nim/templates/tests/test-nimservice.yaml | 15 ++++ charts/nim/values.yaml | 69 +++++++++++++++++++ 11 files changed, 300 insertions(+) create mode 100644 charts/nim/.helmignore create mode 100644 charts/nim/CUSTOM-README.md create mode 100644 charts/nim/Chart.yaml create mode 100644 charts/nim/custom-values.yaml create mode 100644 charts/nim/templates/NOTES.txt create mode 100644 charts/nim/templates/_helpers.tpl create mode 100644 charts/nim/templates/auth-secret.yaml create mode 100644 charts/nim/templates/image-pull-secret.yaml create mode 100644 charts/nim/templates/nimservice.yaml create mode 100644 charts/nim/templates/tests/test-nimservice.yaml create mode 100644 charts/nim/values.yaml diff --git a/charts/nim/.helmignore b/charts/nim/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/charts/nim/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/charts/nim/CUSTOM-README.md b/charts/nim/CUSTOM-README.md new file mode 100644 index 0000000..a7b99a1 --- /dev/null +++ b/charts/nim/CUSTOM-README.md @@ -0,0 +1,31 @@ + +# Nim 배포 + +## 1. 배포 방법 + +- 명령어 + + ``` sh + $ helm upgrade --instal nim ../nim \ + --namespace nim \ + --create-namespace \ + -f custom-values.yaml + ``` + + + +## 2. custom-values.yaml 설명 + +- custom-values.yaml에 정의된 값에 대한 설명이다. + +### 1) Nim 설정 +| Name | 설명 | 기본값 | +| ---------------------- | ------------------------------------------------------------ | ------ | +| `nimService.name` | nim service 이름. | `meta-llama3-8b-instruct` | +| `nimService.existingAuthSecret` | nim service auth secret명. | | +| `image.repository` | nim service model registry. | `nvcr.io/nim/meta/llama-3.2-3b-instruct` | +| `image.tag` | nim service model tag. | `1.8.3` | +| `imagePullSecrets.name` | nim service model secret 명. | `nvcrimagepullsecret` | +| `imagePullSecrets.registry` | nim model resistory. | `nvcr.io` | +| `imagePullSecrets.username` | nim model resistory username. | `$oauthtoken` | +| `imagePullSecrets.password` | nim model resistory password. | | \ No newline at end of file diff --git a/charts/nim/Chart.yaml b/charts/nim/Chart.yaml new file mode 100644 index 0000000..aed7a12 --- /dev/null +++ b/charts/nim/Chart.yaml @@ -0,0 +1,11 @@ +apiVersion: v2 +name: nim +description: A Helm chart for deploying NVIDIA NIMService on Kubernetes + +type: application + +# This is the chart version. +version: 0.1.0 + +# This is the version number of the application being deployed. +appVersion: "25.4.0" diff --git a/charts/nim/custom-values.yaml b/charts/nim/custom-values.yaml new file mode 100644 index 0000000..de2bdfb --- /dev/null +++ b/charts/nim/custom-values.yaml @@ -0,0 +1,14 @@ +nimService: + name: "$nimService.name" + existingAuthSecret: "$INFISICAL_SECRET" + +image: + repository: "$image.repository" + pullPolicy: IfNotPresent + tag: "$image.tag" + +imagePullSecrets: + - name: nvcrimagepullsecret + registry: nvcr.io + username: "$oauthtoken" + password: "$imagePullSecrets.password" diff --git a/charts/nim/templates/NOTES.txt b/charts/nim/templates/NOTES.txt new file mode 100644 index 0000000..e065b61 --- /dev/null +++ b/charts/nim/templates/NOTES.txt @@ -0,0 +1,27 @@ +NVIDIA NIMService "{{ .Values.nimService.name }}" has been deployed! + +{{- if eq .Values.existingImagePullSecret "" }} +NOTE: Image pull secrets have been created. Make sure to set the correct password in values.yaml or using --set imagePullSecrets[0].password=YOUR_PASSWORD +{{- end }} + +{{- if eq .Values.nimService.existingAuthSecret "" }} +NOTE: NGC API authentication secret has been created. Make sure to set the correct NGC API key in values.yaml or using --set nimService.ngcAPIKey=YOUR_NGC_API_KEY +{{- end }} + +1. Check the status of the NIMService: + kubectl get nimservice -n {{ .Release.Namespace }} {{ .Values.nimService.name }} + +2. Access the NIMService API: + kubectl port-forward -n {{ .Release.Namespace }} service/{{ .Values.nimService.name }} {{ .Values.nimService.expose.service.port }}:{{ .Values.nimService.expose.service.port }} + +3. Example API request: + curl -X POST http://localhost:{{ .Values.nimService.expose.service.port }}/v1/completions \ + -H "Content-Type: application/json" \ + -d '{ + "model": "{{ .Values.nimService.name }}", + "prompt": "Hello, how are you?", + "max_tokens": 100 + }' + +For more information on using NVIDIA NIMService, visit: +https://docs.nvidia.com/nim/ diff --git a/charts/nim/templates/_helpers.tpl b/charts/nim/templates/_helpers.tpl new file mode 100644 index 0000000..7d0eb14 --- /dev/null +++ b/charts/nim/templates/_helpers.tpl @@ -0,0 +1,52 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "nim.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "nim.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "nim.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "nim.labels" -}} +helm.sh/chart: {{ include "nim.chart" . }} +{{ include "nim.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "nim.selectorLabels" -}} +app.kubernetes.io/name: {{ include "nim.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + diff --git a/charts/nim/templates/auth-secret.yaml b/charts/nim/templates/auth-secret.yaml new file mode 100644 index 0000000..f3f2ce5 --- /dev/null +++ b/charts/nim/templates/auth-secret.yaml @@ -0,0 +1,12 @@ +{{- if eq .Values.nimService.existingAuthSecret "" }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Values.nimService.authSecret }} + labels: + {{- include "nim.labels" . | nindent 4 }} +type: Opaque +data: + NGC_API_KEY: {{ .Values.nimService.ngcAPIKey | b64enc }} +{{- end }} \ No newline at end of file diff --git a/charts/nim/templates/image-pull-secret.yaml b/charts/nim/templates/image-pull-secret.yaml new file mode 100644 index 0000000..d465761 --- /dev/null +++ b/charts/nim/templates/image-pull-secret.yaml @@ -0,0 +1,14 @@ +{{- if eq .Values.existingImagePullSecret "" }} +{{- range .Values.imagePullSecrets }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ .name }} + labels: + {{- include "nim.labels" $ | nindent 4 }} +type: kubernetes.io/dockerconfigjson +data: + .dockerconfigjson: {{ printf "{\"auths\":{\"%s\":{\"username\":\"%s\",\"password\":\"%s\",\"auth\":\"%s\"}}}" .registry .username .password (printf "%s:%s" .username .password | b64enc) | b64enc | quote }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/nim/templates/nimservice.yaml b/charts/nim/templates/nimservice.yaml new file mode 100644 index 0000000..00c1b1f --- /dev/null +++ b/charts/nim/templates/nimservice.yaml @@ -0,0 +1,32 @@ +apiVersion: apps.nvidia.com/v1alpha1 +kind: NIMService +metadata: + name: {{ .Values.nimService.name }} + labels: + {{- include "nim.labels" . | nindent 4 }} +spec: + labels: + {{- toYaml .Values.nimService.labels | nindent 4 }} + image: + repository: {{ .Values.image.repository }} + tag: {{ .Values.image.tag | default .Chart.AppVersion }} + pullPolicy: {{ .Values.image.pullPolicy }} + pullSecrets: + {{- range .Values.imagePullSecrets }} + - {{ .name }} + {{- end }} + authSecret: {{ if ne .Values.nimService.existingAuthSecret "" }}{{ .Values.nimService.existingAuthSecret }}{{ else }}{{ .Values.nimService.authSecret }}{{ end }} + replicas: {{ .Values.nimService.replicas }} + storage: + pvc: + create: {{ .Values.nimService.storage.pvc.create }} + storageClass: {{ .Values.nimService.storage.pvc.storageClass }} + size: {{ .Values.nimService.storage.pvc.size }} + volumeAccessMode: {{ .Values.nimService.storage.pvc.volumeAccessMode }} + runtimeClassName: {{ .Values.nimService.runtimeClassName }} + resources: + {{- toYaml .Values.nimService.resources | nindent 4 }} + expose: + service: + type: {{ .Values.nimService.expose.service.type }} + port: {{ .Values.nimService.expose.service.port }} \ No newline at end of file diff --git a/charts/nim/templates/tests/test-nimservice.yaml b/charts/nim/templates/tests/test-nimservice.yaml new file mode 100644 index 0000000..81bd964 --- /dev/null +++ b/charts/nim/templates/tests/test-nimservice.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ .Values.nimService.name }}-test-connection" + labels: + {{- include "nim.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['{{ .Values.nimService.name }}:{{ .Values.nimService.expose.service.port }}'] + restartPolicy: Never \ No newline at end of file diff --git a/charts/nim/values.yaml b/charts/nim/values.yaml new file mode 100644 index 0000000..0217526 --- /dev/null +++ b/charts/nim/values.yaml @@ -0,0 +1,69 @@ +# Default values for nim. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +# NVIDIA NIMService configuration +nimService: + # Name of the NIMService + name: meta-llama3-8b-instruct + + # Labels for the NIMService + labels: + app.nvidia.com/nim-type: inference + + # Authentication secret for NVIDIA NGC + # If existingAuthSecret is set, the secret with this name will be used + # If empty, a secret will be created with the name specified in authSecret + existingAuthSecret: "" + authSecret: ngc-api + + # NGC API Key for authentication + ngcAPIKey: "" + + # Runtime class name + runtimeClassName: nvidia + + # Number of replicas + replicas: 1 + + # Storage configuration + storage: + pvc: + create: true + storageClass: longhorn + size: 30Gi + volumeAccessMode: ReadWriteMany + + # Resource requirements + resources: + limits: + nvidia.com/gpu: 1 + + # Service configuration + expose: + service: + type: ClusterIP + port: 8000 + +# This sets the container image +image: + repository: nvcr.io/nim/meta/llama-3.2-3b-instruct + pullPolicy: IfNotPresent + tag: "1.8.3" + +# This is for the secrets for pulling an image from a private repository +# If existingImagePullSecret is set, the secret with this name will be used +# If empty, secrets will be created based on the imagePullSecrets configuration +existingImagePullSecret: "" + +# Image pull secrets configuration +# Used to create secrets if existingImagePullSecret is false +imagePullSecrets: + - name: nvcrimagepullsecret + registry: nvcr.io + username: "$oauthtoken" + password: "" + +# This is to override the chart name +nameOverride: "" +fullnameOverride: ""