Skip to content

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=true set 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.

json
{
  "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:

bash
aws iam put-role-policy \
  --role-name <your-kubespend-core-irsa-role> \
  --policy-name kubespend-core-db-optimizer \
  --policy-document file://db-optimizer-policy.json

Using 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:

bash
kubectl set env deployment/kubespend-core DB_OPTIMIZER_ENABLED=true

Or in your Helm values / manifest:

yaml
env:
  - name: DB_OPTIMIZER_ENABLED
    value: "true"

Core will log at startup:

db-optimizer: enabled, scrape interval 5m0s

If 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 ​

  1. Open the KubeSpend console → DB Optimizer → RDS (or ElastiCache)
  2. The page auto-discovers instances in the default region
  3. Click Register on the instances you want to monitor
  4. 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 ​

VariableDefaultDescription
DB_OPTIMIZER_ENABLEDfalseEnable/disable the entire feature
DB_OPTIMIZER_SCRAPE_INTERVAL300Seconds 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:

InstancesMetrics/monthApprox. 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=true is 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.

Every figure in KubeSpend traces to a real cloud price. Where we cannot measure something, we say so.