Ch3. Computing

EC2

インスタンスタイプ

EC2を起動するときは「インスタンスタイプ」というハードウェアの選択が必要になる。

インスタンスタイプには例えば「t2.micro」といった形式名がついていて、この名前がインスタンスのハードウェアの特徴を示している。

記号 説明
t インスタンスファミリ」を示す。cならコンピューティング・rはメモリが強化されている。tはパフォーマンスのバースト機能を備える。
2 世代」を表す。大きいものが新しい。また大きいものの方が高価とは限らない。
micro インスタンスサイズ」を示す。大きいものの方がスペックが高い。

f:id:Pyons:20210523153517p:plain
tx.microを比較したスペック表。世代が小さくても値段が高い場合がある。

インスタンスファミリはここで述べた他にも下記のようなものがある。

記号 説明
x メモリ強化(ただし通常はrを利用)
m 汎用(ただしtも汎用に含まれる)
p 高速コンピューティング(画像処理)
g 高速コンピューティング(機械学習
d ストレージ最適化(EBSとして高性能HDDが付属)
i ストレージ最適化(EBSとして高性能SSDが付属)

因みにEC2の本名は「Amazon Elastic Compute Colud」でここにもElasticの語がつく。

EBS

f:id:Pyons:20210523161547p:plain
EBSはインスタンスタイプの設定時に決定される。

インスタンスを設定すると必然的に「Elastic Block Store」というディスク機能が付属する。EBSは基本的にOSのローカルディスクとして認識される。 ただし実体としてはEC2インスタンスとは別個のものであり、EC2とのやり取りにはネットワーク越しのやり取りが生じている。

EC2↔EBS間の接続はEC2↔サブネット(IGW等)と同じように、帯域幅が消費される。そのためディスクのIOの処理が大量に走る場合、通常のネットワークの帯域幅が圧迫され期待したパフォーマンスが得られなくなる場合がある。

そこで「EBS最適化インスタンス」と呼ばれる、ネットワークによるトラフィックとディスクIOによるトラフィックを分離したサーバが用意されている。

EC2の利用料金と割引

オンデマンドインスタンス

インスタンスは起動中【Running】のステータスにあるものだけが課金対象となる。但し、後述するEC2にアタッチされたEBSは(たとえ停止中であっても)費用が発生する。このような費用形態のインスタンス

スポットインスタンス

AWSが余らせているコンピューティング能力をオークションで購入するシステム。インスタンスタイプごとに余っているコンピューティングを選択して入札できるが、他の利用者がオンデマンドインスタンスとして利用を開始し、余力がなくなった場合はコンピューティングが停止する。

リザーブインスタンス

長時間の利用をユーザが約束することで、通常より安くコンピューティングを利用できる。

スケジュールされたリザーブインスタンス

リザーブインスタンスのうち日付・利用時間を限定して予約する方法。

Compute Saving Plans と EC2 Instance Saving Plans

リザーブインスタンスと同じであるが、インスタンスタイプなどが更に柔軟に選べるようになった模様。詳細はよくわからないので深堀しない。

Compute Savings Plans – アマゾン ウェブ サービス

ELB

AWSはいろんな種類のインスタンスタイプを用意してくれているので、トラフィックの量が増加してもインスタンスタイプをグレードアップすることである程度までは対応可能である(スケールアップ)。 しかし、単一のインスタンスで全てのトラフィックを捌くこと自体【SPOF(Single Point of Failer)】となるので、好ましいアーキテクチャではない。

ロードバランサを噛ませて、複数のEC2インスタンストラフィックを捌く方法をスケールアウトと呼ぶ。AWSではマネージドサービスとしてロードバランサをサポートしていて「Elastic Load Balancing」と呼んでいる。

ロードバランシング自体のスケーリング

ELB以外の方法でロードバランシングを行う場合、複数のアプリケーションサーバの前にEC2インスタンスを置いてロードバランシング用の処理を担う、と言ったことが考えられる。しかし、その場合ロードバランシングに用いるEC2インスタンス自体のスケーリングを考えなくてはならない。

その点、ELBではロードバランシング処理自体は自動でスケーリングしてくれる。

だだし、そのスケーリング自体は急激には行われない点に注意する必要がある。「×:××のテレビでこのサイトが特集される」と言った事前に短期間でアクセスが集中する事象(スパイクと呼ぶ)がわかっている場合「ELBプレウォーミング」を申請して、事前にロードバランサの処理能力を高めておく必要がある。

ロードバランシングは大きく分けて2種類ある。

  • 【Application Load Balancer】HTTP/HTTPSリクエストを分散させる
  • 【Network Load Balancer】TCP/UDPリクエストを分散させる

ロードバランサにもヘルスチェック機能がある。

例えば「/index.htmlを2秒に1回、3回連続で接続失敗した場合はダウンとみなす」と言った設定が可能。「databasehelth.html」といった隠しファイルを持っておき、DBへのリクエストを送るように仕込んでおけば、DBのヘルスチェックも併せて行える。

Auto Scaling

ELBに紐付くインスタンスの数の最小・最大を事前に設定しておき、インスタンスの数を増やす(減らす)条件を設定しておくことでロードバランシングだけでなく「スケーリング」も自動化できる。

「CPUの使用率がX%を超えた時点で新しいインスタンスを立ち上げる」と言った設定をしておくことで、スパイクによる大量アクセスで商機を失うことも、大して処理していない無駄なインスタンスが【Running】状態となり続けてコストが無駄になる事もない。

なおELBに紐付くインスタンスの最小数を0以上にしておけば、ELBのヘルスチェックの結果を見て死んでいるインスタンスを切り離し新しいインスタンスを紐付けることが出来る。AutoScalingを利用して耐障害性を組み込むことが出来る。

スケーリングポリシーとしては以下のようなものがある。

  • 簡易スケーリング
  • ステップスケーリング
  • ターゲット追跡スケーリング

簡易スケーリングは非推奨となっているのでここでは割愛する。

ステップスケーリングは「CPUの使用率がn%以上でインスタンスを2個にスケールアウト、m%以上で4個にスケールアウト」と言った閾値を設定する。

ターゲット追跡スケーリングは更に指定が簡単で「全体のCPU使用率がn%になるように、インスタンスを適切な数にスケールアウトする」と言った指定の仕方になる。

スケーリングする上で、どのようにバロメータを監視するか・スケーリングする際にどういったイベントを発生させるか、と言ったオプションをAWSでは提供している。

  • 猶予期間
  • ウォームアップ
  • ライフサイクルフック
  • 終了ポリシー

なお、以上の4つはELB(ロードバランサ)の機能ではないことに留意する。 ロードバランサはトラフィックの適正な分散が目的であり、処理できるトラフィックの量をコントロールすることは役割ではない。

猶予期間

ELBに紐付くインスタンスの数を1以上にした場合、紐付いていたインスタンスのヘルスチェックに失敗すると新しいインスタンスが立ち上がるようになる。

しかし、インスタンスはすぐに利用可能になるわけではない。インスタンスが起動してもサーバーが立ち上がるまでにある程度ラグタイムがある。その間に再度ヘルスチェックが走った場合、(当然期待した結果が得られず)ヘルスチェックに再度失敗する。これに反応して新しいインスタンスを立ち上げてしまうと、必要以上にインスタンスが乱立してしまう恐れがある。

そこで、ヘルスチェックに失敗して新しいインスタンスが立ちあがるまでは、次のヘルスチェックを実施しないようインターバルを設けることが出来る。デフォルトは5分になっている。このインターバルのことを猶予期間と呼んでいる。

ウォームアップ

ステップスケーリングでインスタンスを追加している途中に、再度CPUの次の閾値を超えてしまうことがある。その際、追加中のインスタンスを考慮に入れないと余分なインスタンスを立ち上げてしまうことになる。

スケーリングによって間もなく立ち上がるインスタンスがパラメータを変化させることを考慮した調整をAWS AutoScalingでは「ウォームアップ」と呼んでいる。

ライフサイクルフック

AutoScalingによってインスタンスが削除・起動する際に、インスタンスへのデータの投入・削除時のログの退避などを設定できる。これを「ライフサイクルフック」と呼ぶ。

終了ポリシー

ここまでAutoScalingの最大の目的である「インスタンスの増減のさせ方」についてみてきたが、増減させるインスタンスの選び方についてもポリシーを設定できる。

デフォルトでは「(複数のAZ間に跨った)インスタンスによるロードバランシングとAutoScalingを行っている場合、各AZ間で同じ台数のインスタンスが稼働する」ようなインスタンスの削除ポリシーが設定されている。

この他「最も古い・新しいインスタンスを削除する」「インスタンスタイプごとに配分をユーザーが決定する」ポリシーなどが存在する。

ELBとAutoScalingを利用する際のアプリケーション設計

AutoScalingを利用するなら、当然インスタンスはステートレスに設計する必要がある(これがEBSにDBを立てたり、ファイルを保存したりしない最たる理由である)。

またAutoScalingによって複数のインスタンスを稼働させるなら、(AZ全体の障害に備えて)AZを跨いだスケーリング・ロードバランシングを検討すべきである。

ECS

AWS Elastic Container Serviceの略。

GCPのCloud Runを使った経験があるとやや考え方の違いに戸惑うが、ECSの特徴は

「Docker Platform(Docker Platform)」が走るEC2インスタンスを用意して、管理をサポートする。

点にある。 このEC2インスタンスのことを【Cluster】、コンテナのことを【Task】と呼んでいる。

クラスタに利用するEC2インスタンスは自分で決定する必要がある模様。EBSなどの設定も自分で決めるようだ。

f:id:Pyons:20210528163805p:plain
ECSのClusterの設定画面

【Task Definition】とはコンテナ定義書のことである。Docker Fileと同義化と思われたが、Dcoker Imageそのものを記述するDocker Fileに対して、Task DefinitionとはコンテナのIAMロールの設定や、一つのコンテナに許容するリソースの量などを決定する。【Task Definition】の中で利用するDocker Imageも設定するが、そのソースとなるのはECR(Elastic Container Registory)である。

f:id:Pyons:20210528164201p:plain
Task DefinitionとDocker file(Container Definition)の違い

一種類のコンテナを複数起動して、ロードバランシングさせたい、と言ったときは【Service】を利用する。 【Service】とは「一つのTask Definitionを利用して、複数のコンテナをCulster上の展開する」と言った定義を可能にしている。

またTaskごとのIAMが設定可能なので、「バッチサーバ(Task)には【SQS】への出力許可を・WEBサーバー(Task)にはSQSとS3への出力許可を与える」と言った利用方法が可能である。

AWS Fargate と EKS

ECSではClusterとなるEC2インスタンスの管理はユーザー側に任されていた。GCPのCloud Runのように、「コンテナをデプロイしたらそれ以上のインフラについて考えなくても良い」と言ったマネージドサービスも存在する。これがAWS Fargateである。これを利用していると、TaskにはCPUとメモリが自動で割り当てられ、それに応じた課金が行われる。

一方、コンテナオーケストレーションのためのk8sもマネージドサービスとして提供されている(EKS)。EKSなき時代にはculster間のコンテナオーケストレーションのために、新しいマスターインスタンスをたててk8sを走らせる必要があった。

Amazon lambda

サーバレスアーキテクチャの中核を担うサービスでソースコードの実行環境一式が提供される。

実行時の処理は【lambda関数】という名前で定義される。実行のトリガとしては

  • S3へのオブジェクト追加
  • HTTPSリクエス
  • Cloud Watch Eventで定義されたイベント

などがある。 lambdaの利用時には下記のことを設定する必要がある。

  • 割り当てるメモリ
  • タイムアウトまでに時間
  • IAMロール
  • VPCの中で実行するか・外で実行するか

lambdaの課金は

「割り当てたメモリ」量×実行時間×実行回数

で決定される。