Skip to content

Install

Describes Hibernator chart 0.12.44

This page installs Hibernator with Helm, checks that it works, and lists what the chart creates in your cluster. The commands use the release name hibernator in the namespace hibernator.

  • Kubernetes 1.21 or later. The chart refuses an older cluster.
  • Helm 3.8 or later.
  • RBAC on the cluster.
  • Credentials for the registry that holds the chart and the images.
  • A mail server. Users sign in with a one-time code that Hibernator sends by email, so without a mail server nobody can sign in. There is no local account and no bypass. Passkeys are optional. They replace the code for a user who enrols one, but never the email: see passkeys.md.
  • A license that names the place where you install, such as your AWS account. Without a license, Hibernator scales nothing. On AWS, the controller also needs an AWS role and access to AWS STS: see license.md.
  • An HTTPS address for the UI. config.externalUrl must start with https://.

The chart is an OCI artifact at oci://registry.gitlab.com/cirriton/hibernator/charts/hibernator. The images are next to it, under registry.gitlab.com/cirriton/hibernator.

Terminal window
helm registry login registry.gitlab.com

If you copy the chart and the images into your own registry, use your chart reference in the commands below. Then set image.registry, image.repositoryPrefix and imagePullSecrets.registry to your registry.

Terminal window
openssl rand -base64 32 # secrets.jwtSecret
openssl rand -base64 32 # secrets.internalApiSecret

The chart generates neither secret. Keep both values. If jwtSecret changes on a later upgrade, every user must sign in again.

If your secrets come from your own pipeline, the chart can read them from your own Secret: see Secrets from your own pipeline.

Copy this file to my-values.yaml. Replace each value in angle brackets and each example.com address.

imagePullSecrets:
create: true
username: "<registry-username>"
password: "<registry-password-or-token>"
# Or use a pull secret that you manage. Then remove the three lines above.
# existingSecret: "<your-pull-secret>"
# Or put the secrets in a Secret that you manage, and name it in existingSecret.
secrets:
jwtSecret: "<first openssl output>"
internalApiSecret: "<second openssl output>"
smtp:
user: "hibernator@example.com"
password: "<smtp-password>"
# The license file you received, whole and unchanged. Or leave this out and add
# --set-file license=HL-XXXXXXXX.license to the install command. license.md has
# the other ways to install a license.
license: |
-----BEGIN HIBERNATOR LICENSE-----
<the lines of your license file>
-----END HIBERNATOR LICENSE-----
config:
# A name for this cluster. Required. The UI and the notifications show it.
clusterName: "my-cluster"
# The address where users open Hibernator. Required. It starts with https://
# and ends with /. Sign-in emails and satellite redirects use it.
externalUrl: "https://hibernator.example.com/"
auth:
adminUsers:
- "you@example.com"
# The domains whose addresses can sign in.
allowedEmailDomains:
- "example.com"
smtp:
enabled: true
host: "smtp.example.com"
port: 587
from: "hibernator@example.com"
workingHours:
timezone: "Europe/Berlin"
schedule:
monday: "08:00-20:00"
tuesday: "08:00-20:00"
wednesday: "08:00-20:00"
thursday: "08:00-20:00"
friday: "08:00-20:00"
saturday: "off"
sunday: "off"
targeting:
namespaces:
exclude:
- pattern: "kube-*"
- exact: "hibernator"
operations:
# Hibernator writes to its log what it would do, and changes nothing.
# Set this to false when the exclude list above is correct.
dryRun: true

The working hours are the chart defaults. schedule.md has the format.

To keep one workload running at all times, put the annotation hibernator.io/exclude: "true" on it. annotations.md has the details.

Name the release hibernator. The controller and the API find their ConfigMap and their Service by that name. To use a different release name, set fullnameOverride: hibernator in my-values.yaml. The chart refuses every other full name, and the install fails.

Terminal window
helm install hibernator oci://registry.gitlab.com/cirriton/hibernator/charts/hibernator \
-n hibernator --create-namespace \
-f my-values.yaml

If you did not put the license in my-values.yaml, give the license file with --set-file:

Terminal window
helm install hibernator oci://registry.gitlab.com/cirriton/hibernator/charts/hibernator \
-n hibernator --create-namespace \
-f my-values.yaml \
--set-file license=HL-XXXXXXXX.license

When a required value is missing, the install fails, and the message names the value. To check the values file before you install, see Validating a values file before you install.

If External Secrets Operator, Sealed Secrets, Vault or a similar tool supplies your secrets, the chart can read them from a Secret that you manage. Then the chart creates no Secret of its own, and your values file holds no secret.

  1. Create a Secret in the release namespace before you install the chart. Until the Secret exists, the pods do not start.

  2. Put these keys in the Secret:

    Key Value
    jwt-secret The first openssl rand -base64 32 output. Required
    internal-api-secret The second openssl rand -base64 32 output. Required
    smtp-user The user name for the mail server. Only if the mail server needs a sign-in
    smtp-password The password for the mail server. Only if the mail server needs a sign-in
  3. Set secrets.existingSecret to the name of the Secret.

  4. Remove the other secrets values from your values file.

secrets:
existingSecret: "hibernator-app-secrets"

The Secret looks like this:

apiVersion: v1
kind: Secret
metadata:
name: hibernator-app-secrets
namespace: hibernator
type: Opaque
stringData:
jwt-secret: "<first openssl output>"
internal-api-secret: "<second openssl output>"
smtp-user: "hibernator@example.com"
smtp-password: "<smtp-password>"

The mail server’s host, port and sender address stay in config.smtp. They are not secrets, so the Secret does not hold them.

The pods read the Secret when they start. After you change a value in the Secret, restart the pods:

Terminal window
kubectl rollout restart deployment -n hibernator hibernator-app hibernator-controller
Terminal window
kubectl get pods -n hibernator

The controller pod and the app pod must both be Running.

The service is ClusterIP, and the chart creates no Ingress. To check the API before you expose the UI, forward a port to the service:

Terminal window
kubectl port-forward -n hibernator svc/hibernator-app 8080:80
curl -s http://127.0.0.1:8080/api/v1/public/hibernation-status

An answer shows that the API and the ConfigMap store work. Do not open the UI on this address: the UI sends 127.0.0.1:8080 to config.externalUrl. troubleshooting.md tells why.

Set service.type to LoadBalancer, or put your own Ingress or Gateway in front of the service hibernator-app. Make sure that config.externalUrl is the address that results. If it is not, change the value and upgrade the release.

Users must be able to open that address. The UI and the satellites send users to it.

  1. Open config.externalUrl.
  2. Enter an address from config.auth.adminUsers.
  3. Enter the one-time code from the email.

The login page shows that the API, the UI and the ConfigMap store work. The email shows that the mail server works.

Open the Schedule page. It shows the next scheduled transition and the working hours of each day. Make sure that they agree with your values file.

To test a hibernation now:

  1. In Manual Control, click Trigger Manual Hibernation.
  2. Enter a reason of 10 to 50 characters.
  3. Click Hibernate Resources.

While config.operations.dryRun is true, Hibernator changes nothing. It writes each change that it would make to the controller log:

Terminal window
kubectl logs -n hibernator deployment/hibernator-controller | grep "(dry-run)"

The manual hibernation continues until the working hours start. To stop it before then, click Resume Schedule in Manual Control.

When the log shows only the workloads that you expect, set config.operations.dryRun: false in my-values.yaml. Then upgrade the release as upgrade.md shows.

When dry run ends, Hibernator acts at once. Outside the working hours, or while a manual hibernation continues, it scales the workloads to zero. To bring them back before the working hours start:

  1. In Manual Control, click Wake Up Resources.
  2. Select how long the workloads stay awake.
  3. Click Wake Up Resources in the dialog.

When the wake expires, the schedule decides again.

Validating a values file before you install

Section titled “Validating a values file before you install”

Render your values file with the chart before you install it:

Terminal window
helm template hibernator oci://registry.gitlab.com/cirriton/hibernator/charts/hibernator -f my-values.yaml >/dev/null

This command reports the errors of the chart’s schema and of the chart’s own checks. It is the only check that finds both. helm lint alone is not sufficient: it shows a template failure as an INFO line and exits 0.

Helm does not report an unknown key. It ignores a misspelled key and uses the default in its place. The install can then succeed and do something different from what you wrote.

The chart’s values.schema.json closes the objects that it models fully. A typo in a closed object is an error that names the path:

Terminal window
$ helm template ... --set config.smtp.hosst=mail.example.com
Error: values don't meet the specifications of the schema(s) in the following chart(s):
hibernator:
- at '/config/smtp': additional properties 'hosst' not allowed

These objects are closed:

  • namespace, replicaCount, and image with each per-component block
  • imagePullSecrets, secrets and secrets.smtp
  • metrics.serviceMonitor
  • config.workingHours and its schedule
  • config.targeting with .namespaces and its exclude matchers
  • config.resourceRules and each neverScale entry
  • config.serviceRedirection and each service
  • config.smtp, config.dashboardApi and config.auth.webauthn
  • config.notifications.channels.email
  • config.externalDependencies, with secretRef and each resource group
  • config.externalWake and its quotas
  • each entry of config.externalWake.clusters, with secretRef and each resource group

config.databases, config.wakeOrdering and config.hibernateOrdering also refuse unknown keys, but the schema does not check them. The controller reads them with a strict decoder when it loads the ConfigMap. A typo there installs without an error. Then the controller stops at startup and names the path in its log. Check the controller log after you change one of the three.

The schema does not model every key of the objects below, so they stay open. Helm ignores a typo in an open object without an error. Check these objects yourself:

Object Keys the schema does not model
config most of its sections
config.auth privacy (webauthn is closed)
config.operations enableApiAccessLogs
service api, frontend, controller
metrics grafanaDashboard, prometheusRule
global all keys: it stays open on purpose, because Helm shares it with subcharts
resources.*.requests / .limits any resource name other than cpu and memory

To check an open object, compare the rendered ConfigMap with what you expect:

Terminal window
helm template hibernator oci://registry.gitlab.com/cirriton/hibernator/charts/hibernator -f my-values.yaml \
--show-only templates/configmap.yaml

The names below are the same for each release, because the chart accepts only the full name hibernator. Hibernator itself creates more ConfigMaps at runtime; how-it-works.md lists them. The controller also creates two PodDisruptionBudgets at runtime; how-it-works.md has them.

Kind Name When
Deployment hibernator-controller Always
Deployment hibernator-app Always
Service hibernator-app Always
Service hibernator-controller Always. Health and metrics ports only
ConfigMap hibernator-config Always
Secret hibernator-secrets secrets.existingSecret is empty, the default. The two secrets, and the mail server sign-in while config.smtp.enabled is true
ServiceAccount hibernator-api, hibernator-controller serviceAccount.api.create and serviceAccount.controller.create, both true by default
ConfigMap hibernator-license license is set
ConfigMap hibernator-brand A branding value is set
Secret hibernator-registry, or imagePullSecrets.secretName imagePullSecrets.create is true
Secret One per entry of externalWakeSecrets.secrets externalWakeSecrets.create is true
Namespace namespace.name, or the release namespace namespace.create is true
ServiceMonitor hibernator-api, hibernator-controller metrics.serviceMonitor.enabled is true
PrometheusRule hibernator metrics.prometheusRule.enabled is true
ConfigMap hibernator-dashboard metrics.grafanaDashboard.enabled is true

The chart creates these objects while rbac.create is true, the default. With rbac.create: false it creates none of them, and you must grant the same rules yourself.

ClusterRole hibernator-controller, bound to the ServiceAccount hibernator-controller by the ClusterRoleBinding hibernator-controller:

API group Resource Verbs Used for
core namespaces get, list, watch Finding the namespaces in scope
apps deployments get, list, watch, create, update, delete Scaling. The satellites are Deployments too
apps statefulsets get, list, watch, update Scaling
apps replicasets get, list, watch Finding the owner of a pod, for pod protection
batch cronjobs get, list, watch, update Suspending and resuming
batch jobs get, list, watch Finding the owner of a pod, for pod protection
core pods get, list, watch, update, patch The pod protection annotations
core nodes get, list Sustainability (instance type, allocatable resources) and the license check (providerID)
metrics.k8s.io nodes list CPU use for Sustainability, from metrics-server
core configmaps get, list, watch, create, update State and configuration
core services get, list, update Service redirection
policy poddisruptionbudgets get, create, update, delete Protection while it scales
core secrets get, create, delete The image pull secrets of the satellites
core events create Kubernetes events

Role hibernator-api in the release namespace, bound to the ServiceAccount hibernator-api by the RoleBinding hibernator-api:

API group Resource Verbs Used for
core configmaps get, list, watch, create, update Hibernation and wake state, external wake sessions and configuration
core secrets get The external wake HMAC secret

ClusterRole hibernator-api-services, bound to the ServiceAccount hibernator-api by the ClusterRoleBinding hibernator-api-services:

API group Resource Verbs Used for
core services get, list, watch Reading the services in all namespaces

To see the rules as the chart renders them for your values file:

Terminal window
helm template hibernator oci://registry.gitlab.com/cirriton/hibernator/charts/hibernator -f my-values.yaml \
--show-only templates/rbac.yaml