7 min read
Green Computing in the Cloud: Sustainability at Scale
Sustainability became a board-level concern in 2021. Cloud computing offers opportunities to reduce environmental impact, but only with intentional design. Let’s explore how to build greener cloud solutions.
Understanding Cloud Carbon Footprint
from azure.mgmt.carbon import CarbonClient
from azure.identity import DefaultAzureCredential
from datetime import datetime, timedelta
class CarbonFootprintAnalyzer:
def __init__(self, subscription_id: str):
self.credential = DefaultAzureCredential()
self.subscription_id = subscription_id
def get_carbon_emissions(self, days: int = 30) -> dict:
"""Get carbon emissions data for Azure resources"""
# Note: This uses the Microsoft Sustainability Calculator data
# Available through Azure Portal or API
emissions_data = {
"period": {
"start": (datetime.utcnow() - timedelta(days=days)).isoformat(),
"end": datetime.utcnow().isoformat()
},
"total_emissions_kg_co2e": 0,
"by_service": {},
"by_region": {}
}
# Query emissions by service
# Integration with Microsoft Emissions Impact Dashboard
return emissions_data
def estimate_vm_carbon_footprint(
self,
vm_size: str,
region: str,
hours_running: float
) -> dict:
"""Estimate carbon footprint for a VM"""
# Power consumption estimates by VM size (watts)
power_by_size = {
"Standard_D2s_v3": 50,
"Standard_D4s_v3": 100,
"Standard_D8s_v3": 200,
"Standard_E2s_v3": 60,
"Standard_E4s_v3": 120,
"Standard_NC6": 300, # GPU instances have higher consumption
"Standard_NC12": 600
}
# Carbon intensity by Azure region (gCO2/kWh)
# Source: Azure sustainability documentation
carbon_intensity = {
"australiaeast": 700, # Coal-heavy grid
"australiasoutheast": 700,
"westeurope": 300, # More renewable
"northeurope": 200, # Very green (Sweden/Ireland)
"westus2": 350,
"eastus": 400,
"uksouth": 250,
"francecentral": 50, # Nuclear
"norwayeast": 20, # Hydroelectric
}
power_watts = power_by_size.get(vm_size, 100)
intensity = carbon_intensity.get(region, 400)
# Calculate emissions
energy_kwh = (power_watts * hours_running) / 1000
emissions_g = energy_kwh * intensity
emissions_kg = emissions_g / 1000
return {
"vm_size": vm_size,
"region": region,
"hours": hours_running,
"energy_kwh": round(energy_kwh, 2),
"carbon_intensity_g_kwh": intensity,
"emissions_kg_co2e": round(emissions_kg, 3),
"equivalent_km_driven": round(emissions_kg / 0.12, 1) # Average car ~120g/km
}
def recommend_greener_region(self, current_region: str, workload_type: str) -> dict:
"""Recommend lower-carbon regions for workload"""
# Regions ranked by carbon intensity (lower is better)
green_regions = [
("norwayeast", 20),
("swedencentral", 25),
("francecentral", 50),
("uksouth", 250),
("northeurope", 200),
("westeurope", 300)
]
current_intensity = self._get_region_intensity(current_region)
recommendations = []
for region, intensity in green_regions:
if intensity < current_intensity:
latency_impact = self._estimate_latency_impact(current_region, region)
savings_pct = ((current_intensity - intensity) / current_intensity) * 100
recommendations.append({
"region": region,
"carbon_intensity": intensity,
"emissions_reduction_pct": round(savings_pct, 1),
"latency_impact_ms": latency_impact
})
return {
"current_region": current_region,
"current_intensity": current_intensity,
"recommendations": recommendations
}
Sustainable Architecture Patterns
# Sustainable workload design principles
# architecture/sustainability-principles.yaml
principles:
- name: "Right-size resources"
description: "Use only the resources you need"
implementation:
- Use autoscaling to match demand
- Implement aggressive scale-to-zero
- Choose smaller VM sizes and scale horizontally
metrics:
- Average CPU utilization > 40%
- Memory utilization > 50%
- name: "Choose efficient regions"
description: "Deploy to regions with cleaner energy"
implementation:
- Prioritize regions with low carbon intensity
- Use Azure region carbon data in deployment decisions
- Consider multi-region for carbon optimization
metrics:
- Average carbon intensity < 300g CO2/kWh
- name: "Optimize data storage"
description: "Store data efficiently"
implementation:
- Use compression
- Implement data lifecycle policies
- Delete unused data
- Use appropriate storage tiers
metrics:
- Storage efficiency ratio
- Data deduplication rate
- name: "Reduce data transfer"
description: "Minimize network traffic"
implementation:
- Cache aggressively
- Use CDN for static content
- Compress API responses
- Co-locate compute and storage
metrics:
- Cache hit rate > 80%
- Network egress per request
Implementing Carbon-Aware Workloads
// Carbon-aware job scheduler
using System;
using System.Threading.Tasks;
public class CarbonAwareScheduler
{
private readonly ICarbonIntensityService _carbonService;
private readonly IJobQueue _jobQueue;
public CarbonAwareScheduler(
ICarbonIntensityService carbonService,
IJobQueue jobQueue)
{
_carbonService = carbonService;
_jobQueue = jobQueue;
}
public async Task ScheduleJob(Job job, SchedulingOptions options)
{
if (job.IsDeferrable && options.OptimizeForCarbon)
{
// Get carbon forecast for next 24 hours
var forecast = await _carbonService.GetForecastAsync(
options.Region,
TimeSpan.FromHours(24)
);
// Find the lowest carbon window
var optimalWindow = forecast
.Where(f => f.Timestamp >= DateTime.UtcNow)
.Where(f => f.Timestamp <= job.Deadline)
.OrderBy(f => f.CarbonIntensity)
.FirstOrDefault();
if (optimalWindow != null &&
optimalWindow.CarbonIntensity < forecast.First().CarbonIntensity * 0.7)
{
// Defer to lower carbon period
job.ScheduledTime = optimalWindow.Timestamp;
await _jobQueue.EnqueueAsync(job);
Console.WriteLine(
$"Deferred job {job.Id} to {optimalWindow.Timestamp} " +
$"(intensity: {optimalWindow.CarbonIntensity} vs current: {forecast.First().CarbonIntensity})"
);
return;
}
}
// Run immediately if not deferrable or no better window
await _jobQueue.EnqueueAsync(job);
}
public async Task<string> SelectOptimalRegion(
Job job,
IEnumerable<string> availableRegions)
{
var regionIntensities = await Task.WhenAll(
availableRegions.Select(async region => new
{
Region = region,
Intensity = await _carbonService.GetCurrentIntensityAsync(region)
})
);
// Select region with lowest current carbon intensity
// that meets latency requirements
var optimal = regionIntensities
.Where(r => MeetsLatencyRequirements(r.Region, job.LatencyRequirements))
.OrderBy(r => r.Intensity)
.First();
return optimal.Region;
}
}
// Carbon intensity data service
public interface ICarbonIntensityService
{
Task<double> GetCurrentIntensityAsync(string region);
Task<IEnumerable<CarbonForecast>> GetForecastAsync(string region, TimeSpan duration);
}
public class WattTimeCarbonService : ICarbonIntensityService
{
// Integration with WattTime or Electricity Maps API
private readonly HttpClient _client;
public async Task<double> GetCurrentIntensityAsync(string region)
{
var response = await _client.GetAsync($"/v2/index?region={region}");
var data = await response.Content.ReadFromJsonAsync<WattTimeResponse>();
return data.CarbonIntensity;
}
}
Measuring Sustainability
# Sustainability metrics dashboard
from dataclasses import dataclass
from typing import List
import pandas as pd
@dataclass
class SustainabilityMetrics:
period: str
total_emissions_kg: float
emissions_per_request: float
pue_efficiency: float # Power Usage Effectiveness
renewable_energy_pct: float
carbon_offset_kg: float
class SustainabilityReporter:
def generate_report(self, subscription_id: str, period: str) -> dict:
"""Generate sustainability report"""
# Collect metrics
energy_data = self._get_energy_consumption(subscription_id, period)
emissions_data = self._calculate_emissions(energy_data)
efficiency_data = self._calculate_efficiency(subscription_id, period)
report = {
"period": period,
"summary": {
"total_energy_kwh": energy_data["total_kwh"],
"total_emissions_kg_co2e": emissions_data["total_kg"],
"renewable_percentage": self._get_renewable_pct(subscription_id),
"pue": efficiency_data["pue"]
},
"by_service": self._breakdown_by_service(subscription_id, period),
"by_region": self._breakdown_by_region(subscription_id, period),
"trends": self._calculate_trends(subscription_id),
"recommendations": self._generate_recommendations(
energy_data, emissions_data, efficiency_data
)
}
return report
def _generate_recommendations(self, energy, emissions, efficiency) -> List[dict]:
"""Generate actionable recommendations"""
recommendations = []
# Check for inefficient regions
high_carbon_regions = [
r for r in emissions["by_region"]
if r["intensity"] > 400
]
if high_carbon_regions:
recommendations.append({
"priority": "high",
"category": "region_optimization",
"title": "Migrate workloads to lower-carbon regions",
"description": f"Consider moving workloads from {', '.join([r['region'] for r in high_carbon_regions])} to lower-carbon regions",
"potential_reduction_pct": 30
})
# Check resource utilization
if efficiency["avg_cpu_utilization"] < 30:
recommendations.append({
"priority": "medium",
"category": "right_sizing",
"title": "Right-size underutilized resources",
"description": "Average CPU utilization is below 30%. Consider smaller instance sizes.",
"potential_reduction_pct": 20
})
# Check for always-on dev resources
if efficiency["dev_resources_24x7"]:
recommendations.append({
"priority": "medium",
"category": "scheduling",
"title": "Implement shutdown schedules for dev/test",
"description": "Dev resources running 24/7 could be scheduled for business hours only",
"potential_reduction_pct": 60
})
return recommendations
Sustainable Data Practices
# Data sustainability - reduce storage and transfer
class SustainableDataManager:
def optimize_storage_footprint(self, storage_account: str):
"""Implement sustainable data practices"""
optimizations = []
# 1. Enable compression
# 2. Implement deduplication
# 3. Set lifecycle policies
# 4. Remove orphaned data
lifecycle_policy = {
"rules": [
{
"name": "archive-old-data",
"enabled": True,
"type": "Lifecycle",
"definition": {
"filters": {"blobTypes": ["blockBlob"]},
"actions": {
"baseBlob": {
"tierToCool": {"daysAfterLastAccessTimeGreaterThan": 30},
"tierToArchive": {"daysAfterLastAccessTimeGreaterThan": 90},
"delete": {"daysAfterLastAccessTimeGreaterThan": 365}
}
}
}
}
]
}
optimizations.append({
"action": "lifecycle_policy",
"config": lifecycle_policy,
"estimated_storage_reduction_pct": 40
})
return optimizations
def estimate_transfer_impact(
self,
data_size_gb: float,
source_region: str,
dest_region: str
) -> dict:
"""Estimate carbon impact of data transfer"""
# Network energy: ~0.06 kWh per GB transferred
network_energy_per_gb = 0.06
# Add regional grid carbon intensity
avg_intensity = 350 # g CO2/kWh average
energy_kwh = data_size_gb * network_energy_per_gb
emissions_g = energy_kwh * avg_intensity
return {
"data_size_gb": data_size_gb,
"energy_kwh": round(energy_kwh, 3),
"emissions_g_co2e": round(emissions_g, 1),
"recommendation": "Co-locate compute with data" if emissions_g > 100 else "Transfer acceptable"
}
Key Sustainability Practices
- Measure Your Footprint: Use Microsoft Sustainability Calculator
- Choose Green Regions: Deploy to low-carbon regions when possible
- Right-Size Everything: Idle resources waste energy
- Optimize Data: Less storage and transfer means less energy
- Shift Flexible Workloads: Run batch jobs when grid is cleanest
Green computing in 2021 became a real consideration, not just marketing. Azure’s commitment to carbon negative by 2030 provides the tools; it’s up to us to use them wisely.