Karbonetes is a Kubernetes-based system for carbon-aware batch scheduling with Karpenter. It focuses on run-to-completion workloads in Phase 1 and decides whether a Job should run now, wait for a greener time window, or fall back to a default node pool after a maximum delay.
The current repository contains a demo-ready Phase 1 implementation built with Go, controller-runtime style reconciliation, a mutating admission webhook, a mock carbon signal service, Helm packaging, and sample Karpenter manifests.
- Single Kubernetes cluster
- Karpenter-managed node provisioning
- Two NodePools:
defaultandgreen-batch - Run-to-completion workloads only:
JobandCronJob - No live migration of running pods
- No multi-region orchestration
- Mock carbon signal source based on static green windows
- Carbon-aware Jobs are marked with
carbon-aware.io/enabled: "true". - If the current carbon window is green, the admission webhook injects
scheduling preferences so the workload prefers the
green-batchNodePool. - If the current carbon window is not green, the Job is suspended until either
a green window arrives or the configured
maxDelayexpires. - If
maxDelayexpires, the controller releases the Job to the fallback pool. - Non-carbon-aware Jobs bypass the system and run immediately.
CronJobs participate indirectly: the webhook and controller operate on the Jobs
created by the CronJob controller. To make generated Jobs carbon-aware, place
annotations on spec.jobTemplate.metadata.annotations.
cmd/controller: the main controller manager processinternal/webhook: mutating admission webhook forbatch/v1 JobCREATEinternal/controller: reconcile loop for suspended carbon-aware Jobscmd/signal: mock carbon signal HTTP serviceapi/v1alpha1:CarbonAwarePolicyCRD typescharts/karbonetes: Helm chart for controller, webhook, signal, RBAC, and CRDsconfig/samples: Karpenter, policy, and workload examples for demos
- Architecture
- Implementation Plan
- Roadmap
- Evaluation Guide
- Release Process
- Risks and Tradeoffs
- Monitoring Assets
make test
make test-envtest
make build
make helm-lint
make helm-templatekubectl apply -k monitoring
kubectl port-forward -n monitoring svc/prometheus 9090:9090
kubectl port-forward -n monitoring svc/grafana 3000:3000kubectl apply -f config/crd/bases/helm upgrade --install karbonetes charts/karbonetes \
--namespace karbonetes-system \
--create-namespacekubectl apply -f config/samples/00-namespace.yaml
kubectl apply -f config/samples/karpenter-nodeclass.yaml
kubectl apply -f config/samples/karpenter-nodepool-default.yaml
kubectl apply -f config/samples/karpenter-nodepool-green-batch.yaml
kubectl apply -f config/samples/carbonawarepolicy-default.yamlkubectl apply -f config/samples/job-plain.yaml
kubectl apply -f config/samples/job-carbon-aware.yaml
kubectl apply -f config/samples/job-carbon-aware-strict.yaml
kubectl apply -f config/samples/cronjob-carbon-aware.yamlThe Makefile also includes demo helpers such as make demo-green-on,
make demo-green-off, make demo-submit, make demo-status, and
make demo-signal.
The repository is set up for production-style CI/CD:
- pull requests and
mainpushes run verification in GitHub Actions - you decide the semantic version and create the release tag manually
- pushing the tag publishes binaries, multi-arch container images, and the Helm chart through CI/CD
- release artifacts are attached to the GitHub release and pushed to GHCR
See docs/RELEASES.md for the manual tag workflow and GitHub repository settings.
api/: CRD API typescmd/: controller and signal binariesinternal/carbon/: carbon signal provider interface and adaptersinternal/controller/: Job reconciliation logicinternal/webhook/: admission webhook mutation logicinternal/policy/: policy resolution from CRDs and annotationsinternal/metrics/: Prometheus collectorscharts/karbonetes/: production-style Helm chartconfig/crd/bases/: installable CRD manifestsconfig/samples/: demo manifests for policies, NodePools, Jobs, and CronJobs
Phase 1 is implemented as a hybrid webhook + controller design:
- Jobs are intercepted at creation time
- Green windows trigger immediate green-pool preference
- Non-green windows trigger suspend-and-wait behavior
- Suspended Jobs are later resumed by the controller
- CronJob-owned Jobs are unsuspended in place to preserve CronJob ownership
The next layers of work are mainly hardening, richer carbon signals, stronger state management, and broader scheduling scope.