From b8b18ec8a4efa2d7f4f1c1a8a940e85f9d2331bb Mon Sep 17 00:00:00 2001 From: mgianluc Date: Fri, 16 Feb 2024 11:30:13 +0100 Subject: [PATCH] Add automated nightly scaling of Deployments/StatefulSets/DaemonSets --- README.md | 32 +++++--- .../scheduled-scaling/pause.yaml | 74 +++++++++++++++++++ .../scheduled-scaling/resume.yaml | 72 ++++++++++++++++++ .../scale-down-high-restart-deployment.yaml | 0 ...nt-referencing-non-existent-resources.yaml | 0 ...ress-referencing-non-existent-service.yaml | 0 .../pods-with-expired-certificates.yaml | 0 .../pods-with-outdated-secret-data.yaml | 0 .../clusterroles/unused_clusterroles.yaml | 0 .../configmaps/orphaned_configmaps.yaml | 0 .../deployment_with_no_autoscaler.yaml | 0 .../deployment_with_replica_zero.yaml | 0 .../deployments/orphaned_deployment.yaml | 0 .../unused-hpas.yaml | 0 .../ingresses/unused_ingresses.yaml | 0 .../jobs/completed_jobs.yaml | 0 .../jobs/long-running-pods.yaml | 0 .../unbound_persistent-volumes.yaml | 0 .../unused_persistent-volume-claims.yaml | 0 .../unused_pod-disruption-budgets.yaml | 0 .../pods/completed_pods.yaml | 0 .../roles/unused_roles.yaml | 0 .../secrets/orphaned_secrets.yaml | 0 .../unused_service-accounts.yaml | 0 .../statefulset_with_no_autoscaler.yaml | 0 .../statefulset_with_no_replicas.yaml | 0 .../delete_resource_based_on_expire_date.yaml | 0 ...lete_resource_based_on_ttl_annotation.yaml | 0 .../delete_resources_older_than_24hours.yaml | 0 29 files changed, 167 insertions(+), 11 deletions(-) create mode 100644 examples-automated-operations/scheduled-scaling/pause.yaml create mode 100644 examples-automated-operations/scheduled-scaling/resume.yaml rename {unhealthy-resources-examples => examples-unhealthy-resources}/deployments/scale-down-high-restart-deployment.yaml (100%) rename {unhealthy-resources-examples => examples-unhealthy-resources}/object-references/deployment-referencing-non-existent-resources.yaml (100%) rename {unhealthy-resources-examples => examples-unhealthy-resources}/object-references/ingress-referencing-non-existent-service.yaml (100%) rename {unhealthy-resources-examples => examples-unhealthy-resources}/pod-with-expired-certificates/pods-with-expired-certificates.yaml (100%) rename {unhealthy-resources-examples => examples-unhealthy-resources}/pod-with-outdated-secrets/pods-with-outdated-secret-data.yaml (100%) rename {unused-resources-examples => examples-unused-resources}/clusterroles/unused_clusterroles.yaml (100%) rename {unused-resources-examples => examples-unused-resources}/configmaps/orphaned_configmaps.yaml (100%) rename {unused-resources-examples => examples-unused-resources}/deployments/deployment_with_no_autoscaler.yaml (100%) rename {unused-resources-examples => examples-unused-resources}/deployments/deployment_with_replica_zero.yaml (100%) rename {unused-resources-examples => examples-unused-resources}/deployments/orphaned_deployment.yaml (100%) rename {unused-resources-examples => examples-unused-resources}/horizontal-pod-autoscalers/unused-hpas.yaml (100%) rename {unused-resources-examples => examples-unused-resources}/ingresses/unused_ingresses.yaml (100%) rename {unused-resources-examples => examples-unused-resources}/jobs/completed_jobs.yaml (100%) rename {unused-resources-examples => examples-unused-resources}/jobs/long-running-pods.yaml (100%) rename {unused-resources-examples => examples-unused-resources}/peristent-volumes/unbound_persistent-volumes.yaml (100%) rename {unused-resources-examples => examples-unused-resources}/persistent-volume-claims/unused_persistent-volume-claims.yaml (100%) rename {unused-resources-examples => examples-unused-resources}/pod-disruption-budgets/unused_pod-disruption-budgets.yaml (100%) rename {unused-resources-examples => examples-unused-resources}/pods/completed_pods.yaml (100%) rename {unused-resources-examples => examples-unused-resources}/roles/unused_roles.yaml (100%) rename {unused-resources-examples => examples-unused-resources}/secrets/orphaned_secrets.yaml (100%) rename {unused-resources-examples => examples-unused-resources}/service-accounts/unused_service-accounts.yaml (100%) rename {unused-resources-examples => examples-unused-resources}/stateful-sets/statefulset_with_no_autoscaler.yaml (100%) rename {unused-resources-examples => examples-unused-resources}/stateful-sets/statefulset_with_no_replicas.yaml (100%) rename {unused-resources-examples => examples-unused-resources}/time_based_delete/delete_resource_based_on_expire_date.yaml (100%) rename {unused-resources-examples => examples-unused-resources}/time_based_delete/delete_resource_based_on_ttl_annotation.yaml (100%) rename {unused-resources-examples => examples-unused-resources}/time_based_delete/delete_resources_older_than_24hours.yaml (100%) diff --git a/README.md b/README.md index 1500435..1cf7dc9 100644 --- a/README.md +++ b/README.md @@ -24,22 +24,32 @@ Each notification contains list of all resources successfully deleted (or modifi - 👉 For feature requests and bugs, file an [issue](https://github.com/gianlucam76/k8s-cleaner/issues). - 👉 To get updates [⭐️ star](https://github.com/gianlucam76/k8s-cleaner/stargazers) this repository. -- 👉 Working examples can be found in the [examples](https://github.com/gianlucam76/k8s-cleaner/tree/main/unused-resources-examples) section. +- 👉 Working examples can be found in the [examples](https://github.com/gianlucam76/k8s-cleaner/tree/main/examples-unused-resource) section. Currently k8s-cleaner has rich set of working examples to identify and list unused: -- [ConfigMaps](https://github.com/gianlucam76/k8s-cleaner/tree/main/unused-resources-examples/configmaps)/[Secrets](https://github.com/gianlucam76/k8s-cleaner/tree/main/unused-resources-examples/secrets) -- [ClusterRoles](https://github.com/gianlucam76/k8s-cleaner/tree/main/unused-resources-examples/clusterroles)/[Roles](https://github.com/gianlucam76/k8s-cleaner/tree/main/unused-resources-examples/roles) -- [ServiceAccounts](https://github.com/gianlucam76/k8s-cleaner/tree/main/unused-resources-examples/service-accounts) -- [PersistentVolumes](https://github.com/gianlucam76/k8s-cleaner/tree/main/unused-resources-examples/presistent-volumes)/[PersistentVolumeClaims](https://github.com/gianlucam76/k8s-cleaner/tree/main/unused-resources-examples/persistent-volume-claims) -- [Deployments](https://github.com/gianlucam76/k8s-cleaner/tree/main/unused-resources-examples/deployments)/[StatefulSets](https://github.com/gianlucam76/k8s-cleaner/tree/main/unused-resources-examples/stateful-sets) -- [Identify resources based on annotation indicating the maximum lifespan or the expiration date](https://github.com/gianlucam76/k8s-cleaner/tree/main/unused-resources-examples/time_based_delete) +- [ConfigMaps](https://github.com/gianlucam76/k8s-cleaner/tree/main/examples-unused-resource/configmaps)/[Secrets](https://github.com/gianlucam76/k8s-cleaner/tree/main/examples-unused-resource/secrets) +- [ClusterRoles](https://github.com/gianlucam76/k8s-cleaner/tree/main/examples-unused-resource/clusterroles)/[Roles](https://github.com/gianlucam76/k8s-cleaner/tree/main/examples-unused-resource/roles) +- [ServiceAccounts](https://github.com/gianlucam76/k8s-cleaner/tree/main/examples-unused-resource/service-accounts) +- [PersistentVolumes](https://github.com/gianlucam76/k8s-cleaner/tree/main/examples-unused-resource/presistent-volumes)/[PersistentVolumeClaims](https://github.com/gianlucam76/k8s-cleaner/tree/main/examples-unused-resource/persistent-volume-claims) +- [Deployments](https://github.com/gianlucam76/k8s-cleaner/tree/main/examples-unused-resource/deployments)/[StatefulSets](https://github.com/gianlucam76/k8s-cleaner/tree/main/examples-unused-resource/stateful-sets) +- [Identify resources based on annotation indicating the maximum lifespan or the expiration date](https://github.com/gianlucam76/k8s-cleaner/tree/main/examples-unused-resource/time_based_delete) - many more There are also examples to identify unhealthy resources: -- [Pods Mounting Secrets with Old Content](https://github.com/gianlucam76/k8s-cleaner/tree/main/unhealthy-resources-examples/pod-with-outdated-secrets): Detect pods that are not utilizing the most recent Secret data. -- [Pods Using Expired Certificates](https://github.com/gianlucam76/k8s-cleaner/tree/main/unhealthy-resources-examples/pod-with-expired-certificates): Pinpoint pods that are operating with expired security certificates. +- [Pods Mounting Secrets with Old Content](https://github.com/gianlucam76/k8s-cleaner/tree/main/examples-unhealthy-resources/pod-with-outdated-secrets): Detect pods that are not utilizing the most recent Secret data. +- [Pods Using Expired Certificates](https://github.com/gianlucam76/k8s-cleaner/tree/main/examples-unhealthy-resources/pod-with-expired-certificates): Pinpoint pods that are operating with expired security certificates. + +# Manage and Automate Resource Operations: + +K8s-cleaner doesn't just help you identify unused or unhealthy resources; it can also automate various operations to enhance your cluster's efficiency and management. The examples-operations directory showcases practical scripts and configurations covering key tasks: + +## Scaling Deployments/DaemonSets/StatefulSets with Nightly Downtime: + +This [example](https://github.com/gianlucam76/k8s-cleaner/tree/main/examples-automated-operations/scheduled-scaling) demonstrates how to automatically scale down Deployments, DaemonSets, and StatefulSets with a specified annotation at a desired time (e.g., 8 PM nightly). +Before scaling down, the replica count is stored in another annotation for later retrieval. +At the configured scale-up time (e.g., 8 AM), resources are restored to their original replica count, ensuring efficient resource utilization during off-peak hours # Contribute to Cleaner Examples @@ -411,10 +421,10 @@ spec: ## Delete Kubernetes resources on a configured time to live or expiration date Finds resources that have the __cleaner/ttl__ annotation, which specifies their maximum lifespan. Deletes resources that have lived longer than their specified TTL. -YAML can be found [here](https://github.com/gianlucam76/k8s-cleaner/blob/main/unused-resources-examples/time_based_delete/delete_resource_based_on_ttl_annotation.yaml). +YAML can be found [here](https://github.com/gianlucam76/k8s-cleaner/blob/main/examples-unused-resource/time_based_delete/delete_resource_based_on_ttl_annotation.yaml). Find resources that have the __cleaner_expires__ annotation, which specifies their expiration date. Deletes resources that have that have surpassed their expiration date. -YAML can be found [here](https://github.com/gianlucam76/k8s-cleaner/blob/main/unused-resources-examples/time_based_delete/delete_resource_based_on_expire_date.yaml). +YAML can be found [here](https://github.com/gianlucam76/k8s-cleaner/blob/main/examples-unused-resource/time_based_delete/delete_resource_based_on_expire_date.yaml). ## DryRun diff --git a/examples-automated-operations/scheduled-scaling/pause.yaml b/examples-automated-operations/scheduled-scaling/pause.yaml new file mode 100644 index 0000000..c70045e --- /dev/null +++ b/examples-automated-operations/scheduled-scaling/pause.yaml @@ -0,0 +1,74 @@ +# This cleaner: +# - runs at 8PM every day +# - finds all Deployments/StatefulSet/DaemonSet with +# annotation "pause-resume" +# +# For any such resource: +# - store current replicas in the annotation "previous-replicas" +# - set their replicas to zero (scale down and pause) +# +apiVersion: apps.projectsveltos.io/v1alpha1 +kind: Cleaner +metadata: + name: scale-down-deployment-statefulset-daemonset +spec: + schedule: "* 20 * * *" + action: Transform + transform: | + -- Set replicas to 0 + function transform() + hs = {} + + if obj.metadata.annotations == nil then + obj.metadata.annotations = {} + end + -- store in the annotation current replicas value + obj.metadata.annotations["previous-replicas"] = tostring(obj.spec.replicas) + + -- reset replicas to 0 + obj.spec.replicas = 0 + + hs.resource = obj + return hs + end + resourcePolicySet: + resourceSelectors: + - kind: Deployment + group: apps + version: v1 + - kind: StatefulSet + group: "apps" + version: v1 + - kind: DaemonSet + group: "apps" + version: v1 + aggregatedSelection: | + function evaluate() + local hs = {} + + -- returns true if object has annotaiton "pause-resume" + function hasPauseAnnotation(obj) + if obj.metadata.annotations ~= nil then + if obj.metadata.annotations["pause-resume"] then + return true + end + + return false + end + + return + end + + local resourceToPause = {} + + for _, resource in ipairs(resources) do + if hasPauseAnnotation(resource) then + table.insert(resourceToPause, {resource = resource}) + end + end + + if #resourceToPause > 0 then + hs.resources = resourceToPause + end + return hs + end \ No newline at end of file diff --git a/examples-automated-operations/scheduled-scaling/resume.yaml b/examples-automated-operations/scheduled-scaling/resume.yaml new file mode 100644 index 0000000..d5716a7 --- /dev/null +++ b/examples-automated-operations/scheduled-scaling/resume.yaml @@ -0,0 +1,72 @@ +# This cleaner: +# - runs at 8AM every day +# - finds all Deployments/StatefulSet/DaemonSet with +# annotation "pause-resume" +# +# For any such resource: +# - get old replicas in the annotation "previous-replicas" +# - set their replicas to such value (scale deployment/statefulset/daemonset up) +# +apiVersion: apps.projectsveltos.io/v1alpha1 +kind: Cleaner +metadata: + name: scale-up-deployment-statefulset-daemonset +spec: + schedule: "* 8 * * *" + action: Transform + transform: | + -- Set replicas to 0 + function transform() + hs = {} + if obj.metadata.annotations == nil then + return + end + if not obj.metadata.annotations["previous-replicas"] then + return + end + -- reset replicas + obj.spec.replicas = tonumber(obj.metadata.annotations["previous-replicas"]) + hs.resource = obj + return hs + end + resourcePolicySet: + resourceSelectors: + - kind: Deployment + group: apps + version: v1 + - kind: StatefulSet + group: "apps" + version: v1 + - kind: DaemonSet + group: "apps" + version: v1 + aggregatedSelection: | + function evaluate() + local hs = {} + + -- returns true if object has annotaiton "pause-resume" + function hasPauseAnnotation(obj) + if obj.metadata.annotations ~= nil then + if obj.metadata.annotations["pause-resume"] then + return true + end + + return false + end + + return false + end + + local resourceToUnPause = {} + + for _, resource in ipairs(resources) do + if hasPauseAnnotation(resource) then + table.insert(resourceToUnPause, {resource = resource}) + end + end + + if #resourceToUnPause > 0 then + hs.resources = resourceToUnPause + end + return hs + end \ No newline at end of file diff --git a/unhealthy-resources-examples/deployments/scale-down-high-restart-deployment.yaml b/examples-unhealthy-resources/deployments/scale-down-high-restart-deployment.yaml similarity index 100% rename from unhealthy-resources-examples/deployments/scale-down-high-restart-deployment.yaml rename to examples-unhealthy-resources/deployments/scale-down-high-restart-deployment.yaml diff --git a/unhealthy-resources-examples/object-references/deployment-referencing-non-existent-resources.yaml b/examples-unhealthy-resources/object-references/deployment-referencing-non-existent-resources.yaml similarity index 100% rename from unhealthy-resources-examples/object-references/deployment-referencing-non-existent-resources.yaml rename to examples-unhealthy-resources/object-references/deployment-referencing-non-existent-resources.yaml diff --git a/unhealthy-resources-examples/object-references/ingress-referencing-non-existent-service.yaml b/examples-unhealthy-resources/object-references/ingress-referencing-non-existent-service.yaml similarity index 100% rename from unhealthy-resources-examples/object-references/ingress-referencing-non-existent-service.yaml rename to examples-unhealthy-resources/object-references/ingress-referencing-non-existent-service.yaml diff --git a/unhealthy-resources-examples/pod-with-expired-certificates/pods-with-expired-certificates.yaml b/examples-unhealthy-resources/pod-with-expired-certificates/pods-with-expired-certificates.yaml similarity index 100% rename from unhealthy-resources-examples/pod-with-expired-certificates/pods-with-expired-certificates.yaml rename to examples-unhealthy-resources/pod-with-expired-certificates/pods-with-expired-certificates.yaml diff --git a/unhealthy-resources-examples/pod-with-outdated-secrets/pods-with-outdated-secret-data.yaml b/examples-unhealthy-resources/pod-with-outdated-secrets/pods-with-outdated-secret-data.yaml similarity index 100% rename from unhealthy-resources-examples/pod-with-outdated-secrets/pods-with-outdated-secret-data.yaml rename to examples-unhealthy-resources/pod-with-outdated-secrets/pods-with-outdated-secret-data.yaml diff --git a/unused-resources-examples/clusterroles/unused_clusterroles.yaml b/examples-unused-resources/clusterroles/unused_clusterroles.yaml similarity index 100% rename from unused-resources-examples/clusterroles/unused_clusterroles.yaml rename to examples-unused-resources/clusterroles/unused_clusterroles.yaml diff --git a/unused-resources-examples/configmaps/orphaned_configmaps.yaml b/examples-unused-resources/configmaps/orphaned_configmaps.yaml similarity index 100% rename from unused-resources-examples/configmaps/orphaned_configmaps.yaml rename to examples-unused-resources/configmaps/orphaned_configmaps.yaml diff --git a/unused-resources-examples/deployments/deployment_with_no_autoscaler.yaml b/examples-unused-resources/deployments/deployment_with_no_autoscaler.yaml similarity index 100% rename from unused-resources-examples/deployments/deployment_with_no_autoscaler.yaml rename to examples-unused-resources/deployments/deployment_with_no_autoscaler.yaml diff --git a/unused-resources-examples/deployments/deployment_with_replica_zero.yaml b/examples-unused-resources/deployments/deployment_with_replica_zero.yaml similarity index 100% rename from unused-resources-examples/deployments/deployment_with_replica_zero.yaml rename to examples-unused-resources/deployments/deployment_with_replica_zero.yaml diff --git a/unused-resources-examples/deployments/orphaned_deployment.yaml b/examples-unused-resources/deployments/orphaned_deployment.yaml similarity index 100% rename from unused-resources-examples/deployments/orphaned_deployment.yaml rename to examples-unused-resources/deployments/orphaned_deployment.yaml diff --git a/unused-resources-examples/horizontal-pod-autoscalers/unused-hpas.yaml b/examples-unused-resources/horizontal-pod-autoscalers/unused-hpas.yaml similarity index 100% rename from unused-resources-examples/horizontal-pod-autoscalers/unused-hpas.yaml rename to examples-unused-resources/horizontal-pod-autoscalers/unused-hpas.yaml diff --git a/unused-resources-examples/ingresses/unused_ingresses.yaml b/examples-unused-resources/ingresses/unused_ingresses.yaml similarity index 100% rename from unused-resources-examples/ingresses/unused_ingresses.yaml rename to examples-unused-resources/ingresses/unused_ingresses.yaml diff --git a/unused-resources-examples/jobs/completed_jobs.yaml b/examples-unused-resources/jobs/completed_jobs.yaml similarity index 100% rename from unused-resources-examples/jobs/completed_jobs.yaml rename to examples-unused-resources/jobs/completed_jobs.yaml diff --git a/unused-resources-examples/jobs/long-running-pods.yaml b/examples-unused-resources/jobs/long-running-pods.yaml similarity index 100% rename from unused-resources-examples/jobs/long-running-pods.yaml rename to examples-unused-resources/jobs/long-running-pods.yaml diff --git a/unused-resources-examples/peristent-volumes/unbound_persistent-volumes.yaml b/examples-unused-resources/peristent-volumes/unbound_persistent-volumes.yaml similarity index 100% rename from unused-resources-examples/peristent-volumes/unbound_persistent-volumes.yaml rename to examples-unused-resources/peristent-volumes/unbound_persistent-volumes.yaml diff --git a/unused-resources-examples/persistent-volume-claims/unused_persistent-volume-claims.yaml b/examples-unused-resources/persistent-volume-claims/unused_persistent-volume-claims.yaml similarity index 100% rename from unused-resources-examples/persistent-volume-claims/unused_persistent-volume-claims.yaml rename to examples-unused-resources/persistent-volume-claims/unused_persistent-volume-claims.yaml diff --git a/unused-resources-examples/pod-disruption-budgets/unused_pod-disruption-budgets.yaml b/examples-unused-resources/pod-disruption-budgets/unused_pod-disruption-budgets.yaml similarity index 100% rename from unused-resources-examples/pod-disruption-budgets/unused_pod-disruption-budgets.yaml rename to examples-unused-resources/pod-disruption-budgets/unused_pod-disruption-budgets.yaml diff --git a/unused-resources-examples/pods/completed_pods.yaml b/examples-unused-resources/pods/completed_pods.yaml similarity index 100% rename from unused-resources-examples/pods/completed_pods.yaml rename to examples-unused-resources/pods/completed_pods.yaml diff --git a/unused-resources-examples/roles/unused_roles.yaml b/examples-unused-resources/roles/unused_roles.yaml similarity index 100% rename from unused-resources-examples/roles/unused_roles.yaml rename to examples-unused-resources/roles/unused_roles.yaml diff --git a/unused-resources-examples/secrets/orphaned_secrets.yaml b/examples-unused-resources/secrets/orphaned_secrets.yaml similarity index 100% rename from unused-resources-examples/secrets/orphaned_secrets.yaml rename to examples-unused-resources/secrets/orphaned_secrets.yaml diff --git a/unused-resources-examples/service-accounts/unused_service-accounts.yaml b/examples-unused-resources/service-accounts/unused_service-accounts.yaml similarity index 100% rename from unused-resources-examples/service-accounts/unused_service-accounts.yaml rename to examples-unused-resources/service-accounts/unused_service-accounts.yaml diff --git a/unused-resources-examples/stateful-sets/statefulset_with_no_autoscaler.yaml b/examples-unused-resources/stateful-sets/statefulset_with_no_autoscaler.yaml similarity index 100% rename from unused-resources-examples/stateful-sets/statefulset_with_no_autoscaler.yaml rename to examples-unused-resources/stateful-sets/statefulset_with_no_autoscaler.yaml diff --git a/unused-resources-examples/stateful-sets/statefulset_with_no_replicas.yaml b/examples-unused-resources/stateful-sets/statefulset_with_no_replicas.yaml similarity index 100% rename from unused-resources-examples/stateful-sets/statefulset_with_no_replicas.yaml rename to examples-unused-resources/stateful-sets/statefulset_with_no_replicas.yaml diff --git a/unused-resources-examples/time_based_delete/delete_resource_based_on_expire_date.yaml b/examples-unused-resources/time_based_delete/delete_resource_based_on_expire_date.yaml similarity index 100% rename from unused-resources-examples/time_based_delete/delete_resource_based_on_expire_date.yaml rename to examples-unused-resources/time_based_delete/delete_resource_based_on_expire_date.yaml diff --git a/unused-resources-examples/time_based_delete/delete_resource_based_on_ttl_annotation.yaml b/examples-unused-resources/time_based_delete/delete_resource_based_on_ttl_annotation.yaml similarity index 100% rename from unused-resources-examples/time_based_delete/delete_resource_based_on_ttl_annotation.yaml rename to examples-unused-resources/time_based_delete/delete_resource_based_on_ttl_annotation.yaml diff --git a/unused-resources-examples/time_based_delete/delete_resources_older_than_24hours.yaml b/examples-unused-resources/time_based_delete/delete_resources_older_than_24hours.yaml similarity index 100% rename from unused-resources-examples/time_based_delete/delete_resources_older_than_24hours.yaml rename to examples-unused-resources/time_based_delete/delete_resources_older_than_24hours.yaml