atlas-iac/services/hermes/execution-mediator.yaml
jenkins ea97d37524 hermes: derive execution pool key with a supported template function
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 16:19:28 -03:00

477 lines
21 KiB
YAML

# Privileged HMAC and SCM mediation runs outside the model Pods. Each mediator is
# colocated with exactly one ordinal's RWO workspace but has a distinct network
# identity, private HMAC derivation, and durable integrity state.
apiVersion: v1
kind: PersistentVolumeClaim
metadata: {name: hermes-execution-mediator-state-0, namespace: hermes}
spec:
accessModes: [ReadWriteOnce]
storageClassName: astreae
resources: {requests: {storage: 1Gi}}
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata: {name: hermes-execution-mediator-state-1, namespace: hermes}
spec:
accessModes: [ReadWriteOnce]
storageClassName: astreae
resources: {requests: {storage: 1Gi}}
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata: {name: hermes-execution-mediator-state-2, namespace: hermes}
spec:
accessModes: [ReadWriteOnce]
storageClassName: astreae
resources: {requests: {storage: 1Gi}}
---
apiVersion: v1
kind: Service
metadata: {name: hermes-execution-mediator-0, namespace: hermes}
spec:
selector: {app: hermes-execution-mediator, pool-ordinal: "0"}
ports: [{name: mediator, port: 9009, targetPort: mediator}]
---
apiVersion: v1
kind: Service
metadata: {name: hermes-execution-mediator-1, namespace: hermes}
spec:
selector: {app: hermes-execution-mediator, pool-ordinal: "1"}
ports: [{name: mediator, port: 9009, targetPort: mediator}]
---
apiVersion: v1
kind: Service
metadata: {name: hermes-execution-mediator-2, namespace: hermes}
spec:
selector: {app: hermes-execution-mediator, pool-ordinal: "2"}
ports: [{name: mediator, port: 9009, targetPort: mediator}]
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: hermes-execution-mediator-0
namespace: hermes
labels: {app: hermes-execution-mediator, pool-ordinal: "0"}
spec:
replicas: 1
strategy: {type: Recreate}
selector:
matchLabels: {app: hermes-execution-mediator, pool-ordinal: "0"}
template:
metadata:
labels: {app: hermes-execution-mediator, pool-ordinal: "0"}
annotations:
ai.bstein.dev/config-rev: execution-pool-v2-mediated
ai.bstein.dev/security-boundary: model-pod-has-no-hmac-or-scm-network-authority
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: hermes-execution-worker
vault.hashicorp.com/agent-inject-containers: stage-mediator-access
vault.hashicorp.com/agent-service-account-token-volume-name: vault-auth-token
vault.hashicorp.com/agent-inject-secret-execution-pool-key: kv/data/atlas/hermes/agent-tokens
vault.hashicorp.com/agent-inject-perms-execution-pool-key: "0600"
vault.hashicorp.com/agent-inject-template-execution-pool-key: |
{{- with secret "kv/data/atlas/hermes/agent-tokens" -}}
{{ printf "hermes-execution-pool-root-v2:%s" .Data.data.agent_api_key | sha256Hex }}
{{- end }}
vault.hashicorp.com/agent-pre-populate-only: "true"
vault.hashicorp.com/agent-init-first: "true"
vault.hashicorp.com/agent-requests-cpu: 2m
vault.hashicorp.com/agent-requests-mem: 16Mi
vault.hashicorp.com/agent-limits-cpu: 100m
vault.hashicorp.com/agent-limits-mem: 128Mi
spec:
serviceAccountName: hermes-execution-worker
automountServiceAccountToken: false
enableServiceLinks: false
# Priority parity with the worker: a pressured node evicts the pair
# symmetrically instead of moving only the lower-priority half, and the
# pool never preempts anything else in the cluster.
priorityClassName: scavenger
securityContext:
fsGroup: 10000
fsGroupChangePolicy: OnRootMismatch
seccompProfile: {type: RuntimeDefault}
affinity:
# Colocation with the worker is a throughput preference, not a
# requirement. The shared workspace claim is ReadWriteMany, so this
# mediator still schedules and serves when its worker is Pending or
# placed elsewhere -- which is what makes a drain self-healing.
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-04, titan-13, titan-14, titan-17, titan-18, titan-19, titan-22, titan-24]}
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
statefulset.kubernetes.io/pod-name: hermes-execution-worker-0
topologyKey: kubernetes.io/hostname
initContainers:
- name: stage-mediator-access
image: registry.bstein.dev/bstein/hermes-agent
command: [/opt/hermes/.venv/bin/python, /opt/coordinator/stage_runtime_access.py, execution-mediator]
env:
- {name: HERMES_WORKER_ORDINAL, value: "0"}
- {name: HERMES_POOL_ACCESS_ROOT, value: /pool-access}
securityContext:
allowPrivilegeEscalation: false
runAsUser: 0
runAsGroup: 0
seccompProfile: {type: RuntimeDefault}
volumeMounts:
- {name: pool-access, mountPath: /pool-access}
- {name: coordinator, mountPath: /opt/coordinator, readOnly: true}
resources:
requests: {cpu: 2m, memory: 16Mi}
limits: {cpu: 100m, memory: 64Mi}
containers:
- name: execution-mediator
image: registry.bstein.dev/bstein/hermes-agent
command: [/opt/hermes/.venv/bin/python, /opt/coordinator/execution_pool_client.py]
env:
- {name: HERMES_WORKER_ORDINAL, value: "0"}
- {name: HERMES_WORKER_ROOT, value: /workspace}
- {name: HERMES_SCM_STATE_ROOT, value: /scm-state}
- {name: HERMES_EXECUTION_POOL_KEY_FILE, value: /pool-access/execution-pool-key}
- {name: PYTHONPATH, value: /opt/scm:/opt/coordinator:/opt/hermes}
ports: [{name: mediator, containerPort: 9009, protocol: TCP}]
startupProbe:
httpGet: {path: /ready, port: mediator}
periodSeconds: 5
failureThreshold: 60
readinessProbe:
httpGet: {path: /ready, port: mediator}
periodSeconds: 10
securityContext:
allowPrivilegeEscalation: false
capabilities: {drop: [ALL]}
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 10000
runAsGroup: 10000
seccompProfile: {type: RuntimeDefault}
volumeMounts:
- {name: workspace, mountPath: /workspace}
- {name: scm-state, mountPath: /scm-state}
- {name: pool-access, mountPath: /pool-access, readOnly: true}
- {name: scm-broker-client, mountPath: /opt/scm, readOnly: true}
- {name: coordinator, mountPath: /opt/coordinator, readOnly: true}
- {name: tmp, mountPath: /tmp}
resources:
requests: {cpu: 2m, memory: 64Mi}
limits: {cpu: 250m, memory: 256Mi}
volumes:
- name: workspace
persistentVolumeClaim: {claimName: workspace-hermes-execution-worker-0}
- name: scm-state
persistentVolumeClaim: {claimName: hermes-execution-mediator-state-0}
- name: pool-access
emptyDir: {medium: Memory, sizeLimit: 1Mi}
- name: scm-broker-client
configMap: {name: hermes-scm-boundary-v2, defaultMode: 0555}
- name: coordinator
configMap: {name: hermes-execution-pool, defaultMode: 0555}
- name: tmp
emptyDir: {sizeLimit: 64Mi}
- name: vault-auth-token
projected:
defaultMode: 0600
sources:
- serviceAccountToken: {audience: vault, expirationSeconds: 3600, path: token}
- configMap:
name: kube-root-ca.crt
items: [{key: ca.crt, path: ca.crt}]
- downwardAPI:
items: [{path: namespace, fieldRef: {fieldPath: metadata.namespace}}]
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: hermes-execution-mediator-1
namespace: hermes
labels: {app: hermes-execution-mediator, pool-ordinal: "1"}
spec:
replicas: 1
strategy: {type: Recreate}
selector:
matchLabels: {app: hermes-execution-mediator, pool-ordinal: "1"}
template:
metadata:
labels: {app: hermes-execution-mediator, pool-ordinal: "1"}
annotations:
ai.bstein.dev/config-rev: execution-pool-v2-mediated
ai.bstein.dev/security-boundary: model-pod-has-no-hmac-or-scm-network-authority
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: hermes-execution-worker
vault.hashicorp.com/agent-inject-containers: stage-mediator-access
vault.hashicorp.com/agent-service-account-token-volume-name: vault-auth-token
vault.hashicorp.com/agent-inject-secret-execution-pool-key: kv/data/atlas/hermes/agent-tokens
vault.hashicorp.com/agent-inject-perms-execution-pool-key: "0600"
vault.hashicorp.com/agent-inject-template-execution-pool-key: |
{{- with secret "kv/data/atlas/hermes/agent-tokens" -}}
{{ printf "hermes-execution-pool-root-v2:%s" .Data.data.agent_api_key | sha256Hex }}
{{- end }}
vault.hashicorp.com/agent-pre-populate-only: "true"
vault.hashicorp.com/agent-init-first: "true"
vault.hashicorp.com/agent-requests-cpu: 2m
vault.hashicorp.com/agent-requests-mem: 16Mi
vault.hashicorp.com/agent-limits-cpu: 100m
vault.hashicorp.com/agent-limits-mem: 128Mi
spec:
serviceAccountName: hermes-execution-worker
automountServiceAccountToken: false
enableServiceLinks: false
# Priority parity with the worker: a pressured node evicts the pair
# symmetrically instead of moving only the lower-priority half, and the
# pool never preempts anything else in the cluster.
priorityClassName: scavenger
securityContext:
fsGroup: 10000
fsGroupChangePolicy: OnRootMismatch
seccompProfile: {type: RuntimeDefault}
affinity:
# Colocation with the worker is a throughput preference, not a
# requirement. The shared workspace claim is ReadWriteMany, so this
# mediator still schedules and serves when its worker is Pending or
# placed elsewhere -- which is what makes a drain self-healing.
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-04, titan-13, titan-14, titan-17, titan-18, titan-19, titan-22, titan-24]}
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
statefulset.kubernetes.io/pod-name: hermes-execution-worker-1
topologyKey: kubernetes.io/hostname
initContainers:
- name: stage-mediator-access
image: registry.bstein.dev/bstein/hermes-agent
command: [/opt/hermes/.venv/bin/python, /opt/coordinator/stage_runtime_access.py, execution-mediator]
env:
- {name: HERMES_WORKER_ORDINAL, value: "1"}
- {name: HERMES_POOL_ACCESS_ROOT, value: /pool-access}
securityContext:
allowPrivilegeEscalation: false
runAsUser: 0
runAsGroup: 0
seccompProfile: {type: RuntimeDefault}
volumeMounts:
- {name: pool-access, mountPath: /pool-access}
- {name: coordinator, mountPath: /opt/coordinator, readOnly: true}
resources:
requests: {cpu: 2m, memory: 16Mi}
limits: {cpu: 100m, memory: 64Mi}
containers:
- name: execution-mediator
image: registry.bstein.dev/bstein/hermes-agent
command: [/opt/hermes/.venv/bin/python, /opt/coordinator/execution_pool_client.py]
env:
- {name: HERMES_WORKER_ORDINAL, value: "1"}
- {name: HERMES_WORKER_ROOT, value: /workspace}
- {name: HERMES_SCM_STATE_ROOT, value: /scm-state}
- {name: HERMES_EXECUTION_POOL_KEY_FILE, value: /pool-access/execution-pool-key}
- {name: PYTHONPATH, value: /opt/scm:/opt/coordinator:/opt/hermes}
ports: [{name: mediator, containerPort: 9009, protocol: TCP}]
startupProbe:
httpGet: {path: /ready, port: mediator}
periodSeconds: 5
failureThreshold: 60
readinessProbe:
httpGet: {path: /ready, port: mediator}
periodSeconds: 10
securityContext:
allowPrivilegeEscalation: false
capabilities: {drop: [ALL]}
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 10000
runAsGroup: 10000
seccompProfile: {type: RuntimeDefault}
volumeMounts:
- {name: workspace, mountPath: /workspace}
- {name: scm-state, mountPath: /scm-state}
- {name: pool-access, mountPath: /pool-access, readOnly: true}
- {name: scm-broker-client, mountPath: /opt/scm, readOnly: true}
- {name: coordinator, mountPath: /opt/coordinator, readOnly: true}
- {name: tmp, mountPath: /tmp}
resources:
requests: {cpu: 2m, memory: 64Mi}
limits: {cpu: 250m, memory: 256Mi}
volumes:
- name: workspace
persistentVolumeClaim: {claimName: workspace-hermes-execution-worker-1}
- name: scm-state
persistentVolumeClaim: {claimName: hermes-execution-mediator-state-1}
- name: pool-access
emptyDir: {medium: Memory, sizeLimit: 1Mi}
- name: scm-broker-client
configMap: {name: hermes-scm-boundary-v2, defaultMode: 0555}
- name: coordinator
configMap: {name: hermes-execution-pool, defaultMode: 0555}
- name: tmp
emptyDir: {sizeLimit: 64Mi}
- name: vault-auth-token
projected:
defaultMode: 0600
sources:
- serviceAccountToken: {audience: vault, expirationSeconds: 3600, path: token}
- configMap:
name: kube-root-ca.crt
items: [{key: ca.crt, path: ca.crt}]
- downwardAPI:
items: [{path: namespace, fieldRef: {fieldPath: metadata.namespace}}]
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: hermes-execution-mediator-2
namespace: hermes
labels: {app: hermes-execution-mediator, pool-ordinal: "2"}
spec:
replicas: 1
strategy: {type: Recreate}
selector:
matchLabels: {app: hermes-execution-mediator, pool-ordinal: "2"}
template:
metadata:
labels: {app: hermes-execution-mediator, pool-ordinal: "2"}
annotations:
ai.bstein.dev/config-rev: execution-pool-v2-mediated
ai.bstein.dev/security-boundary: model-pod-has-no-hmac-or-scm-network-authority
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: hermes-execution-worker
vault.hashicorp.com/agent-inject-containers: stage-mediator-access
vault.hashicorp.com/agent-service-account-token-volume-name: vault-auth-token
vault.hashicorp.com/agent-inject-secret-execution-pool-key: kv/data/atlas/hermes/agent-tokens
vault.hashicorp.com/agent-inject-perms-execution-pool-key: "0600"
vault.hashicorp.com/agent-inject-template-execution-pool-key: |
{{- with secret "kv/data/atlas/hermes/agent-tokens" -}}
{{ printf "hermes-execution-pool-root-v2:%s" .Data.data.agent_api_key | sha256Hex }}
{{- end }}
vault.hashicorp.com/agent-pre-populate-only: "true"
vault.hashicorp.com/agent-init-first: "true"
vault.hashicorp.com/agent-requests-cpu: 2m
vault.hashicorp.com/agent-requests-mem: 16Mi
vault.hashicorp.com/agent-limits-cpu: 100m
vault.hashicorp.com/agent-limits-mem: 128Mi
spec:
serviceAccountName: hermes-execution-worker
automountServiceAccountToken: false
enableServiceLinks: false
# Priority parity with the worker: a pressured node evicts the pair
# symmetrically instead of moving only the lower-priority half, and the
# pool never preempts anything else in the cluster.
priorityClassName: scavenger
securityContext:
fsGroup: 10000
fsGroupChangePolicy: OnRootMismatch
seccompProfile: {type: RuntimeDefault}
affinity:
# Colocation with the worker is a throughput preference, not a
# requirement. The shared workspace claim is ReadWriteMany, so this
# mediator still schedules and serves when its worker is Pending or
# placed elsewhere -- which is what makes a drain self-healing.
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-04, titan-13, titan-14, titan-17, titan-18, titan-19, titan-22, titan-24]}
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
statefulset.kubernetes.io/pod-name: hermes-execution-worker-2
topologyKey: kubernetes.io/hostname
initContainers:
- name: stage-mediator-access
image: registry.bstein.dev/bstein/hermes-agent
command: [/opt/hermes/.venv/bin/python, /opt/coordinator/stage_runtime_access.py, execution-mediator]
env:
- {name: HERMES_WORKER_ORDINAL, value: "2"}
- {name: HERMES_POOL_ACCESS_ROOT, value: /pool-access}
securityContext:
allowPrivilegeEscalation: false
runAsUser: 0
runAsGroup: 0
seccompProfile: {type: RuntimeDefault}
volumeMounts:
- {name: pool-access, mountPath: /pool-access}
- {name: coordinator, mountPath: /opt/coordinator, readOnly: true}
resources:
requests: {cpu: 2m, memory: 16Mi}
limits: {cpu: 100m, memory: 64Mi}
containers:
- name: execution-mediator
image: registry.bstein.dev/bstein/hermes-agent
command: [/opt/hermes/.venv/bin/python, /opt/coordinator/execution_pool_client.py]
env:
- {name: HERMES_WORKER_ORDINAL, value: "2"}
- {name: HERMES_WORKER_ROOT, value: /workspace}
- {name: HERMES_SCM_STATE_ROOT, value: /scm-state}
- {name: HERMES_EXECUTION_POOL_KEY_FILE, value: /pool-access/execution-pool-key}
- {name: PYTHONPATH, value: /opt/scm:/opt/coordinator:/opt/hermes}
ports: [{name: mediator, containerPort: 9009, protocol: TCP}]
startupProbe:
httpGet: {path: /ready, port: mediator}
periodSeconds: 5
failureThreshold: 60
readinessProbe:
httpGet: {path: /ready, port: mediator}
periodSeconds: 10
securityContext:
allowPrivilegeEscalation: false
capabilities: {drop: [ALL]}
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 10000
runAsGroup: 10000
seccompProfile: {type: RuntimeDefault}
volumeMounts:
- {name: workspace, mountPath: /workspace}
- {name: scm-state, mountPath: /scm-state}
- {name: pool-access, mountPath: /pool-access, readOnly: true}
- {name: scm-broker-client, mountPath: /opt/scm, readOnly: true}
- {name: coordinator, mountPath: /opt/coordinator, readOnly: true}
- {name: tmp, mountPath: /tmp}
resources:
requests: {cpu: 2m, memory: 64Mi}
limits: {cpu: 250m, memory: 256Mi}
volumes:
- name: workspace
persistentVolumeClaim: {claimName: workspace-hermes-execution-worker-2}
- name: scm-state
persistentVolumeClaim: {claimName: hermes-execution-mediator-state-2}
- name: pool-access
emptyDir: {medium: Memory, sizeLimit: 1Mi}
- name: scm-broker-client
configMap: {name: hermes-scm-boundary-v2, defaultMode: 0555}
- name: coordinator
configMap: {name: hermes-execution-pool, defaultMode: 0555}
- name: tmp
emptyDir: {sizeLimit: 64Mi}
- name: vault-auth-token
projected:
defaultMode: 0600
sources:
- serviceAccountToken: {audience: vault, expirationSeconds: 3600, path: token}
- configMap:
name: kube-root-ca.crt
items: [{key: ca.crt, path: ca.crt}]
- downwardAPI:
items: [{path: namespace, fieldRef: {fieldPath: metadata.namespace}}]