Every image in zoo-mainnet except consul and the ingress is published for linux/amd64 alone, and none of these files said so. Unpinned, the scheduler is free to place them on spark, where the kubelet refuses the pull with `no match for platform in manifest` -- which reads as a broken image and is a misplaced pod. zoo-ui, zoo-gym, zoo-bot and zoo-build had been sitting in ImagePullBackOff there. The pin follows the artifact: an image that exists for one architecture may only be scheduled where that architecture is. consul and the ingress are multi-arch and stay free to land anywhere. Co-authored-by: Hanzo Dev <[email protected]>
86 lines
2.8 KiB
YAML
86 lines
2.8 KiB
YAML
# Generated from the live zoo-mainnet/zoo-build Deployment on do-sfo3-zoo-k8s
|
|
# by hack/live2values.py. Live is the source: a repo of hand-applied
|
|
# manifests has unknown currency, the running fleet does not.
|
|
replicas: 1
|
|
selectorLabels:
|
|
app: zoo-build
|
|
containerName: build
|
|
image:
|
|
repository: ghcr.io/luxfi/build-zoo
|
|
tag: 0.1.9
|
|
digest: sha256:946f21b4481d81169a8e104c5669c1fd0f1911c7d8cb6732451442e25c39c03e
|
|
pullPolicy: IfNotPresent
|
|
labels:
|
|
app.kubernetes.io/cluster: zoo-k8s
|
|
app.kubernetes.io/env: mainnet
|
|
env:
|
|
- name: NODE_ENV
|
|
value: production
|
|
- name: NEXT_TELEMETRY_DISABLED
|
|
value: '1'
|
|
# V8 sizes its own heap and caps at ~258 MB inside this 512Mi container, so HALF the
|
|
# granted memory is unreachable and it dies there:
|
|
# FATAL ERROR: Ineffective mark-compacts near heap limit
|
|
# Mark-Compact 251.9 (258.3) -> 251.1 (258.8) MB
|
|
# exit 139
|
|
# The container is never out of memory — only the JS heap is, so raising limits.memory
|
|
# would not have moved a V8-internal ceiling. 384 MB leaves ~128Mi for RSS outside the
|
|
# heap. The lux-k8s copy of this same app crashed ~13-hourly until it got this; this
|
|
# copy has the identical shape and simply has not tripped yet.
|
|
- name: NODE_OPTIONS
|
|
value: --max-old-space-size=384
|
|
resources:
|
|
limits:
|
|
cpu: 500m
|
|
memory: 512Mi
|
|
requests:
|
|
cpu: 100m
|
|
memory: 256Mi
|
|
livenessProbe:
|
|
failureThreshold: 3
|
|
httpGet:
|
|
path: /
|
|
port: 3000
|
|
scheme: HTTP
|
|
initialDelaySeconds: 10
|
|
periodSeconds: 30
|
|
successThreshold: 1
|
|
timeoutSeconds: 1
|
|
readinessProbe:
|
|
failureThreshold: 3
|
|
httpGet:
|
|
path: /
|
|
port: 3000
|
|
scheme: HTTP
|
|
initialDelaySeconds: 5
|
|
periodSeconds: 10
|
|
successThreshold: 1
|
|
timeoutSeconds: 1
|
|
ports:
|
|
- containerPort: 3000
|
|
# ghcr-zooai, because that is the name this namespace has. `ghcr-luxfi` does
|
|
# not exist in zoo-mainnet -- a pod naming it gets no credential at all and the
|
|
# kubelet falls back to anonymous, which GHCR answers 403/NotFound for a private
|
|
# package. That reads as a missing image and is a missing secret. Verified
|
|
# 2026-09-09: ghcr-zooai pulls every repo this namespace references, zooai/* and
|
|
# the luxfi/* ones alike.
|
|
imagePullSecrets:
|
|
- name: ghcr-zooai
|
|
rollingUpdate:
|
|
maxSurge: 25%
|
|
maxUnavailable: 25%
|
|
topologySpread:
|
|
enabled: false
|
|
lifecycle: null
|
|
terminationGracePeriodSeconds: 30
|
|
|
|
# The image for this workload is published for linux/amd64 only, and this
|
|
# cluster has an arm64 node. Unpinned, the scheduler is free to place it on
|
|
# spark, where the kubelet refuses the pull with `no match for platform in
|
|
# manifest` -- which reads as a broken image and is a misplaced pod. Measured
|
|
# 2026-09-09: zoo-ui, zoo-gym, zoo-bot and zoo-build had all been sitting in
|
|
# ImagePullBackOff on spark. Pin follows the artifact: an image that exists for
|
|
# one architecture may only be scheduled where that architecture is.
|
|
nodeSelector:
|
|
kubernetes.io/arch: amd64
|