Configuration¶
Configuration is optional. Use it to select namespaces, context, modeled pricing, currency, and supported collection settings. Review recommendation boundaries in Safety & trust; parsed settings do not all control CLI behavior.
Config file location¶
kube-saver merges config in this order, with later values taking precedence:
- Built-in defaults
~/.kube-saver/config.yaml.kube-saver.yamlin the current directory- Supported
KUBE_SAVER_*environment variables
Generate a full default config:
python3 -c "from kube_saver.config import default_config_yaml; print(default_config_yaml())" > .kube-saver.yaml
Pricing¶
CPU and memory pricing¶
Prices are modeled USD rates per core-hour and GiB-hour, not live cloud quotes. The example below matches the unknown-provider fallback. Provider-specific assumptions differ. Monthly estimates use 730 hours; see the FAQ.
Custom CPU and memory rates can be supplied independently. A positive custom rate replaces that dimension; zero, omitted, negative, non-numeric, and non-finite rates retain the provider default. Numeric strings are accepted.
pricing:
cpu_per_core_hour_usd: 0.040 # fallback, ~$29.20/core/month
memory_per_gb_hour_usd: 0.005 # fallback, ~$3.65/GiB/month
Override at runtime:
Currency¶
Display costs in a non-USD currency:
currency: eur # usd, eur, gbp, aed, jpy, inr
exchange_rate_from_usd: 0.92 # manual rate (not auto-fetched)
Override at runtime:
Cloud provider hints¶
cloud_provider: aws # aws, gcp, azure, on-prem, unknown
provider_tier: general # aws: general/t3/r5; gcp: general/e2_small
These select bundled pricing assumptions without contacting a cloud billing API.
Azure and on-prem use general. Unknown tiers fall back to the provider
general rate; an unknown provider uses $0.040/core-hour and $0.005/GiB-hour.
Exclusions¶
Skip namespaces or specific workloads:
exclude_namespaces:
- kube-system
- kube-public
- kube-node-lease
exclude_labels:
app.kubernetes.io/part-of: monitoring
exclude_annotations:
kube-saver.io/ignore: "true"
For a Role limited to specific namespaces, set namespace_filter to those names. This avoids needing cluster-wide permission to list Namespace objects:
Alerts¶
Thresholds used by the TUI alert panel:
alerts:
warning_waste_ratio: 0.4 # warn at 40% waste
critical_waste_ratio: 0.8 # critical at 80% waste
warning_monthly_usd: 100
critical_monthly_usd: 500
notify --threshold is a command option (default: 100 USD); it does not use
these TUI alert thresholds.
Recommendation floors¶
These are top-level YAML keys (not a nested safety mapping):
min_cpu_millicores: 100
min_memory_bytes: 134217728 # 128Mi
prod_cpu_floor_ratio: 0.5
prod_memory_floor_ratio: 0.5
aggressive_mode: false
The relative floors apply to every eligible workload in normal mode. Aggressive
mode skips relative floors, not absolute minimums. Only a YAML boolean true
(or a supported truthy environment value) enables it; quoted strings such as
"false" and other non-boolean YAML values retain normal-mode protection. CPU × 1.5 and memory × 1.2
remain fixed current-sample buffers. Invalid absolute floors use defaults;
relative floors use defaults if non-positive and cap at 1.0.
Export defaults¶
These are parsed configuration fields, not the CLI output defaults.
pr-plan --dir and notify --dir choose their directories, and both commands
write local files. export.dry_run does not suppress those writes.
TUI¶
HTTP API server¶
These are CLI options, not config keys. The server defaults to loopback. See Safety & trust before exposing it.
Kubernetes API timeouts¶
kube-saver supplies HTTP timeouts to collector and doctor API reads. These bound connection/read waits; they are not a wall-clock deadline for an entire scan, credential plugin, or retry sequence. Three knobs are available; all are optional and have defaults.
timeouts:
connect_seconds: 10 # TCP connect deadline per request
read_seconds: 30 # read deadline per request
operation_seconds: 60 # HTTP timeout passed to list/get calls
Safe defaults and rationale¶
| Key | Default | Why this value |
|---|---|---|
connect_seconds |
10 |
Long enough for a cold TLS handshake to a managed control plane (EKS/GKE/AKS) over a typical corporate link, short enough to fail fast on a dead endpoint. |
read_seconds |
30 |
Covers large namespace listings on busy clusters while still bounding hung responses. |
operation_seconds |
60 |
HTTP timeout passed to list/get requests, including Metrics API reads. This is not an overall scan deadline. |
Invalid values (zero, negative, non-numeric, NaN, inf) are silently replaced with the defaults — kube-saver never runs with timeouts disabled.
Environment overrides¶
export KUBE_SAVER_TIMEOUT_CONNECT=5
export KUBE_SAVER_TIMEOUT_READ=20
export KUBE_SAVER_TIMEOUT_OPERATION=45
Environment variables override config-file values; CLI flags are not provided because timeouts are rarely changed per-invocation. Lower these values for tight CI budgets; raise them only if a large, slow cluster is producing spurious timeouts.
Where timeouts apply¶
Timeouts are applied consistently across:
K8sClientcollectors (cluster info, namespaces, pods, node→pod maps)- metrics-server collection (per-call operation timeout)
kube-saver doctor(version check and RBAC self-subject access reviews)- the HTTP API server and TUI, which both use the same
K8sClientpath
A partial pod scan returns usable data with a warning. If all pod reads fail, the report commands exit with code 4 rather than writing an empty successful report. Other resource failures can leave metadata unavailable.
Environment variables¶
The configuration loader accepts the variables below. They take precedence over
config-file values. doctor --context overrides the configured context;
without that option, doctor checks the same configured context as scans.
| Env var | Config key | Example |
|---|---|---|
KUBE_SAVER_CURRENCY |
currency |
eur |
KUBE_SAVER_EXCHANGE_RATE_FROM_USD |
exchange_rate_from_usd |
0.92 |
KUBE_SAVER_CPU_PER_CORE |
pricing.cpu_per_core_hour_usd |
0.05 |
KUBE_SAVER_MEM_PER_GB |
pricing.memory_per_gb_hour_usd |
0.006 |
KUBE_SAVER_PROVIDER |
cloud_provider |
aws |
KUBE_SAVER_TIER |
provider_tier |
t3 |
KUBE_SAVER_CONTEXT |
kubeconfig_context |
staging |
KUBE_SAVER_TIMEOUT_CONNECT |
timeouts.connect_seconds |
5 |
KUBE_SAVER_TIMEOUT_READ |
timeouts.read_seconds |
20 |
KUBE_SAVER_TIMEOUT_OPERATION |
timeouts.operation_seconds |
45 |
KUBE_SAVER_REFRESH_SECS |
tui.refresh_interval_seconds |
30 |
KUBE_SAVER_MAX_METRIC_AGE_SECONDS |
runtime.max_metric_age_seconds |
300 |
KUBE_SAVER_RETRY_MAX_ATTEMPTS |
retries.max_attempts |
3 |
KUBE_SAVER_RETRY_INITIAL_BACKOFF |
retries.initial_backoff_ms |
200 |
KUBE_SAVER_RETRY_MAX_BACKOFF |
retries.max_backoff_ms |
5000 |
KUBE_SAVER_AGGRESSIVE_MODE |
safety.aggressive_mode (skips relative floors, retains absolute floors) |
false |
KUBECONFIG |
Kubernetes client config path | ~/.kube/config |