【SAA-C03 備忘録】コンピューティング（EC2 / ELB / ECS / Lambda）らへん

# はじめに

問題解いてて問われた内容の備忘録だったもの。

# EC2（Elastic Compute Cloud）

https://aws.amazon.com/jp/ec2/

## 購入オプション

- 【廃止】スケジュールドリザーブドインスタンス
- 【NEW】オンデマンドキャパシティー予約 

日次、週次、月次と３パターンの定期利用に適した購入方法。

## インスタンスタイプ

- 汎用（A, M, T）：バランスの取れたリソース
- メモリ最適化（X, R, z1d, ハイメモリ）：大量のメモリが必要（Redisなどのインメモリデータベースとか）
- ストレージ最適化（H, D, I, I3en）：高い**読み書き性能**や大量のローカルストレージが必要
- コンピューティング最適化（C, C6g）：高いコンピューティング性能（高性能Webサーバー、バッチ処理作業、ゲームサーバー、科学的モデリング）
- ハイパフォーマンスコンピューティング（HPC）最適化：特殊な計算作業（機械学習、ディープラーニング、画像・ビデオ処理など）

試験当日は読み書き性能のストレージ最適化だけ覚えてた。

## EC2のAuto Scalingポリシー

- **シンプルスケーリングポリシー**：単一の閾値に対してスケーリングアクションを指定
- **ステップスケーリングポリシー**：段階的に設定した複数の閾値に対してそれぞれ異なるスケーリングアクションを指定可能
- **ターゲットトラッキングスケーリングポリシー**：指定されたターゲット値にメトリクス値が極力一致するようにスケーリングする


## EC2にホストされたサーバーのパフォーマンス向上

比較的簡単に実施できるパフォーマンス向上の方法。

- EBSボリューム構成を RAID 0 にする
  - 複数のディスクを１台のディスクのように扱って読み書きを高速化してパフォーマンス向上
- インスタンスタイプのサイズを大きくしてインスタンス単体のパフォーマンスを向上


※ RAID 1は2つのボリュームを同時にミラーリングする構成で、ボリュームの冗長性を高めて障害耐性の向上を目的とする

## EC2の休止を有効化した起動時間短縮tips

EC2オンデマンドインスタンスをAuto Scalingウォームプールに設定しておくと起動時間が非常に長いアプリケーションのレイテンシーを低減できる。

### EC2の休止機能：
- アプリケーションが素早く再開でき、短いダウンタイムが可能に
  - EC2インスタンスが休止状態になると、インスタンスのメモリの状態がEBSに保存される
  - 次回起動時に以前のメモリ状態を再読み込みするため、通常の起動プロセスよりも迅速に元の状態へ復帰できる

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-instance-lifecycle.html#lifecycle-differences

### Auto Scalingウォームプール：

- スケーリングの反応速度を向上させられる
  - スケーリングアクションを迅速に実行可能にするため、あらかじめ用意しておいたインスタンスのプール
  - 「コールド」な状態（完全にシャットダウンしたインスタンス）から立ち上げるのではなく、「ウォーム」な状態でインスタンスを利用開始できる

https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/ec2-auto-scaling-warm-pools.html

## vCPU ベースのオンデマンドインスタンス制限（AWSアカウントに対する全般的な制限）

特定のインスタンスタイプに対して、起動できるインスタンスの台数が制限されてたっぽいですが、インスタンスの起動制限がシンプルになって異なるインスタンスタイプの組み合わせを自由に使えるようになっているみたいですね。

https://aws.amazon.com/jp/blogs/news/vcpu-based-on-demand-instance-limits-are-now-available-in-amazon-ec2/

# ELB（Elastic Load Balancing）

https://aws.amazon.com/jp/elasticloadbalancing/

## 主要な機能

- ヘルスチェック：
  - EC2の正常/異常を確認し市場なインスタンスへトラフィックを振り分ける
- クロスゾーン負荷分散：
  - 配下のEC2の負荷に応じて複数AZにまたがるEC2へ、均等に負荷分散
- 暗号化通信：
  - SSL/TLSを使用してAWSリソースと通信
- スティッキーセッション：
  - 同じユーザーからのリクエストを、セッション中に同じEC2インスタンスへ継続して送信する
- Connecting Draining：
  - インスタンスが登録解除されるか異常が発生した場合、新規リクエストの送信を中止
  - インスタンスの登録解除を報告する前に、ロードバランサーが接続を維持する最大時間を指定できる（デフォルトは300秒）
  - 最大タイムアウト値は1〜3600秒に設定可能
- ログ取得：
  - デフォルトでは無効化されている
  - 有効化すると、圧縮ファイルとして指定したS3バケット内に保存

## ELBの仲間たち

- CLB：レイヤー4/7、非推奨
- ALB：レイヤー7
  - **リスナールール**の設定が可能
    - HTTP リクエストを HTTPS にリダイレクトするように設定できる
  - 「1つのリージョン内」において複数のAZにトラフィック分散できる
    - 複数のAWSリージョンに分散させるトラフィック分散は実施できない！
  - URLのパスに基づくパスベースルーティングが可能
- NLB：レイヤー4
  - NLBでHTTPエラーを検出したい場合
    - CloudWatchアラームUnhealthyHostCountメトリクスをモニタリングする
    - Auto Scalingアクションを構成しておけば異常状態のインスタンスを置換できる
- GWLB：レイヤー3/4
  - ユースケース
    - サードパーティの仮想アプライアンス（ファイアウォールや侵入検知システムなど）を展開、拡張、管理するなど
  - 全てのIPパケットを監視し、トラフィックを特定のターゲットグループに振り分ける

## ELBを利用せずに高可用性とフォールトトレランスを適用する方法

レガシーアプリケーションで静的IPアドレスへの接続が必要で、ELBみたいな動的にIP変わるかもしれないやつは使えません！というケースで問われた。

1. Elastic IPを適用して、プロキシサーバーを設置（ELBの代わり）
2. バックエンドサーバーに対してAuto Scalingを構成
3. プロキシサーバーからバックエンドサーバーに対して定期的にヘルスチェックする

# Auto Scaling

https://aws.amazon.com/jp/autoscaling/

## インスタンスタイプの割り当て

Auto Scalingを構成する複数のインスタンスにおいて、オンデマンドインスタンスとスポットインスタンスの割合を制御できる。

https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/allocation-strategies.html

## Auto Scaling グループの容量オプション

- 希望するキャパシティ：
  - Auto Scalingが実行されない状態でのインスタンス数設定
  - 手動でスケーリングさせたいときはここをいじればできる
- 最小キャパシティ：
  - スケールイン時の最低インスタンス数
- 最大キャパシティ：
  - スケールアウト時の最大インスタンス数

https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/asg-capacity-limits.html

## Auto Scalingのヘルスチェックの仕組み

利用可能なヘルスチェックタイプがあり、意図してスケーリングが実施されないときはヘルスチェックのタイプがミスっている可能性がある。（例：EC2タイプのヘルスチェックを利用している場合、ELBのヘルスチェックが異常を示していてもEC2側のステータスに問題がないのでスケーリングされない）

- EC2タイプ
  - インスタンスレベルの基本動作（起動状態）に焦点をあてる
    - runningなってるか~？みたいな
- ELBタイプ
  - インスタンス経由のトラフィックの状態に焦点をあてる
    - HTTPステータスコードやTCP接続の成功など

## スケールアウト時の挙動

- Auto Scalingグループによって追加のインスタンスが起動されると、新規インスタンスに対してアプリケーションを実行するためのソフトウェアをセットアップする準備時間が必要
  - Auto Scalingが実行されてから実際に負荷軽減されるまでに数分~数十分程度のタイムラグが発生する
- スケーリングがうまく実行されずに24時間以上たった場合は、自動的にAuto Scaling処理が停止する
- デフォルトではメモリ利用率をトリガーとした設定ができない（CPUは可）

## スケールイン時のクールダウン
- スケーリングが終了してインスタンス数を削減する段階で、いきなりインスタンスを削除しない
  - 追加のスケーリングが開始されるのを防ぐ（過剰にスケールさせない）
  - クールダウン時間のデフォルトは300秒
  - 例外（クールダウン時間にスケールする場合）
    - スケジュール済みのアクションが開始される
    - ターゲット追跡またはステップスケーリングポリシーによりスケーリングアクティビティが開始される
    - インスタンスが正常でなくなった場合の置き換え

## AutoScalingの終了ポリシー

- **Default**：デフォルトの終了ポリシーに従いインスタンスを終了
- **OldestInstance**：もっとも古いインスタンスから終了
- **NewestInstance**：もっとも新しい起動時刻のインスタンスから終了
- **AllocationStrategy**：様々な購入オプション（オンデマンド、リザーブド、スポット）の最適なコスト効率を考慮してインスタンスを終了
- **OldestLaunchConfiguration**：もっとも古い起動設定により起動しているインスタンスから終了
- **ClosestToNextInstanceHour**：次の課金が始まるタイミングがもっとも近いインスタンスから終了

# ECSとEKS

https://zenn.dev/issy/articles/zenn-ecs-vs-eks

## ECS（Elastic Container Service）

- 課金体系
  - EC2インスタンスの使用に基づいて課金
  - Fargateを使用する場合は、VMではなくコンテナリソース自体に対して課金
- タスク
  - EC2上で実行されるコンテナのこと
  - タスクを実行するインフラとしてEC2やFargateを利用
- クラスター
  - タスクを実行するリソース（EC2インスタンスやFargate）が集合したもの
  - クラスター上で動作するタスクの定義はTask Definition（YAML形式）で行う
- コンテナ実行
  - Fargate：サーバーレスなコンテナ実行環境
  - EC2：インスタンスにコンテナエンジン（Dockerなど）をインストールする必要がある
  - Lambda：Lambda関数空コンテナタスクの呼び出し
- マイクロサービスアーキテクチャ化
  - タスク単位でトランザクションをサービス単位に分割したマイクロサービスを構築できる
- スケジュールタスクはAmazon EventBridgeスケジューラを利用
- ターゲット追跡スケーリングポリシー
  - 需要に応じて自動でスケーリングされるようにコンテナを設定することが可能

## EKS（Elastic Kubernetes Service）

- ユースケース
  - プロビジョニングやスケーリングの管理が不要で、管理の自動化をオープンソースツールで行いたい
  - 広範なオープンソースツールと連携しつつ、インフラ管理をサーバーレス化したい
- AWS Load Balancer Controller
  - EKS上でロードバランサーを自動的にプロビジョニングし、管理
  - ※ ECSでのロードバランシングはELB（ALB・NLB）を利用
- [Kubernetes における永続ストレージ](https://aws.amazon.com/jp/blogs/news/persistent-storage-for-kubernetes/)
  - 1. EFSの作成
  - 2. EFS CSIドライバーのインストール
  - 3. StorageClassの作成
  - 4. EFSをバックエンドとするPVの作成とそれに基づくPVCの作成
  - 5. PodでEFSをマウント
  - ※ ECSの場合はObjectClassではなくTask Definitionを使う
- AWS Controllers for Kubernetes
  - Kubernetesから直接AWSリソースを定義して使用できるようにするツール
  - Kubernetesアプリケーションの運用を効率化するコントローラー
- スケーリング
  - クラスターオートスケーラー
    - リソース制約のためにスケジュールできないクラスター内のポッドを監視する
      - 問題検出時、アプリの需要に合わせてノードプール内のノード数をスケールアップ
      - 実行ポッドの不足を定期的にチェックし、必要に応じてノード数をスケールダウン
  - 水平pod自動スケーリング
    - Kubernetesメトリクスサーバーを使用して、ポッドのスケーリングを行う
  - AWS App Meshの利用（※ ECS/EC2などでも利用可能）
    - App Mesh（AWSコンピューティングサービスのモニタリングとコントロールを容易にするサービスメッシュ）を利用してEKSクラスターをスケーリングするためのメトリクス測定を実現できる

## ECS / EKSどっちも

- CloudWatch Container Insights
  - メトリクスとログの収集：
    - コンテナ化されたアプリケーションとマイクロサービスのメトリクスとログを収集して可視化できる
  - リソースメトリクスの収集：
    - CPU やメモリ、ディスク、ネットワークなどのメトリクスを収集し、問題の特定や解決を支援
- CloudTrailとの比較
  - CloudTrailはAWSサービスに付与されたAPIコールやアクセスを記録するログツールなので、マイクロサービス間のメトリクスは収集できない！


# Lambda

最大10GBまでのデータ容量を扱える。

## Lambdaの課金体系

- Lambda関数の実行数
  - イベント数に応じて自動的に実行する関数をスケーリングさせて並列化した実行数を増加させる
- Lambda関数の実行時間
  - AWS Lambda関数の実行時間は最大で15分なのでタイムアウトする可能性がある

## よくあるアーキテクチャパターン

- S3への画像アップロードでLambda呼んで、LambdaでサムネつくってS3バケットへ
- CloudWatch EventsでLambdaの定期実行
- APIサーバーとしてAPI Gateway と組み合わせる
  - リクエストのあったURIとHTTPの組み合わせで呼び出すLambdaを変える
  - REST APIを構築する場合や、セキュリティおよび管理機能が求められる場合は、API Gatewayとの組み合わせが一般的に推奨
  - 最小の努力で実行することができる性能向上施策
    - APIリクエストに対する一時的な高負荷発生に備えて、Amazon API Gateway APIの処理性能を向上させるための２つ
      - APIゲートウェイのスロットリング制限設定
        - サーバー側：
          - リクエストを制限して鯖落ちを防ぐ
        - クライアント側：
          - Lambda関数の処理が間に合わない場合などに使用料プランに応じて制限をかける
      - APIゲートウェイのキャッシュを有効化

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-services.html

## 関数URL

Lambda × API Gatewayはよくあるけど、Lambda関数URL（Lambda関数のための専用HTTPエンドポイント）を使うことでシンプルに済む場合もある。

- シンプルなマイクロサービス
  - 単一のLambda関数を公開するだけなど、API Gatewayの複雑な設定や機能が不要な場合
- コスト削減
  - API Gatewayの追加費用を抑えたい場合
  - リクエスト数が多くLambda関数のみで十分なパフォーマンスが出る場合
- 基本的なHTTP機能
  - リクエストの検証や認証、キャッシングなどの高度な機能が不要で、単純なHTTPリクエストを処理するだけで済む場合

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/urls-configuration.html

## Lambda Layer

- 複数のLambda関数で使用するライブラリや共通のビジネスロジックを共有できる仕組み
- zipでアーカイブしてLayerに追加する

https://qiita.com/t_okkan/items/394a15577bd1aad46ec3

## Lambdaオーソライザー

- Lambda 関数を使用してAPIへのアクセスを制御するAPI Gatewayの機能
- ユースケース
  - OAuthやSAMLなどの外部認証プロバイダーを使用して、ユーザーの認証を行う場合
  - ヘッダーやクエリパラメータに基づいてリクエストの内容を検証し、特定の条件を満たす場合にのみアクセスを許可したい場合
  - など

https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html