Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions deploy/helm/vanity-gateway/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bin/
packaged-charts/
49 changes: 49 additions & 0 deletions deploy/helm/vanity-gateway/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# AGENTS.md - vanity-gateway helm chart

Native Helm chart subtree. Shared chart rules live in `deploy/helm/AGENTS.md`.

## Chart Facts

- Subproject id: `vanity-gateway-helm`
- Chart name: `helm-nvcf-vanity-gateway`
- Chart directory: `helm-nvcf-vanity-gateway`
- CI values: `tools/ci/helm-validate-values/vanity-gateway.yaml`
- Release service name: `helm-nvcf-vanity-gateway`
- Initial release version: not yet assigned. See "Versioning" below.

## Provenance

This chart was recovered from the published OCI artifact
`helm-nvcf-vanity-gateway:0.1.0-nvcf-10204.1`. No source tree for it existed in
this repo or in any known upstream project, so the imported files are the
unpacked contents of that artifact plus the sibling scaffolding in this
directory. `.helmignore` is not carried in a packaged chart and was added here
to match the other chart subtrees.

## Versioning

The imported `Chart.yaml` still carries the published version
`0.1.0-nvcf-10204.1` and appVersion `1.25.0-nvcf-10204.0`. Neither is a form the
repo release tooling accepts, so no release lane is registered for this chart
and no tag exists. Renumber `version` to a plain `X.Y.Z` before wiring a
release lane.

## Validate

```bash
helm lint helm-nvcf-vanity-gateway -f ../../../tools/ci/helm-validate-values/vanity-gateway.yaml
helm template vanity-gateway helm-nvcf-vanity-gateway -f ../../../tools/ci/helm-validate-values/vanity-gateway.yaml
```

The chart renders with defaults alone, but `vanityGateway.image.registry` is
empty by default and yields an unqualified image reference, so a values
override is used for validation.

`values.schema.json` sets `additionalProperties: false` on `vanityGateway` and
on most of its sub-objects. Adding a value key requires a matching schema
change or the render fails.

This chart pairs with the service image source at
`src/invocation-plane-services/vanity-gateway`, whose service name is
`nvcf-ai-api-gateway-service`. Route configuration for the gateway in front of
it lives in `deploy/helm/gateway-routes`.
1 change: 1 addition & 0 deletions deploy/helm/vanity-gateway/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@AGENTS.md
109 changes: 109 additions & 0 deletions deploy/helm/vanity-gateway/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 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
#
# https://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.

# Variables
release ?= vanity-gateway
namespace ?= nvcf
helm_dir ?= ./helm-nvcf-vanity-gateway
values := $(helm_dir)/values.yaml

# OPTIONAL for deploy target: Path to an additional Helm values file.
# Example: make deploy values=my-values.yaml additional_values=override.yaml
additional_values ?=

# Values used only for local lint/template/validate rendering. The default
# values.yaml leaves vanityGateway.image.registry empty, so rendering with
# defaults alone produces an unqualified image reference. Point at the CI
# validation values by default. Matches the documented helm commands in
# AGENTS.md. Deployment targets keep using $(values).
validation_values ?= ../../../tools/ci/helm-validate-values/vanity-gateway.yaml

# OCI Registry details
OCI_REGISTRY_HOST ?= nvcr.io
OCI_REGISTRY_NAMESPACE ?= 0651155215864979/ncp-dev

# Automatically determine chart name and version from Chart.yaml
# IMPORTANT: For this setup, CHART_NAME is expected to include any desired OCI prefix (e.g., "helm-yourchart")
# as defined in helm/Chart.yaml's 'name' field.
CHART_NAME := $(shell yq -r .name $(helm_dir)/Chart.yaml)
CHART_VERSION := $(shell yq -r .version $(helm_dir)/Chart.yaml)

.PHONY: install uninstall status lint template validate clean package push-oci

install:
ifndef values
$(error "values" variable is not set. Please specify with 'make deploy values=<path-to-your-values.yaml>')
endif
@echo "Deploying $(release) to namespace $(namespace) using values file '$(values)'..."
@echo "Additional values file: '$(if $(additional_values),$(additional_values),N/A)'"
helm install $(release) $(helm_dir) \
--namespace $(namespace) \
--values $(values) \
$(if $(additional_values),--values $(additional_values),) \
--atomic \
--create-namespace \
--wait \
--wait-for-jobs \
--timeout 20m

uninstall:
@echo "Deleting $(release) from namespace $(namespace)..."
helm uninstall $(release) --namespace $(namespace)

status:
@echo "Checking status of $(release) in namespace $(namespace)..."
helm status $(release) --namespace $(namespace)

lint:
@echo "Linting chart $(helm_dir)..."
helm lint $(helm_dir) \
$(if $(validation_values),--values $(validation_values),) \
$(if $(additional_values),--values $(additional_values),)

template:
@echo "Templating chart $(helm_dir)..."
@mkdir -p bin
helm template $(release) $(helm_dir) \
--namespace $(namespace) \
$(if $(validation_values),--values $(validation_values),) \
$(if $(additional_values),--values $(additional_values),) \
> bin/manifest.yaml
@echo "Rendered manifest to bin/manifest.yaml"

validate: template
@echo "Validating manifest with kubeconform..."
@kubeconform -strict -summary -output pretty -kubernetes-version 1.31.5 bin/manifest.yaml

# Publish Chart
# NOTE: this is manual until the CI pipeline is updated to push the chart to the NVCR OCI registry
clean:
rm -rf ./packaged-charts
Comment thread
coderabbitai[bot] marked this conversation as resolved.

package: clean lint
@echo "[package] Packaging Helm chart $(CHART_NAME) version $(CHART_VERSION)..."
@mkdir -p ./packaged-charts
@helm package $(helm_dir) -d ./packaged-charts/
@echo "[package] Packaged chart to ./packaged-charts/$(CHART_NAME)-$(CHART_VERSION).tgz"

push-oci:
@echo "[push-oci] Pushing chart $(CHART_NAME) version $(CHART_VERSION) to oci://$(OCI_REGISTRY_HOST)/$(OCI_REGISTRY_NAMESPACE)/$(CHART_NAME):$(CHART_VERSION)"
@echo "[push-oci] Note: You must be logged into oci://$(OCI_REGISTRY_HOST) for the push to succeed."
@if [ ! -f ./packaged-charts/$(CHART_NAME)-$(CHART_VERSION).tgz ]; then \
echo "[push-oci] Error: Packaged chart ./packaged-charts/$(CHART_NAME)-$(CHART_VERSION).tgz not found. Run 'make package' first."; \
exit 1; \
fi
@helm push ./packaged-charts/$(CHART_NAME)-$(CHART_VERSION).tgz oci://$(OCI_REGISTRY_HOST)/$(OCI_REGISTRY_NAMESPACE)
@echo "[push-oci] Successfully pushed chart to OCI registry."
@echo "[push-oci] Preserved packaged chart at ./packaged-charts/$(CHART_NAME)-$(CHART_VERSION).tgz (run 'make clean' to remove)."
126 changes: 126 additions & 0 deletions deploy/helm/vanity-gateway/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# NVCF Vanity Gateway Helm Chart

This directory contains the Helm chart for deploying the NVCF Vanity Gateway on
Kubernetes. The Vanity Gateway maps OpenAI-compatible and vanity URL routes onto
NVCF function invocations.

## Overview

The chart renders a Deployment, a Service, a ServiceAccount, two ConfigMaps (one
for environment configuration, one for the route mapping file), and an optional
ServiceMonitor.

The route mapping is supplied through `vanityGateway.mappingConfig`, which is
serialized into `config.yaml` and mounted at
`/etc/vanity-gateway/config/config.yaml`. The defaults ship an empty mapping, so
routes must be provided through an override values file.

The default values leave `vanityGateway.image.registry` empty. Set the registry,
and the tag if you do not want the chart `appVersion`, in your override file.

```yaml
vanityGateway:
image:
registry: <your-registry>
repository: nvcf-ai-api-gateway-service
tag: <appVersion>
```

## Prerequisites

- Kubernetes cluster
- Helm 3.x
- `kubectl`
- A reachable NVCF invocation endpoint, set through
`vanityGateway.config.nvcfApiEndpoint`
- The Prometheus Operator CRDs, only if `vanityGateway.serviceMonitor.enabled`
is `true`

## Getting Started

Install the chart with the default values plus your own overrides:

```bash
helm install vanity-gateway helm-nvcf-vanity-gateway \
--namespace nvcf \
--create-namespace \
--values helm-nvcf-vanity-gateway/values.yaml \
--values path/to/values.yaml \
--wait \
--timeout 10m
```

Upgrade an existing release:

```bash
helm upgrade vanity-gateway helm-nvcf-vanity-gateway \
--namespace nvcf \
--values helm-nvcf-vanity-gateway/values.yaml \
--values path/to/values.yaml \
--wait \
--timeout 10m
```

Uninstall the release:

```bash
helm uninstall vanity-gateway --namespace nvcf
```

## Configuration

The default chart configuration lives in
`helm-nvcf-vanity-gateway/values.yaml`, and `values.schema.json` constrains it.
The schema sets `additionalProperties: false` on `vanityGateway` and most of its
sub-objects, so an unrecognized key fails the render rather than being ignored.

Important settings to review before deployment:

- `vanityGateway.image.*` for the container image
- `vanityGateway.imagePullSecrets` for private registry access
- `vanityGateway.replicaCount`, resource requests, and limits for your
environment
- `vanityGateway.config.nvcfApiEndpoint` for the invocation endpoint
- `vanityGateway.config.otelExporterOtlpEndpoint` for trace export, empty by
default
- `vanityGateway.mappingConfig.v2config` for the OpenAI and vanity route tables
- `vanityGateway.serviceMonitor.enabled` for Prometheus Operator scraping

### Ports

The container listens on 10081 for traffic and 10083 for admin and metrics. The
Service exposes those as `httpPort` (8080 by default) and `adminPort` (10083 by
default). Metrics are scraped from `/metrics` on the admin port, and the health
probes use `/health` on the traffic port.

### Shutdown

`vanityGateway.shutdown` controls draining. `preStopSleepSeconds` (70 by
default) is how long the preStop hook sleeps before the container is signaled,
which lets in-flight and newly routed requests settle.
`terminationGracePeriodSeconds` (330 by default) must stay comfortably above it,
or the pod is killed mid-drain.

## Route mapping

`vanityGateway.mappingConfig.v2config` has two sections:

- `openai`: per-endpoint model routes, keyed by endpoint (`chatCompletions`,
`completions`, `embeddings`, `responses`, and the image endpoints). Each route
requires `modelName` and `functionID`, and supports shadow-traffic fields such
as `shadowModelName`, `shadowPercentage`, and
`shadowCancelOnClientDisconnect`.
- `vanity`: host-based routes, each requiring a `host` and a `paths` map. Each
path requires `path` and `functionID`.

Both sections are empty by default. `vanityGateway.config.shadowMaxConcurrent`
bounds concurrent shadow requests across all routes.

## Notes

- The chart version and appVersion carry the versions of the published artifact
this chart was recovered from. They are not in a form the repo release tooling
accepts, and no release lane is registered. See `AGENTS.md`.
- If you publish or mirror the required images into another registry, set the
image registry, repository, tag, and pull secret values explicitly in your
override file.
23 changes: 23 additions & 0 deletions deploy/helm/vanity-gateway/helm-nvcf-vanity-gateway/.helmignore
Original file line number Diff line number Diff line change
@@ -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/
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: v2
appVersion: 1.32.1
description: Helm chart for the NVCF Vanity Gateway
name: helm-nvcf-vanity-gateway
type: application
version: 0.1.0-nvcf-10204.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{{/*
SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
SPDX-License-Identifier: Apache-2.0
*/}}

{{- define "vanity-gateway.name" -}}
{{- default .Chart.Name .Values.vanityGateway.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{- define "vanity-gateway.fullname" -}}
{{- if .Values.vanityGateway.fullnameOverride -}}
{{- .Values.vanityGateway.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.vanityGateway.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}

{{- define "vanity-gateway.labels" -}}
helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" | quote }}
{{ include "vanity-gateway.selectorLabels" . }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end -}}

{{- define "vanity-gateway.selectorLabels" -}}
app.kubernetes.io/name: {{ include "vanity-gateway.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end -}}

{{- define "vanity-gateway.serviceAccountName" -}}
{{- if .Values.vanityGateway.serviceAccount.create -}}
{{- default (include "vanity-gateway.fullname" .) .Values.vanityGateway.serviceAccount.name -}}
{{- else -}}
{{- default "default" .Values.vanityGateway.serviceAccount.name -}}
{{- end -}}
{{- end -}}

{{- define "vanity-gateway.image" -}}
{{- $registry := trimSuffix "/" .Values.vanityGateway.image.registry -}}
{{- $repository := required "A valid image repository (.Values.vanityGateway.image.repository) is required!" .Values.vanityGateway.image.repository -}}
{{- $tag := default .Chart.AppVersion .Values.vanityGateway.image.tag -}}
{{- if $registry -}}
{{- printf "%s/%s:%s" $registry $repository $tag -}}
{{- else -}}
{{- printf "%s:%s" $repository $tag -}}
{{- end -}}
{{- end -}}
Loading
Loading