{"id":36441229,"url":"https://github.com/metral/memhog-operator","last_synced_at":"2026-01-11T21:58:12.995Z","repository":{"id":64305787,"uuid":"86002889","full_name":"metral/memhog-operator","owner":"metral","description":"A Kubernetes Operator that redeploys an app when resource limits are exceeded.","archived":false,"fork":false,"pushed_at":"2017-11-22T19:30:46.000Z","size":37,"stargazers_count":1,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-04-14T15:54:04.763Z","etag":null,"topics":["go","golang","kubernetes","operators"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/metral.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":"2017-03-23T22:19:08.000Z","updated_at":"2019-01-15T01:22:40.000Z","dependencies_parsed_at":"2023-01-15T10:30:21.460Z","dependency_job_id":null,"html_url":"https://github.com/metral/memhog-operator","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/metral/memhog-operator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/metral%2Fmemhog-operator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/metral%2Fmemhog-operator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/metral%2Fmemhog-operator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/metral%2Fmemhog-operator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/metral","download_url":"https://codeload.github.com/metral/memhog-operator/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/metral%2Fmemhog-operator/sbom","scorecard":{"id":638323,"data":{"date":"2025-08-11","repo":{"name":"github.com/metral/memhog-operator","commit":"dcad758aef78c0f9084f99e99674416d84911fc5"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.8,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 0/14 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: containerImage not pinned by hash: Dockerfile:1: pin your Docker image by updating alpine:3.6 to alpine:3.6@sha256:66790a2b79e1ea3e1dabac43990c54aca5d1ddf268d9a5a0285e4167c8b24475","Info:   0 out of   1 containerImage dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 15 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-21T09:55:52.843Z","repository_id":64305787,"created_at":"2025-08-21T09:55:52.843Z","updated_at":"2025-08-21T09:55:52.843Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28324638,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-11T18:42:50.174Z","status":"ssl_error","status_checked_at":"2026-01-11T18:39:13.842Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["go","golang","kubernetes","operators"],"created_at":"2026-01-11T21:58:12.292Z","updated_at":"2026-01-11T21:58:12.988Z","avatar_url":"https://github.com/metral.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Creating Custom Operators\n\nThe `memhog-operator` is an example on how to create custom operators for\nKubernetes.\n\nThe purpose of the `memhog-operator` is to watch for Pods in a namespace and\nmonitor its memory usage. If the memory consumption of the Pod crosses a\nthreshold, it will be vertically autoscaled by the operator.\n\nSpecifically, the operator will deploy a new copy of the Pod with a higher\nset of resource requests and limit, and then terminate the original Pod.\nThe details of the higher resources are held within an `AppMonitor`,\na [CustomResourceDefinition\n(CRD)](https://github.com/kubernetes/apiextensions-apiserver/blob/fbe70034cb9becd97bf8b6207f918c73cadd330e/pkg/apis/apiextensions/types.go#L119-L129).\n\n[memhog](https://github.com/metral/memhog): An example Pod that this operator would monitor.\n\n\u003e Note: The `memhog-operator` is strictly for educational \u0026 demo purposes. It is not intended\nto be used for any other use-cases.\n\n## Operator Structure\n\nThe `memhog-operator` is a combination of a CustomResourceDefinition\nknown as the `AppMonitor`, and a custom Controller to enforce state.\n\nThe `AppMonitor` encapsulates the autoscaling details for a Pod.\nThe controller watches a Namespace for an `AppMonitor`, and for Pods that wish \nto be monitored (via Annotation). It then applies the operational\nthresholds and requirements declared in the `AppMonitor` onto the Pod.\n\n## Requirements\n* Kubernetes v1.7.0+\n* Prometheus on k8s with cAdvisor exposing `container_memory_usage_bytes`\n* glide v0.11.1\n\n## Process\n\n* To monitor the Pod's resource memory consumption, the operator requires that the Pod have an annotation in its `spec.template.metadata` to associate itself with the `memhog-operator`.\n\n  e.g. The [memhog](https://github.com/metral/memhog) example is annotated as such:\n\n  \u003cpre\u003e\u003ccode\u003eapiVersion: extensions/v1beta1\n  kind: Deployment\n  metadata:\n    name: memhog\n  spec:\n    replicas: 1\n    template:\n      metadata:\n        labels:\n          name: memhog\n        \u003cb\u003eannotations:\n          app-monitor.kubedemo.com/monitor: \"true\"\u003c/b\u003e\n      spec:\n        containers:\n        - name: memhog\n          image: quay.io/metral/memhog:v0.0.1\n          imagePullPolicy: Always\n          \u003cb\u003eresources:\n            limits:\n              memory: 384Mi\n            requests:\n              memory: 256Mi\u003c/b\u003e\n          ...\n  \u003c/code\u003e\u003c/pre\u003e\n\n* Run the annotated Pod, noting the resource requests \u0026 limits set that are\nalso required by the Operator.\n\n* In the Pod's namespace there must also be an instantiated object of the custom\n`AppMonitor` CRD that the Operator depends on. For example, this `AppMonitor`\nstates that any Pod being monitored by the `memhog-operator` will have its\nresources doubled when 75% or more of its memory has been used e.g.:\n\n  ```\n  apiVersion: kubedemo.com/v1\n  kind: AppMonitor\n  metadata:\n    name: johnny-cache\n  spec:\n    memThresholdPercent: 75   # Percentage of (memory used) / (memory limit)\n    memMultiplier: 2          # Multiplier factor used to increase memory resource requests \u0026 limits\n  ```\n* The `memhog-operator` will watch the Pod's memory usage by querying\nPrometheus, applying the `AppMonitor` to the Pod as memory usage is retrieved.  If the `AppMonitor` threshold is crossed,\nthe Operator will redeploy the Pod with higher resource requests \u0026 limits based\non the multiplier.\n* If the Pod is redeployed, it will have updated and increased resource requests \u0026 limits\ne.g.:\n```\n  ...\n  resources:\n    limits:\n      memory: 768Mi\n    requests:\n      memory: 512Mi\n  ...\n```\n\n### Building \u0026 Running\n\n```\n// Build\n$ glide install -s -u -v\n$ make\n```\n\n\n#### Run Locally\n\u003e Note: Prometheus is assumed to be running locally on http://localhost:9090\n\n```\n$ $GOPATH/bin/memhog-operator -v2 --prometheus-addr=http://localhost:9090 --kubeconfig=$HOME/.kube/config\n```\n\n#### Run on Kubernetes\n\u003e Note: Prometheus is assumed to be running by default on http://prometheus.tectonic-system:9090 (e.g. Tectonic Cluster) by the Operator Deployment\n\n```\n// Create cluster role \u0026 cluster role binding to work with CRD's.\n$ kubectl create -f k8s/roles/role.yaml\n\n$ kubectl create -f k8s/deploy/memhog-operator-deploy.yaml\n```\n\n### References\n\n* [ThirdPartyResources (TPR) -\u003e CustomResourceDefinitions (CRD)](https://groups.google.com/forum/#!msg/kubernetes-dev/R749_-L_ssc/p-3tyl6mAQAJ)\n* [CRD Example](https://github.com/kubernetes/apiextensions-apiserver/tree/master/examples/client-go)\n* [The TPR is dead. Long live the CRD: Custom Resources in Kubernetes v1.7](https://coreos.com/blog/custom-resource-kubernetes-v17)\n* [Working with Controllers](https://github.com/kubernetes/community/blob/master/contributors/devel/controllers.md)\n* [Writing a Custom Controller - Aaron Levy (CoreOS)](https://github.com/aaronlevy/kube-controller-demo\n)\n  * [KubeCon EU 2017 Video](youtu.be/_BuqPMlXfpE?list=PLj6h78yzYM2PAavlbv0iZkod4IVh_iGqV)\n* [DaemonSet Controller Code](https://github.com/kubernetes/kubernetes/blob/master/pkg/controller/daemon/daemoncontroller.go)\n\n* Deprecated\n  * [TPRs are Deprecated](https://github.com/kubernetes/client-go/tree/df46f7f13b3da19b90b8b4f0d18b8adc6fbf28dc/examples/third-party-resources-deprecated\n)\n  * [Extend the Kubernetes API with TPRs](https://kubernetes.io/docs/tasks/access-kubernetes-api/extend-api-third-party-resource/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmetral%2Fmemhog-operator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmetral%2Fmemhog-operator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmetral%2Fmemhog-operator/lists"}