Files
bikoret/deploy/k8s/manna-cronjob.yaml
T
Scott KarpandClaude Fable 5.1 50b08cba4b manna: the provision falls at the boundary — 00:00Z — and readiness is carried across it
The watchdog's first night (2026-10-21): 503 at 00:00:01Z with
manna_present and esh_tamid failing, recovered 00:05Z. Every night since
the CronJob was applied the site has been dark one to five minutes:
the provision is stale from 00:00:00, the job ran at 00:01, and the
readiness probe (10 s period, default threshold 3) fell in the gap.

Not changed: the rule. A provision is for its day; Friday's double is
the Shabbat's; nothing else crosses the boundary (Shemot 16:19–26,
manna_shabbat_test.exs). Changed: the timing.
- manna-cronjob.yaml: schedule "0 0 * * 0-5" — the manna falls at the
  boundary, not a minute after it.
- deployment.yaml: readinessProbe.failureThreshold 6 — 60 s of failures
  before the Service stops routing. The job writes within seconds of
  00:00; the pod is carried across. A real outage still shows within a
  minute; the watchdog's own threshold is ten.
- KOHEN.md: the night's finding and the new timing.

Both manifests validate (kubectl apply --dry-run=client). Proof: the
watchdog log on the next boundary should show no FAIL at 00:00.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-21 17:53:45 +00:00

101 lines
4.8 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# The manna — written each morning by the system's own hand (Shemot 16).
#
# Until 2026-10-15 the day's provision was written by the kohen with
# `kubectl cp`, and every night at 00:00Z the old one went stale and the
# readiness probe failed until someone woke (13.5 hours on 2026-10-15).
# This CronJob writes today.json onto the manna PVC at 00:00Z, Sunday to
# Friday — a double portion on Friday that is valid through Shabbat, and
# nothing on Shabbat (Shemot 16:22–26: "on the sixth day they gathered
# double … on the seventh day there shall be none"). The kohen still sets
# the amounts (shorashim-config, MANNA_* below) and may still write a
# provision by hand at any hour; the CronJob only ends the gap.
#
# It runs our own korban-processor image (python, pinned to a commit tag)
# with the PVC mounted, as the app's uid/gid, so the file is readable by
# the pod; nothing else, no cluster permissions. ReadWriteOnce is fine:
# the cluster has one node and the job runs beside the pod.
apiVersion: batch/v1
kind: CronJob
metadata:
name: manna
namespace: shorashim
labels:
app.kubernetes.io/name: shorashim
app.kubernetes.io/component: manna
spec:
schedule: "0 0 * * 0-5" # 00:00Z, Sunday–Friday; none on Shabbat. At the boundary, not after it:
# the provision goes stale at 00:00:00 and readiness has a 60 s cushion
# (deployment.yaml failureThreshold 6) — a job that writes within it never
# flips the pod. At 00:01 the site was 503 for 1–5 min every night
# (watchdog, 2026-10-21).
timeZone: "Etc/UTC"
concurrencyPolicy: Forbid
startingDeadlineSeconds: 3600 # a missed 00:00 still runs within the hour
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 3
jobTemplate:
spec:
backoffLimit: 2
template:
metadata:
labels:
app.kubernetes.io/name: shorashim
app.kubernetes.io/component: manna
spec:
restartPolicy: Never
securityContext:
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
imagePullSecrets:
- name: shorashim-registry
volumes:
- name: manna
persistentVolumeClaim:
claimName: manna-pvc
containers:
- name: write-manna
image: exo.container-registry.com/the-recognition-protocol/korban-processor:c0d0555a
imagePullPolicy: IfNotPresent
envFrom:
- configMapRef:
name: shorashim-config
volumeMounts:
- name: manna
mountPath: /var/lib/bikoret/manna
resources:
requests: { cpu: "20m", memory: "32Mi" }
limits: { cpu: "200m", memory: "128Mi" }
command: ["python3", "-c"]
args:
- |
import json, os, datetime as dt
now = dt.datetime.now(dt.timezone.utc)
today = now.date()
friday = today.weekday() == 4
units = int(os.environ.get("MANNA_COMPUTE_UNITS", "1000"))
provision = {
"compute_units": units * (2 if friday else 1),
"memory_mb": int(os.environ.get("MANNA_MEMORY_MB", "32768")),
"api_calls_external": int(os.environ.get("MANNA_API_CALLS_EXTERNAL", "500")) * (2 if friday else 1),
"storage_delta_mb": int(os.environ.get("MANNA_STORAGE_DELTA_MB", "100")),
"sanhedrin_panels_max": int(os.environ.get("MANNA_SANHEDRIN_PANELS_MAX", "5")),
}
# Regular: through the day. Double (Friday): through Shabbat, to Sunday 00:30Z.
expires = (dt.datetime.combine(today + dt.timedelta(days=2), dt.time(0, 30), dt.timezone.utc)
if friday else dt.datetime.combine(today + dt.timedelta(days=1), dt.time(0, 30), dt.timezone.utc))
doc = {
"date": today.isoformat(),
"provision": provision,
"type": "double" if friday else "regular",
"expires_at": expires.strftime("%Y-%m-%dT%H:%M:%SZ"),
"written_by": "manna-cronjob",
"written_at": now.strftime("%Y-%m-%dT%H:%M:%SZ"),
}
path = os.environ.get("MANNA_PROVISION_FILE", "/var/lib/bikoret/manna/today.json")
tmp = path + ".tmp"
with open(tmp, "w") as fh:
json.dump(doc, fh, indent=2)
os.replace(tmp, path)
print("manna written", doc["date"], doc["type"], "expires", doc["expires_at"])