Query amazon ec2 attributes from inside instance for checking pricing - amazon-web-services

Amazon EC2 pricing api provides different attributes for each type of pricing, how am i able to know under which pricing my ec2 instance is running. Because in pricing api i.e. json file, amazon provides few attributes and out of these attributes i am only able to fetch instanceType from inside of an instance. how to get others?
[
{
"TDVRYW6K68T4XJHJ.JRTCKXETXF": {
"effectiveDate": "2016-01-01T00:00:00Z",
"offerTermCode": "JRTCKXETXF",
"priceDimensions": {
"TDVRYW6K68T4XJHJ.JRTCKXETXF.6YS6EN2CT7": {
"appliesTo": [],
"beginRange": "0",
"description": "$4.900 per On Demand Linux hs1.8xlarge Instance Hour",
"endRange": "Inf",
"pricePerUnit": {
"USD": "4.9000000000"
},
"rateCode": "TDVRYW6K68T4XJHJ.JRTCKXETXF.6YS6EN2CT7",
"unit": "Hrs"
}
},
"sku": "TDVRYW6K68T4XJHJ",
"termAttributes": {}
},
"attributes": {
"clockSpeed": "2 GHz",
"currentGeneration": "No",
"instanceFamily": "Storage optimized",
"instanceType": "hs1.8xlarge",
"licenseModel": "No License required",
"location": "EU (Ireland)",
"locationType": "AWS Region",
"memory": "117 GiB",
"networkPerformance": "10 Gigabit",
"operatingSystem": "Linux",
"operation": "RunInstances",
"physicalProcessor": "Intel Xeon E5-2650",
"preInstalledSw": "NA",
"processorArchitecture": "64-bit",
"servicecode": "AmazonEC2",
"storage": "24 x 2000",
"tenancy": "Shared",
"usagetype": "EU-BoxUsage:hs1.8xlarge",
"vcpu": "17"
}
}
]

1) find your instance size and AZ. For example
[ec2-user#ip-10-50-1-171 temp]$ ec2-metadata |grep placement
placement: eu-west-1a
[ec2-user#ip-10-50-1-171 temp]$ ec2-metadata |grep instance-type
instance-type: t2.micro
2) pull the correct file for the pricing of the EC2, for example at the moment it is
https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonEC2/current/index.json
3) within this file there are "products". So for instance within the products find a t2.micro for eu-west
"SYEPG42MVWFMUBT6" : {
"sku" : "SYEPG42MVWFMUBT6",
"productFamily" : "Compute Instance",
"attributes" : {
"servicecode" : "AmazonEC2",
"location" : "EU (Ireland)",
"locationType" : "AWS Region",
"instanceType" : "t2.micro",
"instanceFamily" : "General purpose",
"vcpu" : "1",
"physicalProcessor" : "Intel Xeon Family",
"clockSpeed" : "Up to 3.3 GHz",
"memory" : "1 GiB",
"storage" : "EBS only",
"networkPerformance" : "Low to Moderate",
"processorArchitecture" : "32-bit or 64-bit",
"tenancy" : "Shared",
"operatingSystem" : "SUSE",
"licenseModel" : "No License required",
"usagetype" : "EU-BoxUsage:t2.micro",
"operation" : "RunInstances:000g",
"preInstalledSw" : "NA",
"processorFeatures" : "Intel AVX; Intel Turbo"
}
},
Note the SKU for this product
4) next find the "terms" section in the json file. There are sections for "OnDemand" and "Reserved". In "OnDemand" the SKU for the product of interest (in the example above SYEPG42MVWFMUBT6) is mentioned once. In the "Reserved" there are several entries with different terms
If you need to do all these steps programmatically you'd have to use either a shell script and a tool like jq or a library for json processing like the one included with python

I know this question is old, and I don't have any definitive proof (someone please correct me if its wrong) But through experimenting I've found that to get your specific running instance cost, you really cannot use a combination of the EC2 Metadata and the https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/price-changes.html API.
This is because the information returned from the price API is for current offers available in the near term for instances to be purchased not your specific running instance.
Specifically what you would want to find is the Ratecode associated with your specific instance, and this is not found through calling DescribeInstances. You can apply a series of filters to get a pretty good guess, as to what the instance cost is likely for a specific instance running in your account. However, I am unable to uniquely define a specific instance even with some specific filters like the following
{
Filters: [
{
Type: 'TERM_MATCH',
Field: 'ServiceCode',
Value: 'AmazonEC2',
},
{
Type: 'TERM_MATCH',
Field: 'regionCode',
Value: 'us-east-1',
},
{
Type: 'TERM_MATCH',
Field: 'instanceType',
Value: 't3.medium',
},
{
Type: 'TERM_MATCH',
Field: 'marketoption',
Value: 'OnDemand',
},
{
Type: 'TERM_MATCH',
Field: 'operatingSystem',
Value: 'Linux',
},
{
Type: 'TERM_MATCH',
Field: 'tenancy',
Value: 'Shared',
},
],
FormatVersion: 'aws_v1',
NextToken: null,
ServiceCode: 'AmazonEC2',
};
(The above filter returns like ~50 different price offerings when used to query the GetProductsAPI )
If its any help here is some code I've been using to muck around
I haven't tested it but it might just be easier to Crawl the pricing page
EDIT:
I worked with AWS support a bit and found a workable solution set of filters. Copying the response from AWS here:
I understand that you want to use aws price list query API to output the pricing of onDemand t3.medium instance, however it is throwing results for lot of instances of same instance type instead of getting output for the exact ec2 instance your queried for.
I was able to reproduce the same behavior from my end when I used the same filters you provided over an aws cli get-products request1. After digging into this a bit, I was able to substantially bring down the search result using the below filters with the help of a guide2.
Command:
aws pricing get-products --filters file://filters2.json --format-version aws_v1 --service-code AmazonEC2
Filter json file:
[
{
"Type": "TERM_MATCH",
"Field": "ServiceCode",
"Value": "AmazonEC2"
},
{
"Type": "TERM_MATCH",
"Field": "regionCode",
"Value": "us-east-1"
},
{
"Type": "TERM_MATCH",
"Field": "instanceType",
"Value": "t3.medium"
},
{
"Type": "TERM_MATCH",
"Field": "marketoption",
"Value": "OnDemand"
},
{
"Type": "TERM_MATCH",
"Field": "operatingSystem",
"Value": "Linux"
},
{
"Type": "TERM_MATCH",
"Field": "tenancy",
"Value": "Shared"
},
{
"Type": "TERM_MATCH",
"Field": "preInstalledSw",
"Value": "NA"
},
{
"Type": "TERM_MATCH",
"Field": "licenseModel",
"Value": "No License required"
},
{
"Type": "TERM_MATCH",
"Field": "capacitystatus",
"Value": "Used"
}
]
The following were the results in a nutshell:
On Demand Instance price for the instance matched in filter.
Reserved Instances:
2.1: Term: 1 year or 3 year
2.2: Upfront: none, partial or all
2.3: Convertable: standard or convertable
I understand that you have applied a filter that matches key value 'marketoption:OnDemand', but in the output there is a seperate category called "terms" within "serviceCode" key. The terms then is then a nested array containing different keys for 'OnDemand' and 'Reserved' etc which would not be filtered by the above filters normally.
As for a workaround to filter out just the pricing of On Demand instance, I am afraid you would have to create custon json query to filter out only the values of the On demand instance returned from the output of the updated script.

Related

No TagKey: "<tag>" - User tags are ignored by cost explorer

I want to group the following usages by a tag named "organization":
Client VPN endpoint association hours
Client VPN endpoint connection hours
EC2 instances hours
So I set the "organization" tag on the following resources
Client VPN endpoint
EC2 instances
I also activated the user-defined cost allocation tags in the Billing panel.
Although, when i group my resources using the "organization" tag, here is the output I get :
Seems like none of my resources have the "organization" tag defined, although it's absolutely not the case. For example, this is a shortened describe-vpn-endpoints output :
{
"ClientVpnEndpoints": [
{
"Status": {
"Code": "available"
},
"ClientCidrBlock": "10.1.0.0/16",
"SplitTunnel": false,
"VpnProtocol": "openvpn",
"TransportProtocol": "udp",
"VpnPort": 443,
"Tags": [
{
"Key": "app",
"Value": "xxxxx"
},
{
"Key": "organization",
"Value": "630c8acfd564a41dae9d73e1"
},
{
"Key": "Name",
"Value": "o-ABEFO_XXXXXXX-630c8acfd564a41dae9d73e1"
}
]
},
{
"Status": {
"Code": "pending-associate"
},
"CreationTime": "2022-08-30T12:55:51",
"ClientCidrBlock": "10.1.0.0/16",
"SplitTunnel": true,
"VpnProtocol": "openvpn",
"TransportProtocol": "udp",
"VpnPort": 443,
"Tags": [
{
"Key": "app",
"Value": "xxxxxx"
},
{
"Key": "organization",
"Value": "630e0787814fdcf162bd521f"
},
{
"Key": "Name",
"Value": "xxxxxx-o-flomo-630e0787814fdcf162bd521f"
}
]
}
]
}
What am I missing ?
I don't know about your problem, but I have this issue when my tag not showing on cost explore, and later figure out how to fix it.
I want to track each S3 bucket cost and set the tag following this document.
Link: https://repost.aws/knowledge-center/s3-find-bucket-cost
After the tag is active, wait 24 hours and it will show on cost explore.
On the Cost Explorer ----> Report parameters (on the right-hand side) you can do the filter.
Important: It looks like it will only show the time of cost after the tag applies.
e.g I activate the tag at Feb 9th, if I use cost explore to do the filtering,
it will only start the cost from Feb 9th.
on the Group by ---> Dimension, choose the Tag, and then choose the Tag you create.
Choose the service related to the tag
Choose tag and excludes this one No tag key: xxx, so it will include all the S3 buckets you tag.
Here is the final result:
Hope it helps.

How to fetch GCP billing by instance name? (Not by type) and is there any association between resource and billing sku id?

Can I see GCP billing by instance name? (Not by type)
I am trying to filter GCP billing by instance name, is it possible? I only succeeded to filter by GCP Compute Engine and instance type (n1-standard) etc...
I am trying to programmatically match the machineType associated with a GCP compute instance to the corresponding billing SKU, but am unable to find a key for direct association. For example, here is the response from the machineType API:
{
"kind": "compute#machineType",
"name": "n1-standard-32",
"description": "32 vCPUs, 120 GB RAM",
"guestCpus": 32,
"memoryMb": 122880,
"imageSpaceGb": 0,
"maximumPersistentDisks": 128,
"maximumPersistentDisksSizeGb": "65536",
"zone": "us-east1-b",
"isSharedCpu": false
}
And here is the corresponding SKU from the cloudbilling APIs:
"name": "services/XXXX/skus/XXXX",
"skuId": "XXXX",
"description": "Standard Intel N1 32 VCPU running in Americas",
"category": {
"serviceDisplayName": "Compute Engine",
"resourceFamily": "Compute",
"resourceGroup": "N1Standard",
"usageType": "OnDemand"
},
"serviceRegions": [
"us-central1",
"us-east1",
"us-west1"
],
"pricingInfo": [
{
"summary": "",
"pricingExpression": {
"usageUnit": "h",
"usageUnitDescription": "hour",
"baseUnit": "s",
"baseUnitDescription": "second",
"baseUnitConversionFactor": 3600,
"displayQuantity": 1,
"tieredRates": [
{
"startUsageAmount": 0,
"unitPrice": {
"currencyCode": "USD",
"units": "1",
"nanos": 520000000
}
}
]
},
"currencyConversionRate": 1,
"effectiveTime": "2018-02-22T12:00:16.647Z"
}
],
"serviceProviderName": "Google"
There doesn't seem to be a field with value n1-standard-32 in the billing SKU. How do we tie these two together as this page seems to do: https://cloud.google.com/compute/pricing?
You can create labels and add to your instances in order to get a breakdown of the charges per instance. This label needs to be added on each instance, once added, you will be able to see the charges per instance on the billing reports by sorting it per label.
Creating and managing labels can be found here
You can use the Resource Manager API and perform a request such as
POST https://cloudresourcemanager.googleapis.com/v1beta1/projects
{
"labels": {
"color": "red"
},
"name": "myproject",
"projectId": "our-project-123"
}
You can also add and edit labels for your Compute Engine Instances using the gcloud commands

Aws cli command substitution

I want to list volume's snapshots but in the output I would like to also see the Name of that volume (I mean tag).
So far I was using:
aws ec2 describe-snapshots
And in the reply I got something like:
Snapshots: [
{
"Description": "some description",
"Encrypted": false,
"OwnerId": "someownerid",
"Progress": "100%",
"SnapshotId": "snap-example",
"StartTime": "start time",
"State": "completed",
"VolumeId": "volume id",
"VolumeSize": 32
}
]
But what I would like to have in that output is also a volume name:
Snapshots: [
{
"Description": "some description",
"Encrypted": false,
"OwnerId": "someownerid",
"Progress": "100%",
"SnapshotId": "snap-example",
"StartTime": "start time",
"State": "completed",
"VolumeId": "volume id",
"VolumeSize": 32,
"VolumeName": "Volume Name" #additional key:val
}
]
The aws ec2 describe-snapshots does return tags on snapshots if they are present.
Something similar to this:
{
"Description": "This snapshot is created by the AWS Backup service.",
"Tags": [
{
"Value": "On",
"Key": "Backup"
},
{
"Value": "Jenkins_Machine",
"Key": "Name"
},
{
"Value": "*********",
"Key": "aws:backup:source-resource"
}
],
"Encrypted": false,
"VolumeId": "vol-*****",
"State": "completed",
"VolumeSize": 250,
"StartTime": "2019-08-01T11:29:31.654Z",
"Progress": "100%",
"OwnerId": "******",
"SnapshotId": "snap-******"
}
To be able to see the name (Assuming your snapshots have them) do this:
aws ec2 describe-snapshots --snapshot-id snap-**** --query 'Snapshots[*].{Description:Description,Name:Tags[?Key==`Name`].Value|[0],State:State}'
This should give you output like this:
[
{
"State": "completed",
"Description": "This snapshot is created by the AWS Backup service.",
"Name": "Jenkins_Machine"
}
]
The fields are curtailed but you can add fields that you need at the end of the query like this ...State:State,VolumeId:VolumeId}, where I have newly added the VolumeId.
If you remove the --snapshot-id parameter, the above command should return you all snapshots, however for snapshots that don't have the Name tag its going to print null.
Edit:
As #krishna_mee2004 pointed out, the OP is probably looking for snapshots for a particular volume. If that is the case you can still do it using this command. The filters option can be used to filter based on volume ID.
aws ec2 describe-snapshots --filters Name=volume-id,Values=vol-***** --query 'Snapshots[*].{Description:Description,Name:Tags[?Key==`Name`].Value|[0],State:State,VolumeId:VolumeId}'
If you are referring to snapshot's name tag, you can write a simple python or ruby script using aws sdk. For example, a ruby code to list the snapshot id and value of its name tag will look like this:
require 'aws-sdk'
# provide region and credentials in parameter
ec2 = Aws::EC2::Client.new
# paginate if you have a big list
resp = ec2.describe_snapshots
# iterate snapshots
resp.snapshots.each do |snapshot|
# iterate tags and print if it has a name tag.
snapshot.tags.each do |tag|
# print whatever is required/available in the response structure
puts "#{snapshot.snapshot_id} has the name tag with value #{tag.value}" if tag.key.casecmp? 'Name'
end
end
Refer the respective language api documentation to understand more about the usage of the sdk and the api calls. Make sure to setup the sdk before using and it varies based on the language you choose. For example, steps for setting up the ruby sdk is outlined here. You may also want to checkout the API reference for describe_snaphots used in the above code.

Developing an app to create a stack from a cloudformation template

I am new to AWS and am currently working on simple tasks.
I have created a free tier EC2 instance using a cloudformation template. Now my next task is to write a simple application that uses respective AWS SDK to call CloudFormation API to create a stack from the template.
Here is the cloudformation template:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Ec2 Template",
"Metadata": {
"Copyright":[
"Copyright 2017, All rights reserved"
],
"Comments":[
"Create an EC2"
]
},
"Parameters": {
"KeyName": {
"Type": "AWS::EC2::KeyPair::KeyName",
"Description": "Name of an existing EC2 KeyPair to enable access to join ECS instances."
},
"InstanceTypeParameter":{
"Type": "String",
"Default": "t2.micro",
"AllowedValues": [
"t2.micro",
"m1.small",
"m1.large"
],
"Description": "Enter t2.micro, m1.small, or m1.large. Default is t2.micro."
},
"EcsSecurityGroupLb":{
"Type": "AWS::EC2::SecurityGroup::Id",
"Description":"The ECS ELB Security Group."
},
"vpcid":{
"Type": "AWS::EC2::VPC::Id"
},
"mySubnetIDs": {
"Description":"Subnet IDs",
"Type":"AWS::EC2::Subnet::Id"
}
},
"Resources":{
"Ec2Instance":{
"Type":"AWS::EC2::Instance",
"Properties":{
"ImageId": "ami-bf4193c7",
"KeyName": {
"Ref": "KeyName"
},
"InstanceType":{
"Ref": "InstanceTypeParameter"
},
"NetworkInterfaces":[
{
"AssociatePublicIpAddress":"true",
"DeviceIndex":"0",
"SubnetId":{
"Ref":"mySubnetIDs"
},
"GroupSet":[
{
"Ref": "EcsSecurityGroupLb"
}
]
}
],
"BlockDeviceMappings":[
{
"DeviceName": "/dev/sdc",
"VirtualName":"ephemeral0"
}
]
}
}
},
"Outputs":{
"Ec2Instance":{
"Description": "InstanceId of newly created EC2 instance",
"Value": {
"Ref": "Ec2Instance"
}
},
"InstanceIPAddress":{
"Value":{ "Fn::GetAtt": ["Ec2Instance", "PublicIp"]},
"Description": "Public IP address of instance"
}
}
}
I have gone through a lot of documentation but haven't really understood as to how to proceed. I would like to know if there are any good tutorials on this.
Looking for suggestions with respect to the steps as well.
Thanks!
Since you have to (as a task requirement) write the application yourself, you'll need to use one of the AWS SDKs that are available.
The SDK you choose will depend on what programming language you are most comfortable using (or required by your task).
Roughly, your program will need to do the following:
With the AWS SDK, create an AWS session which uses your IAM user's API keys.
Grab the Cloudformation template off of your local system.
With the AWS SDK, invoke Cloudformation to create the resource stack with your template.
(Optionally) Wait until the stack is complete and output a report on the stack status.
Good luck!

How to get cost for each EC2, not total cost for all EC2 from AWS API

I'm studying AWS api to retrieve requisite information about my EC2 instances.
So, I'm on AWS Cost Explorer Service.
It has function 'GetCostAndUsage' that, for example, sends information below. (this is an example from official AWS document)
{
"TimePeriod": {
"Start":"2017-09-01",
"End": "2017-10-01"
},
"Granularity": "MONTHLY",
"Filter": {
"Dimensions": {
"Key": "SERVICE",
"Values": [
"Amazon Simple Storage Service"
]
}
},
"GroupBy":[
{
"Type":"DIMENSION",
"Key":"SERVICE"
},
{
"Type":"TAG",
"Key":"Environment"
}
],
"Metrics":["BlendedCost", "UnblendedCost", "UsageQuantity"]
}
and retrieve information below. (this is an example from official AWS document)
{
"GroupDefinitions": [
{
"Key": "SERVICE",
"Type": "DIMENSION"
},
{
"Key": "Environment",
"Type": "TAG"
}
],
"ResultsByTime": [
{
"Estimated": false,
"Groups": [
{
"Keys": [
"Amazon Simple Storage Service",
"Environment$Prod"
],
"Metrics": {
"BlendedCost": {
"Amount": "39.1603300457",
"Unit": "USD"
},
"UnblendedCost": {
"Amount": "39.1603300457",
"Unit": "USD"
},
"UsageQuantity": {
"Amount": "173842.5440074444",
"Unit": "N/A"
}
}
},
{
"Keys": [
"Amazon Simple Storage Service",
"Environment$Test"
],
"Metrics": {
"BlendedCost": {
"Amount": "0.1337464807",
"Unit": "USD"
},
"UnblendedCost": {
"Amount": "0.1337464807",
"Unit": "USD"
},
"UsageQuantity": {
"Amount": "15992.0786663399",
"Unit": "N/A"
}
}
}
],
"TimePeriod": {
"End": "2017-10-01",
"Start": "2017-09-01"
},
"Total": {}
}
]
}
The retrieved data in key 'Metrics' I guess, it is total cost. not each.
So, How can I get each usage and cost for each EC2 instance??
This was way harder than I had imagined so I'm sharing in case someone else needs it.
aws ce get-cost-and-usage \
--filter file://filters.json \
--time-period Start=2021-08-01,End=2021-08-14 \
--granularity DAILY \
--metrics "BlendedCost" \
--group-by Type=TAG,Key=Name
Contents of filters.json:
{
"Dimensions": {
"Key": "SERVICE",
"Values": [
"Amazon Elastic Compute Cloud - Compute"
]
}
}
--- Available Metrics ---
AmortizedCost
BlendedCost
NetAmortizedCost
NetUnblendedCost
NormalizedUsageAmount
UnblendedCost
UsageQuantity
Descriptions for most metrics except for usage: https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/ce-advanced.html
Know this question is old, but you will need to use the GetCostAndUsageWithResources call, as opposed to GetCostAndUsage.
https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ce/get-cost-and-usage-with-resources.html
It's going to be difficult to associate an exact cost with each instance - simple example, you have 2 instances of the same size - one reserved and one on-demand - you run both for 1/2 the month and then turn off one of them for the second 1/2 of the month.
You will pay for a reserved instance for the entire month and an on-demand instance for 1/2 the month - but which instance was reserved and which was on-demand? You can't tell; the concept of a reserved instance is just a billing concept, and is not associated with a particular instance.
You might be able to approximate what you are looking for - but there are limitations.
You can use tags to track the cost of resources. In the case of EC2 you can assign tags like Project: myprojcet or Application: myapp and in cost explorer then filter the expenses by tags and use the tag that has been put to track the expenses. If the instance at some point was covered by a reservation plan, the tag will only show you the cost of the period in which your expenses were not covered.