はじめに
本記事を書くきっかけ
最近コンテナを学び始めました。
Docker Desktopや物理サーバーでコンテナを動かすことをしたあと、AWSのECS(Elastic Container Service)に挑戦したのですが、どこにどのような設定を入れるのか少し混乱しました。
ECSの仕組みや構成、設定項目(クラスターの設定、タスク定義、サービスの設定、コンテナの定義)の役割を理解しようと考え、本記事を書くことにしました。
自分のレベル
コンテナ初心者です。
本記事の対象読者はECSをこれから使う方で、コンテナの基礎的な知識は持っている方を想定しています。
今回やること(構成図)
ECSではどのようにコンテナを展開するのか、設定項目の役割を確認しながら単純なWEBサーバーを構築します。
詳細な手順は記載しません。あくまでもECSの設定項目が果たす役割を確認することが目的です。
AWS Fargateではなく、ホストはEC2を使用します。また、ALBは使用しません。
完成形の構成図としては下のようになります。後半でも記載しています。
マルチAZ構成のパブリックサブネットに、1台ずつホスト(EC2)を展開し、その中にコンテナを一つずつ動かします。
コンテナの基本
本題に入る前に、コンテナの基本的な構造をおさらいしたいと思います。
物理構成
ECSではなく、コンテナを物理環境で動かす場合、以下のパターンが考えられます。
それぞれの物理構成について説明します。
物理サーバー/物理サーバー&仮想環境
「物理サーバー」と「物理サーバー&仮想環境」の違いは、仮想環境の有無のみです。
どちらにおいても、Linuxをインストールしてその中にDocker Engineをインストールします。そしてDocker Engineの上でコンテナが動作します。
Docker Desktop
Docker社が提供するDocker Desktopを使用すれば、ノートPCなどでコンテナを動かすことができます。
MacでもWindowsでも、Docker Engineを動かすLinuxはパッケージ(インストーラー)から提供されます。
Windowsでは仮想環境にHyper-V(Microsoftが提供)を使用しますが、Macでは仮想環境(HyperKitと呼ばれるもの)もパッケージから提供されます。
ECSでは物理環境をほぼ意識する必要がない
ECSにおいては、コンテナサービスをAWSがフルマネージドで提供しているので、物理構成を意識することはほぼありません。そのためとっつきにくくなっていると感じます。
やってみる
ではECSでのコンテナ構築を行っていきます。ですがコンテナイメージが無ければ話にならないので、ECSの前にまずECR(Elastic Container Registry)にイメージをプッシュすることから始めます。
事前準備(ECRへのコンテナ登録)
ここでは、httpdのコンテナイメージを使用します。
AWSコンソールで、ECRにリポジトリを作成します。”httpd”という名前にしました。
コンテナイメージのPullとPushはクライアントPC(手元のPC)での作業です。
httpdのコンテナイメージをPullします。
### httpdコンテナイメージを手元のPCにダウンロード
PS > docker pull httpd
Using default tag: latest
latest: Pulling from library/httpd
a603fa5e3b41: Pull complete
4691bd33efec: Pull complete
ff7b0b8c417a: Pull complete
9df1012343c7: Pull complete
b1c114085b25: Pull complete
Digest: sha256:f2e89def4c032b02c83e162c1819ccfcbd4ea6bdbc5ff784bbc68cba940a9046
Status: Downloaded newer image for httpd:latest
docker.io/library/httpd:latest
PS >
### Pullしたイメージの確認
PS > docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
httpd latest 8653efc8c72d 2 weeks ago 145MB
コンテナイメージにタグを付けてECRへPushします。
### AWSクレデンシャル設定
PS > $env:AWS_PROFILE="プロファイル名"
PS >
### ECRレジストリ認証
PS > aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin [AWSアカウントID].dkr.ecr.us-east-1.amazonaws.com
Login Succeeded
PS >
### コンテナイメージにタグ付け
PS > docker tag [コンテナイメージID] [AWSアカウントID].dkr.ecr.us-east-1.amazonaws.com/httpd:latest
PS >
### ECRにプッシュ
PS > docker push [AWSアカウントID].dkr.ecr.us-east-1.amazonaws.com/httpd:latest
The push refers to repository [[AWSアカウントID].dkr.ecr.us-east-1.amazonaws.com/httpd]
a4a57da7ddfc: Pushed
a0b242781abd: Pushed
29657939e55a: Pushed
7603afd8f9aa: Pushed
ec4a38999118: Pushed
latest: digest: sha256:f2f8e87c61c78701277b59757b6e43d531571e4426b512f5248729811508d2de size: 1366
ECRにアップロードされたことが確認できました。
それではECSの設定項目について見ていきながら、コンテナ環境を構築していきます。
クラスターの設定
クラスターはタスクとサービスの集まりです。
※タスクとサービスについては後述しますが、簡単に言うとタスクはコンテナをインスタンス化するもので、サービスはコンテナの数を一定に保つものです。
クラスターの設定では、コンテナを動かすホスト(EC2)の設定と、ネットワーク(VPCやサブネット)の設定を行います。前述した物理構成で言えば、「物理マシン」〜「Linux」の設定といえます。
Fargateの場合はホストはAWSによって管理されるため、ネットワークの設定のみとなります。
下はクラスターを作成開始するときの初期画面です。FargateにするかEC2を使用するか、選択を促されます。
ホストがEC2の場合で話を進めます。クラスターの設定での主な項目は以下になります。
- インスタンスの設定
- インスタンスタイプ
- インスタンス数
- AMI
- ネットワークの設定
- VPC
- サブネット
- セキュリティグループ
- コンテナインスタンスの設定
- コンテナインスタンスのIAMロール
下はクラスターの作成が完了した画面です。クラスターリソースの箇所に、作成されたリソースが表示されています。
各AZのパブリックサブネットを選択し、インスタンス数は”2″としました。これでマルチAZ構成になります。
補足ですが、ECSのクラスターの作成によって、EC2の”起動設定”と”Auto Scalingグループ”も作成されます。”起動設定”と”Auto Scalingグループ”により、ホストのEC2インスタンスが起動することになります。
クラスターだけ作成が完了すると、構成図は概ね以下のようになっています。
タスク定義
タスク定義は一つ以上のコンテナを定義する設定項目です。タスクからコンテナが実行されます。
タスク定義で設定する主な項目は以下です。
- タスクロール
- ネットワークモード
- タスクサイズ
- コンテナの定義
タスクロールはコンテナインスタンスに割り当てるIAMロールです。
ネットワークモードは”bridge”、”ホスト”、”awsvpc”から選びます。ここではポートマッピングを使用しますが、bridgeでのみ実現可能です。
※ネットワークモードの詳細についてはこちらへ。
タスクサイズはタスクに割り当てるメモリとvCPUのハードリミットです。ホストのメモリを超えないように注意します。
コンテナの定義はその名の通りコンテナの設定で、どのイメージを使うかや、ポートマッピングの設定などを行います。
タスク定義を作成して、クラスターに割り当てることで、コンテナが実行されます。
下はタスク定義を作成して、クラスターに登録した画面です。
タスク定義に登録したコンテナは1つです。タスク登録のときに「配置テンプレート」という項目を”AZバランススプレッド”(複数のAZまたは複数のインスタンスにタスクを分散配置)に設定したので、各AZにコンテナが1台ずつ動いています。
ここまでで動作確認をします。タスクの定義画面からコンテナの詳細画面を見ると、”外部リンク”という項目があります。ここに「[EC2インスタンスのパブリックIP]:8080」のリンクがあるのでクリックします。(ポートマッピングしているので「〜:8080」となっています。
コンテナのWEBサーバーにアクセスできて、コンテナ内のindex.htmlの内容が返されます。(デフォルトでは「It works!」)
ここまでの状態を構成図に書くと、概ね以下のようになると思います。
後述しますが、サービスを使用せずタスクのみでコンテナを起動すると、コンテナが障害などで停止してしまった場合、停止したままとなります。
コンテナの実行数を一定に保つための、サービスの定義を見ていきたいと思います。
サービスの定義
タスク定義の登録だけでコンテナを動かすことはできましたが、コンテナ数を一定に保つためにはサービスの定義が必要です。
たとえば、コンテナの実行数を”2″と定義しておけば、障害でひとつのコンテナがダウンしてコンテナ実行数が”1″になっても、自動的に新しいコンテナを起動されコンテナ実行数が”2″に戻ります。
下はクラスターにサービスの定義を作った画面となります。タスクの数(必要なタスク)は”2″としました。
タスクを確認してみると、2つのタスクが起動しています。起動元がecs-svs(ECSサービス)となっており、サービスからタスクが起動されたことがわかります。
すぐに新しいタスクが起動しました。”2″個のコンテナ実行数が保たれています。
構成図は以下となります。サービスがタスクを管理するイメージとなります。