はじめに
コンテナをマネジメントする様々なサービスが登場し、コンテナを利用する敷居が下がってきています。今回はその中でも特に設定が簡単だと思われるAmazon ECSでGoのEchoサーバを立ち上げる方法を紹介します。
全体の流れ
ECSで独自イメージのコンテナを立ち上げるには、以下の4つの手順が最低限必要です。
- ECSで使用するロールをIAMで作成する
- VPCを作成する(defaultのVPCは使わない)
- ECRにDockerイメージをプッシュする
- ECSでコンテナを立ち上げる
まずはこれらのサービスについて簡単に説明します。
サービスの概要
それぞれのサービスで何ができるかについて簡単に説明します。
IAM(Identity and Access Management)
IAMはリソースに紐付ける事ができる権限設定を管理するためのサービスです。
IAMには「グループ」、「ユーザ」、「ロール」、「ポリシー」の4種類があります。
これらのうち、IAMポリシーはAWSリソースにアクセスするための権限設定で、はじめから用意されています。
また、IAMロールはAWSのリソースに付与するもので、IAMロールの実体は1つ以上のIAMポリシーをグループ化したものです。
IAMについてはこちらが参考になります。
VPC(Virtual Private Cloud)
VPCは自由にアクセスのコントロールを設定できるネットワーク空間です。
例えば、アプリケーションは外部からアクセス可能にするが、DBは外部からアクセスできないようにするなどの設定が行えます。
VPCに関連する項目としては、サブネット、インターネットゲートウェイ、セキュリティグループなどがあります。
VPCについてはこちらが参考になります。
ECR(Elastic Container Registry)
ECRはフルマネージドなDockerコンテナレジストリサービスです。
ECRは「レジストリ」と「リポジトリ」から構成され、1つのリージョンに1つのパブリックレジストリとプライベートレジストリを持つことができます。
レジストリには1つ以上のリポジトリを持つことができ、コンテナイメージはリポジトリの中に保存されます。
ECRについてはこちらが参考になります。
ECS(Elastic Container Service)
ECSはフルマネージドなコンテナオーケストレータです。
コンテナオーケストレータというとまずkubernetesが連想される方が多いと思いますが、kubernetesと比べ設定が簡単で運用コストが低い事がメリットです。
一般的にコンテナ運用は複数のホストからなるクラスター構成し、その上で複数のコンテナが連携してアプリケーションを提供します。この際、コンテナのワークロードを管理するシステムがオーケストレータで、AWSではECSがこれにあたります。
ECSでは以下のような設定が行えます。
- コンテナの配置管理
- ロードバランサーによる負荷分散
- コンテナのスケーリング
- コンテナのIAM権限管理
- CloudWatchとの連携
ECSが今回の記事でいちばん重要なサービスなのでより細かく紹介します。
ECSについて詳しく
ECS特有の知識について「データプレーン」と「コントロールプレーン」という概念に分けて説明します。
データプレーン
データプレーンはコンテナが稼働する環境を指します。データプレーンには「ECS on Fargate」、「ECS on EC2」、「ECS Anywher」の3つの種類があり、それぞれ管理の容易さや設定の柔軟さが異なります。
これらを簡単に説明しますと、「ECS on Fargate」はフルマネージドなデータプレーンで、コンテナが動作するホストを意識することなくコンテナを稼働させることができます(ホストマシンやOSの管理を行わなくて良い)
「ECS on EC2」はEC2上で動作するデータプレーンで、自分で構築したEC2上でECSコンテナエージェントを実行することで、EC2上にECSで管理可能なコンテナを稼働させる事ができます。
「ECS Anywher」はオンプレミス上で動作するデータプレーンで、自分が所有しているハードウェアマシン上でコンテナを稼働させます。
この中でよく使われると思われる「ECS on Fargate」と「ECS on EC2」の差としては、EC2インスタンスやクラスターの管理をしなくて良いため「ECS on Fargate」の方が管理が楽ですが、「ECS on EC2」の方がホストマシンの細かい設定ができる点で設定がより柔軟です。
また、「ECS on Fargate」はパブリックIPを固定できない点や、sshやdocker execなどを使って直接コンテナにアクセスできないなどのデメリットがあります。
コントロールプレーン
コントロールプレーンでは以下の4つの概念が登場します。
- クラスター
- サービス
- タスク
- タスク定義
これらの関係については、以下の図をご覧ください。
クラスター
クラスターはタスクまたはサービスの論理グループです。
サービス
サービスは指定した数のタスクを同時に実行し、その実行数を維持するスケジューラーです。
サービスは設定した数のタスクをタスク定義をもとに起動し、タスクの同時起動数を維持します。これにより、何らかの原因でタスクが停止した場合に新たにタスクを起動することで同時起動数を維持したり、タスクの負荷分散やオートスケーリングを行うこともできます。
タスク
タスクはタスク定義をもとに作られるアプリケーションの実行単位です。
タスク定義
タスク定義はコンテナで使用するDockerイメージや各タスク・コンテナに割り当てられるCPUやメモリの量、環境変数などの設定を記述します。これらはJSON形式で記述され、別途コンソール上からGUIで作成・編集することができます。
タスク定義には複数のコンテナを指定することができるので、1つのタスクとして複数のコンテナを稼働させることもできます。
ECSについてもっと詳しく知りたい方はこちらが参考になります。
ECSでEchoサーバを立ち上げる
それでは実際にECSでEchoサーバのコンテナを立ち上げてみます。
IAMでロールを作成する
まずはじめに、ECSで使用するロールを作成します。IAMのサイドメニューの「アクセス管理/ロール」からロールを作成します。
「ユースケース」の「他のAWSサービスのユースケース」で「Elastic Container Service」を選択すると候補が4つ表示されるので、以下の3つを選択してロールを作成します。
- Elastic Container Service
- Elastic Container Service Task
- EC2 Role for Elastic Container Service
「Elastic Container Service」と「EC2 Role for Elastic Container Service」に関しては特に変更する必要はなく、ロール名を設定するだけです。
「Elastic Container Service Task」については「AmazonECSTaskExecutionRolePolicy」のみアタッチします。
VPCを作成する
VPCでは以下の4つを作成します。
- VPC
- サブネット
- インターネットゲートウェイ
- ルートテーブル
一つずつ見ていきます。
VPCを作成する
VPCのサイドメニューの「お使いのVPC」からVPCを作成します。「名前タグ」、「IPv4 CIDER」を以下のように入力してVPCを作成します。
サブネットを作成する
サイドメニューの「サブネット」から先程作成したVPCにサブネットを作成します。「VPC ID」で先程作成したVPCを選択し、以下のようにサブネットを2つ設定してサブネットを作成します。
インターネットゲートウェイを作成する
サイドメニューの「インターネットゲートウェイ」からインターネットゲートウェイを作成します。「名前タグ」を入力してインターネットゲートウェイを作成します。
その後、作成したインターネットゲートウェイの「インターネットゲートウェイID」をクリックして詳細に遷移し、「アクション」から「VPC」にアタッチします。
ルートテーブルを編集する
サイドメニューの「ルートテーブル」から作成したVPCのルートテーブルを編集します。
「VPC」が先程作成したVPCのIDになっているレコードの「ルートテーブルID」をクリックして詳細に遷移し、「ルート」の「ルートを編集」からルートを追加します。
「送信先」を0.0.0.0/16に、「ターゲット」を先程作成したインターネットゲートウェイのIDを選択し、変更を保存します。
ECRにDockerイメージをプッシュする
VPCが作成できたら、ECSで立ち上げたいコンテナのイメージをECRにプッシュします。
「ECS」のサイドメニューの「リポジトリ」からリポジトリを作成します。以下のように「可視化設定」をプライベートにし、リポジトリ名を入力し、イメージスキャンの設定を有効にしてリポジトリを作成します。
リポジトリを作成したら、リポジトリ名をクリックして詳細に遷移し、「プッシュコマンドの表示」をクリックします。すると以下のようなモーダルが表示されるので、記載されているコマンドを順番に実行します。
最後のコマンドを実行して暫く経つと、イメージが反映されます。
Echoサーバのサンプルコード
Echoサーバを立ち上げるためのサンプルコードはこちらです。
1 2 3 4 5 6 7 8 9 10 11 12 | FROM golang:1.19.1-alpine ENV ROOT=/go/src/app ENV CGO_ENABLED 0 WORKDIR ${ROOT} RUN apk update && apk add git COPY go.mod go.sum main.go ./ RUN go mod download RUN go build main.go CMD ["./main"] |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | package main import ( "net/http" "github.com/labstack/echo/v4" ) func main() { e := echo.New() e.GET("/", func(c echo.Context) error { return c.String(http.StatusOK, "Hello, World!") }) e.Logger.Fatal(e.Start(":80")) } |
ECSでコンテナを立ち上げる
最後に、これまでに準備したものを使ってECSでコンテナを立ち上げます。
ECSでは以下の3つを作成します。
- クラスター
- タスク定義
- サービス
一つずつ見ていきます。
クラスターを作成する
サイドメニューの「クラスター」からクラスターを作成します。
クラスターのテンプレートの選択では「ネットワーキングのみ」を選択して「次のステップ」に進みます。
「クラスター名」を入力し、「CloudWatch Container Insights」にチェックを入れて「作成」をクリックします。
タスク定義を作成する
次にタスク定義を作成します。サイドメニューの「タスク定義」から「新しいタスク定義の作成」をクリックします。
「起動タイプの互換性の選択」では「FARGATE」を選択して「次のステップ」に進みます。
「タスクとコンテナの定義の設定」では「タスク定義名」を入力し、「タスクロール」で予め作成したロールを選択し、「オペレーティングシステムファミリー」に「Linux」を選択します。
「タスクサイズ」では「タスクメモリ」と「タスクCPU」を選択します。
「コンテナの定義」では「コンテナの追加」をクリックし、「コンテナ名」を入力し、「イメージ」に作成したECRのURIを入力し、「メモリ制限」と「ポートマッピング」を入力して「追加」をクリックします。
サービスを作成する
最後にサービスを作成します。作成したクラスターの詳細の「サービス」タブの「作成」からサービスを作成します。
「起動タイプ」に「FARGATE」をチェックし、「サービス名」を入力し、同時に起動する「タスクの数」を入力し、「次のステップ」をクリックします。
「VPC とセキュリティグループ」の「クラスターVPC」にすでに作成したVPCを選択し、「サブネット」に作成したサブネットを全て選択します。
「ロードバランシング」では、今回はロードバランサーを使わないのでそのまま「次のステップ」をクリックします。
「Auto Scaling (オプション)」では、今回はオートスケーリングの設定を行わないので、そのまま「次のステップ」をクリックします。
設定内容を確認の上、「サービスの作成」をクリックしてサービスを作成します。
サービスの作成後しばらくするとタスクが起動されるので、タスクの詳細を開き表示されているパブリックIPにアクセスするとEchoサーバが表示されるようになります。
さいごに
ECSでGoのEchoサーバを立ち上げる方法を紹介しました。今回はドメインの設定、ロードバランシングやオートスケーリングの設定等は行いませんでしたが、実際にサービスを動かすにはこれらの設定が必要になると思います。今後もっと掘り下げて行きたいと思います。