Start measuring your infrastructure's energy consumption and cost in 5 minutes. This Terraform module deploys a complete green operations observability stack on Kubernetes, helping you make data-driven decisions about sustainability and efficiency.
Observability First: This module now defaults to observability-only mode — giving you actionable data without any automated changes to your workloads. Enable optimization features when you're ready.
You can't optimize what you don't measure. Most engineering teams lack visibility into:
- How much energy their applications consume
- Which workloads are the most expensive
- Where to focus optimization efforts for maximum impact
This module gives you actionable observability — the foundation for all GreenOps initiatives.
Prerequisites: Kubernetes cluster with cert-manager installed (install here)
# Get visibility into energy and cost - no automation, just data
module "greenops" {
source = "fabiocicerchia/greenops/kubernetes"
}terraform init && terraform applyThat's it! You now have:
- Prometheus monitoring stack with Grafana dashboards
- Kepler measuring real-time energy consumption per pod
- OpenCost tracking infrastructure costs
- CodeCarbon tracking application-level carbon emissions
Access your dashboards:
kubectl port-forward -n monitoring svc/prometheus-community-grafana 3000:80
# Browse to http://localhost:3000 (admin / prom-operator)The GreenOps Module provides a unified way to deploy and manage:
- Observability & Scaling Infrastructure:
- Prometheus - Metrics collection and storage with
kube-prometheus-stack - KEDA - Kubernetes Event Driven Autoscaling with optional example deployments
- Prometheus - Metrics collection and storage with
- Cost & Resource Efficiency:
- OpenCost - Cost monitoring and allocation with carbon cost tracking
- Energy & Power Monitoring:
- Kepler - Environmental impact tracking via the Kepler Operator with optional power monitoring
- Scaphandre - Container-level power consumption monitoring
- Carbon & Emissions Estimation:
- Carbon Intensity Exporter - Grid carbon intensity metrics for location-aware scheduling
- Cloud Carbon Footprint - Cloud infrastructure carbon emissions tracking
- CodeCarbon - Python code carbon emissions tracking
- Sustainability Optimisation & Automation:
- KubeGreen - Automated resource cleanup and pod hibernation for cost optimisation
Default Configuration (Observability):
- ✅ Enabled: Prometheus, Kepler, OpenCost, CodeCarbon (safe, read-only monitoring)
- ❌ Disabled: KEDA, KubeGreen, Carbon Intensity Exporter, Cloud Carbon Footprint (require configuration or perform actions)
Sustainable computing is no longer just about hardware—it's about how software consumes resources. GreenOps sits at the intersection of FinOps and DevOps, enabling you to:
- 👁️ Observe: Gain visibility into the real-time energy and carbon footprint of your clusters (Kepler, Scaphandre).
- 📉 Optimise: Automatically reduce waste by scaling down idle resources (KEDA) and hibernating non-production environments (KubeGreen).
- 💰 Attribute: Connect carbon emissions directly to financial costs for better accountability (OpenCost).
- 🧪 Measure: Quantify the environmental impact of your software code (CodeCarbon).
Efficient infrastructure is cheaper, faster, and greener.
- ⚡ 5-Minute Start: Default configuration deploys observability tools with zero configuration
- 🚀 Unified Deployment: Manage 10+ sustainability tools with a single Terraform module, no "dependency hell."
- 🎛️ Simple Configuration: Toggles for every component mean you can start small (e.g., just Prometheus + OpenCost) and expand later.
- 🔄 Standard Interfaces: Built on Cloud Native standards (Prometheus, Grafana, Helm)
- 🛡️ Non-Intrusive: Most components run as sidecars, daemonsets, or operators without requiring changes to your application code.
- Idle Resource Waste: Automatically shut down development and testing environments off-hours with KubeGreen.
- Over-Provisioning: Use real-time metrics to right-size workloads and infrastructure.
- Energy Transparency: Shift from "estimated" to "measured" energy usage for accurate ESG reporting.
- Carbon-cost Trade-offs: Make informed decisions balancing performance, cost, and carbon footprint.
- ❌ Rewrite your application: It provides the data (CodeCarbon) to identify inefficient code, but the fix is up to you.
- ❌ Compromise availability: Optimisation tools like KubeGreen are strictly opt-in and configurable per-namespace.
This module provides the foundation and tooling to practice GreenOps effectively.
Important: OpenCost, Kepler, KEDA, and Scaphandre require Prometheus to function properly. You must either:
- Deploy Prometheus via this module (enabled by default), or
- Configure them to use an external Prometheus instance
If you disable Prometheus in this module, ensure you configure OpenCost, Kepler, KEDA, and Scaphandre to connect to your existing Prometheus deployment via their values configuration. KEDA's ScaledObject resources need to reference Prometheus for metrics-based scaling.
Kepler Requirement: Kepler requires cert-manager to be installed in your cluster before deployment. Without cert-manager, Kepler will not function properly. You can install it using:
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.18.2/cert-manager.yaml| Name | Version |
|---|---|
| terraform | >= 1.0 or OpenTofu >= 1.6 |
| helm | >= 2.0 |
| null | >= 3.0 |
- Terraform >= 1.0 or OpenTofu
- Kubernetes cluster (v1.24+)
- Kubectl configured to access your cluster
- cert-manager installed in your cluster (required for Kepler)
Get immediate visibility with zero configuration:
module "greenops" {
source = "fabiocicerchia/greenops/kubernetes"
# That's it! Defaults to observability-only mode
# Deploys: Prometheus, Kepler, OpenCost, CodeCarbon
}Set the kubectl context in your provider configuration or as a variable:
# In your example file (e.g., tier1-observe-only.tf)
variable "kubectl_context" {
description = "Kubectl context to use"
type = string
default = "minikube" # Or any context from: kubectl config get-contexts
}
provider "helm" {
kubernetes {
config_path = "~/.kube/config"
config_context = var.kubectl_context
}
}
provider "kubectl" {
config_path = "~/.kube/config"
config_context = var.kubectl_context
}
module "greenops" {
source = "fabiocicerchia/greenops/kubernetes"
providers = {
helm = helm
kubectl = kubectl
}
kubectl_context = var.kubectl_context
}Deploy with:
# Use current kubectl context
terraform apply
# Or override to specific context
terraform apply -var="kubectl_context=staging-cluster"Or use your current context by leaving kubectl_context empty or omitting config_context from providers.
Import these community dashboards for visualization:
- Kepler Main Dashboard
- Kepler Prometheus Dashboard
- Ariewald Kepler Dashboard
- Energy K8s Experiments Dashboard
module "greenops" {
source = "fabiocicerchia/greenops/kubernetes"
observability = {
prometheus = {
enabled = true
}
keda = {
enabled = false
}
}
cost_efficiency = {
opencost = {
enabled = true
}
}
energy_power = {
kepler = {
enabled = true
}
scaphandre = {
enabled = false
}
}
sustainability_optimisation = {
kubegreen = {
enabled = true
}
}
}module "greenops" {
source = "fabiocicerchia/greenops/kubernetes"
observability = {
prometheus = {
enabled = true
namespace = "custom-monitoring"
release_name = "prom"
values = {
prometheus = {
prometheusSpec = {
retention = "30d"
}
}
}
}
keda = {
enabled = true
namespace = "custom-keda"
deploy_example = false
values = {}
}
}
cost_efficiency = {
opencost = {
enabled = true
values = {
opencost = {
carbonCost = {
enabled = true
}
}
}
}
}
energy_power = {
kepler = {
enabled = true
namespace = "sustainability"
}
}
}| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| kubectl_config_path | Path to kubectl config file | string |
"~/.kube/config" |
no |
| kubectl_context | Kubectl context to use for deployment | string |
"" (current context) |
no |
| observability | Observability and scaling tools (Prometheus, KEDA) | object({...}) |
{} |
no |
| cost_efficiency | Cost and resource efficiency tools (OpenCost) | object({...}) |
{} |
no |
| energy_power | Energy and power monitoring tools (Kepler, Scaphandre) | object({...}) |
{} |
no |
| carbon_emissions | Carbon and emissions estimation tools (IE, CCF, CodeCarbon) | object({...}) |
{} |
no |
| sustainability_optimisation | Sustainability optimisation tools (KubeGreen) | object({...}) |
{} |
no |
observability = {
prometheus = optional(object({
enabled = bool # Enable Prometheus (default: true)
release_name = optional(string) # Helm release name
namespace = optional(string) # Kubernetes namespace
values = optional(any) # Helm chart values
chart_version = optional(string) # Helm chart version
}))
keda = optional(object({
enabled = bool # Enable KEDA (default: true)
release_name = optional(string) # Helm release name
namespace = optional(string) # Kubernetes namespace
values = optional(any) # Helm chart values
deploy_example = optional(bool) # Deploy example manifests
manifest_path = optional(string) # Path to example manifest
chart_version = optional(string) # Helm chart version
}))
}cost_efficiency = {
opencost = optional(object({
enabled = bool # Enable OpenCost (default: true)
release_name = optional(string) # Helm release name
namespace = optional(string) # Kubernetes namespace
values = optional(any) # Helm chart values
chart_version = optional(string) # Helm chart version
}))
}energy_power = {
kepler = optional(object({
enabled = bool # Enable Kepler (default: true)
release_name = optional(string) # Helm release name
namespace = optional(string) # Kubernetes namespace
values = optional(any) # Helm chart values
chart_version = optional(string) # Helm chart version
}))
scaphandre = optional(object({
enabled = bool # Enable Scaphandre (default: true)
release_name = optional(string) # Helm release name
namespace = optional(string) # Kubernetes namespace
values = optional(any) # Helm chart values
chart_version = optional(string) # Helm chart version
}))
}carbon_emissions = {
carbon_intensity_exporter = optional(object({
enabled = bool # Enable Carbon Intensity Exporter (default: true)
release_name = optional(string) # Helm release name
namespace = optional(string) # Kubernetes namespace
values = optional(any) # Helm chart values
chart_version = optional(string) # Helm chart version
}))
cloud_carbon_footprint = optional(object({
enabled = bool # Enable Cloud Carbon Footprint (default: true)
release_name = optional(string) # Helm release name
namespace = optional(string) # Kubernetes namespace
values = optional(any) # Helm chart values
chart_version = optional(string) # Helm chart version
}))
codecarbon = optional(object({
enabled = bool # Enable CodeCarbon (default: true)
name = optional(string) # Release name
namespace = optional(string) # Kubernetes namespace
image = optional(string) # Docker image
api_endpoint = optional(string) # CodeCarbon API endpoint
organization_id = optional(string) # Organization ID
project_id = optional(string) # Project ID
experiment_id = optional(string) # Experiment ID
api_key = optional(string) # API Key
}))
}sustainability_optimisation = {
kubegreen = optional(object({
enabled = bool # Enable KubeGreen (default: true)
release_name = optional(string) # Helm release name
namespace = optional(string) # Kubernetes namespace
values = optional(any) # Helm chart values
chart_version = optional(string) # Helm chart version
}))
}All modules support chart_version parameter within their respective configuration blocks.
If set to "" (empty string) or omitted, it will deploy the latest available Helm chart version.
The module provides outputs organised in nested objects for better structure:
Observability and scaling outputs:
observability = {
prometheus = {
namespace = string
release_name = string
version = string
}
keda = {
namespace = string
release_name = string
version = string
}
}Cost and resource efficiency outputs:
cost_efficiency = {
opencost = {
namespace = string
release_name = string
version = string
}
}Energy and power monitoring outputs:
energy_power = {
kepler = {
namespace = string
release_name = string
version = string
}
scaphandre = {
namespace = string
release_name = string
version = string
}
}Sustainability optimisation outputs:
sustainability_optimisation = {
kubegreen = {
namespace = string
release_name = string
version = string
}
}Carbon and emissions estimation outputs:
carbon_emissions = {
carbon_intensity_exporter = {
namespace = string
release_name = string
version = string
}
cloud_carbon_footprint = {
namespace = string
release_name = string
version = string
client_service_url = string
api_service_url = string
}
codecarbon = {
namespace = string
release_name = string
version = string
}
}Map showing which components are enabled:
deployed_components = {
observability = {
prometheus = bool
keda = bool
}
cost_efficiency = {
opencost = bool
}
energy_power = {
kepler = bool
scaphandre = bool
}
sustainability_optimisation = {
kubegreen = bool
}
carbon_emissions = {
carbon_intensity_exporter = bool
cloud_carbon_footprint = bool
codecarbon = bool
}
}Only enable Prometheus for basic monitoring:
module "greenops" {
source = "fabiocicerchia/greenops/kubernetes"
observability = {
prometheus = { enabled = true }
keda = { enabled = false }
}
cost_efficiency = {
opencost = { enabled = false }
}
energy_power = {
kepler = { enabled = false }
}
}Enable Prometheus and OpenCost for cost visibility:
module "greenops" {
source = "fabiocicerchia/greenops/kubernetes"
observability = {
prometheus = { enabled = true }
}
cost_efficiency = {
opencost = { enabled = true }
}
}Complete stack for environmental tracking:
module "greenops" {
source = "fabiocicerchia/greenops/kubernetes"
# All enabled by default, just provide custom values if needed
observability = {
prometheus = {
enabled = true
}
}
cost_efficiency = {
opencost = {
enabled = true
}
}
energy_power = {
kepler = {
enabled = true
}
scaphandre = {
enabled = true # Enable for container-level power monitoring
}
}
sustainability_optimisation = {
kubegreen = {
enabled = true # Enable for resource cleanup and pod hibernation
}
}
carbon_emissions = {
carbon_intensity_exporter = {
enabled = true # Enable for grid carbon intensity metrics
}
cloud_carbon_footprint = {
enabled = true # Enable for cloud infrastructure carbon tracking
}
codecarbon = {
enabled = true # Enable for Python code carbon emissions tracking
}
}
}Deploy from specific tags, branches, or commits:
module "greenops" {
source = "https://github.com/fabiocicerchia/terraform-kubernetes-greenops.git?ref=v1.0.0"
# or use: ref=develop, ref=main, ref=abc1234 (commit SHA)
}minikube start --kubernetes-version=v1.34.0
minikube addons enable metrics-server
kubectl config use-context minikube && kubectl config current-contextterraform init
terraform apply# Check all pods across all namespaces
kubectl get pods -AGet Grafana admin password:
kubectl --namespace monitoring get secrets prometheus-community-grafana \
-o jsonpath="{.data.admin-password}" | base64 -d ; echoPort forward services:
# Prometheus
kubectl port-forward -n monitoring svc/prometheus-community-kube-prometheus 9090:9090
# Grafana (part of Prometheus)
kubectl port-forward -n monitoring svc/prometheus-community-grafana 3000:80
# OpenCost UI
kubectl port-forward -n opencost svc/opencost-charts 9091:9090
# Cloud Carbon Footprint
kubectl port-forward -n cloud-carbon-footprint svc/cloud-carbon-footprint-client 8080:80Test the carbon-intensity-exporter:
kubectl get configmap -n carbon-intensity-exporter carbon-intensity -o jsonpath="{.binaryData.data}" | base64 -d ; echoMIT