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-2
apiVersion: 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
shutdown
expression schedules the deployment to scale down on odd minutes and thewakeup
schedule 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 UTC
wakeup
: cron expression for your wake-up schedulewakeupTimeZone
: the timezone for your wake-up schedule, defaults to UTC
successfulJobsHistoryLimit
: how many completed CronJob Runner Pods to retain for debugging reasons, defaults to 1
failedJobsHistoryLimit
: how many failed CronJob Runner Pods to retain for debugging reasons, defaults to 1
runnerImage
: 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-1
Deployment
that provisions traefik/whoami in namespace app-2
SleepCycle
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-system
marked withrekuberate.io/sleepcycle
will 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/sleepcycles
scalesDeployment
. The same steps count for aStatefulSet
and aHorizontalPodAutoscaler
. There are two exception though:
- a
HorizontalPodAutoscaler
will scale down to1
replica and not to0
as for aDeployment
or aStatefulset
.- a
CronJob
has 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.go
or you can start the controller without debugging with:
make run
[!TIP] Run
make --help
for more information on all potentialmake
targets 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
runnerImage
of yourSleepCycle
manifest to use your own Runner image.
To delete the CRDs from the cluster:
make uninstall