細かいTodoとかスクショは載ってませんm(_ _)m
infraガチ勢じゃないので叩くところあったら叩いてくださいm(_ _)m
DBはSQLServerを使っています
コレは何
社内技術検証中に、ECSにKotlinで書いたAPIをデプロイしたくなったのですが、設定周りで結構つまづいたのでメモ。
詳細な手順は載せませんm(_ _)m。
本業の合間に3日間ぐらいマネジメントコンソールをぽちぽち~詰まってはまたぽちぽちを繰り返しました。(ツラかった)
ECR(DockerイメージをPushする先)とECS(DockerイメージをPushした先)だけ気にしてりゃええやろ、と思っていたらVPCエンドポイント
とApplication Load Balancer
の設定がキーポイントでした。
読者想定
- Dockerfileは書ける/Docker Buildはできる/RepositoryにPushできる
- AWSアカウントを持っていて、コンソールからぽちぽちする
- ネットワーク周りの知見がある
- ここ全然言語化できてなくてスミマセン...自分infraが本職じゃないのでうまく細分化してかけないのですが、cidrとかtcp/ipとかの知識は最低限あると良いと思いました
- 任意の言語でアプリが書ける
- ワイはKotlin*SpringBootで適当なAPIを書きました
作りたかった構成
このブログの構成図をめちゃくちゃ参考にしました
https://blog.not75743.com/post/ecs_private/
参考
必要なもの(改めて言語化)
レシピのようなものです。下記を新規作成しました。
(デフォルトのVPCとかは使ってないです)
VPC周り
- VPC1個
- サブネット4個
- 2AZ * Public/Privateで4つ
- インターネットゲートウェイ1個
- パブリックにしたい方のサブネットに紐づける
- ルートテーブル2個
- Publicに紐づける用/Privateに紐づける用で2個
- セキュリティグループ3つ
- ApplicationLoadBalancer用
- Internetからの入口
- 任意のアドレスからポート8080の通信を許可
- ECSコンテナ用
- ALB->ECSの通信許可用
- 上記ALB用SGからポート8080の通信を許可。(コンテナは8080ポートを解放している前提)
- VPCエンドポイント用
- ECS->CloudWatch等のAWSリソースへの通信許可用
- 後で作るVPCエンドポイントと紐づける
- ECSコンテナ用SGからの443(HTTPS)通信を許可。
- RDS用
- ECS->Databaseの通信許可用
- VPCのCidrからのtcp通信を許可 ポートはどのDB製品を使うかによる(MySQL->3306,SQLServer->1433
- ApplicationLoadBalancer用
EC2
VPCエンドポイント
VPCエンドポイントはインターネットを介さず、VPC内でのAWSリソース間通信を可能にするものです。
- VPCエンドポイント3つ
- ECS->ECR接続用に2つ.DockerImageをPullするための通信に必要.下記サービスを有効化
- com.amazonaws.ap-northeast-1.ecr.dkr/interface型
- com.amazonaws.ap-northeast-1.ecr.api/interface型
- ECS->CloudWatch接続用に2つ.log等を出すためのもの.下記サービスを有効化
- com.amazonaws.ap-northeast-1.logs/interface型
- ECS->S3接続用に1つ.
- com.amazonaws.ap-northeast-1.s3/gateway型
- ECS->ECR接続用に2つ.DockerImageをPullするための通信に必要.下記サービスを有効化
Application Load Balancer
インターネットを通じてAPI叩けるように設定していきます。
- ターゲットグループ
- VPCと紐付け
- port:8080
- protcol: HTTP
- ターゲットタイプ:IP
- ヘルスチェック追加
- APIにヘルスチェック用APIを生やす必要があります
- 作ったヘルスチェック用APIのパスを設定
- LoadBalancer
* ApplicationLoadBalancer型
* internet-facing
* IPv4型
* 上記で作ったALB用セキュリティグループと紐付け
* プライベートサブネット2つ(a,c)と紐付け
* リスナー作成
* port:8080
* protcol:HTTP
* "forward to"として上記ターゲットグループを選択
RDS周り
各種〇〇グループ
- DBサブネットグループ(上で作ったVPCサブネットグループとは別)
- 上記で作ったプライベートグループ2つと紐付け
- DBパラメータグループ(←マネジメントコンソールからDBインスタンス作れば自動生成される)
- DBオプショングループ(←マネジメントコンソールからDBインスタンス作れば自動生成される)
DBインスタンス
- DBインスタンス
- ここまで作ってきたVPC/Subnet/DBSubnetを紐づける
- SSMSとかDBeaver等のSQLクライアントからSQL流したい場合は、パブリックアクセスをtrueに
ECS周り
- Elastic Container Repository(ECR)
- BuildしたイメージをPushする先
- ContainerがイメージをPullし、動作する
- タスク定義
- FARGATEで起動
- コンテナの定義(ここが大事)
- ECRにPushしたイメージ/タグを指定
- ex:{ECR番号}dkr.ecr.{region}.amazonaws.com/{image名}:{タグ名}
- ポートマッピングとしてhostPort:8080,containerPort:8080
- 環境変数が必要ならそちらを利用
- ECRにPushしたイメージ/タグを指定
- クラスター
- "ネットワーキングのみ"指定
- 作成済のVPCと紐付け
- サービス
- 起動タイプはFARGATE型
- 作成したタスク定義(おそらくversionは1になってるはず)を指定
- 作成済のVPC/プライベートサブネット/ECSコンテナようセキュリティグループと紐付け
- タスク数を1に指定
- コレを0にするとタスクが立ち上がらない状態を作れる
- 作成済のロードバランサと紐付け
- 型はApplicationLoadBalancer
動作確認
自分はURLhttp://{ALB名}.{Region名}.elb.amazonaws.com:8080/{アプリで指定したルーティング}
にPostmanで通信しました。curlでやってもブラウザから叩いてもOK、お好きなようにどうぞ!
まずはアプリ側で200を返すだけの"/health_check"をみたいなAPIを生やして、デプロイできたか確認するのがおすすめです。
terraform化してみた
- Lambdaもくっついてるけど無視して下さい
参考文献
特に1件目のブログには大変お世話になりました。
改善点
まだできてない、実運用だと絶対やるべきだよなぁというやつ
※あくまでAPIで200OKが返ってくることをゴールに作ったので許してください
- デプロイ自動化周り
- ECSをBlue/Greenデプロイ仕様にする
- サービス止めずにデプロイするのに便利なはず...
- ECRへのPushも自動化
- GitHubActionsかCodePipeline使うんだろうと思っている
- IAM/権限周りの整理
- 今結構ガバガバ
- ECSをBlue/Greenデプロイ仕様にする
- タグのlatest運用をやめる
- 切り戻しとかができない/いつPushしたバージョンを使ってるのか不明になる、などの理由からNG
- ドメインの設定
- APIを実際に利用したい時、本記事の設定だとALBが自動で発行したドメイン
http://{ALB名}.{Region名}.elb.amazonaws.com:{Port}/{アプリで指定したルーティング}
みたいなやつを利用す流必要があります。 - 多分Route53を使うんだと思う、知らんけど
- APIを実際に利用したい時、本記事の設定だとALBが自動で発行したドメイン