TL;DR Ik heb K8sGPT op een Llama 3.3 70B-model gezet dat op een Mac Studio in m’n eigen kantoor draait, zodat er geen clustermetadata het netwerk verlaat, en er drie kapotte workloads doorheen gehaald. Alle drie gevonden, en de fixes die het schreef had ik van een collega geaccepteerd, op de resource-getallen na, want die waren verzonnen. Assisted diagnose werkt, met 25 seconden per query. Autonomous cluster management is nog steeds marketing, en de security-sectie is waarom ik een model niks op eigen houtje zou laten aanpassen.
Elk vendor-pitchdeck heeft op dit moment dezelfde slide. “Autonomous cluster management.” Een AI kijkt naar je Kubernetes-cluster, ziet het probleem, stelt de diagnose en fixt het terwijl jij slaapt. Platform engineers stoppen met brandjes blussen en het cluster geneest zichzelf.
Ik draai een homelab omdat ik wil weten wat erin gebeurt. Dus zo’n slide wil ik eerst zelf draaien voordat ik ’m geloof.
Het addertje bij de meeste van die tools is wat “AI” blijkt te betekenen als je de kleine lettertjes leest. Het betekent dat je clustermetadata naar OpenAI gaat. Podnamen, labels, foutmeldingen, alles. Ik self-host juist zodat die data op m’n eigen netwerk blijft, en een AIOps-verhaal dat pas werkt als ik dat aan een derde partij geef, heeft mij niks te bieden.
Dus dit is de versie die ik wilde proberen. K8sGPT gericht op een Llama 3.3 70B-model dat lokaal draait op Apple Silicon. Geen cloud-API, geen data die het pand verlaat. Is een lokaal model goed genoeg om nuttig te zijn voor clusterdiagnose? Of kost soevereiniteit hier meer dan het waard is? Die vraag beantwoordt deze post.
Eén ding voor de commando’s beginnen. Dit is een homelab-experiment. Ik beschrijf wat ik getest heb en wat ik vond, en de security-sectie verderop is de reden dat je niks hiervan in productie moet draaien. Lees het zo.
De hardware en de software
De hardware
Een Mac Studio M3 Ultra met 512GB unified memory. De M3 Ultra heeft 80 GPU-cores die je voor inference kunt gebruiken, en unified memory betekent dat er niks gekopieerd wordt tussen CPU-RAM en GPU-RAM.
Met zo’n €10.000 is het een dure bak, en ik doe niet alsof dat anders is. Het is ook zo’n beetje de enige consumentenhardware die een 70B-model op Q8-quantization draait op een snelheid waar je op blijft wachten. Unified memory is de hele truc. Op een gewone PC met een losse kaart betaal je bij elke pass een kopieerbelasting tussen CPU- en GPU-RAM, en die belasting is wat je de das omdoet.
De softwarestack
| Component | Versie | Rol |
|---|---|---|
| vLLM | 0.6.x | Inference server met Metal backend |
| Llama 3.3 70B | Q8_0 | Het taalmodel (~75GB) |
| K8sGPT Operator | 0.1.x | Kubernetes operator voor diagnose |
| k3s | 1.29.x | Lokaal Kubernetes cluster |
vLLM installeren met de Metal-backend
vLLM heeft experimentele Metal-support voor Apple Silicon. De installatie is een conda-environment en één pip:
# Maak een dedicated conda environment
conda create -n vllm python=3.11
conda activate vllm
# Installeer vLLM met Metal support
pip install vllm
# Verifieer Metal backend
python -c "import vllm; print(vllm.__version__)"
Experimenteel is het juiste woord. Op het moment van schrijven is de Metal-support in vLLM ruw, en dat merk je. llama.cpp met z’n Metal-backend is de stabiele optie, maar K8sGPT wil een OpenAI-compatible API en die geeft vLLM me out of the box. Dus ik nam de ruigere route, liever dan een shim schrijven.
Het model downloaden
# Download het model (Q8 quantization, ~75GB)
huggingface-cli download meta-llama/Llama-3.3-70B-Instruct \
--local-dir ./models/llama-3.3-70b-instruct
Je hebt een Hugging Face-account nodig en je moet de Llama-licentie accepteren.
De vLLM-server starten
# Start de inference server
vllm serve ./models/llama-3.3-70b-instruct \
--host 0.0.0.0 \
--port 8000 \
--dtype float16 \
--max-model-len 8192 \
--device mps
De --device mps-flag forceert Metal Performance Shaders. Laat je ’m weg, dan valt vLLM terug op de CPU.
Check dat ie draait:
curl http://localhost:8000/v1/models
De K8sGPT-operator deployen
De operator gaat met Helm het cluster in:
# Voeg de Helm repo toe
helm repo add k8sgpt https://charts.k8sgpt.ai/
helm repo update
# Installeer de operator
helm install k8sgpt-operator k8sgpt/k8sgpt-operator \
-n k8sgpt-operator-system \
--create-namespace
Dan een K8sGPT-resource die de backend naar de vLLM-server op de Mac laat wijzen:
# k8sgpt-config.yaml
apiVersion: core.k8sgpt.ai/v1alpha1
kind: K8sGPT
metadata:
name: k8sgpt-local
namespace: k8sgpt-operator-system
spec:
ai:
enabled: true
model: llama-3.3-70b-instruct
backend: localai
baseUrl: http://192.168.1.100:8000/v1 # IP van je Mac Studio
noCache: false
version: v0.3.40
analyzers:
- Pod
- Deployment
- Service
- ReplicaSet
- PersistentVolumeClaim
- Ingress
- StatefulSet
- CronJob
kubectl apply -f k8sgpt-config.yaml
Drie kapotte dingen
De setup draait. Nu het deel dat telt. Is het nuttig, of is het een heel dure manier om met overtuiging een fout antwoord te krijgen? Ik gooide er drie bewust kapotte dingen in en gaf de output een cijfer zoals ik dat bij de eerste poging van een junior engineer zou doen.
Scenario A: een CrashLoopBackOff
Een deployment die naar een ConfigMap verwijst die niet bestaat:
# broken-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: broken-app
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: broken-app
template:
metadata:
labels:
app: broken-app
spec:
containers:
- name: app
image: nginx:1.25
envFrom:
- configMapRef:
name: app-config # Deze ConfigMap bestaat niet
kubectl apply -f broken-deployment.yaml
Na een minuut staat de pod in CrashLoopBackOff. De operator schrijft z’n analyse naar een results-resource:
kubectl get results -n k8sgpt-operator-system -o yaml
Geparafraseerd was de output dit:
Analysis: Pod broken-app-xxxx is in CreateContainerConfigError state.
The pod is referencing a ConfigMap 'app-config' that does not exist
in the namespace.
Suggested remediation:
1. Create the missing ConfigMap:
kubectl create configmap app-config --from-literal=KEY=value
2. Or remove the configMapRef from the deployment spec
3. Verify the ConfigMap name spelling matches exactly
Bruikbaar. De diagnose klopt en de suggesties zijn praktisch. Een junior engineer kan hiermee uit de voeten zonder op een dwaalspoor te raken. Wat het miste is de ene check die ik als eerste had gedaan, of de ConfigMap in een andere namespace staat. Die fout maak ik ongeveer eens per maand.
Scenario B: geen resource-limits
Een deployment met drie replica’s en helemaal geen resources-blok:
# no-limits.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: no-limits-app
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: no-limits
template:
metadata:
labels:
app: no-limits
spec:
containers:
- name: app
image: nginx:1.25
# Geen resources gedefinieerd
De analyse van K8sGPT:
Analysis: Deployment no-limits-app has containers without resource
requests or limits defined.
Issues identified:
- Container 'app' has no CPU requests/limits
- Container 'app' has no memory requests/limits
Suggested remediation:
Add resource specifications to ensure predictable scheduling and
prevent resource starvation:
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "200m"
Deels bruikbaar. Het probleem ziet het. De getallen die het je geeft zijn verzonnen. Het model heeft geen enkele metric gezien, dus niks in die requests en limits is gebaseerd op wat deze workload doet. Een ervaren engineer haalt eerst echte data op, kubectl top pods of Prometheus, en sized van daaruit. De LLM gokt, en niks in de output zegt dat.
Het noemt ook de Vertical Pod Autoscaler niet, waarschuwt niet dat limits zonder requests kunnen bijten, en de verhouding 1:2 tussen requests en limits komt uit de lucht vallen.
Scenario C: een privileged pod
Een pod die zo’n beetje alles doet waar een security-policy voor bestaat om tegen te houden:
# insecure-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: insecure-pod
namespace: default
spec:
hostNetwork: true
containers:
- name: app
image: nginx:1.25
securityContext:
privileged: true
runAsRoot: true
volumeMounts:
- name: host-root
mountPath: /host
volumes:
- name: host-root
hostPath:
path: /
De analyse, met de Trivy-integratie aan:
Analysis: Pod insecure-pod has multiple security issues:
Critical:
- Container running in privileged mode (privileged: true)
- Container has access to host network (hostNetwork: true)
- Container mounts host root filesystem
High:
- No securityContext.readOnlyRootFilesystem
- No securityContext.allowPrivilegeEscalation: false
Suggested remediation:
1. Remove privileged: true unless absolutely necessary
2. Use a dedicated network namespace (remove hostNetwork: true)
3. Avoid mounting host paths, especially root filesystem
4. Add security hardening:
securityContext:
privileged: false
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
runAsNonRoot: true
capabilities:
drop:
- ALL
Bruikbaar. Deze verraste me. De issues staan er allemaal en de remediatie leest als wat een security engineer je zou vertellen. Trivy verdient hier z’n plek door ook de image-vulnerabilities te flaggen, zodat je de misconfiguratie en het CVE -verhaal in één pass krijgt.
Wat mist is de policy-laag. Geen woord over Pod Security Standards en het restricted-profiel, en geen woord dat een Kyverno- of OPA -policy deze pod had moeten tegenhouden voordat hij ooit gescheduled werd.
Performance
Inference-snelheid
| Metric | Waarde |
|---|---|
| Tokens/seconde (prompt) | ~180 t/s |
| Tokens/seconde (generation) | ~25 t/s |
| Eerste token latency | ~2.5s |
| Typische analyse (500 tokens out) | ~22s |
End-to-end latency
Van het moment dat een probleem bestaat tot het moment dat het rapport er ligt:
| Fase | Tijd |
|---|---|
| Issue detectie (polling) | 30s (configurabel) |
| Context gathering | ~2s |
| LLM inference | ~20-30s |
| Result storage | <1s |
| Totaal | ~55s |
Resourcegebruik
Tijdens inference:
| Resource | Gebruik |
|---|---|
| GPU Memory (Metal) | ~78GB |
| CPU | ~15% (data preprocessing) |
| System Memory | ~12GB (naast model) |
| Power draw | ~180W |
Tegenover de OpenAI-API
| Metric | Lokaal (70B) | OpenAI GPT-4 |
|---|---|---|
| Latency | ~25s | ~5s |
| Kwaliteit | Goed | Zeer goed |
| Kosten | €0 (na hardware) | ~€0.03/query |
| Privacy | Volledig lokaal | Data naar OpenAI |
De OpenAI-API is sneller en de output is wat beter. De prijs is dat je clustermetadata je netwerk verlaat. Voor mij is die ruil de hele kern van de oefening. Ik wacht 25 seconden in plaats van 5 om de data thuis te houden, en dat vind ik geen moeilijke keuze. Of jij dezelfde maakt hangt af van wat er in je pod-labels staat.
Air-gapped
Kan het zonder enige internetverbinding? Ja, met wat voorbereiding. Hier verdient het lokale model zichzelf terug, want de air-gapped case is van tafel zodra je van een cloud-API afhangt.
Wat je vooraf downloadt
# 1. Model weights (~75GB)
huggingface-cli download meta-llama/Llama-3.3-70B-Instruct \
--local-dir ./airgap-bundle/models/
# 2. vLLM Python packages
pip download vllm -d ./airgap-bundle/packages/
# 3. K8sGPT container images
docker pull ghcr.io/k8sgpt-ai/k8sgpt-operator:latest
docker save ghcr.io/k8sgpt-ai/k8sgpt-operator:latest > ./airgap-bundle/images/k8sgpt-operator.tar
# 4. Helm charts
helm pull k8sgpt/k8sgpt-operator --destination ./airgap-bundle/charts/
Transport en installatie
# Op de air-gapped machine:
# 1. Installeer Python packages offline
pip install --no-index --find-links=./airgap-bundle/packages/ vllm
# 2. Laad container images
docker load < ./airgap-bundle/images/k8sgpt-operator.tar
# Of push naar je lokale registry
# 3. Installeer Helm chart
helm install k8sgpt-operator ./airgap-bundle/charts/k8sgpt-operator-*.tgz \
--set image.repository=your-local-registry/k8sgpt-operator
Wat offline werkt
| Component | Air-Gap Ready | Notes |
|---|---|---|
| vLLM | Ja | Geen phone-home |
| Llama model | Ja | Eenmalige download |
| K8sGPT Operator | Ja | Geen telemetry |
| Trivy DB | Nee | Vereist periodieke updates |
De Trivy-vulnerabilitydatabase is de uitzondering. Die heeft periodieke updates nodig, en die moet je apart transporteren. Zonder recente database mist K8sGPT nieuwe CVE’s.
Security en het threat-model
Hier moet ik eerlijk zijn. Een lokaal model geeft je datasoevereiniteit en verder niks aan de securitykant. De setup is zo veilig als de bak waar hij op draait, en een Mac Studio die als inference-server op je netwerk staat brengt z’n eigen stapel problemen mee. De LLM brengt een tweede stapel mee die specifiek voor het model geldt.
Platformproblemen
Een Mac Studio als inference-server heeft beperkingen die je niet wegconfigureert:
| Issue | Impact |
|---|---|
| Geen TPM | Geen hardware attestation, geen measured boot |
| macOS is general-purpose | Niet hardened zoals RHEL/Ubuntu met CIS benchmarks |
| Geen Secure Boot chain | Boot process is niet cryptografisch geverifieerd |
| Updates vereisen internet | Of handmatige interventie in air-gapped scenario |
| Single-user focus | macOS is niet ontworpen voor multi-tenant security |
Dus voor alles met echte compliance-eisen, ISO27001 Annex A, NIS2 , SOC2, is een Mac Studio de verkeerde machine. Voor een homelab of een developmentomgeving is het prima.
Risico’s die bij het model horen
| Risico | Beschrijving |
|---|---|
| Non-determinisme | Dezelfde input kan verschillende outputs geven |
| Prompt injection | Malicious pod names/labels kunnen de LLM manipuleren |
| Hallucinations | Model kan schadelijke remediatie suggereren |
| Context leakage | Info uit eerdere queries kan in responses verschijnen |
| Supply chain | Model weights kunnen backdoored zijn |
Het threat-model
| Threat | Likelihood | Impact | Mitigatie |
|---|---|---|---|
| Prompt injection via pod metadata | Medium | High | Input sanitization, output validation |
| Hallucinated destructive commands | Medium | Critical | Human-in-the-loop, geen auto-remediation |
| Model weights tampering | Low | Critical | Checksum verificatie, trusted source |
| Context window data leakage | Medium | Medium | Korte context, geen persistent memory |
| Unauthorized access to inference API | Medium | High | Network segmentation, auth |
| Resource exhaustion (DoS) | Low | Medium | Rate limiting, resource quotas |
Wat ik ermee zou doen
Bruikbaar, onder voorwaarden
Ja, een lokaal model is bruikbaar voor Kubernetes-diagnose, onder voorwaarden. Het herkent standaardissues correct, geeft remediatie waar je wat mee kunt, vangt securityproblemen, en doet dat allemaal zonder dat er een byte het netwerk verlaat.
Wat het niet kan telt net zo zwaar. Het kan geen probleem debuggen dat over meerdere componenten loopt. Het kan geen auto-remediation doen die je vertrouwt. Het kent jouw setup niet, en het kan niet garanderen dat het gelijk heeft.
Per use case
Homelab en leren
Ga ervoor. Je leert over LLM-inference-infrastructuur, over Kubernetes-troubleshootingpatronen en over waar AI-assisted operations ophouden nuttig te zijn, en de blast radius is je eigen cluster.
Development en staging
Bruikbaar met vangrails. Iemand beoordeelt de output voordat er iets wordt toegepast, elke LLM-interactie wordt gelogd, en er is geen auto-remediation. Alleen diagnose.
Productie, met internet
Gebruik een cloud-API. De modellen zijn beter, GPT-4 of Claude, de latency is lager, er hoeft geen hardware gekocht te worden en iemand anders tekent de SLA . Voor de meeste organisaties is de privacy-afweging acceptabel, zolang er geen PII in de clustermetadata zit.
Productie, air-gapped of soeverein
Alleen als laatste optie. Mag de data écht niet naar buiten, kijk dan eerst naar kleinere, dedicated modellen en zet defense-in-depth om de inference-server heen. Behandel elke regel die het model produceert als untrusted, log en audit alles, en hou het een assistent in plaats van een autoriteit.
Terug naar de slide
Autonomous cluster management met LLM’s is vandaag marketing. Wat ik getest heb is assisted diagnose, een model dat naar problemen wijst en suggesties doet, met mij die elke suggestie leest. De human-in-the-loop is een vereiste, en die gaat er niet af zodra je het model genoeg vertrouwt.
En toch ben ik onder de indruk. Een 70B-model op hardware in m’n eigen kantoor produceerde analyses die ik van een collega had geaccepteerd. Het gat tussen goed genoeg om te lezen en goed genoeg om zonder mij op een productiecluster te handelen is nog breed. Scenario B laat zien hoe breed. Het model verzon resource-limits en presenteerde ze als advies.
Ik heb het antwoord dat ik kwam halen. Een lokaal model is goed genoeg als diagnostische assistent, en het hier draaien betekent dat ik nooit heb hoeven kiezen tussen AIOps en de redenen uit Sovereign Infrastructure. Why Privacy Matters is de andere helft van waarom de data thuisblijft. Dus het blijft een assistent. Elke suggestie lees ik voordat ik ’m intyp, zoals ik dat zou doen bij een scherpe collega die m’n cluster nog nooit gezien heeft.
