{"id":13646863,"url":"https://github.com/gajus/preoom","last_synced_at":"2025-04-15T21:27:25.675Z","repository":{"id":57329820,"uuid":"163897971","full_name":"gajus/preoom","owner":"gajus","description":"Retrieves \u0026 observes Kubernetes Pod resource (CPU, memory) utilisation.","archived":false,"fork":false,"pushed_at":"2019-12-12T09:57:50.000Z","size":18,"stargazers_count":55,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-29T01:34:24.014Z","etag":null,"topics":["kubernetes","oom"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gajus.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-01-02T22:55:37.000Z","updated_at":"2022-08-25T14:08:59.000Z","dependencies_parsed_at":"2022-09-16T17:42:05.100Z","dependency_job_id":null,"html_url":"https://github.com/gajus/preoom","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gajus%2Fpreoom","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gajus%2Fpreoom/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gajus%2Fpreoom/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gajus%2Fpreoom/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gajus","download_url":"https://codeload.github.com/gajus/preoom/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249156186,"owners_count":21221727,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["kubernetes","oom"],"created_at":"2024-08-02T01:03:11.327Z","updated_at":"2025-04-15T21:27:25.647Z","avatar_url":"https://github.com/gajus.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# Preoom 🧐\n\n[![Travis build status](http://img.shields.io/travis/gajus/preoom/master.svg?style=flat-square)](https://travis-ci.org/gajus/preoom)\n[![Coveralls](https://img.shields.io/coveralls/gajus/preoom.svg?style=flat-square)](https://coveralls.io/github/gajus/preoom)\n[![NPM version](http://img.shields.io/npm/v/preoom.svg?style=flat-square)](https://www.npmjs.org/package/preoom)\n[![Canonical Code Style](https://img.shields.io/badge/code%20style-canonical-blue.svg?style=flat-square)](https://github.com/gajus/canonical)\n[![Twitter Follow](https://img.shields.io/twitter/follow/kuizinas.svg?style=social\u0026label=Follow)](https://twitter.com/kuizinas)\n\nRetrieves \u0026 observes Kubernetes Pod resource (CPU, memory) utilisation.\n\n* [Use case](#use-case)\n* [Requirements](#requirements)\n* [Usage](#usage)\n  * [Using Preoom with Lightship to gracefully shutdown service before the OOM termination](#using-preoom-with-lightship-to-gracefully-shutdown-service-before-the-oom-termination)\n* [Related projects](#related-projects)\n\n## Use case\n\nIf node experiences a system OOM (out of memory) event prior to the `kubelet` being able to reclaim memory, then `oom_killer` identifies and kills containers with the lowest quality of service that are consuming the largest amount of memory relative to the scheduling request.\n\nThese pods will be terminated and termination reason will be \"OOMKilled\", e.g.\n\n```\nLast State:   Terminated\nReason:       OOMKilled\nExit Code:    137\n\n```\n\nThe problem is that [Kubernetes OOM termination is performed using SIGKILL](https://github.com/kubernetes/kubernetes/issues/40157), i.e. Pod is not given time for graceful shutdown.\n\nPreoom allows to set up a regular check for memory usage and gracefully shutdown the Kubernetes Pod before the OOM termination occurs (see [Using Preoom with Lightship to gracefully shutdown service before the OOM termination](#using-preoom-with-lightship-to-gracefully-shutdown-service-before-the-oom-termination)).\n\n## Requirements\n\n[Kubernetes Metrics Server](https://github.com/kubernetes-incubator/metrics-server) must be available in the cluster and the metrics.k8s.io API must be accessible by the anonymous service account.\n\n## Usage\n\n```js\nimport {\n  createResourceObserver,\n  isKubernetesCredentialsPresent\n} from 'preoom';\n\nconst main = async () =\u003e {\n  const resourceObserver = createResourceObserver();\n\n  if (isKubernetesCredentialsPresent()) {\n    console.log(await resourceObserver.getPodResourceSpecification());\n\n    // {\n    //   containers: [\n    //     {\n    //       name: 'authentication-proxy',\n    //       resources: {\n    //         limits: {\n    //           cpu: 500',\n    //           memory: 536870912\n    //         },\n    //         requests: {\n    //           cpu: 250,\n    //           memory: 268435456\n    //         }\n    //       }\n    //     },\n    //     {\n    //       name: 'monitoring-proxy',\n    //       resources: {\n    //         limits: {\n    //           cpu: 1000',\n    //           memory: 536870912\n    //         },\n    //         requests: {\n    //           cpu: 500,\n    //           memory: 268435456\n    //         }\n    //       }\n    //     },\n    //     {\n    //       name: 'showtime-api',\n    //       resources: {\n    //         limits: {\n    //           cpu: 2000,\n    //           memory: 2147483648\n    //         },\n    //         requests: {\n    //           cpu: 1000,\n    //           memory: 1073741824\n    //         }\n    //       }\n    //     }\n    //   ],\n    //   name: 'showtime-api-56568dd94-tz8df'\n    // }\n\n    console.log(await resourceObserver.getPodResourceUsage());\n\n    // {\n    //   containers: [\n    //     {\n    //       name: 'authentication-proxy',\n    //       usage: {\n    //         cpu: 0,\n    //         memory: 101044224\n    //       }\n    //     },\n    //     {\n    //       name: 'monitoring-proxy',\n    //       usage: {\n    //         cpu: 1000,\n    //         memory: 42151936\n    //       }\n    //     },\n    //     {\n    //       name: 'showtime-api',\n    //       usage: {\n    //         cpu: 0,\n    //         memory: 1349738496\n    //       }\n    //     }\n    //   ],\n    //   name: 'showtime-api-56568dd94-tz8df'\n    // }\n  }\n};\n\nmain();\n\n```\n\n### Using Preoom with Lightship to gracefully shutdown service before the OOM termination\n\nPreoom allows to set up a regular check for memory usage and gracefully shutdown the Kubernetes Pod before the OOM termination occurs. Graceful termination can be implemented using [Lightship](https://github.com/gajus/lightship), e.g.\n\n```js\nimport {\n  createLightship\n} from 'lightship';\nimport {\n  createResourceObserver,\n  isKubernetesCredentialsPresent\n} from 'preoom';\n\nconst MAXIMUM_MEMORY_USAGE = 0.95;\n\nconst main = async () =\u003e {\n  const lightship = createLightship();\n\n  if (isKubernetesCredentialsPresent()) {\n    const resourceObserver = createResourceObserver();\n\n    resourceObserver.observe((error, podResourceSpecification, podResourceUsage) =\u003e {\n      if (error) {\n        // Handle error.\n      } else {\n        for (const containerResourceSpecification of podResourceSpecification.containers) {\n          if (containerResourceSpecification.resources.limits \u0026\u0026 containerResourceSpecification.resources.limits.memory) {\n            const containerResourceUsage = podResourceUsage.containers.find((container) =\u003e {\n              return container.name === containerResourceSpecification.name;\n            });\n\n            if (!containerResourceUsage) {\n              throw new Error('Unexpected state.');\n            }\n\n            if (containerResourceUsage.usage.memory / containerResourceSpecification.resources.limits.memory \u003e MAXIMUM_MEMORY_USAGE) {\n              lightship.shutdown();\n            }\n          }\n        }\n      }\n    }, 5 * 1000);\n  }\n\n  lightship.signalReady();\n}\n\nmain();\n\n```\n\n## Units\n\n* CPUs are reported as milliCPU units (1000 = 1 CPU).\n* Memory is reported in bytes.\n\n## Related projects\n\n* [Iapetus](https://github.com/gajus/iapetus) – Prometheus metrics server.\n* [Lightship](https://github.com/gajus/lightship) – Abstracts readiness/ liveness checks and graceful shutdown of Node.js services running in Kubernetes.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgajus%2Fpreoom","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgajus%2Fpreoom","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgajus%2Fpreoom/lists"}