doptimusprime
doptimusprime

Reputation: 9415

Detect Cloud Type in VM

In a solution, we are planning multiple clouds (AWS, Azure and GCP) as a solution. Same code will be deployed in multiple VMs running in different clouds.

In many cases, we need to detect cloud and write the code accordingly. e.g. Use AWS S3 SDK when running on AWS and Azure Blob SDK when running on Azure.

In AWS, we can hit metadata URL to detect (http://169.254.169.254/latest/meta-data/) if it is AWS.

I am wondering if there is any way to detect the cloud provider inside the VM (like through environment variables or metadata URL or any other way).

Preferred code can be in python or a shell script.

Upvotes: 2

Views: 1341

Answers (2)

Slava
Slava

Reputation: 743

We may consider multiple ways to identify current Cloud relying to the instance metadata

  1. Cloud-init
  2. Metadata base URL
  3. Metadata specific item
  4. Custom Tag/Metadata

Cloud-init

#! /bin/bash

# cloud-name, cloud_name, cloud_id, platform
cloud=$(cloud-init query cloud-name)

case ${cloud} in
  aws)   echo "AWS Cloud"     ;;
  azure) echo "Azure Cloud"   ;;
  gce)   echo "GCP Cloud"     ;;
  *)     echo "Unknown Cloud" ;;
esac

Metadata base URL

#! /bin/bash

# set -x -e

# AWS Cloud
token=$(curl -X PUT -s -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" http://169.254.169.254/latest/api/token)
status=$(curl -s -o /dev/null -w "%{http_code}" -H "X-aws-ec2-metadata-token: ${token}" http://169.254.169.254/latest/meta-data/)
[[ "${status}" -eq 200 ]] && cloud="aws"

# Azure Cloud
status=$(curl -s -o /dev/null -w "%{http_code}" -H "Metadata: true" --noproxy "*" "http://169.254.169.254/metadata?api-version=2021-02-01&format=text")
[[ "${status}" -eq 200 ]] && cloud="azure"

# GCP Cloud
status=$(curl -s -o /dev/null -w "%{http_code}" -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/ || true)
[[ "${status}" -eq 200 ]] && cloud="gcp"

echo $cloud

Custom Tag/Metadata

For this example, we should set Tag Cloud=aws on AWS, Cloud=azure on Azure and Metadata Cloud=gcp for GCP at instances creation.

#! /bin/bash

# set -x -e

# AWS Cloud
token=$(curl -X PUT -s -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" http://169.254.169.254/latest/api/token)
cloud_tag=$(curl -s -H "X-aws-ec2-metadata-token: ${token}" http://169.254.169.254/latest/meta-data/tags/instance/Cloud)
[[ "${cloud_tag}" == "aws" ]] && cloud="aws"

# Azure Cloud
cloud_tag=$(curl -s -H "Metadata: true" --noproxy "*" "http://169.254.169.254/metadata/instance/compute/tags?api-version=2021-02-01&format=text" | awk -F ';|Cloud:' '/Cloud/ {print $2}')
[[ "${cloud_tag}" == "azure" ]] && cloud="azure"

# GCP Cloud
cloud_tag=$(curl -s -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/attributes/Cloud || true)
[[ "${cloud_tag}" == "gcp" ]] && cloud="gcp"

echo $cloud

Additional information

  1. AWS - Instance metadata and user data
  2. Azure Instance Metadata Service
  3. GCP - Access VM metadata
  4. Cloud-init - Instance metadata

Upvotes: 3

Related Questions