{"id":13581596,"url":"https://github.com/medik8s/node-maintenance-operator","last_synced_at":"2025-07-02T12:35:18.609Z","repository":{"id":37105360,"uuid":"454694127","full_name":"medik8s/node-maintenance-operator","owner":"medik8s","description":"Kubernetes Operator to manage node maintenance through NodeMaintenance custom resources","archived":false,"fork":false,"pushed_at":"2025-04-16T22:55:14.000Z","size":31783,"stargazers_count":39,"open_issues_count":6,"forks_count":16,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-05-20T10:01:53.829Z","etag":null,"topics":["availability","k8s","kubernetes","kubernetes-node","kubernetes-operator","maintenance","operator"],"latest_commit_sha":null,"homepage":"https://www.medik8s.io/maintenance-node/","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/medik8s.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-02-02T08:22:57.000Z","updated_at":"2025-02-12T19:57:55.000Z","dependencies_parsed_at":"2024-01-30T08:32:44.682Z","dependency_job_id":"8c9f3ba7-90a9-427d-8c77-f2da051a7749","html_url":"https://github.com/medik8s/node-maintenance-operator","commit_stats":{"total_commits":472,"total_committers":20,"mean_commits":23.6,"dds":0.6059322033898304,"last_synced_commit":"c7caa052799f0747971e17e437d7b8161cf6bbdd"},"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"purl":"pkg:github/medik8s/node-maintenance-operator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/medik8s%2Fnode-maintenance-operator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/medik8s%2Fnode-maintenance-operator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/medik8s%2Fnode-maintenance-operator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/medik8s%2Fnode-maintenance-operator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/medik8s","download_url":"https://codeload.github.com/medik8s/node-maintenance-operator/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/medik8s%2Fnode-maintenance-operator/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263141167,"owners_count":23420014,"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":["availability","k8s","kubernetes","kubernetes-node","kubernetes-operator","maintenance","operator"],"created_at":"2024-08-01T15:02:06.994Z","updated_at":"2025-07-02T12:35:18.575Z","avatar_url":"https://github.com/medik8s.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# Node Maintenance Operator (NMO)\n\n\u003cp align=\"center\"\u003e\n\u003cimg width=\"100\" src=\"config/assets/nmo_blue_icon.png\"\u003e\n\u003c/p\u003e\n\nThe node-maintenance-operator (**NMO**) is an operator generated from the [operator-sdk](https://github.com/operator-framework/operator-sdk).\nNMO was *previously* developed under [KubeVirt](https://github.com/kubevirt/node-maintenance-operator), and this repository is the up-to-date version of NMO.\n\nThe purpose of this operator is to watch for new or deleted custom resources (CRs) called `NodeMaintenance` which indicate that a node in the cluster should either:\n  - `NodeMaintenance` CR created: move node into maintenance, cordon the node - set it as unschedulable, and evict the pods (which can be evicted) from that node.\n  - `NodeMaintenance` CR deleted: remove node from maintenance and uncordon the node - set it as schedulable.\n\n\u003e *Note*:  The current behavior of the operator is to mimic `kubectl drain \u003cnode name\u003e`.\n\n## Build and run the operator\n\nThere are three ways to run the operator:\n\n- Deploy the latest version, which was built from the `main` branch, to a running OpenShift/Kubernetes cluster.\n- Deploy the last release version from OperatorHub to a running Kubernetes cluster.\n- Build and deploy from sources to a running or to be created OpenShift/Kubernetes cluster.\n\n### Deploy the latest version\n\nAfter every PR merge to `main` branch images were build and pushed to `quay.io`.\nFor deployment of NMO using these images you need:\n\n- a running OpenShift cluster, or a Kubernetes cluster with Operator Lifecycle Manager (OLM) installed.\n- `operator-sdk` binary installed, see https://sdk.operatorframework.io/docs/installation/.\n- a valid `$KUBECONFIG` configured to access your cluster.\n\nThen run `operator-sdk run bundle quay.io/medik8s/node-maintenance-operator-bundle:latest`\n\n### Deploy the last release version\nClick on `Install` in the Node Maintenance Operator page under [OperatorHub.io](https://operatorhub.io/operator/node-maintenance-operator), \nand follow its instructions to install the [Operator Lifecycle Manager (OLM)](https://olm.operatorframework.io/), and the operator.\n\n### Build and deploy from sources\nFollow the instructions [here](https://sdk.operatorframework.io/docs/building-operators/golang/tutorial/#3-deploy-your-operator-with-olm) for deploying the operator with OLM.\n\u003e *Note*: Webhook cannot run using `make deploy`, because the volume mount of the webserver certificate is not found.\n\n## Setting Node Maintenance\n\n### Set Maintenance on - Create a NodeMaintenance CR\n\nTo set maintenance on a node a `NodeMaintenance` custom resource should be created.\nThe `NodeMaintenance` CR spec contains:\n- nodeName: The name of the node which will be put into maintenance mode.\n- reason: The reason why the node will be under maintenance.\n\nCreate the example `NodeMaintenance` CR found at `config/samples/nodemaintenance_v1beta1_nodemaintenance.yaml`:\n\n```sh\n$ cat config/samples/nodemaintenance_v1beta1_nodemaintenance.yaml\napiVersion: nodemaintenance.medik8s.io/v1beta1\nkind: NodeMaintenance\nmetadata:\n  name: nodemaintenance-sample\nspec:\n  nodeName: node02\n  reason: \"Test node maintenance\"\n\n$ kubectl apply -f config/samples/nodemaintenance_v1beta1_nodemaintenance.yaml\n\n$ kubectl logs \u003cnmo-pod-name\u003e\n022-02-23T07:33:58.924Z INFO controller-runtime.manager.controller.nodemaintenance Reconciling NodeMaintenance {\"reconciler group\": \"nodemaintenance.medik8s.io\", \"reconciler kind\": \"NodeMaintenance\", \"name\": \"nodemaintenance-sample\", \"namespace\": \"\"}\n2022-02-23T07:33:59.266Z INFO controller-runtime.manager.controller.nodemaintenance Applying maintenance mode {\"reconciler group\": \"nodemaintenance.medik8s.io\", \"reconciler kind\": \"NodeMaintenance\", \"name\": \"nodemaintenance-sample\", \"namespace\": \"\", \"node\": \"node02\", \"reason\": \"Test node maintenance\"}\ntime=\"2022-02-24T11:58:20Z\" level=info msg=\"Maintenance taints will be added to node node02\"\ntime=\"2022-02-24T11:58:20Z\" level=info msg=\"Applying medik8s.io/drain taint add on Node: node02\"\ntime=\"2022-02-24T11:58:20Z\" level=info msg=\"Patching taints on Node: node02\"\n2022-02-23T07:33:59.336Z INFO controller-runtime.manager.controller.nodemaintenance Evict all Pods from Node {\"reconciler group\": \"nodemaintenance.medik8s.io\", \"reconciler kind\": \"NodeMaintenance\", \"name\": \"nodemaintenance-sample\", \"namespace\": \"\", \"nodeName\": \"node02\"}\nE0223 07:33:59.498801 1 nodemaintenance_controller.go:449] WARNING: ignoring DaemonSet-managed Pods: openshift-cluster-node-tuning-operator/tuned-jrprj, openshift-dns/dns-default-kf6jj, openshift-dns/node-resolver-72jzb, openshift-image-registry/node-ca-czgc6, openshift-ingress-canary/ingress-canary-44tgv, openshift-machine-config-operator/machine-config-daemon-csv6c, openshift-monitoring/node-exporter-rzwhz, openshift-multus/multus-additional-cni-plugins-829bh, openshift-multus/multus-qwfc9, openshift-multus/network-metrics-daemon-pxt6n, openshift-network-diagnostics/network-check-target-qqcbr, openshift-sdn/sdn-s5cqx; deleting Pods not managed by ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet: openshift-marketplace/nmo-downstream-8-8nms7\nI0223 07:33:59.500418 1 nodemaintenance_controller.go:449] evicting pod openshift-network-diagnostics/network-check-source-865d4b5578-n2cxg\nI0223 07:33:59.500790 1 nodemaintenance_controller.go:449] evicting pod openshift-ingress/router-default-7548cf6fb5-rgxrq\nI0223 07:33:59.500944 1 nodemaintenance_controller.go:449] evicting pod openshift-marketplace/12a4cfa0c2be01867daf1d9b7ad7c0ae7a988fd957a2ad6df0d72ff6875lhcx\nI0223 07:33:59.501061 1 nodemaintenance_controller.go:449] evicting pod openshift-marketplace/nmo-downstream-8-8nms7\n...\n```\n\n### Set Maintenance off - Delete the NodeMaintenance CR\n\nTo remove maintenance from a node, delete the corresponding `NodeMaintenance` (or `nm` which is a shortName) CR:\n\n```sh\n$ kubectl delete nm nodemaintenance-sample\nnodemaintenance.nodemaintenance.medik8s.io \"nodemaintenance-sample\" deleted\n$ kubectl logs \u003cnmo-pod-name\u003e\n2022-02-24T14:27:35.332Z INFO controller-runtime.manager.controller.nodemaintenance Reconciling NodeMaintenance {\"reconciler group\": \"nodemaintenance.medik8s.io\", \"reconciler kind\": \"NodeMaintenance\", \"name\": \"nodemaintenance-sample\", \"namespace\": \"\"}\ntime=\"2022-02-24T14:27:35Z\" level=info msg=\"Maintenance taints will be removed from node node02\"\ntime=\"2022-02-24T14:27:35Z\" level=info msg=\"Applying medik8s.io/drain taint remove on Node: node02\"\n...\n```\n\n## NodeMaintenance Status\n\nThe `NodeMaintenance` CR can contain the following status fields:\n\n```sh\n$ kubectl get nm nodemaintenance-sample -o yaml\napiVersion: nodemaintenance.medik8s.io/v1beta1\nkind: NodeMaintenance\nmetadata:\n  name: nodemaintenance-sample\nspec:\n  nodeName: node02\n  reason: Test node maintenance\nstatus:\n  drainProgress: 40\n  evictionPods: 5\n  lastError: \"Last failure message\"\n  lastUpdate: \"2022-06-23T11:43:18Z\"\n  pendingPods:\n  - pod-A\n  - pod-B\n  - pod-C\n  phase: Running\n  totalpods: 19\n```\n\n`drainProgress` shows the percentage completion of draining the node.\n\n`evictionPods` is the total number of pods up for eviction, before the node entered maintenance mode.\n\n`lastError` represents the latest error if any for the latest reconciliation.\n\n`lastUpdate` is the last time the status has been updated.\n\n`pendingPods` is a list of pending pods for eviction.\n\n`phase` is the representation of the maintenance progress and can hold a string value of: Running|Succeeded.\nThe phase is updated for each processing attempt on the CR.\n\n`totalPods` is the total number of pods, before the node entered maintenance mode.\n\n## Debug\n### Collecting cluster data with must-gather\n\nUse NMO's must-gather from [here](https://github.com/medik8s/node-maintenance-operator/tree/main/must-gather) to collect related debug data.\n\n## Tests\n\n### Run code checks and unit tests\n\n`make check`\n\n### Run e2e tests\n\n1. Deploy the operator as explained above\n2. run `make cluster-functest`\n\n## Releases\n\n### Creating a new release\n\nFor new minor releases:\n\n  - create and push the `release-0.y` branch.\n  - update OpenshiftCI with new branches!\n\nFor every major / minor / patch release:\n\n  - create and push the `vx.y.z` tag.\n  - this should trigger CI to build and push new images\n  - if it fails, the manual fallback is `VERSION=x.y.z make container-build-and-push-community`\n  - make the git tag a release in the GitHub UI.\n\n## Help\n\nFeel free to join our Google group to get more info - https://groups.google.com/g/medik8s\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmedik8s%2Fnode-maintenance-operator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmedik8s%2Fnode-maintenance-operator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmedik8s%2Fnode-maintenance-operator/lists"}