titan-iac/services/hermes/switchyard-deployment.yaml
jenkins 9df896c64c
Some checks failed
Tests / Declarative: Post Actions testing.tests.test_hermes_chat_quality.test_compact_image_edit_resolves_latest_tenant_artifact failed
hermes: reload image routing policy
2026-08-12 08:43:33 -03:00

253 lines
8.2 KiB
YAML

# services/hermes/switchyard-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hermes-switchyard
namespace: hermes
labels:
app: hermes-switchyard
spec:
replicas: 1
revisionHistoryLimit: 2
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: hermes-switchyard
template:
metadata:
labels:
app: hermes-switchyard
annotations:
ai.bstein.dev/config-rev: "20260812-image-continuity"
prometheus.io/scrape: "true"
prometheus.io/port: "9005"
prometheus.io/path: /metrics
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: hermes-agent
vault.hashicorp.com/agent-inject-secret-anthropic-token: kv/data/atlas/hermes/agent-tokens
vault.hashicorp.com/agent-inject-template-anthropic-token: |
{{- with secret "kv/data/atlas/hermes/agent-tokens" -}}
{{ .Data.data.anthropic_oauth_token }}
{{- end }}
vault.hashicorp.com/agent-inject-secret-relay-key: kv/data/atlas/hermes/chat-telegram
vault.hashicorp.com/agent-inject-template-relay-key: |
{{- with secret "kv/data/atlas/hermes/chat-telegram" -}}
{{ .Data.data.relay_key }}
{{- end }}
vault.hashicorp.com/agent-pre-populate-only: "true"
vault.hashicorp.com/agent-init-first: "true"
vault.hashicorp.com/agent-requests-cpu: 25m
vault.hashicorp.com/agent-requests-mem: 32Mi
vault.hashicorp.com/agent-limits-cpu: 100m
vault.hashicorp.com/agent-limits-mem: 128Mi
spec:
serviceAccountName: hermes-switchyard
automountServiceAccountToken: true
terminationGracePeriodSeconds: 330
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-14, titan-18, titan-22, titan-24]
containers:
- name: switchyard
image: registry.bstein.dev/bstein/hermes-switchyard@sha256:3d952d528a4e4cb8afdf84f8995272f5d6107dc127b68cc20234b1da4aff43eb
imagePullPolicy: IfNotPresent
command: [/bin/sh, -ec]
args:
- |
ATLAS_BROKER_KEY="$(tr -d '\r\n' < /vault/secrets/relay-key)"
export ATLAS_BROKER_KEY
exec switchyard-server \
--config /etc/switchyard/routes.toml \
--host 0.0.0.0 \
--port 9005 \
--shutdown-timeout 5m \
--routing-log-file /var/lib/switchyard/routing.jsonl
env:
- name: RUST_LOG
value: switchyard_server=info,libsy=info
ports:
- name: http
containerPort: 9005
protocol: TCP
readinessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 3
periodSeconds: 10
timeoutSeconds: 3
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 15
periodSeconds: 30
timeoutSeconds: 5
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: [ALL]
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 10000
runAsGroup: 10000
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: "2"
memory: 1Gi
volumeMounts:
- name: config
mountPath: /etc/switchyard
readOnly: true
- name: state
mountPath: /var/lib/switchyard
- name: tmp
mountPath: /tmp
- name: claude-oauth-broker
image: registry.bstein.dev/bstein/hermes-switchyard-brokers@sha256:ee7e95e060ef8083da505162d7e9030daba15fdd828cc047bbcbe6aa409d2083
imagePullPolicy: IfNotPresent
command:
- python
- /opt/coordinator/claude_oauth_broker.py
env:
- name: HERMES_CLAUDE_OAUTH_TOKEN_FILE
value: /vault/secrets/anthropic-token
- name: HERMES_CLAUDE_BROKER_KEY_FILE
value: /vault/secrets/relay-key
- name: HERMES_CLAUDE_BROKER_READ_TIMEOUT
value: "1800"
- name: HERMES_ROUTING_CATALOG_PATH
value: /routing-catalog/catalog.json
ports:
- name: claude
containerPort: 9006
protocol: TCP
readinessProbe:
httpGet:
path: /health
port: claude
initialDelaySeconds: 3
periodSeconds: 10
timeoutSeconds: 3
livenessProbe:
httpGet:
path: /health
port: claude
initialDelaySeconds: 15
periodSeconds: 30
timeoutSeconds: 5
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: [ALL]
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 10000
runAsGroup: 10000
resources:
requests:
cpu: 50m
memory: 96Mi
limits:
cpu: 500m
memory: 384Mi
volumeMounts:
- name: coordinator
mountPath: /opt/coordinator
readOnly: true
- name: tmp
mountPath: /tmp
- name: routing-catalog
mountPath: /routing-catalog
readOnly: true
- name: worker-route-broker
image: registry.bstein.dev/bstein/hermes-switchyard-brokers@sha256:ee7e95e060ef8083da505162d7e9030daba15fdd828cc047bbcbe6aa409d2083
imagePullPolicy: IfNotPresent
command:
- python
- /opt/coordinator/worker_route_broker.py
ports:
- name: worker-route
containerPort: 9007
protocol: TCP
env:
- name: HERMES_ROUTING_CATALOG_PATH
value: /routing-catalog/catalog.json
readinessProbe:
httpGet:
path: /health
port: worker-route
initialDelaySeconds: 2
periodSeconds: 10
timeoutSeconds: 3
livenessProbe:
httpGet:
path: /health
port: worker-route
initialDelaySeconds: 10
periodSeconds: 30
timeoutSeconds: 5
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: [ALL]
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 10000
runAsGroup: 10000
resources:
requests:
cpu: 10m
memory: 24Mi
limits:
cpu: 100m
memory: 96Mi
volumeMounts:
- name: coordinator
mountPath: /opt/coordinator
readOnly: true
- name: tmp
mountPath: /tmp
- name: routing-catalog
mountPath: /routing-catalog
readOnly: true
volumes:
- name: config
configMap:
name: hermes-switchyard
- name: coordinator
configMap:
name: hermes-coordinator
defaultMode: 0555
- name: state
persistentVolumeClaim:
claimName: hermes-switchyard-state-rwx
- name: routing-catalog
persistentVolumeClaim:
claimName: hermes-routing-catalog
- name: tmp
emptyDir: {}