[レポート]「JAWS-UG コンテナ支部 入門編 #6 コンテナの始め方」 ~コンテナワークロード編~ #jawsug_ct

「Dockerについて使い方はわかったけど本番環境にどうやって導入するの?」

こんな状態に陥っていません? そうです、私のことです。どうも奥です。

自分の開発環境に導入して便利だなぁと思ったり、チュートリアルを一通り試してはみたものの、本番環境にDockerを導入、運用するのかのイメージが全く浮かび上がりません。
そしてDockerを導入することがサービスのマイクロサービス化であるとどうしても意識してしまいより一層わからないものになっています。

そんな中今回受講した「JAWS-UG コンテナ支部 入門編 #6」では下記のような内容を学ぶことができました。

  • コンテナを導入するまでの流れを掴み、具体的なイメージできるようになる
  • コンテナの導入までのタスクを理解する

本記事では私が学んだことをまとめますので、同じ様な疑問を持った方の助けになれば幸いです。

講演内容

講演者 : 原 康紘さん(@toricls)
講演資料: これからはじめるコンテナワークロード

なぜコンテナか?

大きな理由としてコンテナ化のメリットである「CI/CDによる自動化、それによるデリバリ速度の向上」や、「リソース集約率を高めることでの仮想マシンコストの削減」を享受することが大きなモチベーションです。
そして、このメリットを作り上げるコンテナの特性は大きく3点挙げられます。

Run Anywhere

どのような環境でも一貫して実行できます。
サーバにDockerエンジンを導入しておけば、本番環境でもローカル環境でも同じDockerコンテナを起動することができます。

Portability

Run Anywhreを捕捉するように可搬性が高いです。
そしてこの可搬性の高さを支えるエコシステム(コンテナイメージの作成からレジストリ、アップロード、そしてダウンロード)が存在することも強みの1つです。

Isolated Processes

コンテナ単位でのプロセスレベルで柔軟にリソースを割り当てられます。
それによって高速な起動と停止も実現されます。

なぜオーケストレーションツールか?

先ほど挙げたコンテナの機能性は単一ノードにおけるライフサイクルで生じます。 そのため複数サーバにまたがって同じコンテナを実行したり、スケジューリングしたり、コンテナのオートヒーリングといったことが苦手です。 なのでオーケストレーションツールを用いることでこれらのような機能性も実現させます。

コンテナ化を阻む4つの誤解

コンテナにまつわるいくつかの誤解がコンテナを導入する壁を高くしています。
なのでまずは、この誤解を無くして導入までの障壁を少しでも低くしましょう。

まずはどのオーケストレーションツールを使うかを考えなければならない

オーケストレーションツールの選択と導入が目的になっていませんか。
先に何を実現したいのか何を解決したいかといったゴールがあってその上で正しいツールを選択する必要があります。
ECS か EKS の選択が目的になるとコンテナで何を解決したいかが有耶無耶になってしまいます。
解決したいことに対して最適なアプローチを取れるようにツールを選択するべきです。

コンテナを使うならマイクロサービス化をしなければならない

コンテナの導入がマイクロサービスとイコールではありません
マイクロサービスはあくまでもユースケースの1つです。

コンテナ化で開発・運用手法が大きく変わる

コンテナ導入による影響範囲を狭めて導入していけば問題ありません。
またそういった導入方法もあり、本セッションで触れています。

はじめてのコンテナ利用は新規開発プロジェクトが良い

ケースバイケースですが、既存ワークロードをコンテナ化した方がやりやすいことが多いです。
また本セッションでは既存ワークロードへのコンテナ導入のことに触れます。

コンテナの導入から運用まで

コンテナ、オーケストレーションツール、そしてコンテナ化を阻む誤解について理解したところでどのようにコンテナを導入していくかについて確認します。
新しい技術を導入するには何をするのか、何でやるのかといった目的ゴールを明確にして、それへの道筋を描く必要があります。

また、ゴールに到るまでのマイルストーンを適切に配置する必要があります。
マイルストーンを元にタスクを作り、そしてタスクで何を実現するのか、しないのかをはっきりさせます。

そしてイテレーションを常に回す必要があります。
ポイントとしては常にイテレーションを回せる状態を維持することです。

それでは初めてのコンテナ環境を作るのにオススメのゴールや進め方はどういったものでしょうか。
「既存システムを構成するアプリケーションの1つをコンテナに置き換える」のがオススメです。
なのでゴールは置き換え前と後で同じ動きをすることになります。
そして、既存の開発・運用フロー変えないように進めることも必要になります。

何故これがオススメなのでしょうか。理由としては下記の通りです。

  • コンテナを本番環境に投入できる状態になるまでの間でもコンテナ化するアプリケーション以外は今まで通り変更を加えていくことができる
  • コンテナ化がうまくいかなかったとしてもコンテナを消すことで元の環境に戻せる
  • 新規アプリケーションにコンテナを採用すると、やりたいことが増えすぎることが多い

それでは実際にマイルストーンをどのようにおいて、実際に何をするかの確認をしていきましょう。

1st Milestone

まずは多くの変更を加えずにコンテナでの動作検証をすることが目的です。
またそのために最低限の改修点を改修してシステムが動作するようにさせます。
なのですることは下記のような流れになります。

  1. コンテナの特性とそれらが解決する課題を知る
  2. コンテナ化
  3. 手動でのデプロイ

コンテナの特性とそれらが解決する課題を知る

そもそも今回解決したい課題がコンテナ化で解決するのかどうかを判断します。
例えばAWS Lambdaを使用した方が良いケースなども存在するのでしっかりと検討をします。

コンテナ化

アプリケーションをひとまずコンテナ化させます。
既存システムのシンプルなWebアプリがもっとも向いており、バッチシステムなどがコンテナ化に向いています。
Webアプリの場合だとシンプルなGET、POSTリクエストやWebブラウザから動作確認ができたりするので非常におすすめです。また、ローカルでの開発環境があるとさらに検証しやすくなります。
バッチシステムも同様にシンプルではありますが、データ投入、初期化といった作業に手間がかかる場合もあるのでWebアプリの方が良いです。

コンテナのビルド

コンテナの実際に作るためにDockerfileを書いて、docker buildをします。
その際にはオフィシャルベースのDockerfileを使ったり、今まで使用していたビルドスクリプトを利用してとにかくシンプルにDockerイメージを作成します。 とにかくシンプルにやることがポイントです。目的は既存のシステムをコンテナに置き換えることです。

アプリケーション側の改修

次にアプリケーションをコンテナに適するように少しアプリケーション側に改修を加えます。

ポイントはこの2点です。

  • 1コンテナに1つのプロセスだけを入れる
  • アプリケーションをステートレスにする
1コンテナに1つのプロセスだけを入れる

1つのコンテナに1つのプロセスだけを入れるようにします。Nginx + PHP-FPMを使用したアプリケーションであればこの2つを同伴させずに別々のコンテナに分けます。

アプリケーションをステートレスにする

例えばセッション情報がローカルディスクに出力されていたり、ユーザのアップロードする画像がローカルディスクに保存されていたりした場合はAWSのサービスで置き換えましょう。
セッション情報はElastiCacheへ、画像の保存などはS3を使用するように変更を加えます。この際にアーキテクチャが複雑にならないように気をつけましょう。
ログは一旦標準出力、標準エラー出力に吐かせます。現段階では動作の検証が目的なのでログ収集やパフォーマンスについては考慮から外します。

手動でのデプロイ

ECS/FargateのGetting Startedで作成されるタスク定義を元に少し書き換えてデプロイしましょう。
仮想マシンの考慮や、VPC内のAWSリソースへのアクセスが簡単なので便利です。

2nd Milestone

複数ノードにまたがるコンテナ操作の特性を知ることで、コンテナイメージ作成のベストプラクティス知識の裏付けになります。
そして、仮想マシン群を1つの大きなリソースプールとみなす考え方を身に着けることも目標です。
Webサーバが何台必要で、DBサーバが何台必要で...といった1つ1つの仮想マシンを丁重に扱う状態から、仮想マシン群を1つのリソースプールとみなす考え方を身に着けることで非常に良いコンテナワークロードを作れます。

  1. オーケストレータの特性と解決する課題を知る
  2. 仮想マシンの家畜化

オーケストレータはどのようにコンテナをデプロイするか

ECSやEKS、そのほかのツールでも同じような動作をします。

  1. タスク定義を元にリソース要求量などの条件を満たすノードを探す
  2. そのノードにデプロイする
  3. 何も指定しなければAZを分散させるようにデプロイメントをさせる(ECSの場合)

AWS上でのベストプラクティスとしてクラスタを組む場合は、ノードに使用するインスタンスタイプを複数種別ミックスさせるべきです。
使用するインスタンスタイプ自体に問題が起きた際に最悪の場合デプロイができなくなるという可能性を防ぐためのベストプラクティスであり、コンテナに限った話ではなくAuto Scalingなどでも同じです。

3rd Milestone

これまでの開発や運用フェーズでやれていたことをコンテナ化後もできるようにし、移行容易性を高めます。 また、コンテナ導入のメリットを最大化して再利用可能なノウハウを蓄積させます。

  1. チーム開発のための開発環境整備、自動化、CI/CD
  2. 運用を見据えたデザイン

チーム開発のための開発環境整備、自動化、CI/CD

「ローカル開発環境でコードを書き換えたら即反映されて動作検証可能」といった環境は多くの開発者が既に持っています。 なのでコンテナ導入後もこういった環境より悪くならないように、あわよくばさらによくなるような開発環境の構築をめざします。

そのためにもドキュメンテーションをしっかりと作りましょう。 トラブル対処方法、ハウツー、自動でやっていたことをマニュアルでやる方法などをしっかりドキュメンテーションにします。

また、今まで行ってきたビルドなどをCI/CDパイプラインの中で自動化したり、既存のものをコンテナに置き換えたりします。

運用を見据えたデザイン

現行システムで満たされているレベルを達成できるようにしましょう。
下記のような内容が達成されるかを確認しましょう。実際はもっと考慮事項が出てくると思います。

  • ロールバック
  • データベーススキーママイグレーション
  • オートスケーリング
  • Securit Group/NACL などのネットワークポリシー
  • ログ分析
  • IAMロール設計
  • 負荷試験による適切なタスクリソース量の割り当て
  • 秘密情報・設定情報の取り扱い

そして、ドキュメンテーションをしっかりと整備しましょう。
ロールバックがうまくいかなかった場合に手動でやる方法や、Auto Scalingの失敗時に確認することなどをドキュメンテーション化しましょう。

4th Milestone

ここのマイルストーンは本番環境に導入できるかのボーダーになります。

コンテナ構築のプロジェクトに携わった人だけが仕組みを知っているという状態は非常に脆弱です。
なので、社内、そしてチームの教育をします。
トラブルや障害時に誰でも対応できるようにすることと、コンテナ化をしてきた意図を共有することが大事になります。
そのためにしっかりとドキュメンテーションを作りましょう。

次のステップ システムとチームの成長を見据えたモダナイゼーションと最適化

本番環境に導入してもまだまだ手動でやっている作業がある場合はさらなる自動化の推進をしたり、デリバリの高速化、マイクロサービス化などをしていくと良いです。
またセキュリティやコストの削減といった部分にも着手できる部分はたくさんあるので改善を進めていきましょう。

さいごに

今回のセッションでコンテナ導入に対する具体的なイメージがわきました。
今後はどんどんコンテナに携わり様々なユースケースを知り、提案できるようになれればいいなと思いました。