2020/09/05 Amazon ECS
祝 100記事!!
どうでもいい記事が多いけど
こうやって書くの嫌いじゃないので苦ではないです。
学校の授業でECサイトを作ろうということで、今回はコンテナ技術のECSを利用する。
https://gyazo.com/e23e790f5a097b6a226d15c9f8d95692
手順を書いていく。
AWS
リージョンの選定
まずはリージョンを決める。
お財布のことを考えつつも、低レイテンシーな東京を選択。
VPCの作成
まずはVPCを作る。
コンソール上でサービスからVPCを選択。
https://gyazo.com/5c67a343984cca46d85f6ab156196f14
https://gyazo.com/be295f19e8eabbf594994a30f510be9a
名前
名前の命名規則は作るべき。
自分の中でまだ定まっていないので、とりあえず、
<名前>-<サービス>
という形にする。
IPv4 CIDRブロック
最低プレフィックスは16
今回は10.0.0.0/16 を選択
テナンシーはデフォルト。
サブネットの作成
左のタブからサブネットを選択。
サブネットを作成。
名前をつける。
命名規則の通り、
<名前>-subnet-a
<名前>-subnet-b
<名前>-subnet-c
と名をつける。
3つあるのは東京リージョンのAZそれぞれに名をつけるため。
VPCはさっき作った、<名前>-vpcを選択
CIDRブロックはVPCのネットワークをサブネット化する。
10.0.0.0/24 10.0.1.0/24 10.0.2.0/24
の3つを作成する。
インターネットゲートウェイの作成
現在、3つのサブネットにはインターネットへの経路がない。
そこで、まずはインターネットに出るための経路を作る。
左タブからインターネットゲートウェイを選び、作成。
名前をつける。
<名前>-internetgateway
作るだけでなく、VPCにアタッチする必要がある。
作成したインターネットゲートウェイを選び、
VPCにアタッチ。
https://gyazo.com/dc49307f3380537832e7a8689de0763b
デフォルトルートの作成
VPCに対して、インターネットへの出口を作成した。
しかし、ルーティングしなければ外へ向かうことができない。
左のタブからルートテーブルを選択。
VPCに紐づくルートテーブルを選択し、下のルートタブを選択。
ルートの編集から、ルートの追加。
現在は、自分のサブネットに対して、「local」のみ。
追加内容は、
送信先: 0.0.0.0/0
ターゲット:前に作ったインターネットゲートウェイ
ルートを保存する。
セキュリティグループの作成
次に、セキュリティグループを作成する。
便利なファイアウォールのようなもの。
今回作成するセキュリティグループは
<名前>-instance
<名前>-alb
<名前>-rdb
の3つ。
見ればわかる通りに割り当てる。
<名前>-instance
これはECSで使うホストに割り当てる。
このホストにはロードバランサーからの通信がランダムなポートでやってくる。(詳細は後で)
また、家からはSSHのアクセスを許可する。
したがって、インバウンドに2つ設定する。
タイプ:すべてのトラフィック
ソース:カスタム(<名前>-alb),
タイプ:SSH
ソース:マイIP
<名前>-alb
これはALBに割り当てる。ALBは次で設定する。
このALBにはネットワーク上からHTTP、HTTPSがやってくる。
したがって、インバウンドに2つ設定する。
タイプ:HTTP
ソース:任意,
タイプ:HTTPS
ソース:任意
<名前>-rdb
これはRDBに割り当てる。RDBはあとで設定する。
このRDBにはインスタンスからMySQLの3306にやってくる。
したがって、インバウンドに1つ設定する。(後にPHPMyAdminを構築するため、実際は2つ)
タイプ:MySQL
ソース:<名前>-instance,
これらを設定するには、
左上のサービスからEC2を選び、左タブのセキュリティグループを選択。
セキュリティグループの作成。
名前を上の通りにつける。
説明はわかりやすく自由に。
VPCは作成したものに。
インバウンドルールにそれぞれ設定する。
アウトバウンドはデフォルトのまま、すべてのトラフィックで良い。
TagsにはName:<名前>を付けておくといい。
ターゲットグループの作成
今回はECSを利用するため、タスクがターゲットとなる。
ECSに必要な知識
コンテナ、タスク、サービス、クラスター
コンテナはDockerエンジンの上で動く、Namespaceで隔離された仮想のホスト。
タスクはコンテナを複数格納するECS上での最小単位。
サービスはサービスと提供するために、タスクをまとめることが出来る。クラスターにサービスとしてデプロイする。
クラスターはECSの管理の元立ち上がるEC2インスタンス。自動的にクラスターに登録される。
つまり、タスクに対してパケットをロードバランシングしたい。
待受ポートどうするの問題
タスクという単位でコンテナを動かす。
同じタスクを同一EC2上に複数立ち上げる場合、待受ポートが重複してしまう。
ECSではこれを解決する仕組みがある。
Nginx(Webサーバ)の待受を8080とすると、
EC2待受ポート:コンテナ待受ポート
に対して、
0:8080と設定することで、
AWSが勝手にEC2待受ポートをランダムで設定してくれる。
被ることがないのでコンテナを同じEC2の上に複数立ち上げられるすげーやつ。
上の2つを踏まえて、ターゲットを設定する。
左タブのターゲットグループを選択。
Create target groupを選択。
ECSをEC2で動作させる場合はInstancesを選択(Fargateの場合は違う…?未検証)
ターゲットグループ名を決める。
<名前>-ecs-task
プロトコルとポートは、実際はランダムだが、ここは仮で決める。
HTTP:8080
設定したVPCを選択。
ヘルスチェック
これはロードバランス時に、ターゲットが落ちていないかを確認するヘルスチェックという機能。
これで失敗(Unhealthy)になると、ターゲットに対して通信を割り振ってくれない。
自分はここでドハマリした。
というのも、Basic認証をかけていたので、ヘルスチェックが常に失敗し、タスクが起動しては落ちるを繰り返す。
そこで、ヘルスチェック用にBasic認証のないパスを作り、そのパスにヘルスチェックを行うようにした。
次にタグを作る。これも名前をつける。
Next
ターゲットを設定するが、ここは無視する。
ECSのサービス作成時に、ここに自動で追加する設定があるため必要ない。
ここで設定しても、毎回ポートが変わるので意味ない。
最後に作成をして終了
ALB(ロードバランサー)の作成
左タブからロードバランサーを選択。
今回はアプリケーションロードバランサーを利用する。
ロードバランサーを作成を選択し、Application Load Balancerを選択。
名前をつける。
<名前>-alb
IPアドレスタイプはipv4にする。
リスナーはHTTPとHTTPS
VPCを選択。
アベイラビリティーゾーンの設定は最初に作ったサブネットのAZを選択。
今回は最大で3台のインスタンスをオートスケールで実装し、各ホストを違うAZに置くので、3つ指定する。
2回次に進み、セキュリティグループの設定。
作成した、<名前>-albを選択。
ルーティング設定では作成したターゲットグループを選択。
そのまま進み、作成。
Amazon Certificate Manager
途中でHTTPSを選択した場合、証明書の選択が必要になる。
HTTPSを利用するには、サーバ証明書と秘密鍵が必要になる。
ALBを利用する場合、AWS上で無料で利用できる。
ACMのページに向かい、ドメインを入力する。
すると、認証方法が聞かれるので、DNSを選択する。
そこで表示された、TXTをDNSレコードに登録する。
Route53を利用している場合は簡単に登録出来るが、利用していない場合は各DNSサーバにて設定する。
認証が通ると、利用できるようになる。
ECSクラスター作成
左上サービスからECSを選択。
左のクラスタータブからクラスターの作成。
「EC2Linux+ネットワーキング」を選択。
クラスター名を決める。
<名前>-cluster
プロビジョニングはオンデマンドのまま。
EC2インスタンスタイプは気をつける。(ミスると高い課金されるかも)
今回は無料枠のインスタンスタイプである「t2.micro」を選択。
インスタンス数は「1」
キーペアは作成したものを選択。
作成していない場合は新たに作成する。
VPCを選び、3つのAZを選ぶ。
Autoassignpublicipについては有効にする。
ハマリポイント
自分はここでハマった。
パブリックのIPを割り当てないと自動でクラスターに登録されない。
EC2は起動するのにクラスターに無いのはなぜだとかなり悩んだ。。。
セキュリティグループは前に作成したものを選択。
<名前>-incetance
IAMロールはデフォルトにある「ecsInstanceRole」を選択
タグはつけると良い。
タスク定義の作成
左タブからタスク定義を選択。
新しいタスク定義の作成を押す。
タイプはEC2
タスク定義名をつける。
<名前>-task
ロールは「ecsTaskExecutionRole」を選択。
ネットワークはデフォルト。
ロールも同様に「ecsTaskExecutionRole」を選択。
タスクサイズはここでは指定しない。
コンテナを追加する。
コンテナ名を決める。
次にイメージ。
自分は自分で作成したコンテナをECRにアップロードしているため、
それを選択。
もしくはDockerhubから取得できる。
メモリ制限は128MiBを選択。
ポートマッピング
これはかなり重要。
ホストポートを0にすることで、ランダムポートで待ち受ける。
ホスト:コンテナ
0:8080に設定する。
8080については、自分のコンテナによって変わる。
スタートアップ依存
コンテナの立ち上げる順番を決める。
自分の場合は、PHPFPMにあるコンテンツをNginxで共有するため、
PHPFPMを先に立ち上げる必要がある。
そこで、Nginx側では、スタートアップにPHPFPMをSTARTとして設定している。
NginxではPHPFPMのボリュームをマウントするため、
ボリュームソースにPHPFPMのコンテナ名を入力。
作成する。
サービスの作成
サービスはクラスターにデプロイするために設定する。
左のクラスタータブを選択し、作成したクラスターを選ぶ。
サービスタブの作成を選択。
起動タイプはEC2
リビジョンはまだ1回目なのでデフォルト。
サービス名をつける。
<名前>-service
タスクの数は、タスク定義で256MiBだったので、t2.microのメモリ1GBを考えると、
タスクの数3がMAX。とりあえず3を選択。
配置テンプレートに関しては、スケールインを考えてビンパック
ただフォールトトレラントを考えると、複数AZのAZバランススプレッドが良い?
ロードバランサの選択。
ALBを選ぶ。
IAMはデフォルトであるものを選び、
ロードバランサは作成したものを選ぶ。
ターゲットグループも作成したものを選ぶ。
次へ進む。
AutoScalingはとりあえず後回しなので次に進む。
サービスの作成。
以上でデプロイされる。
これでブラウザから表示できるはず。
状態のチェック方法としては、
クラスターのサービス内、タスクタブのステータス、
クラスターのインスタンスタブのEC2の状態。
ターゲットグループのターゲットのヘルス。
https://gyazo.com/f5dded583d6de862408f9f99e12476f2
=====================================
余談。
東京リージョンとバージニア北部リージョンで同じコンテンツを置いた比較。
東京:144ms
北アメリカ:760ms
ぜんぜん違う:D