Files
k8s-manifests/ollama/ollama.yaml
T
chemavxandClaude Opus 4.8 b40790155e ollama: el arranque descarga qwen2.5:7b + bge-m3 (los que se usan), no qwen2.5:3b
Borrados qwen2.5:3b y nomic-embed-text (sin consumidores tras subir a 7b/bge-m3).
El script de arranque solo traía 3b: tras perder el PVC, un reinicio dejaba a
researchowl y roswell sin el modelo de embeddings. Ahora trae los dos reales.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 09:47:52 +00:00

204 lines
6.6 KiB
YAML

# Ollama en chemavx-k8, bajo ArgoCD (selfHeal).
#
# 2026-07-23 — iGPU POR FIN ACTIVA, vía device plugin (device-plugin.yaml).
# El hostPath de /dev/dri hacía visible el dispositivo pero el cgroup de
# dispositivos negaba open() (EPERM): la GPU nunca llegó a usarse. El recurso
# devic.es/gpu entrega card0+renderD128 con el cgroup bien puesto, y el
# backend Vulkan (la imagen no trae ROCm) enumera la Radeon 780M.
# Ese mismo día se cerró la exposición pública: el Ingress lleva ahora el
# forward-auth de Authentik (mismo middleware que Grafana).
#
# 2026-07-22 — deriva corregida: todo el paso de la iGPU vivía puesto a mano
# en el objeto vivo (merge de tres vías) y no en git. Ahora git es la verdad.
---
apiVersion: v1
kind: Namespace
metadata:
name: ollama
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
annotations:
# Never let ArgoCD prune this PVC: it holds the downloaded models (20Gi).
argocd.argoproj.io/sync-options: Prune=false
name: ollama-models
namespace: ollama
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-path
resources:
requests:
storage: 20Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ollama
namespace: ollama
labels:
app: ollama
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: ollama
template:
metadata:
labels:
app: ollama
spec:
nodeSelector:
kubernetes.io/hostname: chemavx-k8
containers:
- name: ollama
image: ollama/ollama:0.20.7
command: ["/usr/bin/bash", "-c"]
args:
- |
ollama serve &
SERVE_PID=$!
echo "Waiting for ollama to start..."
until ollama list >/dev/null 2>&1; do
sleep 2
done
# Los modelos que usan los consumidores (researchowl genera con
# qwen2.5:7b y embebe con bge-m3; roswell hace fallback a 7b y
# embebe con bge-m3). Antes solo se traía 3b: si se perdía el PVC,
# un reinicio dejaba a ambos bots sin embeddings.
for M in qwen2.5:7b bge-m3; do
echo "Pulling $M..."
ollama pull "$M"
done
echo "Models ready."
wait $SERVE_PID
ports:
- name: http
containerPort: 11434
protocol: TCP
env:
- name: OLLAMA_MODELS
value: /root/.ollama/models
# Límite de contexto para que el KV cache no reviente la iGPU.
# OJO: la variable real es OLLAMA_CONTEXT_LENGTH; OLLAMA_NUM_CTX
# no existe para el servidor (estuvo meses sin aplicarse).
- name: OLLAMA_CONTEXT_LENGTH
value: "8192"
- name: OLLAMA_KEEP_ALIVE
value: "-1"
# --- aceleración por la iGPU (Radeon 780M, Hawk Point) ---
# AQUÍ NO VAN HSA_OVERRIDE_GFX_VERSION NI HIP_VISIBLE_DEVICES.
# Son de ROCm, y esta imagen no trae ROCm (en /usr/lib/ollama sólo
# hay cuda_v12, cuda_v13, mlx_cuda_v13, vulkan y los backends de
# CPU; ni rocBLAS ni hipBLAS). Además de inútiles eran DAÑINAS: con
# ellas puestas, ollama arrancaba avisando «user overrode visible
# devices … if GPUs are not correctly discovered, unset and try
# again» y descubría sólo la CPU (total_vram="0 B"). Si algún día se
# pasa a la imagen con sufijo -rocm, volverán a tener sentido.
#
# OLLAMA_GPU y OLLAMA_METRICS tampoco existen para ollama: no
# aparecen en el volcado de «server config» de su propio arranque.
#
# El camino que sí sirve con esta imagen: backend Vulkan
# (experimental desde ollama 0.12.6, pensado para iGPUs AMD/Intel
# donde ROCm no llega). La imagen ya trae libggml-vulkan.so y el
# driver Mesa RADV (radeon_icd.json), así que no hace falta cambiarla.
- name: OLLAMA_VULKAN
value: "1"
resources:
requests:
memory: 4Gi
cpu: "500m"
limits:
memory: 8Gi
# La iGPU, entregada por el generic-device-plugin
# (device-plugin.yaml): card0 + renderD128 con acceso de cgroup.
devic.es/gpu: "1"
securityContext:
privileged: false
allowPrivilegeEscalation: false
capabilities:
add: ["SYS_PTRACE"]
volumeMounts:
- name: ollama-data
mountPath: /root/.ollama
livenessProbe:
httpGet:
path: /api/tags
port: 11434
initialDelaySeconds: 60
periodSeconds: 30
failureThreshold: 5
readinessProbe:
httpGet:
path: /api/tags
port: 11434
initialDelaySeconds: 30
periodSeconds: 10
failureThreshold: 15
# 44=video, 109=render en chemavx-k8: permisos de grupo sobre los nodos
# DRM (crw-rw---- root:render). El acceso de cgroup lo da el device plugin.
securityContext:
supplementalGroups: [44, 109]
seccompProfile:
type: Unconfined
volumes:
- name: ollama-data
persistentVolumeClaim:
claimName: ollama-models
---
apiVersion: v1
kind: Service
metadata:
name: ollama
namespace: ollama
labels:
app: ollama
spec:
type: ClusterIP
selector:
app: ollama
ports:
- name: http
port: 11434
targetPort: 11434
protocol: TCP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ollama
namespace: ollama
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
traefik.ingress.kubernetes.io/router.entrypoints: websecure
# Cerrado 2026-07-23: la API estaba expuesta SIN autenticación (cualquiera
# podía usar el LLM o llenarte el disco con /api/pull). Mismo forward-auth
# que Grafana; los consumidores del cluster (researchowl, roswell, los
# vigilantes) van por el Service interno y no pasan por aquí.
traefik.ingress.kubernetes.io/router.middlewares: authentik-authentik-forward-auth@kubernetescrd
spec:
ingressClassName: traefik
rules:
- host: ollama.chemavx.xyz
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: ollama
port:
number: 11434
tls:
- hosts:
- ollama.chemavx.xyz
secretName: ollama-tls