Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
retrieve EC2's region from instance metadata

Sometimes you want to retrieve EC2 insntances' region information.

You can query that information through instance metadata(169.254.169.254).

$ curl --silent http://169.254.169.254/latest/dynamic/instance-identity/document
{
  "privateIp" : "172.31.2.15",
  "instanceId" : "i-12341ee8",
  "billingProducts" : null,
  "instanceType" : "t2.small",
  "accountId" : "1234567890",
  "pendingTime" : "2015-11-03T03:09:54Z",
  "imageId" : "ami-383c1956",
  "kernelId" : null,
  "ramdiskId" : null,
  "architecture" : "x86_64",
  "region" : "ap-northeast-1", # <- region
  "version" : "2010-08-31",
  "availabilityZone" : "ap-northeast-1c",
  "devpayProductCodes" : null
}

Response's JSON has a region key, so if you just want to get region, filter the key with jq.

$ sudo yum install -y jq
$ curl --silent http://169.254.169.254/latest/dynamic/instance-identity/document | jq -r .region
ap-northeast-1

Usecase : set aws-cli's region

Even if you launch an EC2 instance with IAM role, you can't run commands without supplying region info. Otherwise, you'll encounter errors as follows.

$ aws ec2 describe-vpcs
You must specify a region. You can also configure your region by running "aws configure".

Here's how to set aws-cli's region.

First, check the curren settings.

$ aws configure  list
      Name                    Value             Type    Location
      ----                    -----             ----    --------
   profile                <not set>             None    None
access_key     ****************GVKA         iam-role
secret_key     ****************bll+         iam-role
    region                <not set>             None    None

region is not set.

Now pass metadata's region to aws configure set region command.

$ aws configure set region `curl --silent http://169.254.169.254/latest/dynamic/instance-identity/document | jq -r .region`
$ aws configure get region
ap-northeast-1
$ aws configure list
      Name                    Value             Type    Location
      ----                    -----             ----    --------
   profile                <not set>             None    None
access_key     ****************GVKA         iam-role
secret_key     ****************bll+         iam-role
    region           ap-northeast-1      config-file    ~/.aws/config
$ cat ~/.aws/config
[default]
region = ap-northeast-1

UserData

To configure API region, just add following code to you UserData.

#!/bin/bash
yum install -y jq
REGION=`curl -s http://169.254.169.254/latest/dynamic/instance-identity/document | jq .region -r`
sudo -u ec2-user aws configure set region $REGION
@tomislacker

This comment has been minimized.

Copy link

@tomislacker tomislacker commented May 17, 2016

I've also been frustrated by this and made myself a little native-Python workaround if someone else is interested: https://gist.github.com/tomislacker/da48e4023131a4ac8308b84fa6892b41

@yossale

This comment has been minimized.

Copy link

@yossale yossale commented Aug 6, 2017

Super useful! Thanks!

@georgechang0117

This comment has been minimized.

Copy link

@georgechang0117 georgechang0117 commented Aug 18, 2017

Yes. It's useful. Thank you!

@adv4000

This comment has been minimized.

Copy link

@adv4000 adv4000 commented Aug 18, 2017

AWSAVZONE='curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone'
will give you Avalability Zone

AWSREGION=${AWSAVZONE::-1}
will strip last character from Availability Zone, and this will be your Region

@mduca

This comment has been minimized.

Copy link

@mduca mduca commented Sep 6, 2017

This was helpful thank you!

@nestorbolivar

This comment has been minimized.

Copy link

@nestorbolivar nestorbolivar commented Jan 7, 2018

Cheers!!

I was Getting the Region from http://169.254.169.254/latest/meta-data/placement/availability-zone yet it's better to use curl --silent http://169.254.169.254/latest/dynamic/instance-identity/document | jq -r .region

@leonmax

This comment has been minimized.

Copy link

@leonmax leonmax commented Sep 27, 2018

in case you don't want to install jq:
curl -s http://169.254.169.254/latest/dynamic/instance-identity/document | grep region | cut -d" -f4

@SantoshKumarA

This comment has been minimized.

Copy link

@SantoshKumarA SantoshKumarA commented Oct 9, 2018

useful, thank you..

@carlosmarin

This comment has been minimized.

Copy link

@carlosmarin carlosmarin commented Feb 26, 2019

In case someone was looking for the Windows way, here's the powershell form:

  $availability_zone = invoke-restmethod -uri http://169.254.169.254/latest/meta-data/placement/availability-zone
  $region = $availability_zone.Substring(0,$availability_zone.Length-1)
@cc4i

This comment has been minimized.

Copy link

@cc4i cc4i commented Sep 10, 2019

Awesome!

@doublenns

This comment has been minimized.

Copy link

@doublenns doublenns commented Oct 18, 2019

I had to do the same thing recently, but for a completely different use case. Created a Python function that does the same thing:
https://gist.github.com/doublenns/7e3e4b72df4aaeccbeabf87ba767f44e

import requests
import sys
from requests.packages.urllib3 import Retry

def get_instance_region():
    instance_identity_url = "http://169.254.169.254/latest/dynamic/instance-identity/document"
    session = requests.Session()
    retries = Retry(total=3, backoff_factor=0.3)
    metadata_adapter = requests.adapters.HTTPAdapter(max_retries=retries)
    session.mount("http://169.254.169.254/", metadata_adapter)
    try:
        r = requests.get(instance_identity_url, timeout=(2, 5))
    except (requests.exceptions.ConnectTimeout, requests.exceptions.ConnectionError) as err:
        print("Connection to AWS EC2 Metadata timed out: " + str(err.__class__.__name__))
        print("Is this an EC2 instance? Is the AWS metadata endpoint blocked? (http://169.254.169.254/)")
        sys.exit(1)
    response_json = r.json()
    region = response_json.get("region")
    return(region)

From an EC2 instance:

>>> region = get_instance_region()
>>> print(region)
us-east-2

From system that isn't an EC2 instance:

>>> region = get_instance_region()
Connection to AWS EC2 Metadata timed out: ConnectTimeout
Is this an EC2 instance? Is the AWS metadata endpoint blocked? (http://169.254.169.254/) 
@kulswaroop

This comment has been minimized.

Copy link

@kulswaroop kulswaroop commented May 5, 2020

I had to do the same thing recently, but for a completely different use case. Created a Python function that does the same thing:
https://gist.github.com/doublenns/7e3e4b72df4aaeccbeabf87ba767f44e

import requests
import sys
from requests.packages.urllib3 import Retry

def get_instance_region():
    instance_identity_url = "http://169.254.169.254/latest/dynamic/instance-identity/document"
    session = requests.Session()
    retries = Retry(total=3, backoff_factor=0.3)
    metadata_adapter = requests.adapters.HTTPAdapter(max_retries=retries)
    session.mount("http://169.254.169.254/", metadata_adapter)
    try:
        r = requests.get(instance_identity_url, timeout=(2, 5))
    except (requests.exceptions.ConnectTimeout, requests.exceptions.ConnectionError) as err:
        print("Connection to AWS EC2 Metadata timed out: " + str(err.__class__.__name__))
        print("Is this an EC2 instance? Is the AWS metadata endpoint blocked? (http://169.254.169.254/)")
        sys.exit(1)
    response_json = r.json()
    region = response_json.get("region")
    return(region)

From an EC2 instance:

>>> region = get_instance_region()
>>> print(region)
us-east-2

From system that isn't an EC2 instance:

>>> region = get_instance_region()
Connection to AWS EC2 Metadata timed out: ConnectTimeout
Is this an EC2 instance? Is the AWS metadata endpoint blocked? (http://169.254.169.254/) 

Thanks, it helped!

@doublenns

This comment has been minimized.

Copy link

@doublenns doublenns commented Jul 9, 2020

Thanks, it helped!

Awesome. I'm glad!

@qingbozhou

This comment has been minimized.

Copy link

@qingbozhou qingbozhou commented Aug 19, 2020

Now AWS provides a more convenient way for getting the region: http://169.254.169.254/latest/meta-data/placement/region

See https://forums.aws.amazon.com/thread.jspa?threadID=77228

@jbenninghoff

This comment has been minimized.

Copy link

@jbenninghoff jbenninghoff commented Feb 17, 2021

There is a builtin command to get the ec2 metadata:
/opt/aws/bin/ec2-metadata -z
placement: us-west-2a

OR:

/opt/aws/bin/ec2-metadata -z |cut -d' ' -f2
us-west-2a

Many other options too, use --help to list them

@fadyWageehRack

This comment has been minimized.

Copy link

@fadyWageehRack fadyWageehRack commented Apr 18, 2021

In case someone was looking for the Windows way, here's the powershell form:

  $availability_zone = invoke-restmethod -uri http://169.254.169.254/latest/meta-data/placement/availability-zone
  $region = $availability_zone.Substring(0,$availability_zone.Length-1)

It can be easier and in one command:

Windows Powershell:
Invoke-RestMethod -uri http://169.254.169.254/latest/meta-data/placement/region

Linux:
curl -s http://169.254.169.254/latest/meta-data/placement/region

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment