AWS CodePipelineでAmazon ECS(Fargate)上にREST APIを自動デプロイする

Pocket

はじめに

こんにちは!山内です。最近マイクロサービスについて勉強していまして、ついにECSを触る機会がありました。(遅いって言わないで!)
API Gateway + Lambda構成と違うところが結構ありましたので、備忘録も兼ねて記事にします!※スクリーンショットは2021/03時点のものです。

環境準備

AWSリソースの作成

まずは下記のAWSリソースを作成します。

  • CodeCommit
  • ECR
  • ECS(Fargate)
  • CodePipeline
    • CodeBuild

CodeCommit

まず、CodeCommitのリポジトリを作成します。特に注意点はありませんが、ローカルで開発するので、CloneとFirst Commitを済ませておきましょう。その際に、IAMユーザの「認証情報」タブから「AWS CodeCommitのHTTPS Git認証情報」を発行する必要があります。

ECR

  1. ECRのマネジメントコンソールを開き、「リポジトリを作成」をクリック
  2. 下記設定を行い、「リポジトリを作成」をクリック
    1. 可視設定  : プライベート
    2. リポジトリ名: 任意
  3. プライベートリポジトリ一覧から、作成したリポジトリをクリックし、「プッシュコマンドの表示」をクリック
  4. AWS CLIが叩ける環境にて、Node.jsプロジェクトおよびDockerfile(下記を参考)を用意し、コピーしたコマンドを実行

  5. AWSコンソールで、対象のリポジトリにイメージが登録されていることを確認
    ※後で使うので、「イメージのURI」>「URIのコピー」からイメージURIをコピーし、メモしておくこと

ECS(Fargate)

  1. ECSのマネジメントコンソールを開く ※ECSの機能の一部がFargate
  2. 左サイドメニューから「クラスター」をクリック
  3. 「クラスターの作成」をクリック
  4. 「ネットワーキングのみ」を選択し、「次のステップ」をクリック
  5. 下記設定を行い、「作成」をクリック
    1. クラスター名: 任意
    2. その他: デフォルト

  6. 「クラスターの表示」をクリック
  7. 左サイドメニューの「タスク定義」をクリック
  8. 「新しいタスク定義の作成」をクリック
  9. Fargateを選択し、「次のステップ」をクリック
  10. 下記設定を行い、「作成」をクリック
    1. タスク定義名: 任意
    2. タスクメモリ (GB): 0.5GB
    3. タスクCPU (vCPU): 0.25vCPU
    4. 「コンテナの追加」から下記を設定し、「追加」をクリック
    5. コンテナ名: 任意
    6. イメージ: ECR設定時にコピーしたイメージのURI
    7. ポートマッピング: 8080/tcp ※API用
    8. その他: デフォルト

  • 「タスク定義の表示」をクリック
  • 「アクション」>「サービスの作成」をクリック
  • 下記サービスの設定を行い、「次のステップ」をクリック
    1. 起動タイプ: FARGATE
    2. クラスター: 先ほど作成したクラスター
    3. サービス名: 任意
    4. タスクの数: 1
    5. その他: デフォルト

  • 下記ネットワーク構成の設定を行い、「次のステップ」をクリック
    1. クラスターVPC: 任意のVPC(必要に応じて新規作成してもOK)
    2. サブネット: 任意のサブネット(今回はパブリックサブネット2つを指定)
    3. セキュリティグループ: 任意(8080ポート/TCPへのアクセスを許可してあるもの)
    4. その他: デフォルト

  • Auto Scaling設定はデフォルトのまま、「次のステップ」をクリック
  • 設定を確認し、「サービスの作成」をクリック
  • 「サービスの表示」をクリックし、作成されていることを確認

CodePipeline

CodePipelineを作成しつつ、一緒にECRとCodeBuildを作成します。なお、API Gateway + Lambda構成のときとほとんど変わらなかったので、スクショは割愛します。

  1. CodePipelineコンソール上で「パイプラインを作成する」をクリック
  2. パイプライン名とサービスロールを選択して、「次に」をクリック
  3. 下記ソースステージの設定を行い、「次に」をクリック
    1. ソースプロバイダー: AWS CodeCommit
    2. リポジトリ名: 先ほど作ったCodeCommitのリポジトリ名
    3. ブランチ名: 任意(今回は簡単のため「master」のまま)
    4. その他: デフォルト
  4. 下記ビルドステージの設定を行い、「次に」をクリック
    1. プロバイダー: AWS CodeBuild
    2. リージョン: アジアパシフィック(東京)
    3. プロジェクト名: 「プロジェクトを作成する」から作成
        下記設定を行い、「CodePipelineに進む」をクリック

      1. プロジェクト名: 任意
      2. 説明: 任意
      3. 環境イメージ: マネージド型イメージ
      4. オペレーティングシステム: Amazon Linux 2
      5. ランタイム: Standard
      6. イメージ: aws/codebuild/amazonlinux2-x86_64-standard:3.0
      7. 特権付与: チェックを入れる
      8. その他: デフォルト
    4. その他: デフォルト
  5. 下記デプロイステージの設定を行い、「次に」をクリック
    1. プロバイダー: AWS ECS
    2. リージョン: アジアパシフィック(東京)
    3. クラスター名: 先ほど作成したECSのクラスター名
    4. サービス名: 先ほど作成したECSのサービス名
    5. その他: デフォルト
  6. 「パイプラインを作成する」をクリック

自動デプロイの設定

下記buildspec.ymlファイルをプロジェクトのルートに配置します。後述しますが、5、6行目でDockerHubのアカウント情報を使っています。実際の開発ではハードコーディングだと問題なので、SecretManagerなどを活用しましょう。

APIの実装

いよいよ、「server.js」ファイルにAPIを実装します。今回は「Hello MISO」と返すAPIにします。 「express」というモジュールを使っているので、npm install expressして、package.jsonの依存関係に追加しておきましょう。Gitにモジュールを載せたくないので、「.gitignore」ファイルの設定も忘れずに!

デプロイ

APIの実装が終わったら、GitコマンドでGitリポジトリへ変更をpushします。 GitへのpushをトリガーにCodePipelineが動いて、ECSへのデプロイまでの流れが全て成功するまで待ちます。

動作確認①

デプロイまで成功したら、ECSの「サービス」から作成したサービスを選びます。「設定とタスク」タブを選択すると、タスクが1件表示されているので、そのタスク名をクリックします。その後、「ネットワーキング」タブを選択し、「パブリックIP」のIPアドレスをコピーします。ブラウザにて、「コピーしたIPアドレス:8080」にアクセスし、「Hello MISO」と表示されることを確認します。

APIの変更とデプロイ

APIを少し変更して、再度デプロイしてみます。今回は「Hello MISO v2」と返すようにserver.jsを変更し、Gitへpushします。

動作確認②

今回はDNSの設定など何もしていないので、タスクごとに新しいパブリックIPアドレスが割り当てられています。そのため、先ほどと同じ手順で「パブリックIP」のIPアドレスをコピーします。ブラウザにて、「コピーしたIPアドレス:8080」にアクセスし、「Hello MISO v2」と表示されることを確認します。

苦労したところ

1つ苦労したのが、自動デプロイ時にDocker Hubのダウンロード数制限に引っかかってエラーで落ちてしまうことがありました。Docker Hubからコンテナイメージをダウンロードするリクエスト数に制限があり、匿名ユーザーだとIPアドレスごとに6時間に100リクエストしかダウンロードできません。 CodeBuildの東京リージョンのIPアドレスは2020/10時点で8つしかないので、東京リージョンを利用している全ユーザで6時間に100リクエストしかダウンロードできないことになります。ただ、Docker Hubのアカウントを作成すれば、アカウントごとに6時間に200リクエストまで可能になるので、小規模なアプリケーションを開発する分には問題ないでしょう。それ以上のリクエストを行いたい場合は、ECRに専用のイメージを登録して、直接ダウンロードする方が良いと思います。

おわりに

ECS初めて触ったのですが、結構楽しいですね!マイクロサービスってフワフワした概念で難しいですが、実際に構築してみると感覚が身に付いてくると思います。皆さまも是非、チャレンジしてみてはいかがでしょうか!

お問い合わせ先

執筆者プロフィール

Yamauchi Kentaro
Yamauchi Kentarotdi デジタルイノベーション技術部
社内の開発プロジェクトの技術支援や、Javaにおける社内標準フレームワークの開発を担当しています。Spring BootとTDDに手を出しつつ、LINE Botとかもいじったりしています。最近はマイクロサービスを勉強しつつ、クラウドアプリケーションを開発できるエンジニアの育成にも力を入れてます!
Pocket

関連記事