This document provides guidance for AI assistants working with the OpenCost codebase.
- Never include claude.ai session links or URLs in commit messages or pull request bodies.
OpenCost is an open source Kubernetes cost monitoring tool maintained by the Cloud Native Computing Foundation (CNCF). It provides real-time cost allocation, asset tracking, and cloud cost monitoring for Kubernetes clusters across multiple cloud providers.
Key Features:
- Real-time cost allocation by namespace, pod, controller, service, etc.
- Multi-cloud cost monitoring (AWS, Azure, GCP, Alibaba, Oracle, OTC, DigitalOcean, Scaleway)
- Dynamic on-demand pricing via cloud provider APIs
- CSV-based custom pricing for on-prem clusters
- MCP (Model Context Protocol) server for AI agent integration
- Prometheus metrics export
opencost/
├── cmd/costmodel/ # Main entry point (main.go)
├── core/ # Core module (shared libraries)
│ └── pkg/
│ ├── clusters/ # Cluster management
│ ├── env/ # Environment variable utilities
│ ├── filter/ # Query filter implementations
│ ├── log/ # Structured logging
│ ├── model/ # Core data models
│ ├── opencost/ # OpenCost domain types (Allocation, Asset, CloudCost)
│ ├── storage/ # Storage abstractions
│ └── util/ # Utility packages
├── modules/
│ ├── collector-source/ # Custom metrics collector (alternative to Prometheus)
│ └── prometheus-source/ # Prometheus data source implementation
├── pkg/
│ ├── cloud/ # Cloud provider implementations
│ │ ├── aws/
│ │ ├── azure/
│ │ ├── gcp/
│ │ ├── alibaba/
│ │ ├── oracle/
│ │ ├── digitalocean/
│ │ ├── scaleway/
│ │ └── otc/ # Open Telekom Cloud
│ ├── cloudcost/ # Cloud cost processing pipeline
│ ├── clustercache/ # Kubernetes cluster caching
│ ├── cmd/costmodel/ # Cost model command implementation
│ ├── config/ # Configuration management
│ ├── costmodel/ # Core cost model logic and API handlers
│ ├── customcost/ # Custom cost plugin support
│ ├── env/ # Environment variable definitions
│ ├── mcp/ # MCP server implementation
│ └── metrics/ # Prometheus metrics
├── configs/ # Default pricing configurations
├── kubernetes/ # Kubernetes manifests (deprecated - use Helm)
├── protos/ # Protocol buffer definitions
├── spec/ # OpenCost specification
└── ui/ # UI components (main UI in opencost/opencost-ui repo)
- Go 1.25+ (see go.mod for exact version)
- Docker with
buildxsupport - just - command runner
- Tilt - for local Kubernetes development
- Kubernetes cluster (local or remote)
- Prometheus instance
# Run all unit tests
just test
# Run tests for specific module
just test-core
just test-opencost
just test-prometheus-source
just test-collector-source
# Build local binary
just build-local
# Run locally (requires Prometheus and optionally Kubernetes access)
PROMETHEUS_SERVER_ENDPOINT="http://127.0.0.1:9080" go run ./cmd/costmodel/main.go
# Start development environment with Tilt
tilt upSet PROMETHEUS_SERVER_ENDPOINT to your Prometheus URL:
# Port-forward to Prometheus in your cluster
kubectl port-forward svc/prometheus-server 9080:80
# Run OpenCost
PROMETHEUS_SERVER_ENDPOINT="http://127.0.0.1:9080" go run ./cmd/costmodel/main.goINTEGRATION=true just test-integration# Build local binary
just build-local
# Build multi-arch binaries
just build-binary <version>
# Build and push Docker image
just build <image-tag> <release-version>
# Validate protobuf definitions
just validate-protobuf| Variable | Default | Description |
|---|---|---|
PROMETHEUS_SERVER_ENDPOINT |
(required) | Prometheus server URL |
API_PORT |
9003 |
OpenCost API port |
CLUSTER_ID |
auto-detected | Cluster identifier |
CONFIG_PATH |
/var/configs |
Configuration directory |
| Variable | Default | Description |
|---|---|---|
MCP_SERVER_ENABLED |
true |
Enable MCP server |
MCP_HTTP_PORT |
8081 |
MCP server HTTP port |
| Variable | Description |
|---|---|
AWS_ACCESS_KEY_ID |
AWS authentication |
AWS_SECRET_ACCESS_KEY |
AWS authentication |
AZURE_OFFER_ID |
Azure pricing offer ID |
AZURE_BILLING_ACCOUNT |
Azure billing account |
CLOUD_PROVIDER |
Force cloud provider (aws, azure, gcp, etc.) |
USE_CSV_PROVIDER |
Enable CSV-based custom pricing |
CSV_PATH |
Path to CSV pricing file |
| Variable | Default | Description |
|---|---|---|
PROMETHEUS_QUERY_TIMEOUT |
120s |
Query timeout |
PROMETHEUS_QUERY_RESOLUTION_SECONDS |
300 |
Query resolution |
MAX_QUERY_CONCURRENCY |
5 |
Concurrent queries |
PROM_CLUSTER_ID_LABEL |
cluster_id |
Cluster ID label name |
| Variable | Default | Description |
|---|---|---|
CLOUD_COST_ENABLED |
false |
Enable cloud cost ingestion |
CARBON_ESTIMATES_ENABLED |
false |
Enable carbon estimation |
COLLECTOR_DATA_SOURCE_ENABLED |
false |
Use collector instead of Prometheus |
Main API runs on port 9003 by default:
| Endpoint | Description |
|---|---|
GET /allocation |
Cost allocation data |
GET /allocation/summary |
Summarized allocation |
GET /assets |
Asset cost data |
GET /assets/carbon |
Asset carbon estimates |
GET /cloudCost |
Cloud cost data |
GET /customCost/status |
Custom cost status |
GET /metrics |
Prometheus metrics |
- Use structured logging via
github.com/opencost/opencost/core/pkg/log - Environment variables accessed through
pkg/envorcore/pkg/env - Errors should be wrapped with context
Before committing, always run:
go fmt ./...
go vet ./...OpenCost uses Go workspace with multiple modules:
github.com/opencost/opencost- Main modulegithub.qkg1.top/opencost/opencost/core- Core shared librarygithub.qkg1.top/opencost/opencost/modules/prometheus-source- Prometheus integrationgithub.qkg1.top/opencost/opencost/modules/collector-source- Metrics collector
When adding dependencies, ensure they're added to the correct module.
- Unit tests use standard Go testing (
*_test.gofiles) - Integration tests require
INTEGRATION=trueenvironment variable - Use mocks for external dependencies
- Test files should be co-located with implementation
import "github.com/opencost/opencost/core/pkg/log"
log.Infof("Processing allocation for window: %s", window)
log.Errorf("Failed to query Prometheus: %v", err)
log.Warnf("Missing pricing data, using defaults")
log.Debugf("Detailed debug information")- Link related issues using:
Fixes #123,Closes #456 - Describe user-facing changes and breaking changes
- Include test coverage for new functionality
- Run
just testbefore submitting - Use signed commits (
Signed-off-byheader required)
- Prometheus collects Kubernetes metrics (CPU, memory, etc.)
- OpenCost queries Prometheus for resource usage data
- Cloud Provider APIs provide pricing information
- Cost Model combines usage × pricing to compute costs
- API/MCP exposes cost data to users and AI agents
Allocation- Cost allocation for a workload over a time windowAsset- Infrastructure asset (node, disk, load balancer)CloudCost- Cloud service costs from billing APIsWindow- Time range for queries
OpenCost auto-detects the cloud provider from:
CLOUD_PROVIDERenvironment variable (explicit override)- Kubernetes node labels
- Instance metadata services
- Create package under
pkg/cloud/<provider>/ - Implement the
models.Providerinterface - Add environment variables in
pkg/env/costmodel.go - Register in
pkg/cloud/provider/provider.go - Add default pricing config in
configs/
- Add handler method to
pkg/costmodel/router.goor appropriate file - Register route in
pkg/cmd/costmodel/costmodel.go - Add tests in corresponding
*_test.gofile
- Edit
.protofiles inprotos/ - Run
./generate.shto regenerate Go code - Run
just validate-protobufto verify
Core formulas from the OpenCost Specification (spec/opencost-specv01.md):
- Total Cluster Costs = Cluster Asset Costs + Cluster Overhead Costs
- Cluster Asset Costs = Resource Allocation Costs + Resource Usage Costs
- Workload Costs = max(request, usage) for CPU/memory resources
- Idle Costs = Allocation costs not attributed to any workload