Posted on
Artificial Intelligence

Artificial Intelligence Helm Best Practices

Author
  • User
    linuxbash
    Posts by this author
    Posts by this author

Artificial Intelligence Helm Best Practices: Ship Reliable AI on Kubernetes (from Your Bash Shell)

AI apps are hungry for GPUs, data, and fast iteration. Kubernetes can give you scale and resilience—but YAML sprawl and environment drift can turn your day into fire-fighting. Helm changes that. With a few sane patterns, you can package, version, and promote AI workloads across dev, staging, and prod without guesswork.

This guide explains why Helm is the right tool for AI on Kubernetes and gives you actionable best practices you can apply today, from GPU-aware scheduling to safe rollouts. You’ll also get ready-to-run Bash commands and distro‑specific install steps.


Why Helm for AI?

  • Reproducibility: Charts freeze app, infra, and configuration into versioned, auditable bundles.

  • Environment parity: Values files let you cleanly separate dev/stage/prod without forking templates.

  • Upgrades and rollbacks: One command to migrate, diff, and roll back when something misbehaves.

  • Team velocity: Share best-practice templates for GPUs, storage, and observability across teams.


Prerequisites (Bash-friendly)

You need kubectl and Helm on your workstation, plus a Kubernetes cluster with node access. Replace v1.30 below to match your cluster’s minor version.

Install kubectl:

  • Debian/Ubuntu (apt)
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg
sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key
echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubectl
  • Fedora/RHEL/CentOS (dnf)
sudo rpm --import https://pkgs.k8s.io/core:/stable:/v1.30/rpm/repodata/repomd.xml.key
cat <<'EOF' | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.30/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.30/rpm/repodata/repomd.xml.key
EOF
sudo dnf install -y kubectl
  • openSUSE/SLES (zypper)
sudo rpm --import https://pkgs.k8s.io/core:/stable:/v1.30/rpm/repodata/repomd.xml.key
sudo zypper addrepo https://pkgs.k8s.io/core:/stable:/v1.30/rpm/ kubernetes
sudo zypper refresh
sudo zypper install -y kubectl

Install Helm:

  • Debian/Ubuntu (apt)
sudo apt-get update
sudo apt-get install -y apt-transport-https curl gnupg
curl https://baltocdn.com/helm/stable/debian/helm-signing.gpg | sudo gpg --dearmor -o /usr/share/keyrings/helm.gpg
echo "deb [signed-by=/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
sudo apt-get update
sudo apt-get install -y helm
  • Fedora/RHEL/CentOS (dnf)
sudo rpm --import https://baltocdn.com/helm/stable/rpm/repodata/repomd.xml.key
cat <<'EOF' | sudo tee /etc/yum.repos.d/helm.repo
[helm]
name=Helm Stable
baseurl=https://baltocdn.com/helm/stable/rpm
enabled=1
gpgcheck=1
gpgkey=https://baltocdn.com/helm/stable/rpm/repodata/repomd.xml.key
EOF
sudo dnf install -y helm
  • openSUSE/SLES (zypper)
sudo rpm --import https://baltocdn.com/helm/stable/rpm/repodata/repomd.xml.key
sudo zypper addrepo https://baltocdn.com/helm/stable/rpm/ helm-stable
sudo zypper refresh
sudo zypper install -y helm

Quick checks:

helm version
kubectl version --client
kubectl get nodes -o wide

GPU clusters need the NVIDIA device plugin. If you use GPUs:

helm repo add nvidia https://nvidia.github.io/k8s-device-plugin
helm repo update
helm install nvidia-device-plugin nvidia/k8s-device-plugin -n kube-system

5 Helm Best Practices for AI Workloads

1) Treat charts as products: version, sign, and store in an OCI registry

  • Pin app and chart versions. Set appVersion in Chart.yaml to the container tag you actually deploy.

  • Push charts to OCI registries for immutable, scoped access control.

Example:

# Package and push a chart to GHCR
helm package charts/ai-inference
helm registry login ghcr.io -u YOUR_GH_USER
helm push ai-inference-0.1.0.tgz oci://ghcr.io/YOUR_ORG/charts

# Pull with exact version in CI/CD
helm pull oci://ghcr.io/YOUR_ORG/charts/ai-inference --version 0.1.0

Why it matters: Teams can promote the exact artifact from staging to prod, preventing “works on my machine” drift.


2) Make GPU scheduling first‑class in values.yaml

AI services need predictable GPU, CPU, and memory reservations, plus tolerations and selectors.

values.gpu.yaml:

resources:
  requests:
    cpu: "2"
    memory: "8Gi"
    nvidia.com/gpu: 1
  limits:
    cpu: "4"
    memory: "16Gi"
    nvidia.com/gpu: 1

nodeSelector:
  nvidia.com/gpu.present: "true"

tolerations:
  - key: "nvidia.com/gpu"
    operator: "Exists"
    effect: "NoSchedule"

Apply with:

helm upgrade --install ai-svc ./charts/ai-inference -f values.gpu.yaml

Why it matters: Without requests/limits and proper scheduling, autoscaling, binpacking, and QoS become unpredictable—kryptonite for latency-sensitive inference.


3) Design for data gravity: PVCs, object storage, and model preload

Models and datasets are big. Make data locality explicit.

values.storage.yaml:

persistence:
  enabled: true
  existingClaim: ""         # or leave blank to create
  size: 200Gi
  storageClassName: "fast-ssd"

env:
  - name: MODEL_ID
    value: meta-llama/Llama-2-7b-hf

volumeMounts:
  - name: models
    mountPath: /models

volumes:
  - name: models
    persistentVolumeClaim:
      claimName: {{ include "ai-inference.fullname" . }}-models

initContainers:
  - name: fetch-model
    image: ghcr.io/yourorg/model-sync:latest
    env:
      - name: MODEL_ID
        valueFrom:
          secretKeyRef:
            name: hf-credentials
            key: model-id
    volumeMounts:
      - name: models
        mountPath: /models

Why it matters: Preloading models on PVCs slashes cold-starts. Using initContainers decouples model acquisition from your main image and lets you rotate credentials safely.


4) Keep environments clean: layer values and externalize secrets

  • Use a base values.yaml plus small env overlays:
helm upgrade --install ai-svc ./charts/ai-inference \
  -f values.yaml \
  -f values.gpu.yaml \
  -f values.prod.yaml
  • Don’t commit secrets. Create them once and reference them:
kubectl create secret generic hf-credentials \
  --from-literal=model-id=meta-llama/Llama-2-7b-hf \
  -n ai

values.yaml (reference only):

envFrom:
  - secretRef:
      name: hf-credentials

Why it matters: Values layering prevents copy-paste environments. Secrets live in your cluster’s secret manager, not in Git.


5) Upgrade safely: diff, probe, and roll back fast

  • Lint and dry-run against the API server before you touch live objects:
helm lint ./charts/ai-inference
helm template ai-svc ./charts/ai-inference -f values.prod.yaml | kubectl apply -n ai --dry-run=server -f -
  • Use helm-diff to preview changes:
helm plugin install https://github.com/databus23/helm-diff
helm diff upgrade ai-svc ./charts/ai-inference -f values.prod.yaml
  • Ensure health checks are accurate (don’t just probe TCP 80): values.yaml
readinessProbe:
  httpGet:
    path: /healthz
    port: http
  initialDelaySeconds: 10
  periodSeconds: 5
livenessProbe:
  httpGet:
    path: /livez
    port: http
  initialDelaySeconds: 30
  periodSeconds: 10
  • Roll back instantly if SLOs degrade:
helm rollback ai-svc  # or specify a revision: helm history ai-svc

Why it matters: Diffs prevent surprise mutations; probes ensure rollouts only proceed when your model is actually serving; rollbacks buy you time.


Real‑world quickstart: Scaffold an AI inference chart

Create a new chart and wire in AI‑friendly defaults.

1) Scaffold:

helm create ai-inference

2) Set your image and GPU resources in values.yaml:

image:
  repository: nvcr.io/nvidia/tritonserver
  tag: 23.10-py3
  pullPolicy: IfNotPresent

command: ["/opt/tritonserver/bin/tritonserver"]
args:
  - "--model-repository=/models"

resources:
  requests:
    cpu: "2"
    memory: "8Gi"
    nvidia.com/gpu: 1
  limits:
    cpu: "4"
    memory: "16Gi"
    nvidia.com/gpu: 1

nodeSelector:
  nvidia.com/gpu.present: "true"

tolerations:
  - key: "nvidia.com/gpu"
    operator: "Exists"
    effect: "NoSchedule"

service:
  type: ClusterIP
  port: 8000

volumeMounts:
  - name: models
    mountPath: /models
volumes:
  - name: models
    persistentVolumeClaim:
      claimName: ai-models-pvc

3) Create a models PVC and deploy:

kubectl apply -n ai -f - <<'EOF'
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ai-models-pvc
  namespace: ai
spec:
  accessModes: ["ReadWriteOnce"]
  resources:
    requests:
      storage: 200Gi
  storageClassName: fast-ssd
EOF

helm upgrade --install ai-svc ./ai-inference -n ai --create-namespace
kubectl rollout status deploy/ai-svc -n ai

4) Verify:

kubectl get pods -n ai -o wide
kubectl logs -n ai deploy/ai-svc | tail -n +1

Optional: expose via a LoadBalancer or Ingress once you’ve validated internal traffic.


Conclusion and Next Steps

Helm turns AI deployment from artisanal YAML into a disciplined release process:

  • Package and store charts like real artifacts.

  • Encode GPU, data, and health as values—not tribal knowledge.

  • Upgrade with diffs and rollbacks, not hope.

Your next step:

  • Install kubectl and Helm (commands above).

  • Scaffold a chart with helm create and add GPU resources, storage, and probes.

  • Wire CI to run helm lint, helm template | kubectl --dry-run=server, and helm diff.

  • Promote the same chart through environments with layered values.

Have a favorite AI stack (Ray, Triton, TGI) you want Helmified? Tell me what you’re running, and I’ll share a tuned values.yaml you can drop into prod.