なぜDockerを使うのかを整理する
※追記
整理とかいいつつ、雑に書きなぐっただけだったので少し文章と見栄えを直しました。
背景
いま作っているシステムではECSのクラスタ上に、Dockerコンテナを配置してアプリケーションをデプロイしている。 なぜ一般的なEC2にアプリケーションを配置する手法を使わずに、ECSでDockerを使用するのか。 自分の考えを整理する。前提知識
ECSとは
AWSのサービスの1つでEC2ContainerServiceの略。 Dockerコンテナを運用をいい感じにやってくれるサービスです。TL;DR;
●アプリケーションの運用はいろいろ大変 ●運用を楽にするために色々な技術がある ●Dockerを使うとより楽になるEC2にアプリケーションを配置する手法
通常EC2を使い際に、AWSが用意しているAMIをそのまま使用することは多くない。 理由としては幾つかあるが、雑に思いついたのはイカ ●デフォルトでインストールされている言語以外、または別バージョンを使用したい ●アプリケーションで使用するライブラリをインストールする必要がある ●インスタンスにSSHする際に使う鍵を起動時の設定とは別に用意したい 1つずつ詳しく解説していく。デフォルトでインストールされている言語以外、または別バージョンを使用したい
いまは知らないが、一昔前のAmazonLinuxであればRubyのversionは2.0だった。 たぶん当時の最新は2.1とか2.2だったと思う。 バージョンがいくつ違うとかはまぁいいとして、重要なのは常に最新に追随するわけではないということ。 Rubyはversionupのたびに高速化している。 いままで最新バージョンを使用していて、既存のアプリケーションが動かなくなるというようなバグに遭遇したことはなく、基本的にはversionは上げ得である。 であれば、最新のメソッドも追加されているしRubyのversionは新しいほうがいい。アプリケーションで使用するライブラリをインストールする必要がある
すぐに思いつくのはImageMagicとかだろうか。 画像処理を行うアプリケーションであればほぼ入れることになるであろうライブラリである。インスタンスにSSHする際に使う鍵を起動時の設定とは別に用意したい
EC2ではインスタンスにSSHするためにkey pairと呼ばれる鍵を作成し、公開鍵をインスタンスに配置してくれる。 ユーザーは公開鍵を自身のマシンにセットしec2-user
とかAMIごとに指定のユーザーとしてSSHをする。
チームで開発する際に、SSHする可能性のあるメンバーには鍵を渡す必要がある。また、このデフォルトのユーザーはroot権限︵sudo︶を持っているため全員に配布するのはリスクがある。
そこで、インスタンスにデフォルトとは違うユーザーを作成し、そこにチームメンバーの公開鍵を配置する。
そうすることで各メンバーは自分のユーザーを持ち、自分の秘密鍵でSSHが可能になる。
デフォルトのCloudwatchのメトリクスとは別にメトリクスを収集したい
Prometheusとか、そういうエージェントを入れることもあるよね。どのようにEC2インスタンスを作るのか。︵設定するのか︶
簡単な方法だと、ユーザーデータと呼ばれるインスタンス起動時に実行されるスクリプトがある。ここに各種インストールのコマンドを記述すると起動時に色々インストールしてくれる。 しかし、これだと起動時に言語のビルドなども含まれると異常に起動が遅くなる。︵正確に言うとすでに起動はしているので、起動後に自分の使いたいものが揃うのが遅くなる︶ その為、一般的にはインスタンスを起動後、SSHして自分好みにセットアップし、AMI︵インスタンスのイメージ︶に保存する。 保存したAMIから起動することでセットアップされた状態でインスタンスを起動する。この手法を使うことで同じ環境のインスタンスを複数起動することが可能になる。 更に言うとそれらをいちいち手でセットアップするかというとそんな面倒なことはしたくない。その為、Chef、Ansibleなどの構成管理ツールと呼ばれるものを使用し、セットアップを行う。 それも面倒なのでPackerでAMIが自動生成されるようにしたりする。(実はPakcerはあんまりちゃんと使ったことがない︶EC2インスタンスで配置したアプリケーションの運用
アプリケーションを運用をしていく上で、いろいろな機能追加が入ると思う。 またRubyは毎年12月25日に最新バージョンがリリースされる。︵バグフィックス等のバージョンアップは随時行われている︶ Rubyのバージョンだけなら、アップデートしない。という選択もあるだろう。しかし、先述したようなImageMagickのようなライブラリが追加で必要になった場合はインスタンスにインストールをする必要がある。 運用しているサーバーが1台、2台ならSSHして手でセットアップ、または構成管理ツールでセットアップするという選択肢もあるだろう。︵動いているサーバーにそんなことおれはやりたくないけど︶ あんまりないけど再起動が必要なアップデートもある︵近年ありがちなSSL,SSHの脆弱性アップデートは再起動が必要だった気がする︶そうなると、1台運用ならサーバーが停止することになり、複数台運用ならローリングアップデートが必要になる。 自分が昔関わっていたサイトでは毎月必ずインフラの定期メンテがあったりしたこともある。そこに併せて色々やる。Dockerの良さ
ここまでの流れで運用の大変さとそれを回避するためにいろいろな技術があることがわかったと思う。 DockerはDockerイメージを作成しそのイメージからコンテナを生成しサーバーに配置する。 Dockerイメージは、イカのようなDockerfileから生成する。 イカから生成されるイメージはRuby2.4.1がインストールされたalpine linuxのイメージになる。 このイメージをベースに、自分のアプリケーションに必要な設定を追加していくことになる。FROM ruby:2.4.1-apline ADD . /appすでにわかったかもしれないが、Dockerfileを更新し、イメージを再作成、再作成したイメージのコンテナをサーバーに配置する。これがDockerを利用した場合のアプリケーション︵サーバー︶の更新になる。 ここまでに記述したようなインフラの更新に必要なのは、 Dockerfileの更新、イメージのPush、新しいイメージからコンテナを配置になる。 またDockerは1つのコンテナに複数アプリを起動するようなことはせず、1コンテナ1プロセスが基本です。 EC2インスタンスで行うような1サーバーのリソースを有効に使うために複数アプリを起動したりするために1つのサーバーにいくつもの言語を入れたり、いくつものアプリケーションを起動するようなことはありません。1つ1つのDockerfileは1つのことをするための設定だけになり設定の管理としてもシンプルになりやすいと思っています。 それに加え、ECSクラスタ内のインスタンスにコンテナを配置する際にはMultiAZやリソースを考慮して配置するため、インスタンスのリソースを自動的に有効に使えるようになります。