先日のVPCに引き続き今度は個人的にEC2のあまり触ってなかったところを触っていきます。普段ElasticBeanstalkやOpsWorksをメインで触っている事もあって細かいところはあまり試してませんでした。やっぱり自分で触りながら疑問に思ったところをググったりすると理解がだいぶ深まりますね。
Elastic Network Interface(ENI)
プライベートIPアドレスを固定する
EC2インスタンスの生成時に指定することができます。簡単ですね。ただ、いずれにしろ特定のIPアドレスに依存する作りはあまり良くないのでRoute53を利用して名前解決できるようにしたほうが良いと思います。なのであまり使わないかな…。
複数のプライベートIPアドレスを利用する
上記のこの画面でセカンダリのIPアドレスを指定すると1つのENIで複数のプライベートなIPアドレスを持つことができます。もちろんあとからENI側の設定でもできます。追加したプライベートIPアドレスにEIPを紐付けると2種類のIPアドレスでインターネットアクセスができるようになります。
ちなみに下記の記事に書かれているようにOS側の設定が必要になります。
複数ENIをアタッチするとどうなるのか
ひとつのEC2インスタンスに複数のENIをアタッチする事ができます。ただ、問題がいろいろあるようでAWSの仕様上自動でパブリックなIPアドレスが振られなくなるようです。調べてるとルーティングの問題が発生しやすいので基本的にはやめましょうという事のようです。
EC2に複数のENIをアタッチする手順と制約(Public-ip,DNSが割当てられなくなる)
Elastic Block Store(EBS)
既存のEC2インスタンスにEBSを追加
EBSのメニューからボリュームを新規作成しEC2インスタンスにアタッチします。
最初はマウントされていません。OS側で処理が必要です。
# df -h ファイルシス サイズ 使用 残り 使用% マウント位置 /dev/xvda1 7.8G 1.1G 6.6G 15% / devtmpfs 490M 60K 490M 1% /dev tmpfs 498M 0 498M 0% /dev/shm
EBSボリュームをフォーマットしてマウントします。
# mkfs -t ext4 /dev/sdf mke2fs 1.42.12 (29-Aug-2014) Creating filesystem with 26214400 4k blocks and 6553600 inodes Filesystem UUID: 11c0c4c2-f508-432b-a626-60d7b1ad3fda Superblock backups stored on blocks: 32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 4096000, 7962624, 11239424, 20480000, 23887872 Allocating group tables: done Writing inode tables: done Creating journal (32768 blocks): done Writing superblocks and filesystem accounting information: done # mkdir /data2 # mount /dev/sdf /data2
正常にマウントされました。
# df -h ファイルシス サイズ 使用 残り 使用% マウント位置 /dev/xvda1 7.8G 1.1G 6.6G 15% / devtmpfs 490M 60K 490M 1% /dev tmpfs 498M 0 498M 0% /dev/shm /dev/xvdf 99G 60M 94G 1% /data2
再起動時もマウントが必要な場合はfstabの設定を行っておきます。
既存EC2インスタンスにEBSボリュームを追加(アタッチ)する
領域を拡張したい場合にどうするか?
追加ではなく拡張したい場合は、スナップショットを利用してボリュームを作成し直します。その際にEC2インスタンスは一旦止めておく必要があります。
Linux で EBS ボリュームのストレージ領域を拡張する
下記のような手順になります。
- EC2インスタンスをStopする
- 該当のボリュームのスナップショットを作成する
- スナップショットからより大きな領域を指定して新たにボリュームを作成する
- EC2インスタンスから古いボリュームをデタッチする
- 新しいボリュームを同じデバイス名でアタッチする
- EC2インスタンスを開始する
スナップショットのコピー
スナップショットはS3に格納されます。ただS3のメニューからどこにあるかは分からないようになっています。スナップショットのメニューからコピーで、複製したいさきのリージョンを選んでやることができます。
AMI
普段は基本的にAWSから提供されているプレーンなAMIに対してプロビジョニングツールを実行して環境構築するという運用をしています。なので個人的にはAMIを利用するのはプロビジョニングがうまくいかない場合への備えとしてのバックアップ用途くらいです。
仮想化方式の種類(hvm, paravirtual)
提供されているAMIを見てるとhvmとかparavirtualとか種類がある事に気づきます。これは仮想化方式の違いなんですが、対応している仮想化方式はAMIによって異なります。AMIによってどちらか一方をサポートするという事のようです。流れ的にはparavirtualが元々あってhvmが主流になってきているという感じのようです。
Amazon Linux AMI インスタンスタイプマトリックス
pravirtualは準仮想化方式で、hvmはhardware assisted VMの略で完全仮想化方式と呼ばれるそうです。下記の記事が詳しいです。
EC2はXenベースなんですね。paravitualとHVMではOSの起動シーケンスが違うようです。
HVM の場合、起動シーケンスは物理マシンに OS をインストールした場合と何ら変わりません。 ルートデバイスにあるブートローダから、デバイス内に含まれる kernel を起動していきます。
ちなみに調べてるとparavirtualからhvmへAMIを移行するという事も行われているようです。
すごい大変そうというか秘伝のタレすぎてそんなAMIずっと使い続けて大丈夫なんでしょうか。こういう仮想化方式にまで依存するのはどうかと思うのでChefやAnsibleで常に構成をプロビジョニングできるようにしておくと乗り換えも本当に楽だし安全だなと思いました。
EBSタイプとインスタンスストアタイプ
AMIによってサポートされているrootデバイスが異なります。インスタンスストアが元々あってEBSタイプのほうが新しいですがもうEBSが主流なのかな。下記の記事がとても分かりやすかったです。
AMIをEBSのスナップショットベースで作っているか、S3上にあるAMIイメージから生成しているかの違いのようです。大きな違いは選べるインスタンスタイプが違う(インスタンスストアはmicroより上)なのと、停止ができるか・できないかというところが大きいです。特に理由がなければEBSタイプにするのが良いようです。
また、中の人ではありませんが、『Amazon Cloudテクニカルガイド』の著者の方も、特に理由がなければEBSタイプのAMIをすすめるスタンスのようです。
EC2停めるとデータが消えるみたいな話はこのインスタンスストアが主流だった頃の話ですよね。また、上記の記事では下記のようにインスタンスストアの利点も挙げられていますが、
たとえば、もしあるリージョンがダウンした時、AMIを作成可能な最近のデータがS3に保存されていれば、それを元にAMIを作成して、インスタンスを立ち上げることが可能です。しかし、EBSスナップショットだけに頼っていると、そのリージョンにアクセスできない限り、インスタンスを作成し直すことができません。
異なるリージョンへはスナップショットをコピーできるのでこれも今は優位点にはならなさそうです。
スナップショットとの関係
AWSで下記の4つの概念の関係を明確に教えていただけないでしょうか?
AMIというのはInstanceを起動するためのHDD構成を記述した設定ファイルだと思えば良いと思います。SnapshotやVolumeと一緒に出てきますが、その外にあり、どのSnapshotを元にしたVolumeを繋げて起動するかが書いてあるモノです。
AMIを作るとスナップショットもいっしょに作られてるよなと思ってましたがそういうことなんですね。
IAMロール
アクセスキーとシークレットをEC2上にベタ書きしなくてもロールとしてEC2に権限を委譲し権限的にAWSのサービスへのアクセスを制御するための仕組みです。IAMロールはEC2じゃなくてもLambda等の他のサービスでもよく出てきますよね。ウィザードでそのまま適切なロールを自動で作ってくれるようになっているのであまりマニュアルで作成・設定したことがありませんでした。
[AWS] EC2インスタンスにIAMロールを適用して、S3へファイルアップロードする。
上記の記事にしたがって、ロールを作成の上EC2にSSHログインしてaws s3 ls
したら自分のバケットを参照する事ができました。EC2の場合AWSコマンドやAWS SDKで有効な機能なんですね。下記の記事も参考になります。
IAM Roleの仕組みを追う – なぜアクセスキーを明記する必要がないのか
上記の記事のように下記のコマンドでロール名から有効期限付きの一時的なクレデンシャルを取得する事ができます。コマンドやSDKはこういった仕組みを利用して権限を取得してAWSのサービスの操作を実行しているという事なんですね。
$ curl http://169.254.169.254/latest/meta-data/iam/security-credentials/ default-role $ curl http://169.254.169.254/latest/meta-data/iam/security-credentials/default-role { "Code" : "Success", "LastUpdated" : "2014-07-05T06:30:19Z", "Type" : "AWS-HMAC", "AccessKeyId" : "ASIAxxx...", "SecretAccessKey" : "xxxxx........", "Token" : "xxxxxxxxxxxxxxxxxxxxx...", "Expiration" : "2014-07-05T13:05:33Z" }
Auto Recovery
EC2のステータスチェック(システムステータスチェックおよびインスタンスステータスチェック)の異変時にCloudWatchの機能であるEC2アクションによってEC2の再起動を行う機能です。2015年の新機能のようですが以前はインスタンスの停止や削除しか行えなかったようです。
アプリケーション層でのチェックではなく、AWS環境のシステムチェックなのでELBのヘルスチェックのような用途では使えません。
新機能】EC2 Cloudwatchの新機能「Auto Recovery」を使ってみた
上記の記事だとCloudWatchの画面からEC2アクションを指定していましたが今はEC2の画面内で再起動のEC2アクションを指定したアラートが作れるようです。ステータスチェックの詳細については下記が詳しいです。
システムステータスのチェックはAWS側のハードウェアやネットワークが原因になりますが、インスタンスステータスのチェックは下記のようなものが原因となるようです。
- 失敗したシステムステータスチェック
- 正しくないネットワークまたは起動設定
- メモリの枯渇
- 破損したファイルシステム
- 互換性のないカーネル
Run Command
EC2でシェルコマンドやスクリプトを実行する機能です。単体のEC2インスタンスだけでなく複数のEC2インスタンスに対して処理実行することができます。OpsWorksでレシピを実行するのに少し似てますね。こちらのRun Commandはamazon-ssm-agent
というエージェントをEC2インスタンスに事前に入れておく必要があります。
EC2 Run Commandアップデート – Linuxインスタンスで利用可能に
下記の記事を見ると動画付きでどのように実行できるか見ることができます。
EC2 Run CommandがLinux対応したので簡易実行コマンドを作ってみた
用途としてはOpsWorks等を使っていない環境でEC2インスタンスが多くなってきた時にパッチをあてたりルーチン(ユーザー追加・削除等)を自動化したりするのに便利だと思います。OpsWorks使ってる人は使う必要ないと思います。
ユーザーデータとインスタンスメタデータ
マニュアルにそのままのページがあります。
ユーザーデータ
EC2インスタンスの生成時に指定できるデータです。下記のようにテキストかファイルの形式で入力できます。
指定したものはEC2インスタンスにSSHログインしてるとcurl http://169.254.169.254/latest/user-data/
で取得する事ができます。テキストデータは普通のテキストとして取得できますしバイナリデータもやってみたらいけました(但しサイズ上限は16KB)。
EBSタイプのEC2の場合はStopしてから「ユーザーデータの表示/変更」から変更を加える事ができます。
ちなみに169.254.169.254
っていつも忘れちゃうので良い語呂合わせないのかなと思ってます。「いちろーくん、2個読む」というのを無理やり今考えました。。
インスタンスメタデータ
EC2インスタンスのメタデータ情報です。http://169.254.169.254/latest/meta-data
から取得することができます。基本的な情報は全て取得することができます。
$ curl http://169.254.169.254/latest/meta-data/ ami-id ami-launch-index ami-manifest-path block-device-mapping/ hostname instance-action instance-id instance-type kernel-id local-hostname local-ipv4 mac network/ placement/ public-hostname public-ipv4 public-keys/ reservation-id security-groups services/
動的データ
http://169.254.169.254/latest/dynamic
から取得することができるインスタンス・アイデンティティの情報です。
インスタンスが起動するときにインスタンスアイデンティティドキュメントが生成され、インスタンスメタデータを通じてインスタンスに公開されます。このドキュメントは、サブスクライブしたソフトウェア、インスタンスサイズ、インスタンスタイプ、オペレーティングシステム、AMI など、インスタンスの属性を検証します。
入っているのはインスタンスの情報及びその署名なので、情報の正当性が必要になる時に利用するのかな。
起動時のコマンド実行
シェルスクリプトあるいはcloud-initディレクティブを利用することでEC2起動時に任意の処理を実行することができます。いずれもユーザーデータに記述する事で実現します。
シェルスクリプトの場合は単純に#!/bin/bash
からユーザーデータを始めれば以降はシェルスクリプトとして実行されます。
#!/bin/bash yum update -y yum install -y httpd24 php56 mysql55-server php56-mysqlnd service httpd start chkconfig httpd on groupadd www usermod -a -G www ec2-user chown -R root:www /var/www chmod 2775 /var/www find /var/www -type d -exec chmod 2775 {} + find /var/www -type f -exec chmod 0664 {} + echo "<?php phpinfo(); ?>" > /var/www/html/phpinfo.php
cloud-initディレクティブの場合は下記のような形で記述します。packages
でyumインストールができるので記述がより宣言的で良いですね。
#cloud-config repo_update: true repo_upgrade: all packages: - httpd24 - php56 - mysql55 - server - php56-mysqlnd runcmd: - service httpd start - chkconfig httpd on - groupadd www - [ sh, -c, "usermod -a -G www ec2-user" ] - [ sh, -c, "chown -R root:www /var/www" ] - chmod 2775 /var/www - [ find, /var/www, -type, d, -exec, chmod, 2775, {}, + ] - [ find, /var/www, -type, f, -exec, chmod, 0664, {}, + ] - [ sh, -c, 'echo "<?php phpinfo(); ?>" > /var/www/html/phpinfo.php' ]
ところでこのcloud-initディレクティブってElasticBeanstalkのebextensionsの構文にすごく似てますね。試しにcommands
等のElasticBeanstalkで使われるディレクティブを使ってみたんでしたが無視されました。あれはやはりElasticBeanstalkを使った時だけの独自拡張なのかな。
シェルスクリプトの場合もcloud-initディレクティブの場合もログは/var/log/cloud-init-output.log
で確認することができます。
プレイスメントグループ
同じアベイラビリティゾーンの中で複数のEC2インスタンスを論理的にグルーピングする事ができ、プレイスメントグループにあるEC2インスタンスは10Gbpsネットワークが利用できるようになるというオプションです。
低レイテンシが必要だったりネットワークのスループットが必要なアプリケーションだと使いたいオプションですね。設定の仕方はとても簡単でプレイスメントグループを作成し(名前しか入力がありません)、EC2インスンタンス生成時にプレイスメントグループを指定するだけです。ただし利用できるEC2インスタンスは限定されていて現時点だと下記になります。
汎用: m4.large | m4.xlarge | m4.2xlarge | m4.4xlarge | m4.10xlarge コンピューティングを最適化: c4.large | c4.xlarge | c4.2xlarge | c4.4xlarge | c4.8xlarge | c3.large | c3.xlarge | c3.2xlarge | c3.4xlarge | c3.8xlarge | cc2.8xlarge メモリを最適化: cr1.8xlarge | r3.large | r3.xlarge | r3.2xlarge | r3.4xlarge | r3.8xlarge ストレージを最適化: d2.xlarge | d2.2xlarge | d2.4xlarge | d2.8xlarge | hi1.4xlarge | hs1.8xlarge | i2.xlarge | i2.2xlarge | i2.4xlarge | i2.8xlarge GPU: cg1.4xlarge | g2.2xlarge | g2.8xlarge
さらに10Gbsをサポートするインスタンスは限られているようなので、ネットワーク速度に拘ろうとするとさらに高価なインスタンスが必要になります。
Auto Scaling
Auto ScalingはElasticBeanstalkを通してよく使っていたんですが、素のEC2のメニューから作成した事がなかったので試してみます。概要や手順は下記のブログがイラスト付きでとても分かりやすかったです。
Amazon EC2でオートスケーリングを行う方法 – 技術の犬小屋
起動設定
Auto Scalingで利用されるEC2の設定(AMI、ストレージ、セキュリティグループ等)です。設定はEC2インスタンスの生成時ととても似ていますが、カーネルIDやRAMディスクID等を設定することができるようです。AMIを作っても良いですがユーザーデータも指定できるので簡単なものだったらスクリプト等でインストールしてしまっても良いですね。
Auto Scalingグループ
起動設定を作ったら次にAuto Scalingグループを作成します。
作成する際に最初の「高度な詳細」の欄で、ELBを使うか使う場合はヘルスチェックをELBにするかEC2にするかが聞かれます(デフォルトだとEC2になります)。ELBを使うとELBのヘルスチェック(HTTP等)が使えるのでアプリケーションレベルでヘルスチェックができます。ヘルスチェックがEC2の場合だとAuto Recoveryのところで見たヘルスチェックと同じでサーバーインスタンスレベルになります。
希望のインスタンス数とは?
Auto Scalingグループを作成する際には出てこない項目なんですが、作成後Auto Scalingグループを参照すると項目として表示されているはずです。これ詳しいことは分からないんですが設定値でもあり、かつスケーリングポリシーによって動的に変更される値でもあるようです。
What “desired instances” is needed for? AWS Amazon Webservices AutoScaling group
たとえば最初1だった希望の値が負荷をかけて試していくとたとえば2などに値が変更されます。これはスケーリングポリシーによってインスタンスの数を増やそうとし希望の値が書き変わるようです。逆もしかりで負荷がない場合などはスケーリングポリシーによって-1などされます。マニュアルで希望の値を書き換えてもそのようにインスタンス数が自動で調整されるようです。
スケジュールされたアクション
日時設定(Cron形式, 5分毎, 毎週等)でアクションを実行し最小、最大、希望のインスタンス数を変更する事ができるようです。
終了ポリシー
スケールインする際の動作(どのインスタンスを破棄するか)についてです。デフォルトだと下記の動作をします。
- Auto Scaling は、複数のアベイラビリティーゾーンにインスタンスがあるかどうかを判断します。該当する場合、インスタンスが最も多く、スケールインから保護されていないインスタンスが最低 1 つあるアベイラビリティーゾーンを選択します。複数のアベイラビリティーゾーンでこのインスタンス数が同じである場合、最も古い起動設定を使用するインスタンスのあるアベイラビリティーゾーンを Auto Scaling は選択します。
- Auto Scaling は、選択したアベイラビリティーゾーンで、保護されていないどのインスタンスが最も古い起動設定を使用しているかを判断します。このようなインスタンスが 1 つある場合、そのインスタンスを終了します。
- 最も古い起動設定を使用するインスタンスが複数ある場合、Auto Scaling は次の課金時間に最も近い保護されていないインスタンスを判断します(これによって、Amazon EC2 の使用に対して課金される時間数を最小限に抑えながら、EC2 インスタンスの使用を最大化することができます)。このようなインスタンスが 1 つある場合、Auto Scaling はそのインスタンスを終了します。
- 次の課金時間に最も近い保護されていないインスタンスが複数ある場合、Auto Scaling はこれらのインスタンスのいずれかをランダムに選択します。
スケールイン時に Auto Scaling がどのインスタンスを終了するかを制御する
カスタマイズも可能です。
インスタンスの保護
スケールインの是非の設定です。Auto ScalingグループそのものとAuto Scalingグループに含まれる個別のEC2インスタンスに設定することができます。
スケールアウト/スケールインのテスト
CPU負荷でスケーリングポリシーを使っている場合は下記の方法でCPU負荷を上げるのがお手軽です。
$ yes > /dev/null
上記のコマンドでCPU100%になります。しばらくすると新しいEC2インスタンスが生成されます。yesコマンドを止めてしばらく待ってればスケーリングポリシーが適用されてインスタンス数が減るはずです。今回は待てなかったのでスケーリングポリシーのタブメニューからDecrease Group Sizeを実行しました。
リカバリーのテスト
ELBを使ってヘルスチェックタイプをELBにした場合は、httpd等のELBのヘルスチェックを受けているプロセスを停止すると、まずELBからそのインスタンスが外れAuto Scalingの設定的にその時最低のインスタンス数に満たなければ新たにEC2インスタンスが起動設定から生成されELBから外れたEC2インスタンスは削除されます。
ヘルスチェックタイプにEC2を使ってる場合は、EC2を停めるとELBの場合と同じように新たにEC2インスタンスが起動設定から生成され停止したEC2インスタンスは削除されます。
VM Import/Export
VMware等の仮想マシンイメージからのEC2へのインポートあるいはその逆のエクスポートができる。
VMImportでVMware仮想マシンイメージをEC2インスタンスとしてインポートする
Google Compute Platformにもインポートできる模様。