Setup & IAM Permissions
This page is for self-hosted and Private Cloud deployments
Here kubespend-core runs in your AWS account and scrapes CloudWatch with its own IRSA role. On KubeSpend Cloud the server runs in KubeSpend's account and never calls AWS for you, so there is no role to grant it: discovery and CloudWatch collection move to the agent in your cluster, which is not available yet. See Where AWS is called from. Query capture works on KubeSpend Cloud today.
DB Optimizer scrapes CloudWatch metrics from kubespend-core using the same IRSA role your pricing service already uses. No agent-side configuration is needed for CloudWatch collection — the eBPF agent is only required for the optional query capture layer.
Prerequisites
- KubeSpend core deployed with IRSA (the same setup that enables live AWS pricing)
DB_OPTIMIZER_ENABLED=trueset on the kubespend-core deployment- The IAM permissions below added to the core's IRSA role
Step 1: Add IAM permissions
Add the following inline policy to the IAM role annotated on the kubespend-core ServiceAccount. This is the same role that already holds pricing:GetProducts and ec2:DescribeSpotPriceHistory.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"cloudwatch:GetMetricData",
"rds:DescribeDBInstances",
"rds:DescribeDBClusters",
"rds:DescribeDBParameters",
"rds:DescribeEngineDefaultParameters",
"rds:DescribeOrderableDBInstanceOptions",
"elasticache:DescribeCacheClusters",
"elasticache:DescribeReplicationGroups",
"elasticache:DescribeServerlessCaches",
"elasticache:DescribeCacheParameters",
"elasticache:DescribeEngineDefaultParameters"
],
"Resource": "*"
}
]
}Why Resource: "*"?
None of the RDS Describe, ElastiCache Describe, or CloudWatch GetMetricData actions support resource-level permissions. The scope is carried entirely by the action list — these are all read-only operations that cannot modify any resource.
Using the install-irsa.sh script
If you deployed using the KubeSpend scripts, add a second inline policy:
aws iam put-role-policy \
--role-name <your-kubespend-core-irsa-role> \
--policy-name kubespend-core-db-optimizer \
--policy-document file://db-optimizer-policy.jsonUsing Terraform / CloudFormation
Add the actions to whatever module manages the IRSA role. The trust policy does not change — it is already scoped to the kubespend-core ServiceAccount.
Step 2: Enable DB Optimizer
Set the environment variable on your kubespend-core deployment:
kubectl set env deployment/kubespend-core DB_OPTIMIZER_ENABLED=trueOr in your Helm values / manifest:
env:
- name: DB_OPTIMIZER_ENABLED
value: "true"Core will log at startup:
db-optimizer: enabled, scrape interval 5m0sIf no IAM credentials are available, discovery will fail and the console will show the setup guide. Core itself starts normally — the feature is gated, not required.
Step 3: Discover and register instances
- Open the KubeSpend console → DB Optimizer → RDS (or ElastiCache)
- The page auto-discovers instances in the default region
- Click Register on the instances you want to monitor
- Metrics start appearing within 5 minutes (one scrape interval)
Only registered instances are polled. Deregistering an instance stops polling immediately; historical metrics are retained for 15 days.
Configuration
| Variable | Default | Description |
|---|---|---|
DB_OPTIMIZER_ENABLED | false | Enable/disable the entire feature |
DB_OPTIMIZER_SCRAPE_INTERVAL | 300 | Seconds between CloudWatch polls (300–3600) |
Multi-region
The IRSA role must have the permissions above in every AWS region where you register a DB instance. A single IAM policy with Resource: "*" covers all regions — no per-region configuration is needed.
Discovery scans one region at a time. Select the region in the console and click Discover to scan a different one.
Cost
CloudWatch GetMetricData is billed per metric requested (~$0.01 per 1,000 metrics). At the default 300-second interval with 11 metrics per RDS instance:
| Instances | Metrics/month | Approx. cost |
|---|---|---|
| 10 | ~950,000 | ~$9.50 |
| 50 | ~4,750,000 | ~$47.50 |
| 100 | ~9,500,000 | ~$95.00 |
The console shows the projected monthly metric-request count so you can predict cost before it appears on your AWS bill.
Troubleshooting
Discovery returns "Unable to discover"
The IRSA role is missing the rds:DescribeDBInstances or elasticache:DescribeCacheClusters permission. Add the policy above, restart core, and try again.
"Discovered from your own AWS account" instead of a list
The deployment runs with DB_OPTIMIZER_AWS_SOURCE=agent, as KubeSpend Cloud does, so core refuses to call AWS (HTTP 409, agent_collection_required). That is intended, not a permissions problem. On a self-hosted deployment where core runs in your own account, unset the variable or set it to core.
Metrics show as unavailable (em dash)
- Check that
DB_OPTIMIZER_ENABLED=trueis set - Check core logs for
db-optimizer: PROBE FAILED— this means CloudWatch credentials are not working - Verify the IRSA role has
cloudwatch:GetMetricData
Discovery works but shows no instances
The instances exist in a different region. Change the region selector and discover again.