titan-iac/services/hermes-chat/deployment.yaml

221 lines
7.0 KiB
YAML

# services/hermes-chat/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hermes-chat
namespace: hermes-chat
labels:
app: hermes-chat
spec:
replicas: 1
revisionHistoryLimit: 2
progressDeadlineSeconds: 1800
strategy:
type: Recreate
selector:
matchLabels:
app: hermes-chat
template:
metadata:
labels:
app: hermes-chat
annotations:
ai.bstein.dev/model: gpt-oss:20b with independent openai-codex fallback
ai.bstein.dev/role: personal-chat-research
ai.bstein.dev/isolation: observer-only Kubernetes RBAC, private-service egress denied
spec:
serviceAccountName: hermes-chat
automountServiceAccountToken: true
securityContext:
fsGroup: 10000
fsGroupChangePolicy: OnRootMismatch
seccompProfile:
type: RuntimeDefault
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/arch
operator: In
values:
- arm64
- key: node-role.kubernetes.io/worker
operator: In
values:
- "true"
- key: kubernetes.io/hostname
operator: NotIn
values:
- titan-13
- titan-15
- titan-17
- titan-19
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: atlas.bstein.dev/spillover
operator: DoesNotExist
- weight: 90
preference:
matchExpressions:
- key: hardware
operator: In
values:
- rpi5
- weight: 50
preference:
matchExpressions:
- key: hardware
operator: In
values:
- rpi4
initContainers:
- name: init-config
image: busybox:1.37
imagePullPolicy: IfNotPresent
command:
- sh
- -c
- |
set -eu
mkdir -p /opt/data/workspace/skills /opt/data/home/.local/bin /opt/data/logs
cp /config/config.yaml /opt/data/config.yaml
cp /config/SOUL.md /opt/data/SOUL.md
cp /config/AGENTS.md /opt/data/workspace/AGENTS.md
touch /opt/data/.env
if ! grep -q '^API_SERVER_KEY=' /opt/data/.env; then
api_key="$(dd if=/dev/urandom bs=32 count=1 2>/dev/null | od -An -tx1 | tr -d ' \n')"
printf '\nAPI_SERVER_KEY=%s\n' "${api_key}" >> /opt/data/.env
fi
chmod 0600 /opt/data/.env
chown -R 10000:10000 /opt/data
securityContext:
allowPrivilegeEscalation: false
runAsUser: 0
runAsGroup: 0
seccompProfile:
type: RuntimeDefault
volumeMounts:
- name: home
mountPath: /opt/data
- name: config
mountPath: /config
readOnly: true
resources:
requests:
cpu: 25m
memory: 32Mi
limits:
cpu: 100m
memory: 64Mi
- name: install-kubectl
image: bitnami/kubectl@sha256:554ab88b1858e8424c55de37ad417b16f2a0e65d1607aa0f3fe3ce9b9f10b131
imagePullPolicy: IfNotPresent
command:
- /bin/sh
- -c
- |
set -eu
cp "$(command -v kubectl)" /tools/kubectl
chmod 0755 /tools/kubectl
chown 10000:10000 /tools/kubectl
securityContext:
allowPrivilegeEscalation: false
runAsUser: 0
runAsGroup: 0
seccompProfile:
type: RuntimeDefault
volumeMounts:
- name: tools
mountPath: /tools
resources:
requests:
cpu: 25m
memory: 32Mi
limits:
cpu: 100m
memory: 64Mi
containers:
- name: hermes-chat
image: nousresearch/hermes-agent@sha256:9c841866021c54c4596849f6135717e8a4d52ba510b7f52c50aef1de1a283973
imagePullPolicy: IfNotPresent
args:
- gateway
- run
ports:
- name: dashboard
containerPort: 9119
protocol: TCP
env:
- name: HERMES_HOME
value: /opt/data
- name: HOME
value: /opt/data/home
- name: PATH
value: /opt/data/home/.local/bin:/opt/hermes/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
- name: HERMES_DASHBOARD
value: "1"
- name: HERMES_DASHBOARD_HOST
value: 0.0.0.0
- name: HERMES_DASHBOARD_PORT
value: "9119"
- name: HERMES_DASHBOARD_PUBLIC_URL
value: https://chat.bstein.dev
- name: HERMES_DASHBOARD_OIDC_ISSUER
value: https://sso.bstein.dev/realms/atlas
- name: HERMES_DASHBOARD_OIDC_CLIENT_ID
value: hermes-chat-dashboard
- name: HERMES_DASHBOARD_OIDC_SCOPES
value: openid profile email groups
- name: API_SERVER_ENABLED
value: "true"
- name: API_SERVER_HOST
value: 0.0.0.0
- name: API_SERVER_PORT
value: "8642"
- name: API_SERVER_CORS_ORIGINS
value: https://chat.bstein.dev
volumeMounts:
- name: home
mountPath: /opt/data
- name: tools
mountPath: /opt/data/home/.local/bin
readinessProbe:
httpGet:
path: /api/status
port: dashboard
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
livenessProbe:
httpGet:
path: /api/status
port: dashboard
initialDelaySeconds: 90
periodSeconds: 30
timeoutSeconds: 10
securityContext:
allowPrivilegeEscalation: false
seccompProfile:
type: RuntimeDefault
resources:
requests:
cpu: 100m
memory: 768Mi
ephemeral-storage: 256Mi
limits:
cpu: "1"
memory: 2Gi
ephemeral-storage: 1Gi
volumes:
- name: home
persistentVolumeClaim:
claimName: hermes-chat-home
- name: config
configMap:
name: hermes-chat-config
- name: tools
emptyDir: {}