Local Development (k3d)
Local Development (k3d)
Run the full NVCF self-hosted control plane on your laptop using k3d for development, testing, or demos.
This setup is for local development only. It uses fake GPUs, a single Cassandra replica, and ephemeral storage. Do not use this for production workloads.
Assumptions
This guide assumes:
- Helm charts are pulled from the NGC registry (
nvcr.io/0833294136851237/nvcf-ncp-staging) - Container images are pulled from the same NGC registry
- Image pull secrets are configured in the environment YAML using
imagePullSecretsto authenticate with NGC
If you are using a different registry (e.g., Amazon ECR, a private Harbor instance, or a
local mirror), update the helm.sources and image sections in the environment file
and adjust the pull secret configuration accordingly. See self-hosted-image-mirroring
for details on mirroring artifacts to other registries.
A ready-to-use k3d configuration and setup script is available in the
nv-cloud-function-helpers
repository. Clone it and run ./setup.sh to create the cluster with all prerequisites,
then skip to [Deploy the NVCF Stack].
Prerequisites
Install the following tools:
- Docker (running)
- k3d v5.x or later
kubectlhelm>= 3.12helmfile>= 1.1.0, < 1.2.0helm-diffplugin (helm plugin install https://github.com/databus23/helm-diff)- NGC API Key from ngc.nvidia.com with access to the NVCF chart/image registry
Step 1: Create the k3d Cluster
Save the following configuration as k3d-config.yaml:
This creates a 6-node cluster: 1 server (control plane) and 5 agents. Agents 3 and 4 are pre-labeled for the fake GPU operator. Traefik is disabled because NVCF uses Envoy Gateway.
Create the cluster:
Verify:
Step 2: Install the Fake GPU Operator
The fake GPU operator simulates GPU resources on the pre-labeled nodes so the NVCA agent can discover them. See fake-gpu-operator for full details.
Verify fake GPUs appear on the labeled nodes:
Step 3: Install CSI SMB Driver
The CSI SMB driver is required for NVCA shared model cache storage:
Deploy the NVCF Stack
With the cluster ready, follow the helmfile-installation guide. The steps below call out the local-specific differences for each step.
Step 1 (Ingress)
Follow as documented, but skip the cloud-provider annotations on the Gateway resource.
k3d handles LoadBalancer services automatically via its built-in klipper-lb.
Step 2 (Environment file)
Create a local development environment file from the template below
(local-dev-env.yaml).
Save it as environments/<name>.yaml (e.g., environments/my-local.yaml) in your
nvcf-self-managed-stack directory.
This template is pre-configured for local development:
- Storage:
local-path(2Gi volumes, the default k3d StorageClass) - Cassandra: Single replica with fast startup JVM options
- Node selectors: Disabled (pods schedule on any available node)
- Registry:
nvcr.io/0833294136851237/nvcf-ncp-staging - Gateway:
nvcf-gatewayinenvoy-gatewaynamespace (matches Step 1) - Domain:
localhost - imagePullSecrets: Pre-configured to reference
nvcr-pull-secret(created in Step 4)
Step 3 (Secrets)
Create secrets/<name>-secrets.yaml (e.g., secrets/my-local-secrets.yaml) from
the template in the control plane guide. The file name must match your environment name.
Fill in your NGC base64-encoded credentials for the NGC org you’ll be deploying function images from:
Step 4 (Pull secrets)
Run the helper script to create the nvcr-pull-secret Kubernetes secret in all NVCF namespaces:
The environment file template from Step 2 already references this secret via imagePullSecrets.
Step 5 (Deploy)
Authenticate helm and deploy using your environment name:
Replace <name> with the name you chose for your environment file (e.g., my-local).
Step 6 (Verify)
Check that all pods are running:
Verify the NVCA agent discovered the fake GPUs:
Verify API connectivity using the .localhost routing (not the Gateway address, which
is cluster-internal on k3d):
The standard control plane verification commands use the Gateway address from
kubectl get gateway. On k3d this returns a cluster-internal IP that is not reachable
from the host. Use localhost:8080 with .localhost hostnames instead, as shown above.
Accessing Routes Locally
NVCF routes use the .localhost top-level domain, which resolves to 127.0.0.1
automatically on most systems. Access services via the k3d load balancer on port 8080:
http://api.localhost:8080— NVCF APIhttp://api-keys.localhost:8080— API Keys servicehttp://invocation.localhost:8080— Function invocation
If .localhost does not resolve automatically, add entries to /etc/hosts:
Wildcard subdomains (e.g., <function-id>.invocation.localhost) cannot be added to
/etc/hosts. For local testing with dynamic function IDs, add specific entries or use
a local DNS resolver such as dnsmasq.
Teardown
Limitations
- Fake GPUs — Function containers will be scheduled and deployed but cannot execute actual GPU workloads.
- Single Cassandra replica — No high availability. Data may be lost on pod restart.
- Ephemeral storage —
local-pathvolumes are deleted when the cluster is destroyed. - Not suitable for performance testing — Resource constraints of a laptop do not represent production environments.