Skip to content

AWS integration

Describes Hibernator chart 0.12.44

Two optional AWS features: Cost Explorer, which shows what the cluster costs and what hibernation saved, and managed databases, which stops and starts RDS instances alongside the workloads. Both authenticate through IRSA, and neither is on by default.

On AWS the license check is not optional: the controller proves its account with sts:GetCallerIdentity, which needs no IAM permission. The controller role below serves it. license.md says which role sources count, and covers the proxy and the CA bundle.

Managed databases are configured as databases.md describes; their IAM permissions are on this page, because they share the controller role with everything else here.

Hibernator can optionally integrate with AWS Cost Explorer to display daily costs per cluster and calculate savings from hibernation. All services tagged with the cluster name are captured (EC2, Fargate, EKS, etc.). This feature is disabled by default and requires IRSA (IAM Roles for Service Accounts) for authentication.

  1. EKS cluster with OIDC provider configured
  2. Cost allocation tag aws:eks:cluster-name activated in AWS Billing console
  3. IAM role with Cost Explorer read permissions (see IRSA setup below)
serviceAccount:
api:
annotations:
eks.amazonaws.com/role-arn: "arn:aws:iam::ACCOUNT_ID:role/HibernatorCostExplorerRole"
config:
awsCosts:
enabled: true
tagKey: "aws:eks:cluster-name" # AWS-managed EKS tag
tagValue: "my-cluster" # Your EKS cluster name (required)
cacheTTL: "1h" # How long to cache responses
  • Daily costs for the past 30 days, filtered by cluster tag (includes EC2, Fargate, EKS, and other tagged services)
  • Hibernation savings calculated from actual running vs. hibernated hours
  • Savings percentage comparing actual cost to projected always-on cost
  • Uses NetUnblendedCost metric by default (reflects enterprise/EDP discounts, excludes SP amortization)
  • Configurable via config.awsCosts.costMetric (valid: UnblendedCost, BlendedCost, AmortizedCost, NetUnblendedCost, NetAmortizedCost)
  • Cost Explorer data has a ~24 hour delay
  • Only captures costs for resources tagged with aws:eks:cluster-name (untagged resources like NAT Gateways are not included)
  • Cost Explorer does not support resource-level IAM permissions (Resource: "*" is required)

Hibernator uses two separate IAM roles via IRSA (IAM Roles for Service Accounts):

  • API role: Cost Explorer access (ce:GetCostAndUsage) + Parameter Store for hibernation stats (ssm:GetParameter, ssm:GetParameters, ssm:PutParameter) + optional tagging (ssm:AddTagsToResource, ssm:ListTagsForResource)
  • Controller role: Parameter Store for hibernation stats (ssm:GetParameter, ssm:GetParameters, ssm:PutParameter) + optional tagging (ssm:AddTagsToResource, ssm:ListTagsForResource) + the managed databases (rds:DescribeDBInstances, rds:StartDBInstance, rds:StopDBInstance) and their hourly rate (pricing:GetProducts)

Both roles are required when config.awsCosts.enabled: true. The RDS statement is required when config.databases.enabled: true.

API policy (Cost Explorer + Parameter Store):

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CostExplorerReadOnly",
"Effect": "Allow",
"Action": "ce:GetCostAndUsage",
"Resource": "*"
},
{
"Sid": "ParameterStoreHibernator",
"Effect": "Allow",
"Action": [
"ssm:GetParameter",
"ssm:GetParameters",
"ssm:PutParameter",
"ssm:AddTagsToResource",
"ssm:ListTagsForResource"
],
"Resource": "arn:aws:ssm:REGION:ACCOUNT_ID:parameter/hibernator/*"
}
]
}

Controller policy (Parameter Store, plus RDS when managed databases are configured):

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ParameterStoreHibernator",
"Effect": "Allow",
"Action": [
"ssm:GetParameter",
"ssm:GetParameters",
"ssm:PutParameter",
"ssm:AddTagsToResource",
"ssm:ListTagsForResource"
],
"Resource": "arn:aws:ssm:REGION:ACCOUNT_ID:parameter/hibernator/*"
},
{
"Sid": "ManagedDatabasesRead",
"Effect": "Allow",
"Action": [
"rds:DescribeDBInstances",
"pricing:GetProducts"
],
"Resource": "*"
},
{
"Sid": "ManagedDatabasesStopStart",
"Effect": "Allow",
"Action": [
"rds:StartDBInstance",
"rds:StopDBInstance"
],
"Resource": [
"arn:aws:rds:REGION:ACCOUNT_ID:db:INSTANCE_IDENTIFIER"
]
}
]
}

rds:DescribeDBInstances does not support resource-level permissions either, but the start and stop actions do. In ManagedDatabasesStopStart, list the ARN of every managed instance and nothing else. A controller bug can then never stop an instance that the configuration does not name.

2. Create the IAM roles with trust policies

Section titled “2. Create the IAM roles with trust policies”

Replace ACCOUNT_ID, REGION, and CLUSTER_OIDC_ID with your values.

API role trust policy:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::ACCOUNT_ID:oidc-provider/oidc.eks.REGION.amazonaws.com/id/CLUSTER_OIDC_ID"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"oidc.eks.REGION.amazonaws.com/id/CLUSTER_OIDC_ID:sub": "system:serviceaccount:hibernator:hibernator-api",
"oidc.eks.REGION.amazonaws.com/id/CLUSTER_OIDC_ID:aud": "sts.amazonaws.com"
}
}
}
]
}

Controller role trust policy:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::ACCOUNT_ID:oidc-provider/oidc.eks.REGION.amazonaws.com/id/CLUSTER_OIDC_ID"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"oidc.eks.REGION.amazonaws.com/id/CLUSTER_OIDC_ID:sub": "system:serviceaccount:hibernator:hibernator-controller",
"oidc.eks.REGION.amazonaws.com/id/CLUSTER_OIDC_ID:aud": "sts.amazonaws.com"
}
}
}
]
}
serviceAccount:
api:
annotations:
eks.amazonaws.com/role-arn: "arn:aws:iam::ACCOUNT_ID:role/HibernatorApiRole"
controller:
annotations:
eks.amazonaws.com/role-arn: "arn:aws:iam::ACCOUNT_ID:role/HibernatorControllerRole"