Skip to main content

Installing on Amazon Web Services (AWS)

OpenCost may be installed on Kubernetes clusters running on EC2 or on Elastic Kubernetes Service (EKS).

You will need to install Prometheus, create your OpenCost namespace, configure your cluster pricing and cloud costs, and then install OpenCost.

Install Prometheus

Prometheus is a prerequisite for OpenCost installation. OpenCost requires Prometheus for scraping metrics and data storage. For the installation of Prometheus please use the following command:

helm install prometheus --repo https://prometheus-community.github.io/helm-charts prometheus \
--namespace prometheus-system --create-namespace \
--set prometheus-pushgateway.enabled=false \
--set alertmanager.enabled=false \
-f https://raw.githubusercontent.com/opencost/opencost/develop/kubernetes/prometheus/extraScrapeConfigs.yaml

This will install Prometheus in the prometheus-system namespace with default settings for use with OpenCost.

If you wish to use a different Prometheus installation or work with another compatible technology, please refer to the Prometheus installation page.

Create the OpenCost Namespace

Create the opencost namespace for your installation:

kubectl create namespace opencost

Alternate namespaces may be used if necessary.

AWS Configuration

Cost Allocation

OpenCost will automatically read the node information node.spec.providerID to determine the cloud service provider (CSP) in use. If it detects the CSP is AWS, it will attempt to pull the AWS on-demand pricing from the configured public API URL with no further configuration required.

OpenCost will request pricing data from the us-east-1 region for your node_region using the template:

https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonEC2/current/${node_region}/index.json

The location should be automatically detected, but this URL can be overwritten using the environment variable AWS_PRICING_URL.

AWS Spot Instance Data Feed

AWS Spot Instance Data Feed from the configured S3 bucket

  • Set up Spot Instance Data Feed.
  • Create a role for OpenCost with access to the spot feed bucket. Attach the policy below to the role and replace CHANGE-ME with your spot bucket name.
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:ListAllMyBuckets",
"s3:ListBucket",
"s3:HeadBucket",
"s3:HeadObject",
"s3:List*",
"s3:Get*"
],
"Resource": [
"arn:aws:s3:::CHANGE-ME"
],
"Effect": "Allow",
"Sid": "SpotDataAccess"
}
]
}

Configuration

The data feed will provide specific pricing information about any Spot instances in your account on an hourly basis. After setting this up, the bucket information can be provided through options in the AWS provider configuration file.

  • awsSpotDataBucket - The name of the S3 bucket Spot Instance Data Feed is publishing to.
  • awsSpotDataRegion - The region configured for Spot Instance Data Feed
  • awsSpotDataPrefix - The prefix (if any) configured for Spot Instance Data Feed
  • projectID - The AWS Account ID

Example configuration:

{
"provider": "aws",
"description": "AWS Provider Configuration. Provides default values used if instance type or spot information is not found.",
"CPU": "0.031611",
"spotCPU": "0.006655",
"RAM": "0.004237",
"GPU": "0.95",
"spotRAM": "0.000892",
"storage": "0.000138888889",
"zoneNetworkEgress": "0.01",
"regionNetworkEgress": "0.01",
"internetNetworkEgress": "0.143",
"spotLabel": "kops.k8s.io/instancegroup",
"spotLabelValue": "spotinstance-nodes",
"awsSpotDataRegion":"us-east-2",
"awsSpotDataBucket": "my-spot-bucket",
"awsSpotDataPrefix": "spot_pricing_prefix",
"projectID": "012345678901"
}

Security for AWS integration

OpenCost uses the AWS SDK for Go to pull Spot data feed information. There are multiple supported ways to configure security.

The recommended setup is to leverage IAM roles for Service Accounts or EKS Pod Identities.

IAM Roles for Service Accounts

After creating the role and policy, attach the role as an annotation on the service account in your local OpenCost Helm values file:

serviceAccount:
create: true
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/S3Access

EKS Pod Identities

See AWS Documentation on EKS Pod Identities

To use EKS Pod Identities with OpenCost:

  1. Configure the EKS Pod Identities add on: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-agent-setup.html
  2. Create the EKS Pod Identity association: https://docs.aws.amazon.com/eks/latest/userguide/pod-id-association.html
  3. Update your local OpenCost Helm values file with:
serviceAccount:
create: true
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/S3Access
name: name-of-service-account-from-step-2 # can be omitted if the name of the service account is exactly 'opencost'

AWS Cloud Costs

info

The Cloud Costs feature is included in the stable releases as of 1.108.0. Please ensure you have the latest release to access this new feature.

Prerequisites: Cost and Usage Report with Athena

Before OpenCost can query your AWS Cloud Costs, you must have a Cost and Usage Report (CUR) exported to S3 and made queryable through Amazon Athena. AWS publishes a CloudFormation template that creates the S3 bucket, Glue database, Glue crawler, and Athena workgroup for you. Follow Setting up Athena using AWS CloudFormation templates before continuing.

When the CloudFormation stack finishes, take note of the following — you will need them below:

  • The CUR S3 bucket name (the bucket the CUR is written to)
  • The Athena query-results S3 bucket name (created by the stack, typically matching aws-athena-query-results-*)
  • The Athena/Glue database name (the AWSCURDatabase output of the stack)
  • The Athena table name (typically the database name with the leading athenacurcfn_ removed)
  • The AWS region Athena is running in
  • The AWS account ID
note

The legacy CUR export format ("CUR" / "Legacy CUR Export") is what the CloudFormation template above provisions and what this guide covers. AWS also offers a newer "Data Exports" / CUR 2.0 format; if you are using CUR 2.0 you will need to confirm field and table-name compatibility with your OpenCost version separately.

Choose an authentication method

OpenCost supports several ways to authenticate against AWS for Cloud Costs. Pick one:

  • IAM Role for Service Account (IRSA) or EKS Pod Identity — recommended on EKS. The role is attached to the OpenCost service account (see the IAM Roles for Service Accounts and EKS Pod Identities sections above). The authorizer block in cloud-integration.json can use AWSAssumeRole (with a roleARN) when crossing accounts, or be omitted/left to the default SDK credential chain when the pod's own role has the required permissions.
  • IAM User with Access Key — works anywhere but requires managing a long-lived secret. Create an IAM user dedicated to OpenCost, attach the policy below to it, then create an Access Key (IAM Console → Access Management > Users > Security Credentials > Create Access Key) and use the AWSAccessKey authorizer shown in the example.

You do not need both an IAM user and a role — choose whichever fits your environment.

IAM permissions for CUR / Athena

Attach a policy similar to the following to the IAM user or role that OpenCost will use. Replace <CUR_BUCKET> with the bucket holding your CUR data and <ATHENA_RESULTS_BUCKET> with the bucket Athena writes query results to.

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AthenaQueryAccess",
"Effect": "Allow",
"Action": [
"athena:GetQueryExecution",
"athena:GetQueryResults",
"athena:GetWorkGroup",
"athena:StartQueryExecution",
"athena:StopQueryExecution"
],
"Resource": "*"
},
{
"Sid": "GlueCatalogAccess",
"Effect": "Allow",
"Action": [
"glue:GetDatabase",
"glue:GetDatabases",
"glue:GetTable",
"glue:GetTables",
"glue:GetPartition",
"glue:GetPartitions"
],
"Resource": "*"
},
{
"Sid": "CURBucketRead",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::<CUR_BUCKET>",
"arn:aws:s3:::<CUR_BUCKET>/*"
]
},
{
"Sid": "AthenaResultsBucketReadWrite",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::<ATHENA_RESULTS_BUCKET>",
"arn:aws:s3:::<ATHENA_RESULTS_BUCKET>/*"
]
}
]
}

cloud-integration.json configuration

Fill in the values you captured in the prerequisites step:

  • <ATHENA_BUCKET_NAME> is the S3 bucket Athena writes query results to (typically matches s3://aws-athena-query-results-*). The bucket can have a canned ACL set to Private or other permissions as needed.
  • <ATHENA_REGION> is the AWS region Athena is running in.
  • <ATHENA_DATABASE> is the name of the database created by the Athena setup. The Athena database name is available as the value (physical id) of AWSCURDatabase in the CloudFormation stack you created in the prerequisites step.
  • <ATHENA_TABLE> is the name of the table created by the Athena setup. The table name is typically the database name with the leading athenacurcfn_ removed (but is not available as a CloudFormation stack resource).
  • <ATHENA_WORKGROUP> is the workgroup assigned to be used with Athena. Default value is primary.
  • <ACCOUNT_NUMBER> is the AWS Account ID where the Athena CUR is. For example: 530337586277.
  • <ACCESS_KEY_ID> is the ID of the Access Key created in the previous step (only required if you chose the IAM User authentication method).
  • <ACCESS_KEY_SECRET> is the secret of the Access Key created in the previous step (only required if you chose the IAM User authentication method).

Set these values into the AWS array in the cloud-integration.json:

{
"aws": {
"athena": [
{
"bucket": "<ATHENA_BUCKET_NAME>",
"region": "<ATHENA_REGION>",
"database": "<ATHENA_DATABASE>",
"table": "<ATHENA_TABLE>",
"workgroup": "<ATHENA_WORKGROUP>",
"account": "<ACCOUNT_NUMBER>",
"authorizer": {
"authorizerType": "AWSAccessKey",
"id": "<ACCESS_KEY_ID>",
"secret": "<ACCESS_KEY_SECRET>"
}
}
]
}
}

Load the cloud-integration.json into a Kubernetes secret in your opencost namespace.

kubectl create secret generic cloud-costs --from-file=./cloud-integration.json --namespace opencost

Update your local OpenCost Helm values file to match the name of the secret and enable Cloud Costs:

opencost:
cloudIntegrationSecret: cloud-costs
cloudCost:
enabled: true

You may refer to the Cloud Costs documentation for configuring Cloud Costs for multiple accounts and cloud service providers.

Install OpenCost

Helm is the preferred installation method for OpenCost.

Using the OpenCost Helm Chart

You may check out the source for the OpenCost Helm Chart or you may install the Helm chart directly to your Kubernetes cluster. Review the values.yaml for the settings available for customization. With your custom settings in the Helm values file local.yaml, install OpenCost:

helm install opencost --repo https://opencost.github.io/opencost-helm-chart opencost \
--namespace opencost -f local.yaml

Updating OpenCost via Helm

Upgrading the Helm chart version or updating settings may be done with the following:

helm upgrade opencost --repo https://opencost.github.io/opencost-helm-chart opencost \
--namespace opencost -f local.yaml

Installing with the OpenCost Manifest

Installing from the OpenCost manifest is supported on AWS.

OpenCost standalone Kubernetes manifest installation is no longer supported. Use the OpenCost Helm chart for installation and upgrades:

helm repo add opencost https://opencost.github.io/opencost-helm-chart
helm repo update
helm install opencost opencost/opencost --namespace opencost --create-namespace
Documentation Distributed under CC BY 4.0.  The Linux Foundation® (TLF) has registered trademarks and uses trademarks. For a list of TLF trademarks, see: Trademark Usage.