Skip to content
Docs
Release candidateThese docs are for Napwake 0.2.0-rc.9, a release candidate, and may change before it's released. Read the docs for the latest release.

Guides

Opting in

Install Napwake once per cluster, then label what it should manage. The label says which workloads, and annotations say how.

View .mdAsk Claude (opens claude.ai)Ask ChatGPT (opens chatgpt.com)
  1. Label the workload, measuring first.

    deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: checkout-api
    namespace: preview-42
    labels:
    napwake.dev/managed: "true"
    annotations:
    napwake.dev/dry-run: "true" # measure first; nothing is paused
    napwake.dev/idle-after: "2h"

    Napwake creates a ManagedWorkload for it, kept in step with the annotations. The label is usually one line in Helm values or manifests in Git.

  2. See what pausing would free.

    Terminal window
    kubectl napwake scan

    It lists every workload in dry-run.

  3. Start pausing.

    Terminal window
    kubectl napwake enable checkout-api -n preview-42
    kubectl napwake enable --all -n preview-42 # every workload in the namespace

    enable sets the workload’s own napwake.dev/dry-run to "false", which wins wherever the dry-run came from. See enable for --all, GitOps and Helm.

Napwake pauses the workload once it has had no activity for idle-after, 2 hours here.

Label a namespace to opt in every Deployment and StatefulSet in it, with its annotations as their defaults. It suits dev and preview namespaces, and third-party charts you can’t label.

apiVersion: v1
kind: Namespace
metadata:
name: preview-42
labels:
napwake.dev/managed: "true"
annotations:
napwake.dev/dry-run: "true"
napwake.dev/idle-after: "2h"

To leave one workload out, label it napwake.dev/ignore: "true" or napwake.dev/managed: "false".

Use one of these. Each leaves the workloads’ selectors alone.

If the kustomization has the Namespace, label and annotate it there, as in A whole namespace. Nothing on the workloads changes.

commonAnnotations puts settings on the pod templates too. Adding or changing one, such as dry-run, then restarts every workload’s pods. Napwake counts each restart as a deploy, which is activity. Use the Namespace or a patch.

Set them on the workload or its namespace. Settings annotations lists the values each accepts.

Annotation Default What it does
napwake.dev/dry-run "false" Measures, and records what pausing would free, without pausing
napwake.dev/idle-after 1h Time without activity before pausing, at least 1m
napwake.dev/cpu-threshold 10 CPU use, as a percentage of requests, above which it’s active
napwake.dev/auto-resume "false" Wakes it ahead of the demand a confident forecast predicts
napwake.dev/pause-early "false" Pauses before idle-after runs out when a confident forecast expects quiet. Never with wake: "ask"
napwake.dev/forecast "balanced" How soon the forecast acts. "eager", "balanced" or "cautious"
napwake.dev/depends-on none Workloads this one needs
napwake.dev/wake "request" What wakes it through the doorman. "request" is any request. "ask" is only a person’s click, for a public URL
napwake.dev/wake-max-wait 2m How long a request is held while it wakes, at most 1h
napwake.dev/wake-page "true" Shows browsers a waking-up page

Leave one out for its default. A value that can’t be read is skipped, with an InvalidSetting warning event, and the next place below decides. An unreadable dry-run turns dry-run on instead, and an unreadable wake asks.

  1. 1The workload's annotation
  2. 2Its namespace's
  3. 3The Helm defaultsdefaults.idleAfter, defaults.cpuThreshold, defaults.dryRun, defaults.pauseEarly, defaults.forecast, defaults.wake
  4. 4The built-in default

So a namespace can measure everything with dry-run: "true" while one workload in it goes live with dry-run: "false".

Terminal window
kubectl label namespace payments napwake.dev/protected=true

Napwake never manages anything in a protected namespace, such as production, whatever the labels. A warning event on each workload says why.

In a protected namespace What happens
A labelled workload It isn’t opted in
A ManagedWorkload you wrote It reports Protected=True and never pauses
A workload Napwake had paused It’s woken, so protecting never leaves anything off
Always protected, with no label So that
kube-system and every other kube-* Labelling every namespace can’t pause CoreDNS or metrics-server
Napwake’s own namespace, and the doorman’s if it runs elsewhere Napwake can’t pause itself

Protect more by name, such as every prod-*, with the Helm value protectedNamespaces. Only napwake.dev/allow-protected: "true", set on purpose, lets Napwake manage a protected namespace. Napwake never sets either label. The operator’s and the doorman’s own Deployments are never managed, since nothing would be left to wake them. To keep Napwake out by Kubernetes RBAC, install it with watchNamespaces.

GitOps tools leave the ManagedWorkload alone, but must leave the replicas to Napwake. The ManagedWorkload is owned by the workload, like a Deployment’s ReplicaSets, so Argo CD shows it under the workload. It never takes the workload’s labels, so a tool’s tracking label can’t make the tool claim and prune it.

A tool would scale a paused workload back up. GitOps tools shows how to stop that for Argo CD, Flux, Fleet, kapp and Kluctl. Under Flux, many charts let you leave replicas out, such as when their autoscaling value is on.

When you Napwake
Label a workload Creates a ManagedWorkload named after it, owned by it and marked napwake.dev/from-label: "true", with a Managed event on the workload. When the name is taken, as by a StatefulSet named like a Deployment, it adds the kind, such as api-statefulset
Change its annotations Updates the ManagedWorkload within seconds
Remove the label, or add napwake.dev/ignore Deletes it, first scaling a paused workload back to its replicas
Delete the workload Deletes its ManagedWorkload too
Wrote a ManagedWorkload for it Yours wins, and the label does nothing
Set the label to anything but "true", such as "dry-run" Doesn’t opt it in, and says so in an event. Settings like dry-run are annotations

Settings with more than one value, such as Prometheus activity queries, aren’t annotations. Set them on the ManagedWorkload the label created, which keeps them.