
Define sleep & wake up cycles for your Kubernetes resources. Automatically schedule to shutdown Deployments, CronJobs, StatefulSets and HorizontalPodAutoscalers that occupy resources in your cluster and wake them up only when you need them; in that way you can:
You’ll need a Kubernetes cluster to run against. You can use KIND or K3D to get a local cluster for testing, or run against a remote cluster.
[!CAUTION] Earliest compatible Kubernetes version is 1.25
Under config/samples you will find a set manifests that you can use to test this sleepcycles on your cluster:
SleepCycle resources in namespaces app-1 and app-2apiVersion: core.rekuberate.io/v1alpha1
kind: SleepCycle
metadata:
name: sleepcycle-app-1
namespace: app-1
spec:
shutdown: "1/2 * * * *"
shutdownTimeZone: "Europe/Athens"
wakeup: "*/2 * * * *"
wakeupTimeZone: "Europe/Dublin"
enabled: true
[!NOTE] The cron expressions of the samples are tailored so you perform a quick demo. The
shutdownexpression schedules the deployment to scale down on odd minutes and thewakeupschedule to scale up on even minutes.
Every SleepCycle has the following mandatory properties:
shutdown: cron expression for your shutdown scheduleenabled: whether this sleepcycle policy is enabledand the following non-mandatory properties:
shutdownTimeZone: the timezone for your shutdown schedule, defaults to UTCwakeup: cron expression for your wake-up schedulewakeupTimeZone: the timezone for your wake-up schedule, defaults to UTCsuccessfulJobsHistoryLimit: how many completed CronJob Runner Pods to retain for debugging reasons, defaults to 1failedJobsHistoryLimit: how many failed CronJob Runner Pods to retain for debugging reasons, defaults to 1runnerImage: the image to use when spawn CronJob Runner pods, defaults to akyriako78/rekuberate-io-sleepcycles-runners[!IMPORTANT] DO NOT ADD seconds or timezone information to you cron expressions.
Deployment that provisions traefik/whoami in namespace app-1Deploymentthat provisions traefik/whoami in namespace app-2SleepCycle is a namespace-scoped custom resource; the controller will monitor all the resources in that namespace that
are marked with a Label that has as key rekuberate.io/sleepcycle: and as value the name of the manifest you created:
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-2
namespace: app-2
labels:
app: app-2
rekuberate.io/sleepcycle: sleepcycle-app-2
spec:
replicas: 9
selector:
matchLabels:
app: app-2
template:
metadata:
name: app-2
labels:
app: app-2
spec:
containers:
- name: app-2
image: traefik/whoami
imagePullPolicy: IfNotPresent
[!IMPORTANT] Any workload in namespace
kube-systemmarked withrekuberate.io/sleepcyclewill be ignored by the controller by design.
The diagram below describes how rekuberate.io/sleepcycles are dealing with scheduling a Deployment:
sleepcycle-controller watches periodically, every 1min, all the SleepCycle custom resources for changes (in all namespaces).SleepCycle resource within the namespace app-1, collects all the resources that have been marked with the label rekuberate.io/sleepcycle: sleepcycle-app1.deployment-app1 a CronJob for the shutdown schedule and optionally a second CronJob if a wake-up schedule is provided.ServiceAccount, a Role and a RoleBinding per namespace, in order to make possible for runner-pods to update resources’ specs.Runner pods will be created automatically by the cron jobs and are responsible for scaling the resources up or down.
[!NOTE] In the diagram it was depicted how
rekuberate.io/sleepcyclesscalesDeployment. The same steps count for aStatefulSetand aHorizontalPodAutoscaler. There are two exception though:
- a
HorizontalPodAutoscalerwill scale down to1replica and not to0as for aDeploymentor aStatefulset.- a
CronJobhas no replicas to scale up or down, it is going to be enabled or suspended respectively.
IMG in Makefile:# Image URL to use all building/pushing image targets
IMG_TAG ?= $(shell git rev-parse --short HEAD)
IMG_NAME ?= rekuberate-io-sleepcycles
DOCKER_HUB_NAME ?= $(shell docker info | sed '/Username:/!d;s/.* //')
IMG ?= $(DOCKER_HUB_NAME)/$(IMG_NAME):$(IMG_TAG)
RUNNERS_IMG_NAME ?= rekuberate-io-sleepcycles-runners
KO_DOCKER_REPO ?= $(DOCKER_HUB_NAME)/$(RUNNERS_IMG_NAME)
make docker-build docker-push
IMG:make deploy
and then deploy the samples:
kubectl create namespace app-1
kubectl create namespace app-2
kubectl apply -f config/samples
make undeploy
If you are on a development environment, you can quickly test & deploy the controller to the cluster
using a Helm chart directly from config/helm:
helm install rekuberate-io-sleepcycles config/helm/ -n <namespace> --create-namespace
and then deploy the samples:
kubectl create namespace app-1
kubectl create namespace app-2
kubectl apply -f config/samples
helm uninstall rekuberate-io-sleepcycles -n <namespace>
On the other hand if you are deploying on a production environment, it is highly recommended to deploy the controller to the cluster using a Helm chart from its repo:
helm repo add sleepcycles https://rekuberate-io.github.io/sleepcycles/
helm repo update
helm upgrade --install sleepcycles sleepcycles/sleepcycles -n rekuberate-system --create-namespace
and then deploy the samples:
kubectl create namespace app-1
kubectl create namespace app-2
kubectl apply -f config/samples
helm uninstall rekuberate-io-sleepcycles -n <namespace>
This project aims to follow the Kubernetes Operator pattern. It uses Controllers which provides a reconcile function responsible for synchronizing resources until the desired state is reached on the cluster.
If you are editing the API definitions, generate the manifests such as CRs or CRDs using:
make generate
make manifests
then install the CRDs in the cluster with:
make install
[!TIP] You can debug the controller in the IDE of your choice by hooking to the
main.goor you can start the controller without debugging with:
make run
[!TIP] Run
make --helpfor more information on all potentialmaketargets More information can be found via the Kubebuilder Documentation
You always need to build a new docker container and push it to your repository:
make docker-build docker-push
[!IMPORTANT] In this case you will need to adjust your Helm chart values to use your repository and container image.
make ko-build-runner
[!IMPORTANT] In this case you will need to adjust the
runnerImageof yourSleepCyclemanifest to use your own Runner image.
To delete the CRDs from the cluster:
make uninstall