Skip to content

fix: give the oed-api container a 1Gi memory limit - #7

Merged
matthewberry merged 2 commits into
mainfrom
mjberry/fix/memory-limit
Nov 4, 2026
Merged

matthewberry merged 2 commits into
mainfrom
mjberry/fix/memory-limit

Conversation

@matthewberry

@matthewberry matthewberry commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Why

On 2026-11-04 two mmli2 worker nodes went NotReady three times between them with SystemOOM ... victim process: uvicorn, evicting every pod on them (including the mmli-backend and its MinIO). At 15:31 UTC the container OOM-killed at that moment was this one: it has no memory limit, so a request that grows large uses the node's memory instead of a container's. Its last logged request was GET /api/v1/data?offset=0&limit=5000 from outside the cluster; the request in flight when it died wasn't logged.

What

  • deployment.yaml renders controller.resources when set.
  • values.yaml sets a 256Mi request and a 1Gi limit. If a request exceeds 1Gi, only this container is OOM-killed and restarted; the node and its other pods are unaffected.

Sizing

Idle, the container uses 46–106Mi. A 5000-record response, including the rich.print of all records in app/db/queries.py:143, peaks at about 260Mi (measured locally with synthetic records shaped like the real ones). A full-table request (35,753 records, no cap on an explicit limit) peaks at about 1.6Gi in that print alone, so it will now kill the container instead of the node. Capping limit and removing that print come in a separate PR.

Testing

helm template renders the Deployment with resources.requests.memory: 256Mi and resources.limits.memory: 1Gi. Not yet observed on the cluster.

Deploying

Argo CD (mmli2-mmli-oed-api) tracks this chart on main with automated sync, so merging rolls out a new pod; with one replica, the API is briefly unavailable.

With no limit, a large /api/v1/data request could use all of a node's memory. On
2026-11-04 the kernel OOM-killed this container while the node itself went NotReady,
evicting every pod on it, three times in about 75 minutes. With a limit, only this
container is killed.

@matthewberry matthewberry left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Checked:

  • helm template (after helm dependency build) renders resources.limits.memory: 1Gi and requests.memory: 256Mi in the right place under the oed-api container.
  • The Dockerfile CMD runs one uvicorn process with no --workers, so 1Gi covers a single process.

Nit: the values.yaml comment says "A 5000-record /api/v1/data request peaks at about 260Mi." Once #8 merges that stops being true, because most of the 260Mi was the rich.print. #8 measures about 21 MiB before encoding. Either drop the number or say it was measured before #8.

@matthewberry

Copy link
Copy Markdown
Contributor Author

Fixed in aa58d13: the comment now gives the idle figure (about 50–110Mi, which stays true after #8) instead of the per-request one.

@matthewberry
matthewberry merged commit eaec86b into main Nov 4, 2026
1 check passed
@matthewberry

Copy link
Copy Markdown
Contributor Author

Correction to the PR description: mmli2-mmli-oed-api does not have automated sync. mmli2's charts/apps/templates/oed-api.yaml only enables it when moldb.oedapi.sync is set, and that key isn't set in charts/apps/values.yaml. So merging this didn't deploy it. The 256Mi/1Gi resources were applied by hand at 16:32 UTC on 2026-11-04 (kubectl patch matching this chart), and an Argo sync is still needed to record the change. Details in #9.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant