AWS ハンズオンを一通り

# 実施内容

以下のハンズオンを一通り行う
https://aws.amazon.com/jp/aws-jp-introduction/aws-jp-webinar-hands-on/

ハンズオンの内容が古いものもあったので、2020/11〜12月時点の方法で実行する。
(削除のセッションは基本的に割愛)

なお、筆者のAWSアカウントでは、Cloud9のデプロイが何度も失敗していたので、基本的にEC2インスタンスをCloud9の代わりに構築して作業を行なっている。

EC2上では、後述のCloudFormationコマンドを実行するために以下の設定を行った。

1. PowerUserAccessのIAMを付与したユーザを作成
2. そのユーザのアクセスキー等をコピー
3. EC2にSSHアクセスし、***aws configure***と入力
4. ユーザのアクセスキーを入力
5. ユーザのシークレットキーを入力
6. リージョンを選択、東京の場合はap-northeast-1
7. コマンド出力結果の表示形式を指定（jsonやtableを入力）

***PowerUserAccess***はテンプレの中で2番目に強い権限を持ったポリシーで、IAM以外の操作が全て行えるユーザ。
なお、この設定ではハンズオン９でエラーが出たため、その時に解決を行う。

##１：ハンズオンはじめの一歩
### アカウントの作成
個人情報等を入力してアカウントを作成する
クレジットカードが必要であるため注意
サポートプランの選択も可能（後で変更も可能）

### IAMの作成
アカウント作成時点でできたユーザは***ルートユーザで全ての権限を持つ***
以下のことはルートユーザでしかできない模様
1. EC2メール送信制限解除申請（IPアドレス逆引き申請）
2. 侵入テスト申請
3. CloudFrontのキーペア作成
4. AWSサポートプランの変更
5. 請求情報に対する IAM ユーザーアクセスの許可

ここでは以下の３ユーザを作成
1. 管理ユーザ： 権限...AdministratorAccess
2. S3読み込みユーザ：　権限...AmazonS3ReadOnlyAccess
3. 権限無しユーザ：　権限...無し

権限は既存のポリシーを直接アタッチで付与できる。
なお、この権限を付与したグループをあらかじめ作っておき、ユーザへアタッチすることも可能

ログインには
1. アカウント自体のアカウントID（12桁）
2. 作成したユーザ名
3. 作成したパスワード
でログインする

IAMには３種類がある
1. ***IAMポリシー***：アクセス許可の定義を行うJSONドキュメント。独自ポリシーを作成できる
2. ***IAMグループ***：IAMユーザの集合を定義。複数ユーザに容易にアクセス権限を付与できる
3. ***IAMロール***：リソースへの権限の付与（S3へのアクセスロールを作成し、EC2に付与することでEC2からS3の操作が可能になる）

IAMポリシーは***AWS Policy Generator***で簡単に作ることが可能
https://awspolicygen.s3.amazonaws.com/policygen.html

以下のようなものを作成

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
          "Sid": "Stmt1605838389450",
          "Action": [
            "ec2:Describe*",
            "ec2:StartInstances",
            "ec2:StopInstances"
          ],
          "Effect": "Allow",
          "Resource": "*"
        }
    ]
}
```

Describe*のようにワイルドカードの指定も可能
名前を付与し、作成することで、ポリシーの一覧に表示されるようになる
これはユーザに直接付与することもグループに付与することも可能


IAMロールはEC2などのインスタンスに付与することが可能
ロールの作成から各サービスごとのIAMを作成

EC2のインスタンス一覧画面で付与したいEC2にチェックを入れ、***アクション＞セキュリティ＞IAMロールを変更***を選択
これで付与されたEC2インスタンスはIAMで与えられた権限を持つことになる

##２：Security　#1

***※ログ関連の作業は初回ログの取得までに数分から１日まで時間がかかることがあるため注意***

### コンプライアンス関連
コンプライアンス関連の資料は以下を参照することができる
https://aws.amazon.com/jp/compliance/

### ルートユーザの設定およびパスワードポリシー
ルートユーザは完全なアクセス権限を持っているため日常的に使わない
利用者ごとにIAMユーザを作成することが基本

ルートユーザに以下を設定
1. ***多要素認証(MFA)***の有効化
2. ルートユーザーアクセスキーの削除
3. IAMパスワードポリシーの適用

IAMを開き、セキュリティステータスが完了していないものは！マークが付いているため対応が必要

MFAの有効化をクリックし、仮装MFAデバイスを選択。
対応するアプリをスマートフォンにインストール（ここではGoogle Authenticatorを選択）し、画面のバーコードを読み取り。認証コード１、２を入力。
ここが少しわかりづらいが、認証コードは時間が経つと更新されるので、***認証コード１は現在画面に表示されているコードを入力し、認証コード２はその次に入力されたコードを入力する***

アクセスキーは作ったことがあれば削除する

パスワードポリシーはアカウント設定>パスワードポリシーを変更するから変更可能
IAMユーザのパスワードの入力ルール（最小文字数など）を設定できる

### IAMユーザ
ルートユーザ以外でログインするためにIAMユーザを作成する

以下の理解が必要
1. ***IAMユーザ***：AWS操作用ユーザ
2. ***IAMグループ***：IAMユーザをまとめるグループ
3. ***IAMポリシー***：AWSサービス操作に対する権限設定、IAMユーザやIAMグループに対して設定
4. ***IAMロール***：AWSサービスやアプリケーション等に対してAWSリソースの操作権限を付与するための仕組み

※ここは１：ハンズオンはじめの一歩とほとんど同じなので割愛

### 請求データ確認とアラート

以下を実施
1. ***AWS Budget***を使った請求アラート
2. ***AWS CostExplorer***の有効化と確認
3. ***AWS Cost & Usage Report***の設定

サービスを検索にBillingと入力し、Billing Management Consoleに移動

コストエクスプローラを有効化をクリック

メニューからBudgetをクリックし、予算を作成するを選択
ここでは期間を月ごとを選択し、予算は15ドル、閾値を60%(9ドルでアラート)にする。
これで***閾値を超えた際にメールが送信***される

***定期的にメールが欲しい場合***はBudget Reportを選択し、予算レポートを作成するをクリックし、先ほど作った予算名にチェックを入れ、日次、週次、月次の定期レポートを受け取ることができる。

***各リソースがどれだけの金額を発生しているか確認するため***にCost & Usage Reportを選択し、レポートの作成をクリックし、格納したいS3バケットを設定する。
プレフィックスが現在は必須となっているため好きな文字列を入力しておく

詳細のコストは***Cost Explorerを開き、Cost Explorerタブ***をクリック（初期状態はホーム）することで確認することができる

### 操作履歴とリソース変更履歴の記録

操作履歴：***AWS CloudTrail***を利用してAWSサービスを利用する際に行動履歴をログに記録し監視

リソース変更履歴：***AWS Config***にてリソースの変更履歴・構成情報を管理・監視

検索エリアでCloudTrailと入力し、サービスに移動。
イベント履歴タブから全ての履歴を確認できる。
イベント名を選択し、ConsoleLoginなどを入力することで表示を一部に限定することも可能。

行動履歴を記録するために、証跡の作成をクリックする。
指定したS3にJson形式のログが格納されるようになる。

次に、検索エリアにConfigと入力し、サービスに移動。
今すぐ始めるボタンをクリックする。
設定は標準のままで可能。
AWS Configルールはある一定のルールに則っていないと通知を出すもの。今回は使わないのでスキップ。
作成後、各サービスの一覧が表示されるので表示。
サービスをクリックして、設定タイムラインを押すことで、イベントの履歴が確認できる。
なお、イベントの履歴は９０日間。

## 脅威検知
脅威インテリジェンス（脅威の防止や検知に利用できる情報の総称）を利用した脅威検知

***Amazon GuardDuty***：機械学習を用いたクラウドネイティブな脅威検知サービス
悪意あるスキャン（ポートスキャンや総当たり攻撃）、インスタンスへの脅威（C&Cサーバとの通信、アウトバウンドDDos）、アカウントへの脅威（不正なAPIの呼び出し、予期しないリソースアクセス）を検知

検索エリアにGuardと入力し、サービスに移動。
今すぐ始めるをクリックし、右下のGuardDutyの有効化をクリック。
出力されたログの意味は以下で調査可能。
https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_finding-types-ec2.html#backdoor-ec2-denialofservicetcp

### ベストプラクティスの確認
***AWS Trusted Advisor***：AWS環境を自動監視、最適化するための推奨ベストプラクティスを提供。
５つのカテゴリに分類されている（コスト最適化、パフォーマンス、セキュリティ、フォールトトレランス、サービス制限）

検索エリアにTrusted Advisorと入力し、サービスに移動。
プランによって見れる情報の量が違うので注意。
（Businessサポート以上でないと見れないものも多い）

***通知設定タブ***を選択し、毎週Eメール配信をすることが可能。

## ３：Network編#1

### 流れの説明
***VPC***：仮想ネットワーク空間。内部に複数のサブネットを持つことが可能。
将来的な拡張も踏まえて大きく範囲を取ることが必要。
***サブネット***：VPCの中を細かく分解したネットワーク空間
サブネットは***AZ空間***（同じリーション内の別データセンター）を跨げない仕様となっている

***パブリックサブネット***：インターネットゲートウェイ、プライベートサブネットと通信する空間。つまりDMZ。
***プライベートサブネット***：パブリックサブネットのみと通信できるプライベートな環境。インターネットからは直接アクセスできない。
***インターネットゲートウェイ***：インターネットと通信するための出入口。VPCごとにアタッチする。パブリックサブネットとインターネットを繋ぐ。***冗長化や障害時の復旧が自動的にされる***サービスなので、単一障害点では無い。

ここからはAZ空間1aにパブリックサブネットとプライベートサブネットを１つずつ、AZ空間1cにも同様の環境を作成する。

### VPCの作成

検索エリアにVPCと入力し、サービスに移動。
***VPCウィザード***を使えば用意されているテンプレートを使えるため、楽（このハンズオンでは使わない）。

***VPCタブ***で遷移し、VPCの作成をクリックし、名前やCIDRブロック（10.0.0.0/16）を入力し、作成をクリック。

***サブネットタブ***で遷移し、サブネットを作成をクリック。
まず、パブリックサブネットを作成する。
先ほど作ったVPCの選択・サブネット名・AZ（ここでは1aを選択）・CIDR(10.0.1.0/24)の入力を行い、サブネットの作成ボタンをクリック。
同様に同じVPC内にAZを1c、CIDRを10.0.2.0/24にしたものを作成。

次にプライベートサブネットを作成する。
設定はパブリックと同様で、AZ1aの方はCIDRを10.0.11.0/24、AZ1cの方はCIDRを10.0.12.0/24にして作成する。

***インターネットゲートウェイタブ***で遷移し、インターネットゲートウェイの作成をクリック。名前を入力し、インターネットゲートウェイの作成ボタンをクリック。
作ったインターネットゲートウェイを選択し、アクションからVPCにアタッチを選択。
作成したVPCを選択し、インターネットゲートウェイのアタッチボタンを選択。

### サブネットのプライベート化とパブリック化

***ルートテーブル***：各サブネットに１つずつ定義が割り当てられている。ネットワークトラフィックの経路を決定するルートと呼ばれる一連のルールが定義されたテーブル情報であり、各サブネットにルール付けすることで、サブネットの通信経路が決定。つまり、パブリック化・プライベート化することが可能。
ルーティングの優先度は、最も具体的なルートが優先される（最長プレフィックス一致、ロンゲストマッチ）
つまり、10.0.0.0/16と0.0.0.0/0の２つがあれば、10.0.0.0~10.0.255.255以内のIP通信であれば、前者のルート経路が優先される。

この時点では全てのサブネットは１つのルートテーブルのみがアタッチされており、設定がプライベートサブネットになっているため、***プライベートサブネットのみにインターネットゲートウェイの経路を追加***する。

まずはルートテーブルの作成を選択。VPCは今回作成したものを選択し、作成する。
作成した***ルートテーブルを開き、ルートタブ***を押し、ルートの編集を選択。
ルートの追加ボタンを押し、送信先を0.0.0.0/0、ターゲットを***InternetGateWay***→作成したインテーネットゲートウェイの順番で選択し、ルートの保存を押す。
作成した***ルートテーブルのサブネットの関連付けタブ***を押し、関連付けの編集からパブリックのサブネットを選択する。

なお、***プライベートサブネットは何も関連付けされていないように見えるが、何も関連付けされていないサブネットに関してはデフォルトのルートテーブル（メインと書かれている）に関連付けされる***。



### ルートテーブルによる経路設定の理解

まずはEC2にアタッチするIAMを作成する。ロールを選択し、一般的なユースケースの中にEC2があるので、選択する。ポリシーはAmazonSSMFullAccessを選択する。
このSSM=***AWS Systems Manager***とはAWSでインフラストラクチャを表示および制御するサービスで、オペレーションの自動化などができる。

次に、EC2を作成する。インスタンスをクリックし、インスタンスの起動を選択。
Amazon Linux2を選択し、***ネットワークのVPCを作成したもの、サブネットをパブリックサブネット（1a）***にする。
インターネットに***WEBサーバは公開するため、自動割り当てパブリックIPは有効***にする。
IAMロールは先ほど作成したSSM権限をアタッチ。
ユーザーデータには***インスタンス作成時に実行されるスクリプトを記述できる***ため、以下の通り入力しておく。

```
#!/bin/bash

yum -y update
yum -y install httpd
systemctl enable httpd.service
systemctl start httpd.service
```

これで、***パッケージの更新とhttpdのインストールおよびhttpdの起動とサーバ立ち上げ時にhttpdを起動する設定が行われる**。

タグのキーにはName、値にはWEBと入れておく。
セキュリティグループの設定では、インターネットから通信をするので、HTTPを追加しておく。
このハンズオンでは使用しないが、新しいキーペアを作成することで、SSH通信を行うことができる。
なお、上記の***キーペアでSSH通信をしたい場合はVPCのDNSホスト名の有効化を有効にする必要***がある。
ここまででインスタンスを作成する。
作成したインスタンスの概要を確認し、パブリックIPにアクセスすることでApacheのトップページが表示されればOK。
なお、***作成してすぐにアクセスしてもアクセス禁止になることがあるので、少し待ってからアクセスする。***

また、ここで公開用ルートテーブルのアタッチからこのEC2のサブネットを外すと、インターネットとの疎通が取れなくなるため、アクセスできなくなることが確認できる。
再度アタッチし直せば当然アクセスできるようになる。

SSMをアタッチしているため、ssh通信をせずとも、***インスタンス概要>接続>セッションマネージャー>接続***で接続することができる。
（ただし、この通信はSSM自体がVPC外に存在するため、アウトバウンドでインターネット通信が必要であり、インターネットゲートウェイや後述のNATゲートウェイがサブネットのルートテーブルに紐づけられていることが必要）

なお、ssh通信したい場合は、キーペアが保存されたディレクトリで以下のコマンドを実行。

```
ssh -i キーペア名 ec2-user@パブリック IPv4 DNS
```

***SSHと同じポートでファイル転送したい場合***にも以下のようにできる。

```
scp  -i キーペア名 送りたいファイル ec2-user@パブリック IPv4 DNS:/home/ec2-user
```
もしCloud9が起動しなかった場合はEC2にファイルをおくってハンズオンをする。

なお、MacPCなどで、bad permissionsなどのエラーが出た場合は、キーペアの権限が広すぎるため、以下のコマンドを一度実行する。

```
chmod 0600 キーペア名
```

### プライベートサブネットからインターネットアクセス

インターネットからプライベートサブネットへのアクセスは遮断したいが、プライベートサブネットからインターネットへのアクセスをしたい場合。
***NAT Gateway***を利用する。(NAT instanceは古く今はあまり使われない)

まずはVPCの画面へ移動し、***NATゲートウェイタブ***を選択する。
NATゲートウェイを作成をクリックし、パブリックサブネットの1c側をサブネットにアタッチし、ElasticIPの割り当てボタンをクリックし、NATゲートウェイの作成を行う。

***ルートテーブルタブ***に遷移し、プライベートルートテーブルを開き、ルートタブを選択。
ルートの編集を行い、ルートの追加をクリックした後、送信先を0.0.0.0/0、ターゲットを***NAT Gateway***→先ほど作成したNAT Gatewayを選択する。

ここでEC2の画面へ移動し、作成を行う。
サブネットはプライベート1cを選択するが、外部へこのサーバは公開しないので、自動割り当てパブリック IPは無効にしておく。

この状態で、セッションマネージャーを使い接続することが可能となる。
また、ルートテーブルからNAT Gatewayへのアウトバウンド通信の定義を削除するとセッションマネージャーを用いた接続が不可となる。

### VPC外サービスへの接続方法

ここまではインターネットゲートウェイを使用してSSMへ接続したが、よりセキュアなシステムではプライベートサブネットのみを後世し、VPCからインターネットに接続性を持たせない構成も必要となる。

***VPC Endpoint,AWS PrivateLink***:VPC内Subnet上で稼働するサービスから、Internet Gateway,NAT Gateway,NATインスタンスを経由せずにVPC外サービスと直接通信させることが可能。
以下の二つの型がある。
***Gateway型（Endpoints）***：S3,DynamoDBとの接続方式
***Interface型(AWS PrivateLink)***：SSM,CloudWatchなどその他サポートされているサービス

今回はSSMへの接続を作成するため、PrivateLinkを作成する。

まずは、インターネットへの接続を削除するために、プライベートサブネット用のルートテーブルからNAT Gatewayへの接続定義を削除する。
VPCの画面からVPCのDNSホスト名の有効化を有効にしておく。
***エンドポイントタブ***を開き、エンドポイントの作成を押す。
まずはサービス名com.amazonaws.ap-northeast-1.ssmを選択し、VPCは今回作成したもの、サブネットはパブリック1cに作成したものを選択する。
セキュリティグループは新規作成を行う。
VPCは今回作成したものを選択し、インバウンドはプライベートサブネットからの通信のみを許可するため、HTTPSで10.0.0.0/16の範囲のものを許可する。
作成したセキュリティグループにチェックを入れ、作成を行う。
もう一度、エンドポイントの作成を行い、com.amazonaws.ap-northeast-1.ssmmessagesを選択した同様のものを作成する。
さらに、com.amazonaws.ap-northeast-1.ssmmessagesを選択したものを作成する。
作成後、使用可能になるまでは数分ほどかかるため待機する。

ここまでで、***パブリックサブネット1cにはPrivateLinksのエンドポイントがアタッチされることになり、プライベートサブネット1c内のEC2はパブリックサブネット1cを経由してSSMへアクセスする***ことになる。

最後に、プライベート1c内に作成したEC2インスタンスにセッションマネージャーで接続できることを確認する。

次にGateway型（Endpoints）を作成してS3に接続する。
EndpointsはVPCにアタッチすることになり、S3に接続するときはVPCから直接接続することになるので、インターネットゲートウェイを経由することはない。

まずはS3でバケットの作成を行う。
S3の画面へ遷移し、バケットを作成を選択。名前のみ入れて作成を行う。

次にIAMの画面へ遷移し、***ロールタブ***を開き、すでに作成したSSMの権限がアタッチされたロールを開く。
ポリシーをアタッチを選択し、AmazonS3ReadOnlyAccessをアタッチすることで、***追加で権限をアタッチする。***

次にVPCの画面へ遷移し、エンドポイントタブで遷移し、エンドポイントの作成を選択。
com.amazonaws.ap-northeast-1.s3をアタッチする。VPCは作成したものを選択し、ルートテーブルはパブリックのものとプライベートのもの両方を選択する。
（***ルートテーブルに経路が登録されていないと接続できないため、この画面で自動でルートテーブルに経路を付与できる。***）
ここまで設定し、作成する。ルートテーブルを確認すると、s3への経路も登録されている。

プライベートサブネットのEC2にセッションマネージャーで接続し、以下のコマンドでS3のリスト一覧が出力されればOK。

```
aws s3 ls --region ap-northeast-1
```
インターネットを経由しないセキュアな接続ができたことが確認できる。

## ４：Network編#2

今回はAmazon VPCとオンプレミスの接続を行う。
まず、前提としてVPCはアカウント内で複数作成することができる。
例えば、***テスト環境、本番環境のように環境を分けることやシステムごとに環境を分ける際に別VPCを構成して分ける***ことなどができる。

### VPC間の接続

VPC間接続する方法は２つある
1. VPCピアリング接続を使用する
2. Transit Gatewayアタッチメント接続を使用する

***VPCピアリング***の場合、***２つのVPC間をプライベートに接続***することとなる。
***異なるリージョンや、異なるAWSアカウント間の接続***をサポートしている。
前提として、***IPアドレス空間が重複していないこと、ピアVPCとピアリングしているVPCと接続することはできない***（そのVPCともVPCピアリング接続をする必要があり、接続先が多くなると、ネットワーク構成が複雑になる）。

***Transit Gatewayアタッチメント接続***の場合、TransitGatewayがネットワークの中央ハブとして各VPCの接続を実現するため、***多くのVPCとの接続する場合にネットワーク構成を簡素化***することが可能となる。

今回のハンズオンでは前者を利用。

なお、VPCは***VPCウィザード***でまとめて作成する。
最初はメイン側を作成する。
AZは1aを選択し、CIDRは10.1.0.0/16、サブネットは10.1.0.0/24を入力。

作成後、***VPCでフィルタリングにVPC名を入力することで、そのVPCに紐づくリソースのみを表示できる。***
ルートテーブルを表示し、インターネットゲートウェイへのルートがある方をパブリック、無い方ををプライベートと名前を変更しておく。

さらにVPCをもう一つ作成する。
次はピアリング側を作成する。
AZは1aを選択し、CIDRは10.2.0.0/16、サブネットは10.2.0.0/24を入力。
同様にルートテーブルの名前は変更する。

ここまでできたら、***ピアリング接続タブ***を選択し、ピアリング接続の作成を選択。
まずは接続元のメイン側のVPCを選択する。
次に、接続先のピアリング側のVPCを選択する。
この画面で、アカウントやリージョンを選択できるが、ここで***他のアカウントや他のリージョンなどを指定することが可能となる***。

ここまででピアリング接続の作成を選択。
ステータスが承諾の保留中となっているため、***アクションからリクエストの承諾を選択し、ステータスがアクティブになる***。（まだ接続はできない）
これは、他アカウントと連携する場合などに勝手に接続されないための機能。

次に、ルートテーブルに遷移し、メイン側のパブリックルートテーブルを編集し、
送信先を10.2.0.0/16、ターゲットを***Peering Connection***→ピアリング側のVPCを選択する。
さらに、ピアリング側のパブリックルートテーブルを編集し、
送信先を10.1.0.0/16、ターゲットをPeering Connection→メイン側のVPCを選択する。

ここまでで接続のための設定が完了したので、疎通確認のためにEC2を作成する。
まずはピアリング側のVPCにEC2インスタンスをプライマリIPを10.2.0.100、セキュリティグループを全てのトラフィックを10.1.0.0/16に対して許可して作成する。

次に検索エリアに***Cloud9***と入力し、サービスに移動する。
(ブラウザのみでコードを記述、実行、デバッグできるクラウドベースのIDEだが、ここは疎通の目的のみで使用する)
create environmentを選択し、VPCはメイン側のVPCを選択し、作成を行う。

ここでコンソールから作成したEC2のインスタンスに対してpingを実行する。

```
ping 10.2.0.100

PING 10.2.0.100 (10.2.0.100) 56(84) bytes of data.
64 bytes from 10.2.0.100: icmp_seq=1 ttl=255 time=0.406 ms
```

また、VPCの画面からピアリング接続の画面へ遷移し、アクションからピアリング接続の削除をすることで、pingが通らなくなり、疎通が取れなくなることを確認できる。
再度ピアリングをする場合には***もう一度ピアリング接続の作成とルートテーブルの追加が必要***。なお、前のピアリングの設定がルートテーブルに残っているので、削除が必要。

### VPCとオンプレミスの接続

用途としては以下のようなものが考えられる。
・オンプレとAWSのハイブリッドな環境を作成するため、***セキュアな接続を実現***。
・オンプレからAWSにシステム移行するあたり、***セキュアにデータ転送***を行いたい。

接続方法は以下のようなものがある。
・***AWS Site-to-Site VPN***：Internet VPN接続。AWS側の***VirtualPrivateGateway(VGW)***と顧客側の***CustomerGateway(CGW)***を接続する。ユースケースとしては、拠点とAWSを簡単に早く接続したい、少量のトラフィックの送信、価格重視/スモールスタート、バックアップ回線など。暗号化されるが、インターネットを経由するため、通信は安定しないことがある。
・***AWS Direct Connect***：専用線接続。ユースケースとしては、安定したパフォーマンスが必要、閉域網でも接続が必要、大量のトラフィック送信、主回線、一貫性のある管理の実現。

なお、Site-to-Site VPNを利用する場合には、VPCごとのVPNGatewayが必要となるため、オンプレと直接接続したいVPCがたくさんある場合には、***TransitGatewayアタッチメント***を利用することで簡易に実現可能。

ここから、オンプレミス想定のVPCを作成し、接続の確認を行う。
なお、ここで作るEC2はオンプレミスのルーター想定として作成する。

VPCウィザードからオンプレ側を作成する。
AZは1aを選択し、CIDRは192.168.0.0/16、サブネットは192.168.0.0/24を入力。
同様にルートテーブルの名前は変更する。

次に、EC2の画面へ移動し、***キーペアタブを選択し、キーペアの作成***を選択。

インスタンスの作成を選択し、今回は***AWS Marketplaceタブ***をクリックし、CSRと入力し、検索。
Cisco Cloud Services Router (CSR) 1000V - Security Pkg. Max Performanceを選択する。
なお、この製品は３０日間FreeTrialで利用できるが、そのあとは値段がかかってしまうため注意。
VPCは先ほど作成したオンプレ側のVPCを選択、プライマルIPは192.168.0.200、キーペアは先ほど作成したものを選択して作成する。
なお、ここで<font color="red">The seller has not made this product available in the geo location associated with your customer account.</font>と出力され、インスタンスの作成ができなかった。（リージョンは東京リージョンを使用）
推奨ストレージへの変更、再ログインなど試したが失敗となった。
Cisco Cloud Services Router (CSR) 1000V - BYOL for Maximum Performanceを選択し、作成をしたところ正常終了。
（ステータスチェックが初期化から完了までに数分ほど時間がかかる）

なお、ここで作成した**MarketPlaceのサブスクリプション削除はAWS Marketplace Subscriptionsから行うため、EC2の削除だけでは消えないため注意***。

次に***ElasticIPアドレス***を作成し、割り当てる。
インスタンス一覧から作成したEC2にチェックを入れ、***アクション＞ネットワーキング＞IPアドレスの管理***を選択する。「Elastic IP アドレスを割り当てて」と書いている場所にリンクがあるので、遷移。
Elastic IPアドレスの割り当てボタンを押し、割り当てを選択。
Elastic IPアドレスが追加されるので、チェックを入れたまま、***アクション＞Elastic IPアドレスの関連付け***を選択。
インスタンスは先ほど作成したCSRインスタンス、プライベートIPアドレスは先ほどプライマルIPに入力した192.168.0.200を入力し、関連付けるを押す。
これで作成したCSRのインスタンスを確認したところElasticIPが紐付けられていることが確認できる。

ここでCloud9の画面に移動し、OpenIDEを押す。
FileからUpload local fileを選択し、ダウンロードしていたキーペアをドラッグ＆ドロップでアップロード。
現在はキーペアの権限が広すぎるので、以下のコマンドを入力

```
chmod 400 キーペア名
```

次に、以下のコマンドでSSH通信ができるかを確認

```
ssh -i キーペア名 ec2-user@パブリック IPv4 DNS
```

ログインができればOK（ここはまだパブリックな通信であり、セキュアでは無い。）

VPCの画面へ移動し、***仮想プライベートゲートウェイタブ***を選択し、仮想プライベートゲートウェイの作成を行う。
作成したものにチェックを入れた状態で、***アクション＞VPCにアタッチ***を選択。
アタッチする対象はメイン側のVPCを選択。

次に***カスタマーゲートウェイタブ***を選択し、遷移。カスタマーゲートウェイの作成を選択し、ルーティングは動的、IPアドレスはElasticIPとして作成したものを入力し作成。

***サイト間のVPN接続タブ***を選択し、VPN 接続の作成を選択。
Target Gateway TypeはVirtualPrivateGateway、仮想プライベートゲートウェイは先ほど作成した仮想プライベートゲートウェイ、カスタマーゲートウェイは先ほど作成した既存のカスタマーゲートウェイを選択して作成する。

作成されたVPN接続にチェックを入れた状態で設定のダウンロードを選択し、ベンダーをCisco、プラットフォームをCSR AMIを選択し、ダウンロードする。
ダウンロードしたファイルを開き、<interface_name/private_IP_on_outside_interface>の部分を全てCSRのIPアドレス（192.168.0.200）に変換する。

ここで再度Cloud9を開き、CSRの仮想マシンにSSH通信をする。
以下のコマンドを入力し、設定モードに移動する。

```
configure terminal
```

設定モードに移動したら、変換済みのダウンロードファイルのテキストを全てコピーし貼り付けを行う。
（１行ずつ実行される）
完了後、設定モードからはendで抜けて、以下のコマンドを入力する。

```
show ip route
```
Bがついている場所がBGPによって学習した経路

```
B        10.1.0.0 [20/100] via 169.254.133.73, 00:46:25
```
10.1.0.0はメインVPCのCIDRと一致している。

以下のコマンドでBGPだけの経路情報も確認できる

```
show ip bgp
```

```
 *    10.1.0.0/16      169.254.212.89         200             0 64512 i
 *>                    169.254.133.73         100             0 64512 i
```
IPSecのトンネルが２つ張られていることが確認できる。

以下のコマンドで設定を保存する

```
write memory
```

VPN接続の画面に遷移し、Tunnel Detailsダブから２つのチャネルが張られていることが確認できる。

ここまでで***メイン側のVPCの仮想プライベートゲートウェイとオンプレ（CSR）側のカスタマーゲートウェイが接続***される。(まだ疎通は取れない）

次に、メイン側のパブリックルートテーブルを開き、***ルート伝搬タブを選択***、ルート伝達の編集を選択し、チェックを入れて保存。
ルートタブを開くと、VGWのルートが追加されていることが確認できる。
ただし、送信先が0.0.0.0/0になっており、このままでは優先度でインターネットゲートウェイに通信が行ってしまう。なお、この設定はCGWが伝搬したルートがルートテーブルに追加されているので、CGWの設定を変更する必要がある。

ここで再度Cloud9を開き、CSRの仮想マシンにSSH通信をする。
以下のコマンドでBGPだけの経路情報を確認

```
show ip bgp

Network          Next Hop            Metric LocPrf Weight Path
 *>   0.0.0.0          192.168.0.1              0         32768 i
                       0.0.0.0                                0 i
 *    10.1.0.0/16      169.254.212.89         200             0 64512 i
 *>                    169.254.133.73         100             0 64512 i
```
伝搬したかった192.168.0.0/16が乗っていないので、ここに設定する必要がある。

次に、以下のコマンドでBGPの設定を確認する。

```
show running-config | section router bgp

router bgp 65000
 bgp log-neighbor-changes
 neighbor 169.254.133.73 remote-as 64512
 neighbor 169.254.133.73 timers 10 30 30
 neighbor 169.254.212.89 remote-as 64512
 neighbor 169.254.212.89 timers 10 30 30
 !
 address-family ipv4
  network 0.0.0.0
  neighbor 169.254.133.73 activate
  neighbor 169.254.133.73 default-originate
  neighbor 169.254.133.73 soft-reconfiguration inbound
  neighbor 169.254.212.89 activate
  neighbor 169.254.212.89 default-originate
  neighbor 169.254.212.89 soft-reconfiguration inbound
 exit-address-family
```

上記のnetwork 0.0.0.0とdefault-originateの箇所を削除する必要がある。

まず以下のコマンドで設定モードに移動する。

```
conf t
```

階層構造になっているため、１つずつ階層を入力して上がっていく。

```
ip-192-168-0-200(config)#router bgp 65000
ip-192-168-0-200(config-router)#address-family ipv4
ip-192-168-0-200(config-router-af)#
```

頭にnoを入れれば設定削除ができるので、以下の通り入力する。

```
no network 0.0.0.0
no neighbor 169.254.133.73 default-originate
no neighbor 169.254.212.89 default-originate
```

以下のコマンドで伝搬したいCIDRを設定する。

```
network 192.168.0.0 mask 255.255.0.0
```

endで設定モードを抜けて、再度BGPの設定を確認する。

```
show running-config | section router bgp

router bgp 65000
 bgp log-neighbor-changes
 neighbor 169.254.133.73 remote-as 64512
 neighbor 169.254.133.73 timers 10 30 30
 neighbor 169.254.212.89 remote-as 64512
 neighbor 169.254.212.89 timers 10 30 30
 !
 address-family ipv4
  network 192.168.0.0 mask 255.255.0.0
  neighbor 169.254.133.73 activate
  neighbor 169.254.133.73 soft-reconfiguration inbound
  neighbor 169.254.212.89 activate
  neighbor 169.254.212.89 soft-reconfiguration inbound
 exit-address-family
```

伝搬したい情報が乗っていることが確認できる。
ここで、再度show ip routeで経路情報を確認するが、192.168.0.0/16が存在しないため、ルーティングの登録が必要。
また、以下のコマンドでどんなルート情報があるかを確認できる。

```
show run | section ip route

ip route 0.0.0.0 0.0.0.0 GigabitEthernet1 192.168.0.1
ip route vrf GS 0.0.0.0 0.0.0.0 GigabitEthernet1 192.168.0.1 global
```

ここの２行目はデフォルトルートを192.168.0.1（VPC内で動作する内部ルータのアドレス）に送るという設定である

設定モードに再度移動し、以下のコマンドを入力しルーティング設定を追加する。

```
ip route 192.168.0.0 255.255.0.0 GigabitEthernet1 192.168.0.1
```

endで設定モードを抜けて、show ip routeで192.168.0.0/16の設定が追加されていることが確認できる。
また、show ip bgpでも192.168.0.0/16の設定が追加されていることが確認できる。

BGPの経路を変更したので、すぐに反映されるために以下の２コマンドを入力する。

```
clear ip bgp *
write memory
```

ここまで行うと、メイン側のルートテーブルのルートを見ると、伝搬されたVGWのルートが192.168.0.0/16になっていることを確認できる。

次にオンプレミスのパブリックルートテーブルを開く。
ルートの追加を行い、宛先はメインVPCとなるので、10.1.0.0/16、ターゲットは***Instance＞CSR***を選択する。

次に、***EC2の送信元/送信先宛先チェックを無効化***する必要がある。
この、送信元/送信先宛先チェックは、デフォルトでEC2インスタンス設定されているが、送信先が指定されていないネットワークトラフィックをインスタンスで処理できるようにする場合は、送信元/送信先チェックを停止する必要があり、***ネットワークアドレス変換、ルーティング、またはファイアウォールなどのサービスを実行するインスタンスでは、送信元/送信先チェックを停止することが推奨***されている。

EC2画面に遷移し、CSRにチェックを入れ、***アクション＞ネットワーキング＞ソース/宛先チェックを変更***を選択。停止にチェックを入れ、保存を選択する。

最後にオンプレ想定VPC内にEC2インスタンスを作成し、疎通の確認を行う。

EC2をオンプレ側のVPCにIPアドレス192.168.0.100、セキュリティグループは全てのトラフィックをメインVPC（10.1.0.0/16）に対して許可して作成する。

ここでCloud9にログインして、以下の通りオンプレ用のEC2に対してpingをする

```
ping 192.168.0.100

PING 192.168.0.100 (192.168.0.100) 56(84) bytes of data.
64 bytes from 192.168.0.100: icmp_seq=2 ttl=254 time=10.0 ms
```

確認として、Site-to-Site VPNによって接続していることを確認するために、Site-to-Site VPNの設定を外すと疎通ができなくなることを確認する。

仮想プライベートゲートウェイを開き、***アクション＞VPCからデタッチ***を選択する。

再度、Cloud9からPingを飛ばしても疎通が取れないことが確認できる。

再接続するには、まず***アクション＞VPCにアタッチ***を選択し、メインVPCにアタッチする。
なお、***一度デタッチするとブート伝搬の設定が削除されるため、アタッチした後に再度設定を融合化する必要がある***。

メインパブリックルートテーブルのルート伝搬が外れているので、ルート伝搬を開き、設定を有効化する。
ここまで行うと、ルートに経路が再度追加されるため、Cloud9からPingが通るようになる。


## ５：スケーラブルウェブサイト構築編

### VPC作成

VPCウィザードからCIDRを10.4.0.0/16、サブネットのCIDRを10.4.0.0/24、AZを1a（パブリックサブネット1a）で作成する。
次に作成したVPC以下にサブネットを３つ作成(パブリックサブネット1cの10.4.1.0/24とプライベートサブネット1aの10.4.2.0/24とプライベートサブネット1cの10.4.3.0/24)する。

パブリックサブネット1cはインターネットゲートウェイへのルートテーブルがアタッチされていないので、パブリックサブネット1aにアタッチされているルートテーブルをアタッチする。

### EC2(Wordpressインストール)の作成

次に、パブリックサブネット1a上にEC2インスタンスを作成する。
なお、自動割り当てパブリックIPは有効にし、ユーザーデータは以下のものを記述する。

```
#!/bin/bash

yum -y update
amazon-linux-extras install php7.2 -y
yum -y install mysql httpd php-mbstring php-xml

wget http://ja.wordpress.org/latest-ja.tar.gz -P /tmp/
tar zxvf /tmp/latest-ja.tar.gz -C /tmp
cp -r /tmp/wordpress/* /var/www/html/
chown apache:apache -R /var/www/html

systemctl enable httpd.service
systemctl start httpd.service
```

セキュリティグループはHTTPをソース：任意の場所を選択して追加する。
作成されたサーバにHTTPでアクセスするとWordPressのトップ画面が表示される。

### WordPress用のDB（Amazon RDSの作成）

まずはDBが作成するセキュリティグループを作成する。
EC2画面から***セキュリティグループタブ***を選択し、インバウンドにタイプ：MYSQL/Aurora、ソースをカスタムで先ほど作成した***WordPressのセキュリティグループに対し許可***を入れて作成する。

次にRDSの画面に移動し、***サブネットグループタブ***を選択し、サブネットをプライベートサブネットのもの（10.4.2.0/24と10.4.3.0/24）を選択して作成する。

次にデータベースタブを選択し、MySQLをデフォルトバージョン、VPCは作成したもの、セキュリティグループはRDS用に作成したもの（defaultは消す）、AZは1a、追加設定を開いてDB名を入力し、自動バックアップを無効にして作成する。

DBの作成が完了したらDBを開いてエンドポイントを確認してメモしておく。

### ロードバランサーの作成

ロードバランサーはEC2の画面から作成することになる。
EC２の画面へ移動し、***ロードバランサータブ***を選択。
今回は***Application Load Balancer***を選択し、AZは作成したパブリック1aと1cの両方をアタッチしする。
セキュリティグループは新規作成（ポート80はデフォルトで空いてるので編集しなくてOK）。
***ターゲットの種類は今回EC2インスタンスのロードバランシングをするのでインスタンスを選択***し、***ヘルスチェック***のパスには/wp-includes/images/blank.gifを入力する。
ターゲットの登録では先ほど作成したWordPressをインストールしたEC2インスタンスを選択し、登録済みに追加ボタンを押し、ロードバランサーを作成する。
なお、EC2インスタンスが起動していないと選択肢に出てこないので注意。

状態がActiveになるまで時間がかかるので待機する。

Activeになったら作成したロードバランサーのリスナータブを選択し、デフォルト転送先のリンクを開く。
開いた画面でヘルスチェックの設定が確認でき、ターゲットタブを選択することで、***ターゲットがhealthyなのかunhealthyなのか確認***できる。

ロードバランサーの画面の***説明タブにあるDNS名***をブラウザからアクセスし、WordPressのトップ画面が表示できればOK。

### WordPressの設定
WordPressのトップがのさぁ始めましょうをクリック。
すでに作成したMySQLのユーザ名、パスワードを入力し、***データベースのホスト名にはDBのエンドポイントを入力***する。
無事完了しましたと出れば疎通はOK。インストール実行をクリック。
WordPress用の設定を自由に入力し、作成を行う。
作成後、ログインしダッシュボードを作成する。
左上の最初の記事名を選択すると、記事の画面が表示される。

現時点で、冗長構成はまだだが、ロードバランサーを経由して、EC2のWEBページを表示し、RDBにアクセスする構成となっている。

### AMIと冗長構成の作成

今回は以下の３つをする。
1. AMI(EC2イメージ)の作成
2. AMIからEC2を作成
3. ロードバランサーで２つのEC2に対し冗長構成を実施。

まずはEC2の画面へ移動し、インスタンスタブを選択し、***アクション＞イメージとテンプレート＞イメージを作成***を選択。
名前だけ選択して、作成する。
なお、再起動しないにチェックを入れないので、EC2サーバは再起動がかかる。

EC2の画面から***AMIタブ***を選択し、作成したイメージがあることを確認し、ステータスがavailableになるまで待機。
作成したイメージを選択し、***アクション＞起動***を選択し、パブリックサブネット1cの選択とパブリックIP割り当てにチェックを入れ、（なお、イメージからの作成なので、***ユーザーデータにWordPressインストールのためのコマンドは不要***）、セキュリティグループはすでに作成したWordPress用EC2サーバのセキュリティグループをアタッチして作成する。

EC2サーバが２台とも起動中になれば、EC2画面の***ターゲットグループタブ***を選択し、選択したターゲットグループのターゲットタブを開き、新しいEC2サーバを追加する。
両者のチェックが***healthyになったら冗長構成が完了***している。

### RDSのマルチAZ化

ここまででEC2はマルチAZ構成となったがRDSはシングルAZ構成となっているので、プライベートサブネット1aのRDSを***常時起動のマスターDB***、プライベートサブネット1cのRDSを***複製系のスレーブDB***にする。

RDSの画面を開き、データベースタブを選択し、作成したDBにチェックを入れ、変更ボタンを押す。
マルチAZ配置にチェックを入れ、すぐに適用にチェックを入れて変更を完了する。

ステータスが変更中から利用可能に変わるまでは待機。（***10数分かかる***）。
終われば、マルチAZのステータスがありになる。

この状態で***RDSもマルチAZ構成***となる。

### ロードバランシングとフェールオーバーの確認

まず、ロードバランシングの確認として、EC2の画面を開き、作成したEC2のどちらかを停止させる。
この状態でWordPressにアクセスしても片方が起動しているので、アクセスできることが確認できる。

RDSの画面を開き、データベースタブを選択し、作成したDBにチェックを入れ、アクション＞再起動を選択する。
フェールオーバーで再起動しますかにチェックを入れて再起動をする。
フェールオーバー中はアクセスできないが、完了するとフェールオーバー先にRDSの接続先に切り替わりアクセスができる。

再起動後、通常通りアクセスできることが確認できる。

## ６：AWS 上で静的な Web サイトを公開しよう！

HTMLやCSSを配置して公開する方法を学ぶ。

S3の静的ホスティング機能を使ったり、CloudFrontを使って画像をキャッシュさせたりする。

***Amazon Route53***:ドメイン名を数値のIPアドレスに名前解決するDNSサービス。ユーザはドメイン名でサーバにアクセスできるようになる。


***Amazon CloudFront***:コンテンツのキャッシュをするCDNサービス。WEBサーバのリクエストをキャッシュして保持するため、WEBサーバのアクセス負荷軽減やレスポンス速度向上となる。また、TTL（キャッシュ保持時間）を設定でき、用途に応じてキャッシュ保持の時間を変更できる。

***AWS Certificate Manager***:SSL証明書の発行と設定をする。***ELB,Cloudfrontのみに適用できる。自動更新機能もある。***

***S3バケット***:オブジェクトストレージ。静的コンテンツの配置をして公開することも可能。

### S3の静的ホスティング機能

まずはS3バケットを作成する。
なお、バケット名は***ドメイン名の取得をする場合はドメイン名と同じにしておく必要がある***。
今回は公開するので、パブリックアクセスは許可する必要があるため、アクセスブロックのチェックは外す。

作成後、バケットを開き、プロパティタブを開き、***静的ウェブサイトホスティング***を有効にし、インデックスドキュメントにはindex.htmlを入力。

なお、現時点で、パブリックアクセスになっているわけではない。
***アクセス許可タブのバケットポリシーを編集してパブリックアクセスの許可をすることで初めてパブリックアクセスが許可される***。

以下のような設定をJSONをバケットポリシーに入力する
説明：https://docs.aws.amazon.com/AmazonS3/latest/dev/access-policy-language-overview.html

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::バケット名/*"
            ]
        }
    ]
}
```

次に、index.htmlをアップロードし、プロパティタブの静的ウェブサイトホスティングにあるエンドポイントにアクセスし、正常通り表示できればOK。

### Cloud9から開発し、CLIでアップロード

Cloud9の画面を開き、create environmentからデフォルト設定で作成を行う。
<font color="red">なお、構築時にCloud9が何度かデプロイに失敗したため、VPC、インターネットゲートウェイおよびEC2インスタンスを作成しssh通信をして行った。</font>

以下の通りディレクトリ作成する。

```
mkdir my-webpage
cd my-webpage
```

```
aws s3 cp index.html s3://バケット名
```

<font color="red">なおここでエラーが発生</font>

```
upload failed: ./index.html to s3://バケット名/index.html An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
```

PutObjectを以下の通りバケットポリシーに追加することで、エラーが無くなった。

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::バケット名/*"
        }
    ]
}
```

アップロード完了後、バケットウェブサイトエンドポイントでアクセスできればOK。

CSSファイルなどもまとめてアップロードする場合には以下の通りコマンドを実行する

```
aws s3 cp . s3://バケット名 --recursive
```

### CloudFrontを使った画像キャッシュ

CloudFrontの画面に移動し、Create Distributionをクリックし、Webの方のGet Startedを選択。
Origin Domain NameにS3のバケットウェブサイトエンドポイントを設定して作成。

作成後にGeneralタブのDomain Nameをコピーしてブラウザで開く。

Chromeのデベロッパーツールでネットワークを開き、リロードすることで、リクエストヘッダーにX-Cache: Hit from cloudfrontのような記述があり、キャッシュから取得していることが確認できる。

### Route53で独自ドメインを取得して設定

<font color="red">このハンズオンはドメインの１年間の費用がかかるため注意</font>

Route53の画面からドメインの登録ボタンを押す。

***取得したいドメイン名を入れてチェックを押すことで、そのドメイン名が取得可能か確認***できる。

その後、個人情報を入力して購入する。

メールが届くので、メールを開き、Route53の画面ではステータスの更新ボタンを押し、ステータスに緑のチェックがつく。
ドメインの自動更新もここでONOFFを設定できる。

ここまででドメインの登録が完了でき、保留中のリクエストの一覧にドメインの要求が記録され、１５分くらい経つと、登録済みドメインに登録がされる。

ホストゾーンタブを開き、ドメイン名を選択、レコードセットの作成を選択し、エイリアス名にS3のバケットウェブサイトエンドポイントを設定する。

取得したドメインでアクセスすることで、ページが表示できる。

### ACMを使ってHTTPSでアクセスする

ここでRoute53のエンドポイントはCloudFrontに設定し、
証明書はCloudFrontにインポートする。
また、S3のバケットに直接アクセス禁止し、CloudFrontでしかアクセスできないようにする。

まずは検索ボックスにACMと入力し、AWS Certificate Managerの画面に移動する。
<font color="red">なお、証明書はヴァージニア州で作成しないと使えないので必ずリージョンは変更する</font>
証明書のプロビジョニングで今すぐ始めるを選択し、証明書のリクエストを押す。
ドメイン名にRoute53で取得したドメイン名、検証方法はDNSを選択する。
ステップ 5: 検証ではドメイン名を開き、レコードの作成ボタンを押し、CNAMEレコードを作成する。
最後に続行ボタンを押し、作成をする。

CloudFrontの画面に移動し、作成したリソースを開き、Behaviorsタブを選択し、Editボタンを押す。
***Redirect HTTP to HTTPSにチェックを入れることでHTTPリクエストを強制的にHTTPSリクエストにリダイレクトさせることが可能***。
次にGenaralタブを選択し、Editを押し、***Alternate Domain Names(CNAMEs)に、Route53で取得したドメイン名を入力し、Custom SSL Certificate (example.com)にチェックを入れ、先ほど作成した証明書を選択***する。

ここまでで証明書がCloudFrontにインポートされる。

次にRoute53の画面に移動し、エンドポイントにはCloudFrontを選択する。

全てのアタッチが完了した後にアクセスすることで、HTTPSでアクセスできることになる。また、HTTPはHTTPSにリダイレクトされる。

次に、S3への直接アクセスを抑止する。
まずS3のバケットポリシーを削除し、静的ウェブサイトホスティングも無効にする。
この時点でS3への直接アクセスはできない。

CloudFrontを開き、***Origins and Origin Groupsタブ***を開き、Editを選択。
すでにあるバケットウェブサイトエンドポイントは削除し、プルダウンからS3リソースを選択する。
選択肢が追加されるので、Restrict Bucket Access(ユーザ自身の代わりにオリジンアクセスアイデンティティに設定された権限によりS3にアクセスできる。また、署名付きURLのアクセスのみ許可される)とGrant Read Permissions on Bucket(S3 bucket policyに自動でAccess Identityを追記する)をオンにする。

これにより、CloudFront経由のみのアクセスしかできなくなる。


## ７：監視編 サーバーのモニタリングの基本を学ぼう

サーバー、DBのモニタリングを行う。

モニタリングはシステムのリソース不足、アプリケーションの稼働を確認し、***ユーザ体験を損なわないため***に行う。

インフラ担当者は割り当てている***リソース量に過不足が無いか、不正なアクセスや操作が発生していないか***
開発者は***サービスは適切な応答をしているか、アプリケーションの品質を改善したい***
という思いのもとモニタリングを行う。

今回はCPUのパフォーマンスやDiskのキャパシティ等のリソース監視や各サービスのログ監視を行う。

***AWS X-Ray***:トレース（アプリケーションやサービスの実行状況）を監視する。エラーの原因解明などに使う。

***Amazon CloudWatch***:ログとメトリクス（CPUパフォーマンス等）を監視する。モニタリングに関する様々な機能を所持しており、各種サービスはメトリクスを***CloudWatch Metrics***に送信し、***CloudWatch Alarms***でメトリクス(つまりある閾値を超過するかどうか)に応じたアクションを実行する。なお、***CloudWatch Events***では、イベント（状態の変化など）に応じて「Lambda関数の実行」、「SNSでメール通知」、「Kinesisストリーム」、「SQSキュー」などの実行ができる。
***CloudWatch Logs***はログを収集し、***CloudWatch Log Insights***で可視化する。
***CloudWatch Dashboards***ではメトリクスとログなどを一覧で自由にカスタマイズして確認することができる。



５：スケーラブルウェブサイト構築編で作成したものと同じ構成を実装し監視する。
また、この環境は***CloudFormation***というサービスを利用して作成する。

***CloudFormation***:テキストファイル（テンプレート）を使用して、AWSリソースを環境構築するサービス。
詳細はハンズオン１２で行う。

### 環境の作成
CloudFormationの画面に移動し、スタックの作成を選択。
このハンズオンでは事前ダウンロードしたmonitoring-1.yamlというファイルを使う。（内容は割愛）
完了まで１０分ほどかかる。

作成したら出力タブへ遷移し、２つのEC2DNS名にアクセスする。
WordPressの初期設定は動画に従い入力する。

### メトリクスの確認

CloudWatchを表示し、***メトリクスタブ***を開く。
EC2>インスタンス別メトリクスを開く。
検索ボックスにCPUと入力し、表示されたものの中でにチェックを入れるとグラフで確認できる。
また、上部の時間を選択すると、間隔の時間を選択できる。カスタムで自由な時間間隔のメトリクスも確認できる。

また、ApplicationELB＞AppELB別、TG別メトリクスを選択すると、ELBのメトリクスを確認できる。

次に、RDS＞データベース別メトリクスを選択して、RDSのメトリクスも確認できる。

グラフ化したメトリクスタブを開いて、期間を変更するとグラフの表示間隔の時間を編集することもできる。
グラフのオプションタブを開いて、円形、棒線などグラフの表示の仕方を変更することも可能。

CWAgent>ImageId,InstanceId,InstanceType,device,fstype,pathを開いて、***メトリクスがdisk_used_percent、パスが/のものを開くとディスク使用率***が確認できる。
CWAgent>ImageId,InstanceId,InstanceTypeを開いて、***メトリクスがmem_used_percentのものを開くと、メモリ使用率***が確認できる。

### アラートの使用

アラートは例えば５０％以上ディスク使用率が上がった場合に管理者に通知を送るときなどに利用する。

CloudWatch Metricsの閾値をディスク使用率を設定してCloudWatch AlarmsでSNSのアクションを実行し、Lambdaを実行することなどができる。

今回は、CloudWatch Alarmsでメールを送信する。

***Amazon SNS***:特定のサービスにメッセージを送信するためのサービス。Amazon SQS、AWS Lambda、HTTP、HTTPS、Eメール、SMSなどで受け取れる。

CloudWatch画面からアラームタブを選択し、アラームの作成をクリック。
CWAgent>ImageId,InstanceId,InstanceType,device,fstype,pathを開いて、メトリクスがdisk_used_percent、パスが/のものを選択する。
アラームの条件を90%以上にする。
トリガーは通知にアラーム状態（メトリクスまたは式が定義したしきい値の範囲外にある時）を選択し、メールアドレスを入力し、アラームを作成する。

***通知***:メールなどによって管理者に通知を行う。
***AutoScalingアクション***:オートスケールを実施する。なお、事前にAutoScalingグループの作成をしておくことが必要
***EC2アクション***:EC2の削除や再起動を行う。

作成後、確認メールが届くので開いて紐付けを完了する。

### ログの確認

CloudWatchLogには階層がある
***ロググループ***：複数のログストリームで構成。一般的にはアプリケーションの単位（WEBServerなど）で集約。

***ログストリーム***：複数のログイベントで構成。一般的にはリソースの単位（インスタンスごと）で集約

***ログイベント***：実際のアプリケーションログ

CloudWatchを表示し、***ログタブ***を開く。
View log groupを選択し、ロググループの一覧が表示される。（すでにCloudFormationで作成されている）
保持を失効しないから変更することでログの保存期間も変更できる。
ロググループを開いて、ログストリームからログが確認できる。
フィルターにGETなどを入れてフィルタリングをすることなどが可能。

ハンズオンでは省略したが、CloudWatchグループを作成してEC2からログを収集するにはCloudWatchエージェントのインストールなどが必要。
参照：https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/Install-CloudWatch-Agent.html

### ログ分析

ログ分析は***アクセスログやエラーログの解析によりビジネス、アプリケーションの改善のため***に行う。

ここではCloudWatch Log Insightsでログを検索して分析する。
これはクエリ構文を利用してログの分析を行う。
構文：https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/CWL_QuerySyntax.html

CloudWatchを表示し、***インサイトタブ***を開く。
ロググループを選択し、クエリはデフォルトのままクエリ実行をするだけでもログイン数を確認できる。
また、右側にサンプルのクエリがあるため、それを選択し利用することもできる。

今回はクエリに以下のものを入力する

```
parse '* - * [*] "* * *" * * * *' as host, identity, dateTimeString, httpVerb, url, protocol, statusCode, bytes, referrer, userAgent
| sort maxBytes desc
```

次に400番台のエラーを確認するクエリを以下の通り実行する

```
parse '* - * [*] "* * *" * * * *' as host, identity, dateTimeString, httpVerb, url, protocol, statusCode, bytes, referrer, userAgent
| sort maxBytes desc
 | filter statusCode like /(4\d\d)/
```

なお、この分析の結果はダッシュボードに表示したり、エクスポートしたりすることができる。

### WordPressの監視

ダッシュボードは***１つのサービス、１つのプロダクトのステータスを効率的に確認できるため***、必要。

***Automatic Dashboard***ではAWSが推奨するベストプラクティスに基づいたダッシュボードが作成できる。

CloudWatchを表示し、***ダッシュボードタブ***を開く。
線、メトリクスを選択して作成し、EC2から２つのWebサーバのCPUUtilizationにチェックを入れ、ウィジェットの作成をする。

さらにウィジェットの追加を押し、テキストを選択し、MarkDownを編集し、メモや実行ボタンを作成できる。

次にウィジェットの追加を押し、ログテーブルを選択し、グループからアクセスログを選択することで、ログ一覧を表示させることができる。

最後にダッシュボードの保存を押す。

また、CloudWatchトップにあるCloudWatchタブを押して概要からEC2を選択することで、EC2全体のログを確認できる。

さらにすべてのリソースと書かれているドロップダウンリストからリソースグループの作成を選択し、CloudFormation スタックベースにチェックを入れ、CloudFormation スタックに作成したCloudFormationを選択することでリソースグループの作成ができる。
これを作成した後にドロップダウンからリソースグループを選択することで、特定リソースグループの監視ができる。

### EC2停止時に通知

CloudWatchEventsでイベントをトリガーにアクションを実行する。
今回はアクションでSNSを実行してメールを送信する。

CloudWatchを表示し、***イベントタブ***を開く。
今すぐ始めるを選択し、
イベントソースは***イベントパターンで（スケジュールなども可能）***EC2 Instance State-change NotificationがStoppedの時を選択する。
ターゲットはSNSトピックをCloudWatchAlarm作成時に作成したトピックを選択して作成する。

この状態でEC2を停止させると通知が飛ぶ。


## ８：サーバーレスアーキテクチャで翻訳 Web API を構築する

***サーバレスアーキテクチャ***：インフラの管理や運用が不要で自動でスケールし、高い可用性を持ったリクエストの従量課金制のサービス。EC2に比べて自由度は少ないが、管理の手間は少ない。

***Amazon API Gateway***:サーバを構築、管理することなくAPIを作成、管理するサービス。***可用性、スケーリング、APIキー管理などのAPI開発で必要なことを一任***し、開発者はビジネスの差別化に繋がる作業に中中できる。REST APIとWebSocketに対応している。APIなのでリソース×メソッドの組み合わせでフローを定義する。フローにはメソッドリクエスト、統合リクエスト、統合バックエンド、統合レスポンス、メソッドレスポンスがある。設定はリソースとメソッドごとに定義を行い、APIごとにデプロイする。また、***ステージを作成してそのステージのみにデプロイ可能（本番用と開発用を分けれる）***。その他、バージョニングやログ収集、モニタリングが可能。
***メソッドリクエスト***では、リクエストの受付として認証や受け付けるパラメータ、必須HTTPヘッダなどを設定できる。
***統合リクエスト***では、統合バックエンドで何を使用するか(LambdaやHTTP,Mock、AWSサービスなど)を指定できる。リクエストの変換(XMLをJSONにするなど)も可能、プロキシ統合で変換せずにスルーできる。
***統合レスポンス***では、レスポンスの変換(XMLをJSONにするなど)も可能、プロキシ統合で変換せずにスルーできる
***メソッドレスポンス***では、リクエストに対する最終的なAPI Gatewayとしてのレスポンスに関する設定(ステータスコードやHTTPレスポンスヘッダなど)ができる。

***AWS Lambda***:サーバレスのサービスであり、開発者はコードの記述に集中できる。実行回数や実行時間で課金がされる。対応している言語はいくつかあり、サポートされていない言語はカスタムランタイムを実装して利用する。最初に呼び出される関数はハンドラで指定する。設定できる項目としては確保するメモリの量（CPUはメモリ量に比例する）、タイムアウト値、実行IAMロール（例えばDynamoDBへの書き込み権限など）がある。呼び出し方式としては***非同期型***(例えば、S3へのファイル格納を契機にLambdaが呼び出され、Lambdaへの***リクエストが正常に受付けられたかどうかのみ返却***する)や***同期型***(API Gatewayなどを通じて、Lambdaに***リクエストが飛び、レスポンスを返却***する)がある。Lambdaはコンテナ上で動作し、１つのコンテナでは１つの１つのリクエストまでを受け付ける。***コンテナは再利用される（ウォームスタート）が、利用できるコンテナがない場合新しいコンテナを起動して実行する（コールドスタート）***。
連携パターンとしては、以下のものがある。
1. Lambda関数を同期的に呼び出す（API GatewayからLambdaを呼び出し）。関数の実行が終わるのを待つ必要があり、実行結果が返される。
2. Lambda関数を非同期的に呼び出す（S3のファイル格納などを契機にLambdaが呼び出される）。実行が終わるのを待つ必要がない代わりに実行結果は返されない。
3. Lambdaがストリームベースでイベントを読み取る(DynamoDBへのデータ格納をLambdaが検知し、実行する）。新しいデータが無いかをポーリングしてあれば処理を実行する。
4. Lambdaがストリームベースでなくイベントを読み取る（SQSへのデータ格納をLambdaが検知し、実行する）。新しいデータが無いかをポーリングしてあれば処理を実行する。
上記の分類は以下の通りになる
ポーリングベース：Lambdaがポーリングして、データがあれば関数を実行
　1. ストリームベース（同期呼び出し）→上記の３
　2. ストリームベースではない（同期呼び出し）→上記の４
ポーリングベースでない：Lambdaはイベントソースから呼ばれる
　1. 同期呼び出しタイプ→上記の１
　2. 非同期呼び出しタイプ→上記の２

*** Amazon S3***：高い耐久性（99.999999999%)をもち、３つのAZに跨ってデータ格納される。容量も無制限で、静的WEBホスティング機能もある。

***Amazon DynamoDB***:フルマネージド型のNoSQL。３つのAZに保存されるため信頼性が高く、ストレージの容量制限が無い。また、性能要件に応じてテーブルごとにキャパシティを定義できる。オートスケールも可能。テーブルには一意のプライマリキーがある（パーティションキーもしくはパーティションキーとソートキーの組み合わせ）。
なお、ソートキー以外に絞り込み検索を行うKeyを持つことができる***ローカルセカンダリーインデックス***（あるテーブルをベースに、***パーティションキーはそのままに、異なるソートキーのテーブルを作成する仕組み***）やパーティションキーの代わりに検索を行うための***グローバルセカンダリーインデックス***(あるテーブルをベースに、***異なるパーティションキー・ソートキーのテーブルを作成する仕組み***)を持つことができる。
キャパシティユニットは１ユニットにつき最大４KBのデータを１秒に１回読み込み可能で、１ユニットにつき最大１KBのデータを１秒に１回書き込み可能。

***Amazon Translate***:翻訳サービス

開発者ガイド：https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/welcome.html
APIリファレンス：https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/index.html

今回のハンズオンではAPI Gatewayを経由してLambdaを呼び出し、Lambda上で動くコードがTranslateを呼び出し翻訳結果を取得し、結果をレスポンスとして返す。また、その翻訳結果をDynamoDBに格納する。

### Lambdaの作成

Lambdaの画面に移動し、関数の作成ボタンを押す。
ランタイムはPython3.7で作成を行う。

下にスクロールし、***基本設定を編集することで、メモリや実行時間、IAMロール***を変更することが可能。
基本設定からIAMロールを開くと、権限としてCloudWatch Logsが割り当てられていることなどが確認できる。

右上のテストボタンではテストを作成でき、ドロップダウンから作成したテストを選択してテストボタンを押すことでテストができる。

ハンズオン用のコードを貼り付け、デプロイで保存ができ、テストでデプロイ後のコードを実行できる。
logger.info(event)でログを出力しているので、コンソールにFunction logs:以下にログが出力される。

また、上部にあるモニタリングタブを開き、CloudWatch のログを表示を押し、貯まったログを確認することができる。

### translateの利用

まずはハンズオン通りにコードを変更する。
ポリシーを開き、TranslateFullAccessをアタッチして実行（本来は権限は絞る）すると、翻訳結果がコンソール出力される。

### API Gatewayの作成-Mock

最初にMockでAPI Gatewayを作成する。

API Gatewayの画面に移動し、APIを作成を押す。
RESTを選択し、名前だけ入れて作成する。

アクションからリソースの作成を選択し、名前を入れて作成する。
次にアクションからメソッドの作成を選択し、GETを選択する。
一旦統合タイプはMockを選択する。
統合レスポンスを開き、三角ボタンを押し、マッピングテンプレートのapplication/jsonをクリックし、以下のようなJSONを定義する。

```
{
    "statusCode": 200,
    "body": {
        {
            "report_id": 5,
            "report_title" : "Hello, world"
        },
        {
            "report_id": 7,
            "report_title" : "Good morning!"
        }
    }
}
```

次にフロー画面に移動し、テストボタンでテストを実行し、上記のJSON結果が返ることを確認する。

次にアクションからAPIのデプロイを選択し、新しいステージでDEV等を入れて作成をする。

ステージタブを開き、DEV>/>/handsonrs>GETを開き、URL の呼び出しに記述されているURLを開くとMockのAPIのレスポンスが返却される。

このように、***バックエンドの開発が終わってなくてもモックのAPIを作成することで、効率的にフロントエンドの開発をすることができる***。

### API Gatewayの作成-Lambda

まず、前回作成したMock呼び出しのリソースをアクションから削除する。
アクションからリソースの作成を選択し、名前を入れて作成する。
次にアクションからメソッドの作成を選択し、GETを選択する。
統合タイプはLambdaを選択し、プロキシ統合にはチェックを入れてに、関数は最初に作ったものを選択する。

***プロキシ統合にチェックを入れたため、統合レスポンスは変換できずにパススルーとなる***。
ここをプロキシ統合にチェックを入れないと以下の通りエラーになってしまうので注意。

```
{"errorMessage": "'queryStringParameters'", "errorType": "KeyError", "stackTrace": ["  File \"/var/task/lambda_function.py\", line 8, in lambda_handler\n    input_text = event['queryStringParameters']['input_text']\n"]}
```

まず、メソッドリクエストを開いて、URL クエリ文字列パラメータにinput_textを必須で保存する。

Lambdaを開いてコードを新しいものに編集する。

***設定されたクエリ文字列パラメータは以下のようにして取得***できる。

```
input_text = event['queryStringParameters']['input_text']
```

なお、返却するJsonにはheaderとisBase64Encodedが必要となる。
統合レスポンスドキュメント：https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-integration-settings-integration-response.html

新しいテストをテストテンプレートAmazon API Gateway AWS Proxyにして、queryStringParametersの中身を以下の通り変更する。

```
"queryStringParameters": {
    "input_text": "おやすみ"
},
```

次にアクションからAPIのデプロイを選択し、新しいステージでDEV等を入れて作成をする。
ステージタブを開き、DEV>/>/handsonrs>GETを開き、URL の呼び出しに記述されているURLを開き、***末尾にクエリパラメータを渡す***(?input_text=おやすみ)とAPIのレスポンスが返却される。

### DynamoDBの作成

DynamoDBの画面に移動し、テーブルの作成を押す。
テーブル名をtranslate-history、パーティションキーをtimestamp、デフォルト設定の使用をチェック外して、キャパシティは読み込みも書き込みも１にして作成する。

作成した後に、項目タブを開き、項目の作成から項目を追加することが可能。

コードをハンズオンにしたがって修正し、IAMにAmazonDynamoDBFullAccessを追加する。
（本来は権限は絞る）

テスト、およびURLでのアクセスが成功すればOK。


## ９：AWS SAM を使ってテンプレートからサーバーレスな環境を構築する 

今回はまず、前回作成したような環境をAWS SAMでテンプレートから作成する。

AWS SAM：サーバレスアプリケーション構築用のオープンソースフレームワーク。CloudFormationより簡潔に記述できる。テンプレートを記述してパッケージングしてデプロイする。
使い方は以下の順序で行う。
1. SAMテンプレートを記述
2. パッケージングする
3. デプロイする

SAMプロパティのリファレンス：https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/sam-specification-resources-and-properties.html

### 開発環境の構築

まずはCloud9を構築する。
AWS Resourcesを押し、Lamdbaファンクションのマークを選択して新規作成画面を開く。
ランタイムをPython3.6を選択して他はデフォルトで作成する。
作成が完了したら、Lambdaの画面にもLambdaが追加される。

ソースを編集してRUNボタンを押すとソースを実行できる。
また、Lambdaファンクションボタンを選択して、↑ボタンを押すとデプロイすることができる。

### SAMでLambdaを作成

まずは以下の通りs3バケットを作成する。

```
aws s3 mb s3://バケット名
```

なお、バケット名の命名規則に誤りがあると以下の通りエラーが起こる。

```
make_bucket failed: s3://誤りのあるバケット名 An error occurred (InvalidBucketName) when calling the CreateBucket operation: The specified bucket is not valid.
```

コマンドでディレクトリとpyファイル、yamlファイルを作成する。

```
mkdir 作業ディレクトリ
cd 作業ディレクトリ
mkdir スクリプトディレクトリ
touch スクリプトディレクトリ/pyファイル
touch yamlファイル
```

pyファイルはハンズオンを参考に編集する
yamlファイル（SAMテンプレート）を以下のように編集する

```
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: 説明
Resources:
  TranslateLambda:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: 関数名
      CodeUri: ./スクリプトディレクトリ
      Handler: translate-function.lambda_handler
      Runtime: python3.7
      Timeout: 5
      MemorySize: 256
```

以下のコマンドでパッケージングする(ファイルはS3に格納される）

```
aws cloudformation package \
     --template-file yamlファイル \
     --s3-bucket バケット名 \
     --output-template-file パッケージしたyamlファイル
```


以下のコマンドでデプロイする

```
aws cloudformation deploy \
     --template-file ./パッケージしたyamlファイル \
     --stack-name CloudFormationのスタック名 \
     --capabilities CAPABILITY_IAM
```

<font color="red">なお、このコマンドでエラーが表示された</font>

```
Failed to create/update the stack. Run the following command
to fetch the list of events leading up to the failure
aws cloudformation describe-stack-events --stack-name CloudFormationのスタック名
```

このスタックを確認すると以下のエラーが表示されていた

```
API: iam:CreateRole User: ユーザ名/AWSCLI is not authorized to perform: iam:CreateRole on resource:
```

EC2のユーザには***PowerUserAccess権限***を付与しているが、IAMのアクションが実行できない権限であるため、***IAMFullAccess***をアタッチし作成済みのスタックは消して、再度実行することでエラーは解決した。

### SAMでTranslateとの連携を作成

次にAmazon Translateをソース中で呼び出すために、
ハンズオン通りにpyファイルを新たに書き換える。

yamlファイルも以下の通り書き換える。
ここに書いているように、***アタッチする権限はPolicies以下に記述***する。

```
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: 説明
Resources:
  TranslateLambda:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: 関数名
      CodeUri: ./スクリプトディレクトリ
      Handler: translate-function.lambda_handler
      Runtime: python3.7
      Timeout: 5
      MemorySize: 256
      Policies:
        - TranslateFullAccess
```

再度、コマンドでパッケージングとビルドを行い、Lambdaが更新されていればOK。

### SAMでAPI Gatewayとの連携を作成

ソースをハンズオンの通りに編集する。

yamlを開き、以下の通り編集する。
ここで、Event以下にどのリクエストでLambdaにアクセスするかを記述する。
なお、呼び出し元のAPIGatewayは!Refで参照を行っている。
その下で、作成するAPIGatewayを作成している。

```
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: 説明
Resources:
  TranslateLambda:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: 関数名
      CodeUri: ./スクリプトディレクトリ
      Handler: translate-function.lambda_handler
      Runtime: python3.7
      Timeout: 5
      MemorySize: 256
      Policies:
        - TranslateFullAccess
      Events:
        GetApi:
          Type: Api
          Properties:
            Path: /translate
            Method: get
            RestApiId: !Ref TranslateAPI
  TranslateAPI:
    Type: AWS::Serverless::Api
    Properties:
      Name: translate-api-2
      StageName: dev
      EndpointConfiguration: REGIONAL
```

### SAMでDynamoDBとの連携を作成

ソースをハンズオンの通りに編集する。

yamlを開き、以下の通り編集する。
ポリシーにはAmazonDynamoDBFullAccessを追加でアタッチしている。
また、作成するDynamoDBを作成する記述も追加している。

```
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: 説明
Resources:
  TranslateLambda:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: 関数名
      CodeUri: ./スクリプトディレクトリ
      Handler: translate-function.lambda_handler
      Runtime: python3.7
      Timeout: 5
      MemorySize: 256
      Policies:
        - TranslateFullAccess
        - AmazonDynamoDBFullAccess
      Events:
        GetApi:
          Type: Api
          Properties:
            Path: /translate
            Method: get
            RestApiId: !Ref TranslateAPI
  TranslateAPI:
    Type: AWS::Serverless::Api
    Properties:
      Name: translate-api-2
      StageName: dev
      EndpointConfiguration: REGIONAL
  TranslateDynamoDbTbl:
    Type: AWS::Serverless::SimpleTable
    Properties:
      TableName: translate-history-2
      PrimaryKey:
        Name: timestamp
        Type: String
      ProvisionedThroughput:
        ReadCapacityUnits: 1
        WriteCapacityUnits: 1
```

### SAM CLIの利用

***SAM CLI***：AWS SAMをローカルで使用する上で様々な機能を提供するCLI。要Dockerインストール。2020/07よりメジャーアップデート。（ハンズオンの動画時点ではベータ版）
以下のようなコマンドがある。

sam init：テンプレートを使ってサーバレスアプリケーションを対話形式で初期化
sam build：ローカル環境でビルド
sam deploy --guided：AWS環境へデプロイ
sam validate：SAMテンプレートの事前検証
sam local start-lambda / start-api：LambdaローカルエンドポイントやAPIエンドポイントを起動し、実行のテストが可能

以下のマニュアルを確認してインストールを実行
SAM CLIインストール：https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/serverless-sam-cli-install-linux.html

Dockerインストールして、その後インスタンスを再起動

```
sudo yum update -y
sudo amazon-linux-extras install docker
```

Dockerを起動

```
sudo service docker start
sudo usermod -a -G docker ec2-user
docker ps
```

gitのインストール

```
sudo yum install git
```

Homebrewのインストール。
なお、現時点のHomebrewインストールでは通常ec2-userのパスワードを聞かれるが、Ctrl+Dを押して、パスワードの入力を回避する。

```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
```

パスの追加

```
test -d ~/.linuxbrew && eval $(~/.linuxbrew/bin/brew shellenv)
test -d /home/linuxbrew/.linuxbrew && eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)
test -r ~/.bash_profile && echo "eval \$($(brew --prefix)/bin/brew shellenv)" >>~/.bash_profile
echo "eval \$($(brew --prefix)/bin/brew shellenv)" >>~/.profile
```

インストールされていることの確認

```
brew --version
```

SAM CLIのインストール

```
brew tap aws/tap
brew install aws-sam-cli
```

インストールの検証

```
sam --version
```

プロジェクトの作成をする。
テンプレートはQuick start、ランタイムはPython3.7、サンプルはHello World Exampleを選択して作成。

```
sam init
```

検証およびビルドを行う

```
sam validate
sam build
```

デプロイを行う。
リージョンは東京にして、
変更点を確認するか、IAMを作成するか、CLIでのやりとりをyamlに保存するかを聞かれるので全部yesを選択する。

```
sam deploy --guided
```

なお、ローカルでテストしたい場合は以下の通り起動する

```
sam local start-lambda
```

別ターミナルを開くなどして、起動したLambdaにむけて通信のテストを実行する。

```
curl http://127.0.0.1:3000/hello
```


## １０：AWS Lambda と AWS AI Services を組み合わせて作る音声文字起こし & 感情分析パイプライン

### S3トリガーで実行する

まずはS3バケットを作成する。

次にLambdaの画面に移動し、関数の作成を選択する。
***設計図の使用***にチェックを入れ、s3-get-object-pythonを選択する。
***S3バケットは先ほど作成したものを選択し、全てのオブジェクト作成イベントをイベントに設定***して作成する。（現在はトリガー有効化チェックは無かったため、次の手順で行う）

関数が作成されたら、***デザイナーのS3を開いて、有効化にチェック***を入れる。

ファイルをS3に格納すると、CloudWatchにログが格納されており、Lambdaが起動したことを確認できる。
このフォルダに、ハンズオンでDLした音声ファイルも格納しておく。

### Amazon Transcribeを使った文字起こし

***Amazon Transcribe***：音声をテキストに変換する文字起こしサービス

まずはLambdaを経由せずTranscribeのみを使ってみる。

Transcribeで文字起こしした文字を格納するS3を作成する。

Amazon Transcribeの画面を開いて、Transcription jobsタブを開き、Create jobを選択する。
言語はJapaneseを選択し、input側を最初に作成したS3バケットとそこに格納した音声ファイル、output側をCustomer specified S3 bucketにチェックを入れ、結果格納先のS3バケットを選択して作成する。

ステータスがCompleteになった後に、格納先のS3バケットを見れば、jsonの中身に文字起こしの結果が格納されていることが確認できる。

### Amazon TranscribeとLambdaの連携

まず、Lambdaを開いて、IAMを表示し、AmazonTranscribeFullAccessとAmazonS3FullAccessを追加する。

ソースコードはハンズオンのソースコード通りに変更し、デプロイを押す。（格納先のS3は自分で作ったものに変更する）

再度、トリガーのS3に音声ファイルをアップロードすると、Lambdaが実行され、Transcription jobsにジョブが追加される。
完了後、結果格納先のS3に文字起こし結果のjsonが格納される。

### 文字起こししたテキストをComprehendで感情分析

***Amazon Comprehend***：機械学習を使用した自然言語処理サービス。キーフレーズやエンティティ（場所、日付）の取得、感情分析ができる

先ほど作った結果格納先のS3に文字起こしファイルが格納されたのを契機にLambdaを起動させて、Comprehendを呼び出して結果を表示する。

まずはComprehendの動きを確認する。
Amazon Comprehendの画面を開いて、Launch Amazon Comprehendを選択する。
何か文字を入れて、analyzeボタンを押すことで、分析することができる。

次にLambdaの画面に移動する。

設計図の使用にチェックを入れ、s3-get-object-pythonを選択する。
S3バケットはTranscribe結果格納用のバケットを選択し、全てのオブジェクト作成イベントをイベントに設定し、***jsonファイルが格納された時のみ動作させていため、サフィックスに.jsonを入力して***作成する。
関数が作成されたら、デザイナーのS3を開いて、有効化にチェックを入れる。

IAMを開いて、ComprehendFullAccessとAmazonS3FullAccessを追加する。
ソースコードはハンズオンのソースコード通りに変更し、デプロイを押す。

再度、音声ファイルを最初に作った音声ファイル格納用のS3に格納して、数秒後にCloudWatchを開くと、感情分析したログが表示されていることが確認できる。

### Amazon Pollyで作成した音声ファイルをパイプラインに投入する

***Amazon Polly***：テキストを音声に変換するサービス。

今回はPollyで作成したテキストの音声データを最初に作成した音声ファイル格納用のS3に格納して、パイプラインを流す。

Amazon Pollyを開いて今すぐ始めるボタンを押す。

テキストを入力して、S3に向けて合成ボタンを押す。
S3 出力バケットに作成した音声ファイル格納用のS3の名前を入力して合成する。

タスクIDのリンクを押して遷移し、ステータスが完了になれば、パイプラインが実行される。
CloudWatchのログを確認して実行されていればOK。


## １１：CloudEndure Migrationを使ってオンプレミスサーバーをAmazon EC2に移行する

クラウド移行への道のりは２種類ある

1. ***クラウドネイティブ***：当初からクラウドに最適化した設計を行い、クラウド最適化したアプリ開発を行う。
2. ***リフト＆シフト→クラウド最適化***：当初はハード老朽化やコスト削減目的でクラウドへ単純移行し、移行した後でクラウド最適化させる。

***CloudEndure Migration***：オンプレのマシン上にインストールしてサーバ移行をするエージェント型サーバ移行サービス。物理、仮想マシン問わない。管理コンソールはSaaS上にある。

CloudEndureエージェントがインストールされたオンプレ環境、移行先のAWS環境（移行先のサーバはCloudEndureが自動生成する）、オンプレとAWSを繋ぐ回線（VPN or Direct Connect、Port:1500　暗号化済み）、CloudEndureのSaaSサービスのアカウントが必要。

流れは以下のように実施する。
1. CloudEndure用IAMユーザを作成し、CloudEndure Consoleから認証
2. 移行対象ソースマシンにCloudEndure Agentをインストール
3. オンプレからデータを非同期で転送する
4. ステージング領域にレプリケーションサーバが作成され、データをEBSにレプリケーション
5. カットオーバーを実行し、ステージングEBSからsnapshotが作成され、コンバーターインスタンスにアタッチ->変換->本番用のターゲットEC2インスタンスにアタッチ。
6. コンバーターインスタンスでは、適切なAWSドライバの挿入、ブートローダーの適切な変更、ネットワークアダプターの修正、AWS KMSを使用したOSのアクティベーションを行う

***EBS***：AWS仮想サーバの外付けHDD
***AWS KMS***：暗号化キーを安全に保護し、他の AWS のサービスやカスタムアプリケーションに対して暗号化/復号、署名、および検証の実行を許可するウェブサービス


### ネットワーク構築

まずはオンプレ想定(10.0.0.0/16 & 10.0.0.0/24)、ステージング(10.1.0.0/16 & 10.1.0.0/24)、ターゲットVPC(10.2.0.0/16 & 10.2.0.0/24)を作成する。

次にオンプレ想定VPC上にパブリックIPありでユーザデータに以下の通り入力し、HTTPをセキュリティグループに追加して作成する。

```
#!/bin/bash
yum -y update
yum -y install httpd
systemctl enable httpd.service
systemctl start httpd.service
```

パブリック IPv4 DNSにHTTPでアクセスすると、Apacheのトップページが表示される。
また、SSH通信できることを確認する。

### CloudEndureアカウントの作成

まずは作成ページに移動する。
CloudEndure作成ページ：https://aws.amazon.com/jp/cloudendure-migration/

CloudEndure Migrationの無料ライセンスを取得ボタンを押し、メールアドレスとパスワードを入力する。
メールが届くので、confirm your account requestのリンクを開き、Sign In to the CloudEndureを押し、先ほどのメールアドレスとパスワードを入力し、ログインする。
ポップアップが表示されるため、StartボタンとContinueボタンを押す。

those permissionのリンクを押して、リンク先のJSONを全てコピーする。

IAMの画面に移動し、ユーザタブからユーザの追加を押し、アクセスの種類はプログラムによるアクセスを選択する。
既存のポリシーを直接アタッチを選択し、ポリシーの作成を押す。
JSONに先ほどコピーした内容を入力し、作成する。
作成したポリシーをアタッチし、ユーザを作成し、
<font color="red">.csv のダウンロードを必ず行い、紛失しないようにする。</font>

csvを開き、Access keyとSecret access keyをコピーしてCloudEndureの画面で貼り付け、Saveボタンを押す。

### レプリケーション実行

CloudEndureの画面でSetup & Infoを開き、REPLICATION SETTINGSタブを選択する。
***Migration SourceにはOther Infrastructure、Migration TargetにはAWS Asia Pacific(Tokyo)を選択し、VPCにはステージング環境のVPCを選択***し、保存する。

以下のようなwgetコマンドが表示されるのでコピーする

```
wget -O ./installer_linux.py https://console.cloudendure.com/installer_linux.py
```

ソースVPCに作ったEC2に接続し、上記のコマンドを実行する。

次に、CloudEndureのPythonコマンドをコピーして実行する。

ここまでオンプレ想定の環境に***CloudEndureエージェントがインストールされる。
この時点ですでにレプリケーションも始まっている。***

CloudEndureの画面に戻ると自動で画面が切り替わり、DATA REPLICATION PROGRESSがContinuous Data Replicationになるまで待機する。（１５分ほどかかる）ここまで完了すればカットオーバーができる状態となる。


### カットオーバー

まず、CloudEndureでレプリケーション完了したリソースを選択し、BLUEPRINTタブを選択する。
MachineTypeを入力し、サブネットはターゲットVPCを選択し、プライベートIPはCreateNewを選択して保存する。

以下のコマンドでオンプレ想定EC2の表示ページを変更する。

```
sudo sh -c 'echo CloudEndureHandson >> /var/www/html/index.html'
```

CloudEndureでレプリケーション完了したリソースを選択し、LAUNCH TARGET MACHINEを押し、カットオーバを選択する。
Job Progressを押せば状況が確認できる。
Job finishedが表示されたらOK。（完了まで数分かかる）

EC2を開くと、レプリケーションサーバ（CloudEndureからのレプリケーション先となるサーバ）、コンバータサーバ（各種変換やクラウドツールのインストール）、ターゲットサーバ（IPアドレスが表示されたサーバ）があり、このターゲットサーバにHTTPでアクセスし、HTMLリソースが表示されることを確認する。


## １２：AWS 環境のコード管理 AWS CloudFormationで Web システムを構築する

なぜ、コードで管理するのか。

***構成がコード管理されていないと…***
・手作業で行うと時間がかかる、再現性も乏しい、ドキュメントを作るのも時間がかかり記述漏れもある、複製が難しくヒューマンエラーもある。
・アプリケーションはCI/CDにしていても、インフラも自動化しないと、両者の品質に差が出る。

***イベントへの対応がコード管理されていないと…***
・人為的ミス発生や対応内容の一貫性への懸念

Well-Archtectedフレームワーク
1. 運用をコードとして実行する
2. ドキュメントに注釈をつける
3. 定期的に、小規模な、元に戻すことができる変更を適用する
4. 運用手順を定期的に改善する
5. 障害を予想する
6. 運用上の全ての障害から学ぶ

***コードを使った運用のポイント***
1. コードで全ての構成を定義→同じ環境を迅速に繰り返し作成可能(CI/CDやCloudFormation)
2. イベントに対してスクリプトで対処→自動的に同じ処理を繰り返し実施(CloudWatchの定期イベントやイベントドリブン）
3. アプリケーションと同じ手法でコードを開発→コードと作成したインフラの品質を担保(CI/CD同様に継続的な品質の担保を行う)

***CloudFormation***:テキストファイル（テンプレート）を使用して、スタック(AWSリソースの集合)を作成し、AWSリソースを環境構築するサービス。作成、変更、削除をまとめて行うことができる。
***作成***：テンプレートに定義された構成をスタックで自動作成。並列で行い、依存関係がある場合は自動で解決。
***変更***：スタックに前回との差分を適用。リソース変更時には無停止変更、再起動、再作成のいずれかが発生。Change Setを作ることで差分の内容を事前に確認可能。
***削除***：依存関係を解決しつつリソースを全て削除。データストアはスナップショットの保持が可能。

テンプレートはスタックの設計図で、どのリソースをどう起動するか記述されている。
必須なのはResources(EC2などのスタックを構成するリソースの定義)のみ。

基本的にはテンプレートリファレンスを確認して、記述を行う。

***テンプレートリファレンス***：https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/template-reference.html


### 環境構築

まずCloud9を構築する。

CloudFormationの画面に移動し、スタックの作成を押し、ハンズオンでダウンロードしたファイル(01_vpc.yml)をアップロードし、作成するとVPCが作成される。

Cloud9を開き、ダウンロードしたcfnフォルダを送る。

なお、Cloud9ではなくEC2で行っている場合は以下のようにフォルダを圧縮した後に送る。

```
zip -r cfn.zip cfn
scp  -i キーペア名 cfn.zip ec2-user@パブリック IPv4 DNS:/home/ec2-user
```

SSH通信後に以下の通り解答する

```
unzip cfn.zip
```

まず、01_vpc.ymlを開いて、PublicSubnet1の名前をPublicSubnet1-updateにする

開き方(操作方法はvimで調べる）

```
vi 01_vpc.yml
```

以下のコマンドで***実行済みのスタックと手元にある更新後のスタックの差分を確認***する

```
aws cloudformation validate-template --template-body file://01_vpc.yml
```

以下のコマンドで***実行済みスタックを差分更新する***

```
aws cloudformation update-stack --stack-name 実行済みスタック名 --template-body file://01_vpc.yml
```

これでサブネット名が更新される。

### EC2の作成

次にEC2を作成する。なお、最初に作成したスタック名をハンズオンと違うものにした場合はvimでファイルを開いて以下を編集する。

```
Parameters:
  VPCStack:
    Type: String
    Default: スタック名
```

変更後、作成コマンドを実行する。

```
aws cloudformation create-stack --stack-name handson-cfn-ec2 --template-body file://02_ec2.yml
```

なお、上記のものはサブネットの設定をしていないので、設定を変更する。

最初に作成したスタックのパブリックサブネット１の物理IDをコピーして、02_ec2.ymlに貼り付ける。
また、UserDataにインストールコマンドを入力する（パイプで複数行の入力をOKにする。）

```
Resources:
  EC2WebServer01:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref EC2AMI
      InstanceType: t2.micro
      SubnetId: サブネットの物理ID
      UserData: !Base64 |
        #! /bin/bash
        yum update -y
        amazon-linux-extras install php7.2 -y
        yum -y install mysql httpd php-mbstring php-xml
        wget http://ja.wordpress.org/latest-ja.tar.gz -P /tmp/
        tar zxvf /tmp/latest-ja.tar.gz -C /tmp
        cp -r /tmp/wordpress/* /var/www/html/
        touch /var/www/html/.check_alive
        chown apache:apache -R /var/www/html
        systemctl enable httpd.service
        systemctl start httpd.service
```

これで以下の通り更新処理を実行する。

```
aws cloudformation update-stack --stack-name handson-cfn-ec2 --template-body file://02_ec2.yml
```

CloudFormationの画面に移動し、完了後、サブネットが最初に作成したものに紐づいているのが確認できる。
また、***アクション＞インスタンスの設定＞ユーザーデータを編集からユーザーデータが入力されていることが確認できる。***


次にセキュリティグループの追加をする。
CloudFormationからVPCの物理IDをコピーして以下の通りymlファイルに追加する。

<font color="red">なお、EC2WebServer01と同じインデントでEC2SGを揃えないとエラーになるため注意</font>

```
EC2SG:
  Type: AWS::EC2::SecurityGroup
  Properties:
    GroupDescription: sg for web server
    VpcId: VPCの物理ID
    SecurityGroupIngress:
      - IpProtocol: tcp
      CidrIp: 10.0.0.0/16
      FromPort: 80
      ToPort: 80
```

更新処理を実行するとセキュリティグループがVPCにアタッチされて作成される。

```
aws cloudformation update-stack --stack-name handson-cfn-ec2 --template-body file://02_ec2.yml
```

### RDS,ELBの作成

RDS,ELBを作成するので以下の通り実行する。

```
aws cloudformation create-stack --stack-name handson-cfn-rds --template-body file://03_rds.yml

aws cloudformation create-stack --stack-name handson-cfn-elb --template-body file://04_elb.yml
```

ELBのリソースにアクセスすることでワードプレスが開ける。


## １３：AWS Code サービス群を活用して、CI/CD のための構成を構築しよう！

今回はAWS CodePipelineを使用して、S3やEC2へCI/CDを行う
S3にはCodeCommitにプッシュしたのを契機にデプロイ。
EC2にはCodeCommitにプッシュしたのを契機にCode Buildがビルドし、CodeDeployがビルド成果物をデプロイする。

***AWS CodePipeline***：フルマネージドな継続的デリバリーサービス。ソースコードの変更をトリガーにビルドやデプロイの流れを自動的に実行する。サービスの流れの中に、CodeCommit、Code Build、CodeDeployがある。

***AWS CodeCommit***：フルマネージドなソース管理サービス。スケーラブルでセキュア、Gitツールと連携できる。

***AWS CodeBuild***：ソースコードをコンパイル、テスト実行し、デプロイ可能なソフトウェアパッケージを作成できるサービス。ビルドサーバを立てる必要がなくなる。

***AWS CodeDeploy***：様々なリソースに対してデプロイを行う。オートスケール構成に対しても自動でデプロイする。


### CodeCommitのデプロイ

S3をパブリックアクセスありで作成する。

S3を開いて、プロパティタブを開いて、静的ウェブサイトホスティングを有効にしてインデックスドキュメントをindex.htmlにする。
アクセス許可タブを開いてバケットポリシーに以下の通り入力

```
{
  "Version": "2012-10-17",
  "Statement": [
      {
          "Sid": "PublicReadGetObject",
          "Effect": "Allow",
          "Principal": "*",
          "Action": [
              "s3:GetObject"
          ],
          "Resource": [
              "arn:aws:s3:::バケット名/*"
          ]
      }
  ]
}
```

index.htmlをアップロードしてバケットウェブサイトエンドポイントを開くことで表示されることを確認。

CodeCommitの画面に移動してリポジトリを作成を選択し、名前を入力して作成。

次に、Cloud9を作成する。
EC2インスタンスで行う場合は、gitとpipのインストールをする。

```
sudo yum update
sudo yum install git

sudo easy_install pip
```

SSH通信で接続した後、AWS CodeCommitの認証ヘルパーを参考に設定する。
CodeCommit認証ヘルパー：https://docs.aws.amazon.com/ja_jp/codecommit/latest/userguide/setting-up-https-unixes.html

以下のコマンドを実行

```
git config --global credential.helper '!aws codecommit credential-helper $@'
git config --global credential.UseHttpPath true
```

次にユーザー設定を行う。

```
git config --global user.name "ユーザー名"
git config --global user.email "メールアドレス"
```

CodeCommitのインストールを行う

```
pip install git-remote-codecommit
```

CodeCommitで作成したリソースを開いて、HTTPS (GRC)にクローンコマンドがあるので、実行する

```
git clone codecommit::ap-northeast-1://リソース名
```

ディレクトリに移動する

```
cd クローンしたディレクトリ名
```

index.htmlを作り少し編集したものを、プッシュする。

```
git add -A
git commit -m "init"

git push origin master
```

CodeCommitの画面に移動すると、index.htmlがアップロードされていることが確認できる。

### CodePipelineの利用

CodePipelineの画面に移動して、パイプラインを作成ボタンを押す。
ソースプロバイダは先ほど作成したCodeCommitのリソースを選択する。
ビルドステージはスキップし、作成したS3バケットを選択し、デプロイする前にファイルを抽出するにチェックを入れて作成する。

これでパイプラインが作成するため、S3上のファイルが入れ替わる。

また、再度EC2でファイルを編集してプッシュすると、ファイルが入れ替わり、バケットウェブサイトエンドポイントにアクセスして確認できる。

### デプロイ先のEC2の作成

まず、IAMに移動し、一般的なユースケースはEC2を選択し、***AmazonS3FullAccess***をアタッチしてロールを作成する。(***S3にビルド成果物が置かれ、それが配置されるため***）

EC2の画面へ移動し、先ほどのIAMをアタッチし、セキュリティグループはHTTPを追加し（本来はIPアドレスを絞る）、作成する。

以下のコマンドを実行し、パッケージの更新とhttpdのインストールおよびhttpdの起動とサーバ立ち上げ時にhttpdを起動するようにする。

```
sudo yum update

sudo yum install httpd -y

sudo systemctl start httpd.service
sudo systemctl enable httpd.service
```

これでHTTPアクセスするとApacheのページが表示される。

次にCodeDeployエージェントのインストールを行う。
CodeDeployインストール：https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/codedeploy-agent-operations-install.html

以下の通り実行し、エージェントをインストールする。

```
sudo yum install ruby

sudo yum install wget

wget https://aws-codedeploy-ap-northeast-1.s3.ap-northeast-1.amazonaws.com/latest/install

chmod +x ./install
sudo ./install auto
```

以下のコマンドを実行して、runnningと出力されればOK

```
sudo service codedeploy-agent status
```

### CodeBuildの作成

まず、S3を作成する（パブリックアクセスなし）。
この***S3にはビルド成果物を置くことになる***。

CodeBuildの画面に移動し、ビルドプロジェクトを作成するを押す。

ソースをAWS CodeCommitの先ほど作成したリポジトリ、ブランチをmasterを選択し、
環境でOSをAmazon Linux2、ランタイムをStandard、イメージとイメージのバージョンは一番下のものを選択し、
アーティファクトをタイプはS3で先ほど作成したバケットを選択してビルドプロジェクトを作成する。

ビルドプロジェクトを開き、ビルド詳細タブを選択し、サービスロールを開き、***AWSCodeDeployDeployerAccessをアタッチする***。

Cloud9(もしくは開発用のEC2）を開き、srcフォルダを作成して、index.htmlを移動させる。
コマンドの場合以下の通り

```
mkdir src
mv index.html ./src/index.html
```

srcと同じディレクトリにbuildspec.ymlを作成し、以下の通り記述する。
CodeBuildのリファレンス：https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/build-spec-ref.html

```
version: 0.2

phases:
  build:
    commands:
      - aws deploy push --application-name コードビルドで作成するアプリケーション（後で入力する） --s3-location s3://ビルド成果物を置くS3名/artifact.zip --source src
artifacts:
  files:
    - '**/*'
  base-directory: src
```

### CodeDeployの作成

IAMに移動し、一般的なユースケースは***CodeDeploy***を選択し、作成する。

CodeDeployの画面に移動して、アプリケーションの作成を選択する。
対象はEC2/オンプレミスを選択して作成する。

作成したら、buildspec.ymlのアプリケーション名を作成したものに変更する。

CodeDeployの画面に戻り、作成したアプリケーションを開いて、デプロイグループタブを選択し、デプロイグループの作成を選択。

先ほど作成したIAMロールを設定、環境設定でデプロイ先のEC2インスタンスの設定、AWS CodeDeploy エージェントのインストールはなし（手動で行ったため）、デプロイ設定はAllAtonce、ロードバランシングを有効にするのチェックを外して作成する。

なお、***デプロイ設定は、サーバが複数台並んでいる場合に、一気にデプロイしたいかしたくないかで変更する***。

index.htmlと同じディレクトリにappspec.ymlを作成し、以下の通り記述する。
CodeDeploy AppSpec File リファレンス：https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/reference-appspec-file.html

```
version: 0.0
os: linux
files:
  - source: index.html
    destination: /var/www/html/
```

gitプッシュを行い、CodeBuildのビルドプロジェクトを開いてビルドの開始ボタンを実行。

ビルド完了後、CodeDeployのアプリケーションを開いて、作成したアプリケーションにチェックを入れてアプリケーションをデプロイするを実行する。
デプロイグループは先ほど作成した物を選択し、リビジョンの場所はビルド成果物置き場のS3のリビジョンを選択し、デプロイを作成する。

<font color="red">なお、IAMをEC2につけ忘れていた場合、以下の通りエラーが発生した。</font>

```
The overall deployment failed because too many individual instances failed deployment, too few healthy instances are available for deployment, or some instances in your deployment group are experiencing problems.
```

デプロイのステータスが１００％になり、成功すると、デプロイ先EC2サーバにHTTPアクセスすれば、デプロイしたhtmlが表示される。

### CodePipelineの作成

CodePipeLineを構築することで、***CodeCommitへのプッシュを検知し、自動でビルドまで行うようになる***。

CodePipelineを開いて、パイプラインを作成するを選択する。
***ソースステージ、ビルドステージ、デプロイステージに作成したCodeCommit、CodeBuild、CodeDeployを設定***し作成する。

パイプライン作成のタイミングでフローが一度実行される。

次にCloud9にログインしてソースを編集し、プッシュする。

デプロイ先EC2にHTTPアクセスして、変更後のHTMLが表示されたらOK。


## 感想

動画視聴だけでなく、実際に一通り構築することで、エラーにも遭遇して、より理解が深まった。

各サービスのUIはよく変更が行われるため、手順よりも実際に何を設定したか理解することで、いつでも誤りなく環境を構築できると感じた。