AWS初心者による、SAA取得に向けた学習の記録③

※記事について著作権等で問題がありましたら、お手数ですがコメントいただけると幸いです。<br>早急に修正か、必要に応じて記事を削除いたします。

[AWS初心者による、SAA取得に向けた学習の記録②](https://qiita.com/t17_hr/items/e8d6d6e97b8b7487a5a4) の続きです。

関連記事はこちらからどうぞ。

* [AWS初心者による、SAA取得に向けた学習の記録①](https://qiita.com/t17_hr/items/106838afc10a54eea3f0)
* [AWS初心者による、SAA取得に向けた学習の記録②](https://qiita.com/t17_hr/items/e8d6d6e97b8b7487a5a4)
* AWS初心者による、SAA取得に向けた学習の記録③
* [AWS初心者による、SAA取得に向けた学習の記録④](https://qiita.com/t17_hr/items/f35cb0e313fd7863afb6)
* [AWS初心者による、SAA取得に向けた学習の記録⑤](https://qiita.com/t17_hr/items/ce20a44f1c586c145da3)
* [AWS初心者による、SAA取得に向けた学習の記録⑥](https://qiita.com/t17_hr/items/cbdc5c053a7bf63fa2a6)

今回は

* EC2
* ECS
* Lambda

についての内容となります。

※参考書籍
[AWS認定資格試験テキスト AWS認定ソリューションアーキテクト・アソシエイト 改訂版第2段](https://www.amazon.co.jp/dp/B08MVXRFFN?
tag=maftracking339397-22&linkCode=ure&creative=6339) 

# EC2

**EC2** は、仮想サーバーを提供するコンピューティングサービスです。

ELB(Elastic Load Balancing)やAuto Scalingといったサービスと組み合わせることで、不可に応じて動的にサーバーの台数を変更することが可能になり、
柔軟にインフラリソースを最適化することができます。

## 性能についての考え方

EC2では **インスタンスタイプ** という形で、インスタンスのスペックを選択します。

アルファベット部分が **インスタンスファミリー** と呼ばれ、最適化しているものを表しています。
数字の部分が世代を表し、大きいものが最新になります。

例）

* コンピューティング重視：c5、c4
* メモリ重視：r5、r4


また、後の章で紹介される **EBS(Elastic Block Store)** は、EC2インスタンスの性能を決める重要な要因であるディスク機能になるようです。

EC2では通常の通信で使用するネットワーク帯域と、EBSとのやり取りで利用する帯域を共有しているため
帯域が不足してしまうことがあります。

その際に利用できるオプションが **EBS最適化インスタンス** です。
これによってEBS用の帯域が確保されるため、ディスクI/Oが増えても外部との通信に影響が出なくなります。

## EC2における費用の考え方

EC2は従量課金型のサービスで、

* インスタンスがRunning(起動中)状態だった時間
* Running状態だったインスタンスのインスタンスタイプ、AMI、起動リージョン

によって決まります。

EC2の状態は以下の３つがあります。

* 起動中(Running)
* 停止中(Stopped)
* 削除済み(Terminated)

（ちなみに、停止中のインスタンスでもEBSの費用はかかります）

## スポットインスタンスとリザーブドインスタンス

先述した、従量課金制の利用形態のことを **オンデマンドインスタンス** と呼びますが、

これ以外に **スポットインスタンス** と **リザーブドインスタンス** があります。

### スポットインスタンス

* AWSが余らせているEC2リソースを入札形式で安く利用する方式
* 余剰なリソースが無くなるとインスタンスが自動で中断
* 一時的にスペックの大きいインスタンスを使いたい場合に便利

### リザーブドインスタンス

* 長期契約によって割引を受けられる利用方式
* サービス開始後にインスタンスタイプの固定ができると判断した際の利用がおすすめ

## インスタンスの分類と用途

インスタンスタイプの分類と最適化要素、それぞれのインスタンスファミリーの例については以下の５つになります。

* 汎用　　　　　　　　　　　：CPUとメモリのバランス型（M5、T3）
* コンピューティング最適化　：CPUの性能（C5など、C系のみ）
* メモリ最適化　　　　　　　：メモリ容量（R5、X1、メインはR系）
* 高速コンピューティング　　：GPUなど、CPU以外の計算リソース（画像処理用のP系、機械学習用のG系）
* ストレージ最適化　　　　　：ストレージ（HDDを利用するD2、SSDを利用するI3）

# ELB

リリースしたサービスの人気が出て負荷が上がった場合、インスタンス（マシン）のスペック自体を上げる対応が **スケールアップ** です。

しかしスケールアップには限界があります。

そこで登場するのが、マシンを水平展開する **スケールアウト** です。
複数並べたEC2インスタンスの前段にロードバランサ―を配置し、リクエストを分散させます。

## ELBの種類

* Classic Load Balancer（CLB）：L4、L7レイヤーでの負荷分散を行う。
* Application Load Balancer（ALB）：L7レイヤーで負荷分散を行う。CLBより後に登場し、機能が豊富に提供されている。
 * WebSocketやHTTP/2に対応
 * URLパターンによって振り分けが可能なパスベースルーティング機能
* Network Load Balancer（NLB）：L4レイヤーでの負荷分散を行う。HTTP（S）以外のプロトコル通信の負荷分散に使用。
 * ロードバランサ―自体が固定のIPアドレスを保持

## ELBの特徴

* ELB自体のスケーリング機能
* ヘルスチェック機能

### ELB自体のスケーリング機能

* EC2インスタンス上にロードバランサ―を導入した場合、そのインスタンスがボトルネックにならないよう設計する必要がある
* ELBを使用した場合、負荷に応じて自動的にスケール

### ヘルスチェック機能

設定された間隔でELB配下にあるEC2にリクエストを送り、各インスタンスが正常に動作しているか確認します。

異常なインスタンスが見つかった場合は自動的に切り離し、その後正常になったタイミングで再度ELBにインスタンスを紐付けます。

以下、ヘルスチェックの設定値です。

* 対象のファイル（例：/index.html）
* ヘルスチェックの間隔（例：30秒）
* 何回連続でリクエストが失敗した場合にインスタンスを切り離すか（例：3回）
* 何回連続でリクエストが成功した場合にインスタンスを紐付けるか（例：5回）

![ヘルスチェック.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1021235/bb0cd7a9-9a0e-e0ca-42b2-746a2962beed.jpeg)

画像引用元：[ELBとHeartbeatでアクティブ/スタンバイ構成](https://cloudpack.media/494)


# Auto Scaling

**Auto Scaling** は システムの利用状況に応じて、自動的にELBに紐付くインスタンスの台数を増減させる機能です。

以下の項目を設定することで、自動的なスケールアウト/スケールインを実現します。

* 最小のインスタンス数
* 最大のインスタンス数
* インスタンスの数を増やす条件と増やす数（例：CPU使用率が80%を超えたら2台増やす）
* インスタンスの数を減らす条件と減らす数（例：CPU使用率が40%を割ったら2台減らす）

インスタンス数を減らす際、どのインスタンスから削除するか（起動時間が最も過去の古いインスタンスから削除）といった設定も可能です。

Auto Scalingによって「リソースの最適化」「耐障害性の向上」につながります。

![AutoScaling.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1021235/1cbb366d-e2ec-9507-2b5a-d2b939351d76.png)

画像引用元：[1年で4億UUを解析したKARTEを支えるAutoscaling 3パターン](https://tech.plaid.co.jp/autoscaling-ec2/)

## Auto Scalingのスケーリングポリシー

* 動的なスケーリング
* 予測スケーリング
* スケジュールスケーリング

頻繁に利用される動的なスケーリングには、更に3つのスケーリングポリシーがあります。

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

### 簡易スケーリング

* CPU使用率が70%を超えたら、といったように **1つのメトリクスに対して1つの閾値** を設定
* 最初からあるスケーリング方式で、現在は非推奨 
* 次で紹介する **ステップスケーリング** で代用可能

### ステップスケーリング

* CPU使用率が50%を超えた場合、60%を超えた場合と、**1つのメトリクスに対して複数の閾値** を設定
* 段階ごとの設定が可能
* 1つのみでも可能

### ターゲット追跡スケーリング

* CPU使用率を50%に、といったように **1つのメトリクスに対して目標値** を設定
* Auto Scalingグループ全体でこれが維持されるように自動で調整
* これから主流になるポリシー

## スケールアウトの猶予期間とウォームアップ・クールダウン

Auto Scalingによるインスタンスの立ち上がり中に、新たなインスタンスが立ち上がることを抑止する必要があり、
それらの機能が **スケールアウトの猶予期間とウォームアップ・クールダウン** になります。

### 猶予期間

* インスタンスの起動時間を考慮すると、すぐに利用可能状態になるわけではない
* その間にヘルスチェックでエラーが出続けると想定したスケーリング動作にならない
* これを防ぐために、一定期間ヘルスチェックをしない猶予期間がある
* 画面コンソールから作成した場合はデフォルトが300秒、CLIやSDKから作成した場合のデフォルトは0秒

### ウォームアップとクールダウン

* クールダウン（正式名称はスケーリングクールダウン）
 * Auto Scalingが発動した直後、追加でインスタンスの増減がなされることを防ぐ設定
 * 猶予期間はヘルスチェックの猶予であり、クールダウンはインスタンス増減アクションに対してのパラメータ
 * 現在では、クールダウンは主に簡易スケーリングのための設定として使用されている
 * それ以外のスケーリングポリシーの場合は、デフォルト設定のままで調整する必要なし
 * ステップスケーリングの場合、メトリクスに対して複数の閾値が設定でき、スケーリング動作中に別の閾値に達した場合はクールダウンと関係なく反応するようになっている

* ウォームアップ
 * ステップスケーリングにおいて差分インスタンスを追加するための機能
 * ウォームアップ期間中には、そのアラームでのインスタンス追加はされない
 * ウォームアップ期間中に次のアラートが発動した場合、差分の台数が追加される
 * ステップスケーリングとターゲット追跡スケーリングに対応

![Scaling.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1021235/8a2b85f8-2380-0e57-a321-4eb0cf47cdbf.png)

画像引用元：[Auto Scalingの段階スケーリングポリシーについて](https://dev.classmethod.jp/articles/auto-scaling-steps/)

## その他のAuto Scalingオプション

### ライフサイクルフック

Auto Scalingグループによるインスタンスの起動時または削除時に、インスタンスを一時停止してカスタムアクションを実行する機能です。
待機時間はデフォルトで1時間、最大48時間まで設定可能になります。

例）

* 起動時のデータ取得
* 削除時のログやデータ退避

![ライフサイクルフック.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1021235/26476daf-c5b2-a97e-b1a4-e4273725b8ba.png)

画像引用元：[Amazon EC2 Auto Scaling ライフサイクルフック](https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/lifecycle-hooks.html)


### 終了ポリシー

負荷に応じてインスタンスを増やすことをスケールアウト、負荷が下がってインスタンスを減らす場合は **スケールイン** といいます。
スケールインの際に削除するインスタンスを決めるのが **終了ポリシー** です。

デフォルトでは、インスタンスがアベイラビリティゾーンに均等に配分されるように削除します。

* 終了ポリシー
 * OldestInstance：最も古いインスタンスを削除
 * NewestInstance：最も新しいインスタンスを削除
 * OldestLaunchConfiguration：最も古い起動設定のインスタンスを削除
 * ClosestToNextInstanceHour：次の課金時間に最も近いインスタンスを削除
 * Default：AZ間の台数の均衡を保つようにインスタンスを削除
 * OldestLaunchTemplate：最も古い起動テンプレートを使用するインスタンスを削除
 * AllocationStrategy：スポットまたはオンデマンドなどのインスタンスタイプの配分戦略に沿って削除

<br>
スケーリングポリシーやスケールアウトの猶予期間・ウォームアップ・クールダウン・終了ポリシーは、
ELBの機能ではなくAuto Scalingの機能です。

# ECS

**ECS（Elastic Container Service）** はDockerコンテナの実行環境を提供するサービスです。

このサービスが登場するまで、AWSでDockerを使用するにはEC2上にコンテナ管理用のソフトウェアを導入する必要がありましたが、
これにより導入作業や継続的なメンテナンスの必要が無くなります。

## ECSの特徴

* Task：EC2インスタンス上で実行されるコンテナ
* Cluster：Task（コンテナ）を起動するEC2インスタンス
 * 1つのCluster上で複数のTaskを実行可能
* Task Definition：Cluster上で起動するTaskの定義（Dockerイメージのようなもの）
 * Taskの役割ごとに用意し、それを基にCluster上でTaskが起動する
* Service：「WebサーバーTaskを複数作成しELBに紐付ける」といったような、同じTaskを複数用意する場合に用いる
 * Webサーバー用のTask DefinitionでTaskを4つ起動する、といった指定が可能
 * Taskの更新をブルーグリーンデプロイメントで行うことが可能
* TaskごとにIAMロールの割り当てが可能
 * EC2の場合はIAMロールをインスタンス単位でしか割り当てができない
 * ECSでは同じCluster上で起動するTaskごとに別のIAMロールを付与することが可能
 * 例）Webサーバー用のTaskにはSQS（Simple Queue Service）へのSendMessage権限のみを付与し、<br>同じCluster上で動くバッチサーバーTaskには、SQSからのReceiveMessageとS3からのGetObjectの権限のみを付与する

※ブルーグリーンデプロイメントとは、
現状の本番環境（ブルー）とは別に新しい本番環境（グリーン）を構築した上で、ロードバランサーの接続先を切り替えるなどして新しい本番環境をリリースする運用方法のこと

引用元：[3分でわかる ブルーグリーンデプロイメント](https://xtech.nikkei.com/atcl/nxt/keyword/18/00002/070800077/#:~:text=%E3%83%96%E3%83%AB%E3%83%BC%E3%82%B0%E3%83%AA%E3%83%BC%E3%83%B3%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%83%A1%E3%83%B3%E3%83%88%E3%81%A8%E3%81%AF,%E3%81%93%E3%81%AE%E9%81%8B%E7%94%A8%E3%82%92%E6%8E%A1%E7%94%A8%E3%81%99%E3%82%8B%E3%80%82)


![ECS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1021235/b3dc7dd2-2a1f-7cd7-1d7c-0e8cfc4b9de2.png)

画像引用元：[Amazon ECS タスク定義の"タスクサイズのCPU"と”コンテナのCPUユニット”の違いを調べてみた](https://nopipi.hatenablog.com/entry/2020/12/13/223713)


## AWSにおけるその他のコンテナサービス

* AWS Fargate
* EKS（Amazon Elastic Container Service for Kubernetes）
* ECR（Amazon Elastic Registry）

### AWS Fargate

* EC2ではCluster用のEC2インスタンスが必要なため、インスタンス自体の管理（Auto Scalingの設定等）は利用者側で設定する必要がある
* FargateはEC2を使わずにコンテナを起動することが可能
* 現在、ECSでTask定義を作成するときは、起動タイプとして以下から選択可能
 * EC2（従来のECS）
 * Fargate（Clusterの管理が不要）
* 利用料金は、各タスクに割り当てるCPUとメモリに応じて決まる

### EKS（Amazon Elastic Container Service for Kubernetes）

* Kubernetesは、コンテナ管理の自動化のためのオープンソースプラットフォーム
* 従来、これを利用するにはマスター用のEC2インスタンスを複数台用意して管理する必要があった
* EKSは、このマスターをサービスとして提供するため 従来の管理が不要になる

### ECR（Amazon Elastic Registry）

* Dockerを用いる場合、そのコンテナイメージをレジストリ（ストレージとコンテンツ配送サービス）で管理する必要がある
* 更に自前で運用する場合には、レジストリ自体の可用性を高める設計が必要
* ECRは、このようなレジストリをサービスとして提供するためレジストリの管理が不要
 * レジストリへのpush/pull権限をIAMで管理することが可能

# Lambda

**Lambda** は、サーバーを用意せずにプログラムを実行できる環境、いわゆる **サーバレスアーキテクチャ** の中核を担うサービスです。

Lambdaによるメリットは以下になります。

* ソースコードの実行環境一式が提供されるため、利用者はソースコードを用意するのみでプログラムの実行が可能
* リクエスト数に応じて自動的にスケールするため、処理に必要なサーバー台数を考える必要がない
 * 同時実行数に上限はあるものの、申請により上限を増やすことが可能
* サーバーを持たないため、バッチ当てなどの保守作業が不要でインフラの大部分をクラウド側に任せることが可能

![Lambda.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1021235/e3e32194-1cf8-8d65-22a2-1da902d8f35f.png)

画像引用元：[【Serverless Framework】Lambda Destinations機能をServerless Frameworkで実装する](https://makky12.hatenablog.com/entry/2020/04/18/191831)


## Lambdaがサポートしているイベントと、よく使われるアーキテクチャパターン

### Lambdaがサポートしているイベント

Lambdaを利用するには **Lambda関数** という単位で、実行するプログラムとその実行トリガーとなるイベントを事前に定義します。

以下、イベントの例になります。

* S3バケットにオブジェクトが追加されたとき/S3バケットからオブジェクトが削除されたとき
* DynamoDBテーブルが更新されたとき
* SNS通知が発行されたとき
* CloudWatch Eventsによって定義されたスケジューリングの実行時

### よく使われるアーキテクチャパターン

* S3トリガーのパターン

S3に画像がアップロードされる
↓
それをトリガーにLambda関数が起動
↓
Lambda関数は対象となる画像を取得し、サムネイル用の画像を作成して別のS3バケットに追加

バッチサーバーを常駐させるのではなく、イベント駆動で特定の処理を行うといったLambdaの良さを活かしたアーキテクチャになっています。

* APIの提供をLambdaを利用して行うパターン

API Gatewayは、リクエストのあったURIとHTTPメソッドの組み合わせによって、呼び出すLambda関数の指定が可能
↓
呼び出されたLambda関数はビジネスロジックを実行し、必要に応じてDynamoDBとデータのやり取りをする
↓
API Gateway経由でレスポンスを返す

APIリクエストのピーク時に自動スケールする構成にできるため、こちらもよく使われるパターンになります。

* 定期実行パターン

CloudWatch Eventsと組み合わせることで、「毎時」や「火曜日の18時」といった形でLambdaの実行タイミングの指定が可能です。
1時間に1回外部のAPIから情報を取得するクローラーとしての利用や、定期的にSlackに何かしらの情報をつぶやくボットを実装する、といったことに利用できます。


## Lambdaがサポートしているプログラミング言語

Lambdaでは2020年12月時点で、以下のプログラミング言語をサポートしています。

* Node.js
* Ruby
* PowerShell
* Python
* C#
* Java
* Go

また、Lambdaでは利用する言語以外に以下の項目を設定する必要があります。

* 割り当てるメモリ量（例：256MB）
* タイムアウトまでの時間（例：10秒）
* Lambdaに割り当てるIAMロール
* VPC内で実行するかVPCの外で実行するか

## Lambdaの課金体系

Lambdaはリクエストの数と処理時間によって決まる、リクエスト課金モデルになっています。

以下、2020年12月時点での利用料です。

* Lambda関数の実行数：1,000,000件のリクエストにつき0.20USD
* Lambda関数の実行時間：Lambda関数ごとに割り当てたメモリ量によって、単位課金額が決まる

|  割り当てたメモリ量  |  実行時間課金（USD/100ミリ秒）  |
| ---- | ---- |
|  128  |  0.0000002083  |
|  512  |  0.0000008333  |
|  1024  |  0.0000016667  |
|  1536  |  0.0000025000  |
|  2048  |  0.0000033333  |
|  3008  |  0.0000048958  |


# 終わりに

以前までECSやEKSに対して勝手な苦手意識を持っていましたが、ある程度概要は掴めたかと思いますので
これから問題集を解いたり、実際に触りながら習得していきたいです。

最後まで読んでいただきありがとうございました。

<br>

関連記事はこちらからどうぞ。

* [AWS初心者による、SAA取得に向けた学習の記録①](https://qiita.com/t17_hr/items/106838afc10a54eea3f0)
* [AWS初心者による、SAA取得に向けた学習の記録②](https://qiita.com/t17_hr/items/e8d6d6e97b8b7487a5a4)
* AWS初心者による、SAA取得に向けた学習の記録③
* [AWS初心者による、SAA取得に向けた学習の記録④](https://qiita.com/t17_hr/items/f35cb0e313fd7863afb6)
* [AWS初心者による、SAA取得に向けた学習の記録⑤](https://qiita.com/t17_hr/items/ce20a44f1c586c145da3)
* [AWS初心者による、SAA取得に向けた学習の記録⑥](https://qiita.com/t17_hr/items/cbdc5c053a7bf63fa2a6)

※参考書籍
[AWS認定資格試験テキスト AWS認定ソリューションアーキテクト・アソシエイト 改訂版第2段](https://www.amazon.co.jp/dp/B08MVXRFFN?
tag=maftracking339397-22&linkCode=ure&creative=6339)