This documentation is now organized around EdgeLLM Observability: private LLM deployment and observability on NVIDIA-powered Linux edge devices using k3s, Helm, GGUF/Ollama, OpenTelemetry GenAI-instrumented tracing, Prometheus/Grafana, and NVIDIA GPU metrics.
Use this document as the deep reference after the focused guides:
EdgeLLM Observability Platform uses the llm-observability-stack Helm chart as its open-source
deployment engine. It targets NVIDIA-powered Linux laptops, workstations, and small edge clusters,
with a credible path to GPU Operator/DCGM, NIM, and cloud GPU fleets.
Primary goals:
- Run local LLM inference with Ollama using GGUF models.
- Provide UI access through Open WebUI.
- Provide an API integration surface through a native Go Ollama gateway.
- Provide observability and connectivity triage vian OpenTelemetry and an in-cluster Go edge toolbox.
The current implementation is a local-ready, production-oriented reference architecture with a verified local edge profile. It is not yet customer-production-proven and requires workload-specific security, reliability, storage, and scale validation.
- Umbrella chart:
llm-observability-stack - Vendored dependency charts:
charts/ollamacharts/open-webui
- Custom glue resources in
templates/:- OpenTelemetry Secret (optional)
- Open WebUI Secret (optional)
- Ollama Modelfile ConfigMap
- Ollama gateway app ConfigMap (optional mount-over-image mode)
- Ollama gateway Deployment + Service
- Go edge toolbox Deployment (optional)
- OpenTelemetry dashboard seeder CronJob (optional)
- Optional Redis Deployment/Service/PVC/Secret
- Optional etcd StatefulSet + Services
- User -> Open WebUI (
open-webui:8080) - Open WebUI -> Ollama gateway (
ollama-gateway:8000/ollama) - Ollama gateway -> Ollama (
OLLAMA_UPSTREAM_BASE_URL=http://ollama:11434) - Ollama gateway -> OpenTelemetry API for proxy traces (when configured)
- Optional Go edge toolbox -> OpenTelemetry API (when enabled)
- Open WebUI websocket manager -> Redis
- Default: subchart
open-webui-redis - Optional: custom
redisresource from root templates
- Default: subchart
llm-observability-stack/
├── Chart.yaml
├── Chart.lock
├── values.yaml
├── values.local-k3s.example.yaml
├── values.local-k3s.yaml # local only, gitignored
├── templates/ # root custom manifests
├── charts/
│ ├── ollama/ # vendored dependency
│ └── open-webui/ # vendored dependency
├── ollama-gateway/ # native Go gateway image source
├── edge-toolbox/ # debug image source + scripts
├── hack/ # local image build/import helpers
├── files/ # pre/post change cluster snapshots
└── docs/ # documentation
- Deployed via vendored Ollama chart.
- GPU support enabled by values.
- Model creation at startup from ConfigMap-backed Modelfile.
- Persistent model storage with PVC (
local-pathby default).
Key value paths:
ollama.enabledollama.runtimeClassNameollama.ollama.gpu.*ollama.ollama.models.create[]ollama.persistentVolume.*ollama.volumes[]andollama.volumeMounts[]
- Deployed via vendored Open WebUI chart.
- Configured to use Ollama endpoint in-cluster.
- Websocket support enabled.
- Persistence enabled using PVC.
Key value paths:
- Dependency gate:
openWebUI.enabled - Subchart runtime config:
open-webui.* - Secret input wrapper:
openWebUI.webuiSecretKeyandopenWebUI.existingSecret
- Containerized native Go gateway in
cmd/ollama-gatewayandinternal/gateway. - Exposes:
GET /GET /healthzGET /configPOST /invoke
- Uses
langchain-ollama(ChatOllama) against Ollama API. - Can emit tracing to OpenTelemetry when API key is configured.
- Utility pod for in-cluster diagnosis.
- Ships troubleshooting scripts for:
- DNS/service checks
- Ollama chat smoke
- Redis ping
- OpenTelemetry API health
- Disabled by default.
- If enabled, deploys Secret + ConfigMap + PVC + Deployment + Service.
- Supports Redis ACL auth (
redis.auth.enabled=true).
- Disabled by default.
- Deploys single or multi replica StatefulSet depending on
etcd.replicaCount. - Intended for targeted troubleshooting scenarios.
Use a layered values strategy:
values.yaml: non-secret, stable defaults tracked in git.values.enterprise-pilot-k3s.yaml: verified local single-node k3s/NVIDIA profile.values.local-k3s.example.yaml: sanitized local template tracked in git.values.local-k3s.yaml: machine + secret overrides, gitignored.
Recommended verified local install command:
helm upgrade --install llm-observability-stack . \
-n llm-observability --create-namespace \
-f values.enterprise-pilot-k3s.yaml \
--set kube-prometheus-stack.crds.enabled=falseIf you install an existing release with a private values.local-k3s.yaml, keep the ollama.persistentVolume.size value aligned with the existing ollama PVC. The k3s local-path provisioner does not resize that PVC in place.
- k3s cluster running and reachable by
kubectl - NVIDIA runtime configured on node
- NVIDIA device plugin healthy in cluster
- Helm 3 installed
- Docker or nerdctl available for local image workflows
- GGUF model file available on host filesystem
Quick prerequisite checks:
kubectl cluster-info
kubectl get nodes -o wide
kubectl get pods -n nvidia-device-plugin
helm version./hack/build-local-image.sh ollama-gateway 0.2.0 . ollama-gateway/Dockerfile
./hack/build-local-image.sh edge-toolbox 0.2.0 . edge-toolbox/Dockerfile./hack/import-local-image-to-k3s.sh ollama-gateway 0.2.0
./hack/import-local-image-to-k3s.sh edge-toolbox 0.2.0sudo k3s ctr images ls | grep -E 'ollama-gateway|edge-toolbox'helm lint .
helm template llm-observability-stack . > /tmp/rendered-default.yaml
helm template llm-observability-stack . -f values.local-k3s.example.yaml > /tmp/rendered-example.yaml
helm template llm-observability-stack . \
-n llm-observability \
-f values.enterprise-pilot-k3s.yaml \
--set kube-prometheus-stack.crds.enabled=false \
> /tmp/rendered-enterprise-pilot.yamlhelm upgrade --install llm-observability-stack . \
-n llm-observability --create-namespace \
-f values.enterprise-pilot-k3s.yaml \
--set kube-prometheus-stack.crds.enabled=falsekubectl get all -n llm-observability
kubectl get pvc -n llm-observability
kubectl get pods -n llm-observability -o wide
kubectl get svc -n llm-observabilityhelm upgrade llm-observability-stack . \
-n llm-observability \
-f values.enterprise-pilot-k3s.yaml \
--set kube-prometheus-stack.crds.enabled=falsehelm history llm-observability-stack -n llm-observability
helm rollback llm-observability-stack <REVISION> -n llm-observabilityTypical service endpoints in namespace:
- Ollama:
http://ollama:11434 - Open WebUI:
http://open-webui:8080 - Ollama gateway:
http://ollama-gateway:8000
Local access options:
- expose only required services as
LoadBalancerin local k3s overrides - or
kubectl port-forward
Example:
kubectl port-forward -n llm-observability svc/open-webui 8080:8080
kubectl port-forward -n llm-observability svc/ollama 11434:11434
kubectl port-forward -n llm-observability svc/ollama-gateway 8000:8000kubectl get pods -n llm-observability
kubectl logs -n llm-observability deploy/ollama-gateway --tail=100
kubectl logs -n llm-observability deploy/ollama --tail=100
kubectl logs -n llm-observability statefulset/open-webui --tail=100kubectl port-forward -n llm-observability svc/ollama-gateway 8000:8000
curl -s http://localhost:8000/healthz | jq
curl -s http://localhost:8000/config | jq
curl -s http://localhost:8000/invoke \
-H 'Content-Type: application/json' \
-d '{"prompt":"Say hello in one short sentence."}' | jqOnly when edgeToolbox.enabled=true.
kubectl exec -it -n llm-observability deploy/edge-toolbox -- bash
edge-toolbox dns ollama ollama-gateway open-webui open-webui-redis
edge-toolbox http http://ollama:11434/api/tags
edge-toolbox redis-ping
edge-toolbox ollama-smoke
edge-toolbox seed --count 2- Keep secrets only in local untracked files or external secrets.
- Do not commit real values in
values.local-k3s.yaml. - Never print or paste secret values into issue trackers.
- Consider using
existingSecretreferences backed by manually managed Kubernetes secrets. - Restrict service exposure when not required (avoid broad
LoadBalancerin shared environments).
Cause:
- local images were not built/imported to k3s runtime.
Fix:
./hack/build-local-image.sh ollama-gateway 0.2.0 . ollama-gateway/Dockerfile
./hack/import-local-image-to-k3s.sh ollama-gateway 0.2.0
./hack/build-local-image.sh edge-toolbox 0.2.0 . edge-toolbox/Dockerfile
./hack/import-local-image-to-k3s.sh edge-toolbox 0.2.0
kubectl rollout restart deploy/ollama-gateway -n llm-observability
# only if enabled
kubectl rollout restart deploy/edge-toolbox -n llm-observabilityCause:
- GGUF host path mismatch or model filename mismatch.
Fix:
kubectl describe pod -n llm-observability deploy/ollama
kubectl logs -n llm-observability deploy/ollama --tail=200
kubectl exec -it -n llm-observability deploy/ollama -- ls -lah /models/gguf
kubectl exec -it -n llm-observability deploy/ollama -- ollama listCause:
- service DNS mismatch, endpoint not ready, or wrong
ollamaUrls.
Fix:
kubectl get svc -n llm-observability ollama open-webui
kubectl get endpoints -n llm-observability ollama open-webui
kubectl exec -it -n llm-observability deploy/edge-toolbox -- edge-toolbox dns ollama ollama-gateway open-webui open-webui-redisCause:
- mismatch between Open WebUI websocket URL and deployed Redis mode.
Fix:
kubectl get deploy,svc -n llm-observability | grep -E 'open-webui-redis|redis'
kubectl logs -n llm-observability statefulset/open-webui --tail=200
kubectl logs -n llm-observability deploy/redis --tail=200Default persisted data:
- Ollama model/data PVC
- Open WebUI PVC
- Optional Redis PVC
- Optional etcd PVCs
Check storage state:
kubectl get pvc -n llm-observability
kubectl describe pvc -n llm-observability- CI currently validates Helm syntax and rendering.
- Refer to
docs/GITHUB-PUBLISHING.mdfor publish process. - Use issue/PR templates in
.github/for reproducible reports.
docs/KUBECTL-COMMAND-REFERENCE.mddocs/KUBERNETES-NETWORKING.mddocs/GO-KUBERNETES-AUTOMATION.mddocs/GITHUB-PUBLISHING.md