こんにちは。4課の古川です。今回は、現在(2020/03/23)開催中のAWS Innovate 2020でのセッション「ところで、コンテナ化ってどうやってやれば良いの」を視聴して、学んだことを記事にしたいと思います。
そもそも、なぜこのセッションを視聴しようかと思ったのかというと、以前自身でwebアプリを開発した際に、開発環境ではdocker,docker-composeを使用して開発を行っていたものの、本番環境へのデプロイができなかったからです。
それではよろしくお願いします。
セッション概要
ワークロードをコンテナ化する際のよくある質問として下記3つがあげられます。
- Webサーバー1台をコンテナ化すると、1つのコンテナイメージになるのか
- DockerコンテナとECSのタスクやEKSのpodってどう関係するのか
- アプリケーションをコンテナ化するには、まず何をすれば良いのか
今回のセッションではこういった質問に対して、どうアプローチすれば良いのかを紹介しています。
コンテナ化に向けた検討のSTEP
コンテナ化に向けて、どんな取り組みを行わなければならないのか下記に示します。
- コンテナ化するワークロードの特定
- 小さな既存システムを対象にすることで、コンテナ化に向けて変えるべきもの、変更の影響を具体的に把握する。
- コンテナ化するコンポーネントの特定
- ECSやEKS等の、コンテナ関連ツール・サービスの準備
- コンテナイメージの作成
- オーケストレーションツールを利用したデプロイ
今回のセッションでは、
コンテナ化するコンポーネントの特定する
コンテナ関連ツール・サービスの準備
コンテナイメージを作成
の3つにフォーカスします。
想定するワークロードイメージ
今回のセッションで想定するワークロードは、下図のようなWEB3層モデルです。
- ELB(Elastic Load Balancing)を利用した負荷分散
- DBはマネージドサービスを使用
- 各層はそれぞれ独立的にスケールin/out,up/downを行う
コンテナ化するコンポーネントの特定する
3つの基本的な考え方を押さえる必要があります。
- 1つの仮想サーバには、複数のコンテナ化対象のコンポーネントがある
- 例えば、Webサーバーを考えた時に、apacheやNginxなど複数のprocessが動いている
- 複数のプログラムの各々が、コンポーネントの対象であると見なす
- 仮想サーバをコンテナ化する
- 1つのDockerイメージで構成するわけではない
- アプリケーションのdeployは複数のコンテナを同時に実施する必要がある。
では、これらの考え方を元に、もう少し掘り下げます。
layer(役割)ごとに考える
Webサーバ層で考えると、httpサーバとしてApachやNginxが動作しており、他にも監視エージェントやloggingプログラムなどが動作しています。そして、それぞれがコンテナイメージ化の対象となります。
deployする単位を考える
各レイヤー毎に複数のコンテナを同時にdeployする必要があります。また、各コンテナに割り当てるCPU/メモリリソースの設定や、downstreamへの接続エンドポイント・認証情報などの、レイヤー内のコンテナに関する設定は共通化する必要があります。
スケーリングする単位を考える
コンテナの場合、複数のコンテナの固まりでスケーリングする。そのため、複数のコンテナの固まりをどのように捉え、どのように増減するかを考える必要があります。
コンテナ関連ツール・サービスの準備
コンテナ関連のAWSコンテナサービスを下記に記載します。
役割 | 説明 | サービス名 |
---|---|---|
オーケストレーション | コンテナのデプロイ、スケジューリング、スケーリング | ECS、EKS |
イメージレジストリ | コンテナイメージの格納 | ECR |
ホスティング | コンテナ実行環境 | EC2、Fargate |
初めてのコンテナワークロードにオススメのサービス
運用についての検討事項を減らしつつ、少ない学習量で利用開始ができる組み合わせとして以下があげられます。
- Amazon ECS(※EKSも選択可)
- コンテナを本番環境で利用するためのAWSネイティブなオーケストレータ
- Amazon ECR
- 高可用かつスケーラブルなプライベートイメージレジストリ
- AWS Fargate
- AWSがユーザーにかわって、コンテナ実行環境の仮想マシンを管理・運用
- コンテナネイティブな実行環境を提供
以降は、この組み合わせについて説明します。
Amazon ECS/Fargate アーキテクチャに整理
3つの概念
抑えるべき3つの概念について説明します。
- Task(定義)
- アプリケーションを構成する1つ以上のコンテナ群(を定義したもの)
- Service(定義)
- 維持・戦略に基づきTaskをスケジュールする(設定を定義したもの)
- Cluster
- TaskやServiceをまとめる論理グループ
これまで整理してきた考え方と上記3つの概念を対応させます。
Task定義
- 複数のコンテナの固まり + コンテナに関する設定 => Task定義
Task定義では、利用するDockerイメージの指定や、コンテナに割り当てるリソースの設定を行います。
Service定義
- 複数のコンテナの固まりの数を設定する => Service定義
Service定義では、起動しているTaskの数や、Taskを配置する条件を設定します。
ツール・サービスが提供する機能
ツール・サービスの機能を利用することで、構成をシンプルにすることが可能になります。
- ロギング
- ベストプラクティスとして、ログを標準出力/エラー出力に出力することによって、CloudWatch Logsに自動で出力される
- ロギングコンテナが不要になる
- モニタリング
- CloudWatch Container Insights /CloudWatch Logs Insightsを利用すれば、Taskやコンテナレベルでメトリクス・ログを取得可能
- 監視エージェントコンテナが不要になる
コンテナイメージを作成
オーケストレーションによってコンテナはデプロイされます。
Dockerコンテナとして必要となるポイント
- サーバアプリケーションをフォアグランドで実行する
- SIGTERMをハンドリングできるようにする
- コンテナが止まった場合、「docker stop」というdockerコマンドに似たシグナルが発行され、これがDockerアプリケーションに渡される仕組みを作る。
- ログ出力に標準出力/エラー出力を活用する
DB接続について
DBへの接続情報を外部から取得します。
RDSの場合であれば、接続エンドポイント、ユーザ・パスワード等の環境に依存する設定や認証情報を、環境変数などを利用して外部から取得する様に変更する必要があります。
まとめ
- コンテナ化するコンポーネントの特定
- layerごとに考える
- deployする単位を考える
- スケーリングする単位を考える
- コンテナ関連ツール・サービスの準備
- 運用の観点から、初めはECS、ECR、Fargateの組み合わせがオススメ
- Task、Service、Clusterの3つの概念を理解する
- ツール・サービスが提供する機能によって、ロギング・モニタリングが可能
- コンテナイメージを作成
- Dockerコンテナとして必要なポイント
- DB接続情報の取得方法
所感
Ruby on Railでアプリケーションを作成しEC2上にデプロイする際、WEBサーバ(apache、nginx)やAPサーバ(puma、unicorn)、場合によってはDBを1つのサーバ上にデプロイします。
このままコンテナ化しようと思うと、コンポーネントを大きく捉えてしまうかもしれません。
コンテナ化する際は、layerとデプロイする単位をしっかり意識することが大事だと思います。
次回は、コンテナ運用の、考え方について投稿したいと思います。