ほぼ 10 年モノ熟成 Perl の倒し方 (Docker 移行編)(ShanonAdventCalendar2017・9日目)

このエントリーをはてなブックマークに追加
これはShanon Advent Calendar 2017の 9日目の記事です。

どうも、何気にアドベントカレンダー3本目、 @__munepom__ です。

今回は、予告通り ほぼ 10 年モノ熟成 Perl の倒し方 (AWS 移行編) の続きのお話です。

前回までのおはなし


まあ、スーパーざっくりまとめますと、、、
複数サービスが稼働しているサーバーから、熟成されたあるサービスを AWS へ移行できましたというお話でした。

今回は、その後のお話です。
(2017年3月頃なので、 Docker version 1.13 の頃のお話)


移行から 1 年後

サービスは安定して稼働していますね。
(よかったよかった。)

ただ、もうちょっとリリースしやすくしたいねぇ。。。
(ですよね〜。。。)

最近だと、 Docker とかでプロセスの仮想化が流行ってるっぽいよね。
(うん、会社でやれるならやってみたいよ。自分の PC では素振りしとるし。)

社内サービスをいい感じに Docker Image 化してくれるくん (大工さんと呼びます) を作ってみたから、調整してリリースしてみて!
(ほぅ!)

あ、これ1ヶ月でよろしくね~!
(無理無理無理無理!!!)

という天の声が聞こえたので、よしやるか!ということになりました。


Docker 移行やってみた

EC2 or ECS ???

コンテナを AWS 上 で動かすということで、フルマネージドな ECS はどうかなー?と思いましたが、
まぁ知見も何も無い状態でいきなり ECS に持っていくのはリスクあるのでは?ということで、
EC2 インスタンスで自前の docker プロセスを立て、そこでサービスを動作させることにしました。

プロセス分割できるかな???

今回 コンテナ化するサービスですが、 EC2 内部では以下のような構成になっています。 (図略)
  • フロントサーバ (ELB からの リクエストを受け付ける)
  • アプリケーションサーバ (フロントサーバからのリクエストを受け付ける)
  • 非同期処理用 Worker プロセス
  • 定期実行バッチ
  • Jenkins が無かった頃に作られた 、定期的にジョブを実行してくれるくん

Web サーバとアプリケーションサーバは、 普通に docker-compose を使って何とかなりそう、
定期実行系のは、 Jenkins ジョブで使い捨てコンテナを起動すれば何とかなりそう 、
ですが、 Worker プロセスは 深遠なる事情から、分割は無理そう、、、

というわけで、典型的な docker-compose.yml が出来上がりました。
version: "3" services: web: ... container_name: service_web links: app:service_app ... sysctls: - net.core.somaxconn=65535 ... app: ... container_name: service ...
app コンテナ内で、アプリケーションサーバ と 非同期処理用 Worker プロセスが稼働することに。。。

rolling update できるかな???

えー、 docker-compose.yml で links 指定してることから、お察しください。。。

現状だと、 docker stack deploy による rolling update ができないサービスっぽいことが発覚したので、 links で名前を指定しちゃってます。
(シグナルベースでプロセスを安全に落とせるようにしておかないと、 docker swarm 使えないですね。。。かなしい。。。)

ミドルウェアどうしましょ???

さて、あとは docker-compose up で適当にサービス立ち上げればええやんと思ったら、ミドルウェアの罠がありました。

アラートメール送信するための MTA として qmail を利用していましたが、これをコンテナ内に新規インストールして設定 するのが案外大変だと分かりまして。

そのため、 docker host 側で postfix をインストールして、それを利用することにしました。
  • で、この MTA も docker-compose 連携できるよう、コンテナ使ったほうが良いの???
  • 今後、他のミドルウェア増えたら、どんどん連携コンテナ増えるの???
という問題が浮かび上がりましたが、一旦 host 側でミドルウェアを管理しておこうということになりました。

(ミドルウェア管理おじさん爆誕 の危機???)

コンテナ内からの名前解決どうしましょ???

さてさて、 docker-compose up で起動やー♪
と思ったら、サービスが立ち上がりません。。。

AWS 外の社内サーバーに立っているモノ (gearman とか gearman とか) と名前解決できていなかったためでした。。。

とりあえず、お手軽な解決手段ということで、
dnsmasq を host 側に立てて、 何とか 解決しています。。。

ベストプラクティス、ゆる募です。。。
(docker 用に DNS バーンと立てちゃうとか?)

FCGI やめよっか

アプリケーションプロセスですが、せっかくなので、
熟成された Apache de FCGI から PSGI 実装の Starman サーバへ変更 してみました。
(熟成モノの Catalyst だと、すでに deprecated な Catalyst-Engine-PSGI を使わにゃならんのがつらいところでした。。。)

Starman worker さえ温まってしまえば、あとは速く処理ができることが分かりました。
(それが分かっていなくて、最初数リクエストでパフォーマンス激落ちくんじゃん!と悩んでいましたw)

パフォーマンス計測

本番と同じ構成でやらないと意味がないので、
複数台 EC2 インスタンスを起動して、
RDS も本番と同じ容量で用意して (IOPS の影響 受けたくないし)
やりました。

その結果、 Nginx がやばそう、ということで、 docker-compose.yml で net.core.somaxconn の上限を引き上げました。
version: "3" services: web: ... sysctls: - net.core.somaxconn=65535 ... app: ...

Makefile で手順簡略化

Makefile というと、なんかコンパイルのために使うヤツという認識でした。

しかし、単なるタスク定義しておけるくんと考えると、これ案外便利じゃん!ということで、
環境変数設定や docker 関連のコマンドを一纏めにした Makefile を 作成し、
リリース時に複雑なコマンド入力せずに済むようにしました。
... deploy: update-static-resources up check-domain update-static-resources: ... @... up: ... @docker-compose up -d check-domain: ... @...
こんな感じの Makefile を作って make deploy と叩けば OK という流れです。


いざリリース

実は一度失敗しましたが、、、二度目でやり遂げました。ふぅ。
(HTTP header 周りの処理が Starman か何かの影響で変わったようで、完全に 見落としていました。)
(あ、 EBS ガチャで当たりを引いて、起動数日で壊れたものがありました。かなしい。。。)


リリース自動化運動

QA 環境では Jenkins Job で定期的な更新に成功しているので、
そろそろリリースを Jenkins くんにお任せしても良いかな?
というところまでたどり着きました。


俺たちの戦いはこれからだ!

というわけで、ほぼ 10 年モノ熟成 Perl サービスがようやくリリースしやすくなり、
アプリケーションサーバもモダンなものに変更されました。

今後、このサービスの Perl バージョンを上げてみたり、アプリのフレームワークを変更したりといった活動がどのようなものになるか、、、
次回作にご期待ください。
次の記事
« Prev Post
前の記事
Next Post »
Related Posts Plugin for WordPress, Blogger...