EC2インスタンスのホストでいくつかのスクリプトを実行したいのですが、ホストが本当に EC2インスタンスであることを確認する方法がわかりません。
私はいくつかのテストを行いましたが、これは十分ではありません:
- バイナリーec2_userdataが使用可能であることをテストします(ただし、これは常に正しいとは限りません)
- 「http://169.254.169.254/latest/meta-data」の可用性をテストします(ただし、これは常に真実ですか?この「魔法のIP」とは何ですか?)
EC2インスタンスのホストでいくつかのスクリプトを実行したいのですが、ホストが本当に EC2インスタンスであることを確認する方法がわかりません。
私はいくつかのテストを行いましたが、これは十分ではありません:
回答:
実際、ホストがEC2インスタンスであるかどうかを検出する非常に簡単な方法があります。パブリックIPの逆ルックアップを確認してください。EC2の反転は見逃しがたいものです。
また、変更しなかった場合は、ホスト名を逆にして、見つけやすくする必要があります。
実際にEC2インスタンスタグを取得する標準的な方法であるため、先ほど説明した「マジカルIP」を使用することもできますが、EC2ネットワーク上にいない場合は、一般的にはタイムアウトになるまで待つ必要があります。望ましい...
これらの方法で十分でない場合は、IPのwhoisを実行し、Amazon EC2 IPブロック内にいるかどうかを確認してください。
編集:この小さなシェルビットを使用することができます:
#!/bin/bash
LOCAL_HOSTNAME=$(hostname -d)
if [[ ${LOCAL_HOSTNAME} =~ .*\.amazonaws\.com ]]
then
echo "This is an EC2 instance"
else
echo "This is not an EC2 instance, or a reverse-customized one"
fi
ただし、[[はバシズムです。PythonまたはPerlユニライン、YMMVを使用することもできます。
hostname -d
リターンeu-west-1.compute.internal
Hannesの回答を変更して、エラーメッセージを回避し、スクリプトでの使用例を含めました。
if [ -f /sys/hypervisor/uuid ] && [ `head -c 3 /sys/hypervisor/uuid` == ec2 ]; then
echo yes
else
echo no
fi
これは、Windowsインスタンスでは機能しません。カールに対する利点は、EC2と非EC2の両方で瞬時に近いことです。
ec2
-誤検知。その可能性は低く(256分の1の可能性)、そのファイルを取り込むハイパーバイザーを使用している場合のみです。上記のリンクのドキュメントに「おそらく EC2インスタンスを見ている」と書かれている理由です。
まず、既存の回答に関する次の微妙な問題のため、および@qwertzguyの回答に関する私のコメントについて質問を受けた後、新しい回答を投稿する必要があると感じました。現在の回答の問題は次のとおりです。
hostname -d
では、「amazonaws.com」が含まれているものではなく、内部DNSに使用されるのVPC名を取得します。)instance-data.ec2.internal
。私がテストしたばかりのUbuntu EC2 VPCインスタンス
$ curl http://instance-data.ec2.internal
curl: (6) Could not resolve host: instance-data.ec2.internal
では、このメソッドに依存するコードがEC2にないという誤った結論を下す原因となります。dmidecode
@tamaleからは動作しますが、あなたに依存していることがあります。)を有するdmidecode
、あなたのインスタンスで利用できると、b。)rootまたは持つsudo
あなたのコード内からパスワードなしの能力を。bios_version
の1.0
。このファイルはAmazonのドキュメントにはまったく記載されていませんので、私は実際にはそれに依存しません。whois
し、その結果を使用することは、いくつかのレベルで問題があります。その回答で提案されているURLは、現在404ページです!動作するサードパーティのサービスを見つけたとしても、(ローカルでファイルをチェックするのに比べて)比較的非常に遅く、レート制限の問題やネットワークの問題が発生する可能性があります。外部ネットワークアクセス。-m
か、--max-time
特にこのアドレスはどこにつながると(のようにハングアップすることが非EC2インスタンス上で、非常に長い時間のためにぶら下げ、それを避けるために、カールの引数を@藻類の答え)。また、(可能性のある)ファイルをチェックするというAmazonの文書化されたフォールバックについて誰も言及していないようです/sys/devices/virtual/dmi/id/product_uuid
。
EC2で実行しているかどうかを判断するのが非常に複雑になることを誰が知っていましたか?!リストされたアプローチの(ほとんどの)問題がリストされているので、EC2で実行しているかどうかを確認するための推奨bashスニペットを次に示します。これは、ほぼすべてのLinuxインスタンスで一般的に機能するはずだと思います。Windowsインスタンスは読者にとっての演習です。
#!/bin/bash
# This first, simple check will work for many older instance types.
if [ -f /sys/hypervisor/uuid ]; then
# File should be readable by non-root users.
if [ `head -c 3 /sys/hypervisor/uuid` == "ec2" ]; then
echo yes
else
echo no
fi
# This check will work on newer m5/c5 instances, but only if you have root!
elif [ -r /sys/devices/virtual/dmi/id/product_uuid ]; then
# If the file exists AND is readable by us, we can rely on it.
if [ `head -c 3 /sys/devices/virtual/dmi/id/product_uuid` == "EC2" ]; then
echo yes
else
echo no
fi
else
# Fallback check of http://169.254.169.254/. If we wanted to be REALLY
# authoritative, we could follow Amazon's suggestions for cryptographically
# verifying their signature, see here:
# https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html
# but this is almost certainly overkill for this purpose (and the above
# checks of "EC2" prefixes have a higher false positive potential, anyway).
if $(curl -s -m 5 http://169.254.169.254/latest/dynamic/instance-identity/document | grep -q availabilityZone) ; then
echo yes
else
echo no
fi
fi
明らかに、さらに多くのフォールバックチェックでこれを拡張し、たとえば/sys/hypervisor/uuid
偶然 "ec2"で始まる偶然の誤検出などの処理についての妄想を含めることができます。しかし、これは説明の目的のための十分なソリューションであり、おそらくほぼすべての非病理学的ユースケースです。
[†] c5 / m5インスタンスの変更に関するAWSサポートからのこの説明に戻りました。
C5およびM5インスタンスは新しいハイパーバイザースタックを使用し、他の/古いインスタンスタイプで使用される Xenドライバーが行うように、関連するカーネルドライバーはsysfs(/ sysにマウントされる)にファイルを作成しません。オペレーティングシステムがEC2インスタンスで実行されているかどうかを検出する最良の方法は、リンクしたドキュメントに記載されているさまざまな可能性を考慮することです。
elif
が、そのブロックの上のコメントが言っていることであり、それelif
が-r
テストがテスト演算子を使用する理由です。
IPではなくEC2内部ドメイン名でメタデータを探します。これにより、EC2を使用していない場合に高速DNSエラーが返され、IPの競合やルーティングの問題が回避されます。
curl -s http://instance-data.ec2.internal && echo "EC2 instance!" || echo "Non EC2 instance!"
一部のディストリビューションでは、非常に基本的なシステム、またはインストールの非常に早い段階でcurlを使用できません。代わりにwgetを使用します。
wget -q http://instance-data.ec2.internal && echo "EC2 instance!" || echo "Non EC2 instance!"
-bash: !": event not found
。echo
代わりに、これらのs に対して一重引用符を使用してください。
目標がEC2インスタンスか、googleのような別の種類のクラウドインスタンスかを判断することである場合、dmidecode
非常にうまく機能し、ネットワークは必要ありません。メタデータのURLパスがEC2とGCEで異なるため、このアプローチと他のアプローチのいくつかが好きです。
# From a google compute VM
$ sudo dmidecode -s bios-version
Google
# From an amazon ec2 VM
$ sudo dmidecode -s bios-version
4.2.amazon
1.0
-の言及はありませんamazon
。
ホスト名は変更される可能性が高いため、パブリックIPに対してwhoisを実行します。
if [[ ! -z $(whois $(curl -s shtuff.it/myip/short) | grep -i amazon) ]]; then
echo "I'm Amazon"
else
echo "I'm not Amazon"
fi
またはAWSメタデータURLをヒット
if [[ ! -z $(curl -s http://169.254.169.254/1.0/) ]]; then
echo "I'm Amazon"
else
echo "I'm not Amazon"
fi
これはec2のLinuxホストでもうまく機能し、ネットワークおよび関連するタイムアウトを必要としません。
grep -q amazon /sys/devices/virtual/dmi/id/bios_version
Amazonはこのエントリを次のように定義しているため、これは機能します。
$ cat /sys/devices/virtual/dmi/id/bios_version
4.2.amazon
1.0
。の言及はありませんamazon
。
test -f /sys/hypervisor/uuid -a `head -c 3 /sys/hypervisor/uuid` == ec2 && echo yes
しかし、これがディストリビューション間でどれほど移植性があるかはわかりません。
素早い回答:
if [[ -f /sys/devices/virtual/dmi/id/product_uuid ]] && \
grep -q "^EC2" /sys/devices/virtual/dmi/id/product_uuid
then
echo "IS EC2"
else
echo "NOT EC2"
fi
私はここに投稿された回答の1つを1年以上使用していましたが、新しい「c5」インスタンスタイプでは機能しません(現在「c4」からのアップグレードに取り組んでいます)。
このソリューションが好きなのは、将来的に壊れる可能性が最も低いと思われるからです。
古いインスタンスタイプと新しいインスタンスタイプでは、このファイルが存在し、「EC2」で始まります。VirtualBoxで実行されているUbuntuをチェックし(これもサポートする必要がある)、文字列「VirtualBox」が含まれています。
前のポスターに書かれているように(しかし見逃しがちだった)-これを行う方法に関するAmazonのドキュメントがあります-私の答えが含まれています。
https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/identify_ec2_instances.html
おそらく、「facter」を使用できます。
「Facterは、オペレーティングシステム、Linuxディストリビューション、MACアドレスなど、シンプルなオペレーティングシステムのファクトを取得するためのクロスプラットフォームライブラリです。」
http://www.puppetlabs.com/puppet/related-projects/facter/
たとえば、ec2ファクト(facter-1.6.12 / lib / facter / ec2.rb)を見てみると:
require 'facter/util/ec2'
require 'open-uri'
def metadata(id = "")
open("http://169.254.169.254/2008-02-01/meta-data/#{id||=''}").read.
split("\n").each do |o|
key = "#{id}#{o.gsub(/\=.*$/, '/')}"
if key[-1..-1] != '/'
value = open("http://169.254.169.254/2008-02-01/meta-data/#{key}").read.
split("\n")
symbol = "ec2_#{key.gsub(/\-|\//, '_')}".to_sym
Facter.add(symbol) { setcode { value.join(',') } }
else
metadata(key)
end
end
end
def userdata()
begin
value = open("http://169.254.169.254/2008-02-01/user-data/").read.split
Facter.add(:ec2_userdata) { setcode { value } }
rescue OpenURI::HTTPError
end
end
if (Facter::Util::EC2.has_euca_mac? || Facter::Util::EC2.has_openstack_mac? ||
Facter::Util::EC2.has_ec2_arp?) && Facter::Util::EC2.can_connect?
metadata
userdata
else
Facter.debug "Not an EC2 host"
end
このパーティーに少し遅れましたが、この投稿に出会い、AWSのドキュメントを見つけました。
EC2インスタンスを特定する決定的かつ暗号で検証された方法については、署名を含むインスタンスIDドキュメントを確認してください。これらのドキュメントは、ローカルのルーティング不可能なアドレスhttp://169.254.169.254/latest/dynamic/instance-identity/のすべてのEC2インスタンスで利用可能です
https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/identify_ec2_instances.html
もちろん、次のようにカールタイムアウトを設定できますが、これにはネットワークオーバーヘッドが必要です。
curl -s --connect-timeout 5 http://169.254.169.254/latest/dynamic/instance-identity/
これにより、タイムアウトが5秒に設定されます。