This release includes breaking changes for platform teams planning a safe upgrade.
Published 3mo
Dashboards & Visualization
✓ No known CVEs patched
✓ No known CVEs patched in this version
Topics
carbon-emissions
carbon-footprint
cloud
co2
cost-optimization
devops
+12 more
fastapi
finops
grafana
green-computing
green-software
greenops
helm
kubernetes
prometheus
python
sustainability
svelte
Affected surfaces
auth
rbac
Summary
AI summaryAdds frontend config persistence, GHG Scope 2/3 classification, and pre‑computed dashboard caches for raw and archived metrics.
Full changelog
What's Changed
Added
- Frontend config persistence via K8s Secret (#219): UI-applied settings (
PROMETHEUS_URL,OPENCOST_API_URL,ELECTRICITY_MAPS_TOKEN,BOAVIZTA_API_URL) are now patched into the GreenKube Kubernetes Secret immediately after being saved, so they survive pod restarts andhelm upgrade --reuse-valueswithout manual intervention. A namespacedRole/RoleBindinggrants the service accountget+patchaccess to exactly the GreenKube Secret (no cluster-wide secret access). - GreenKube favicon: The browser tab now displays the real GreenKube logo (
favicon.ico) instead of the Svelte placeholder SVG. The SVG favicon reference has been removed fromapp.htmlandbuild/index.html;favicon.icois served with the correctimage/vnd.microsoft.iconMIME type. GET /api/v1/metrics/by-namespace: New lightweight endpoint returning CO2e, embodied emissions, energy, and cost aggregated by namespace over a time window. Queries bothcombined_metrics(raw) andcombined_metrics_hourly(archived) tables via a singleUNION ALL + GROUP BY— avoids loading full row sets into memory.GET /api/v1/metrics/top-pods: New lightweight endpoint returning the top-N pods by CO2e over a time window, also using the dual-tableUNION ALL + GROUP BYpattern. Dashboard donut and top-pods charts now call these two endpoints instead of the expensiveGET /metricsroute, eliminating OOM restarts when browsing large time ranges.- GHG Scope 2 / Scope 3 carbon classification: Emissions are now formally categorised per the GHG Protocol Corporate Standard.
- Pre-computed dashboard cache (
metrics_summary+metrics_timeseries_cache): Two new database tables (migrations0004and0005for PostgreSQL and SQLite) store pre-aggregated KPI scalars and time-series buckets for five fixed windows (24h,7d,30d,1y,ytd). Tables are refreshed hourly by the background scheduler, eliminating full-table scans on every dashboard load and preventing OOM errors on large datasets. SummaryRefresher: Newsrc/greenkube/core/summary_refresher.pyservice that computes cluster-wide and per-namespace KPI totals and time-series buckets, then upserts them into the two cache tables. Supports adaptive granularity per window (hourly / daily / weekly / monthly buckets).SummaryRepositoryandTimeseriesCacheRepository: New abstract base classes instorage/base_repository.pywith PostgreSQL and SQLite implementations.- Dashboard API endpoints: Three new FastAPI routes for the pre-computed tables:
GET /api/v1/metrics/dashboard-summary— cached KPI scalars, optionally filtered by namespace.GET /api/v1/metrics/dashboard-timeseries/{window_slug}— cached time-series buckets for24h,7d,30d,1y, orytd.POST /api/v1/metrics/dashboard-summary/refresh— trigger an on-demand background refresh (HTTP 202 Accepted).
MetricsSummaryRowandTimeseriesCachePointPydantic models: New DTOs insrc/greenkube/models/metrics.pyrepresenting rows from the two cache tables.- Adaptive chart granularity (frontend): Dashboard charts now select the optimal time bucket per window — hourly for
24h, daily for7d/30d, weekly for1y, monthly forytd— resulting in consistently readable x-axes regardless of the selected range. - Boavizta fallback with configurable default: When the Boavizta API does not recognise a cloud provider or instance type (returns no data),
EmbodiedEmissionsServicenow injects a fallback embodied-emissions profile usingDEFAULT_EMBODIED_EMISSIONS_KG(default: 350 kg CO2e) instead of silently using 0 g, which was incorrect. The resultingCombinedMetricis flaggedis_estimated=Truewith a descriptiveestimation_reasonsentry. Exposed asconfig.boavizta.defaultEmbodiedEmissionsKginvalues.yamlandDEFAULT_EMBODIED_EMISSIONS_KGinconfigmap.yaml. EmbodiedEmissionsService.is_embodied_fallback(): New helper method returnsTruewhen a node's cached profile was produced by the fallback rather than a real Boavizta response, enabling the metric assembler to set estimation flags accurately.
Fixed
- Async K8s Secret patching (
kubernetes_asyncio): The in-cluster Secret patch now correctly useskubernetes_asyncio(the async client that is actually installed) instead of the synckubernetespackage.load_incluster_config()is called withoutawait(it reads files synchronously); failures are caught and logged without interrupting the API response. - Elasticsearch removed from production dependencies:
elasticsearchandelasticsearch-dslpackages moved to an optional extra (pip install greenkube[elasticsearch]). All imports are now lazy (loaded only when the ES storage backend is actually selected), removing heavy transitive dependencies and startup warnings for users on PostgreSQL or SQLite. - Trivy KSV-0109 false positive:
GREENKUBE_SECRET_NAMEis a resource name, not a secret value — suppressed in.trivyignorewith justification.KSV-0113(Role granting secret access) also documented as intentional for the UI persistence feature. - Electricity Maps API not called for OpenStack-based providers (zone =
nova): The scheduler's carbon-intensity collection loop now falls back to the node's geographic region when the provider-specific zone identifier is not a recognised Electricity Maps zone code. This restores carbon-intensity data collection on OVH, Infomaniak, and similar OpenStack-based clouds where the K8s node zone label is set tonovarather than a country/region code. - Race condition in collection orchestrator:
CollectionOrchestratorno longer collects nodes internally. Node collection is now an explicit Phase 1 inDataProcessor.run()that runs alone before any concurrent collection, preventing shared Kubernetes API client races and the cascade of Electricity Maps API errors they caused. DEFAULT_ZONEspurious warning: TheNodeZoneMapperno longer emits a warning when the zone was actually resolved correctly — the warning was incorrectly triggered even when a validDEFAULT_ZONEwas set.- Pod CPU utilisation aggregation per node:
CollectionOrchestratorwas averaging pod CPU usage per node across timestamps instead of summing, causing underestimated energy figures on nodes with multiple measured pods. - Chart legends overlapping (frontend): ECharts legend layout fixed to prevent label overlap on small viewports.
Changed
DataProcessor.run()pipeline restructured into four explicit phases: Phase 1 (node discovery, sequential), Phase 2 (zone resolution), Phase 3 (parallel metrics + Boavizta), Phase 4 (carbon-intensity prefetch + assembly). This eliminates the previous race condition and removes the redundant secondcollect_instance_types()K8s call that used to happen at the end of the pipeline.CollectionOrchestratorsimplified:NodeCollectordependency removed; node enrichment for Prometheus instance-type labels now uses thenodes_infodict passed in from Phase 1, avoiding any duplicate K8s API calls.
Docker: docker pull greenkube/greenkube:0.2.9
Helm:
helm repo add greenkube https://GreenKubeCloud.github.io/GreenKube
helm repo update
helm install greenkube greenkube/greenkube -n greenkube --create-namespace
Weekly OSS security release digest.
The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.
No spam, unsubscribe anytime.
Share this release
About GreenKube
All releases →Beta — feedback welcome: [email protected]