Django
AWS
Fluentd
Docker
Mackerel

Dockerを使った個人WEBアプリの運用周りでやったこと

Dockerを使ったWEBアプリケーションを12月頃から個人で開発し始め、2月頃にVer1.0.0を公開しました。以前からDockerに興味はあったのですが仕事で使う機会もなく中々手を出すことができずにいました。

今回、初回リリースを終えて、特に本番環境の運用周りでは直接ホスト上にアプリケーションを構築する場合と比べて勝手が違う部分が多く、一通りの運用の仕組みを整えるまで苦労したため、このタイミングで振り返りも兼ねて実施したこと・工夫したことまとめておきたいと思います。


対象者

とりあえずHello WorldしてみたDocker初心者の方から、検証環境で利用している方を対象としています。Docker SwarmやKubernetesのようなオーケストレーションツールは出てきません。一台のサーバ上でDocker Composeを使っていくつかのコンテナを管理しているミニマルな環境となっています。


作ったもの

IT DOUJOU - ITエンジニアの問題投稿サイト

https://it.doujou.work

IT技術の問題を出し合って、相互理解を深めるための学習サイトです。他の人が作った問題を解いたり、問題を作成することができます。テキストを読むだけよりも、問題を解くほうが勉強になると思い作成しました。後、Qiitaやブログに書くほどでもない技術的なTipsを手軽にアウトプットできる場所が欲しかったいう思いがあります。

it.doujou.work_question_5_13_.png

AWS・Azureなどのクラウド系からOS・ミドルウェア系の問題を充実させていきたいと思っています(増やしてほしいカテゴリなど随時募集中です!)。


システム構成

VPSに立てたLinuxサーバ一台で動かしています。構成は以下の図のような感じ。一台構成なので必要性は薄いですが、今後スケールしやすいよう、全ての機能をコンテナで完結できることにこだわりました。各機能ごとの設定をGitで管理しやすくなったり、ホスト側はいくつかディレクトリ作る程度の設定で済んだり(移行しやすい!)と、いくつかメリットは感じています。

構成図1.png



  • WEBコンテナ(Nginx)... 外部からのリクエストの受け付け。APサーバと連携。


  • APコンテナ(Django)... アプリケーションを動作させている。Pythonで実装。


  • DBコンテナ(MySQL)... APのデータを保存。DBをコンテナにするのはナンセンスな気がするが、Master-Slave構成にする予定もないので。


  • 監視コンテナ(Mackerel)... はてな社が提供している、監視サービスのSaaS。


  • 運用バッチコンテナ(Cron)... 定期処理をCronで実行。


  • ログ収集コンテナ(fluentd) ... 他のコンテナのログを収集。


監視コンテナ(Mackerel)

Mackerelははてな社が提供しているサーバ監視のSaaSです。日本製サービスだけあってCloudWatchやDataDogに比べ使いやすいです(個人の感想です)。フリーライダーですが、監視対象が本番環境とステージング環境の2台だけなので無料プランで運用しています。また、Mackerel-AgentのDockerイメージがDockerHubに公開されているので、ほとんど何も考えずに導入することができます。アラートが挙がったときはSlackに発報するように設定しています。

構成図3.png


監視内容

無料プランの場合、取得したメトリクスの保持期間が1日なので、サーバ負荷の傾向分析などには使えませんが、サーバの現在の状態を知るだけなら十分な機能があります。下記のような監視を行っています。



  • ホストの死活監視... Agentと疎通が取れないと発報


  • ホストのCPU使用率... 90%以上で発報


  • ホストのメモリ使用率... 90%以上で発報


  • ホストのディスク使用率... 80%以上で発報


  • 各コンテナの死活監視... コンテナが停止していると発報


  • 各コンテナのCPU使用率... データ収集のみ


  • 各コンテナのメモリ使用率... データ収集のみ


  • サービスのHealthCheck... 200番台のレスポンスが返ってこなければ発報


運用バッチコンテナ(Cron)

運用系のスクリプトを定期実行するのに利用しているコンテナです。ホスト側のCronを利用してもよかったのですが、運用バッチに必要なパッケージリストやcrontabの設定をGitで管理しやすくなると思いコンテナ化しました。

この辺の記事を参考にさせて貰い、実装しています。

https://shimoju.org/2017/10/09/busybox-crond/

スケジューリングしている定期処理の中で主要なものだと、DBのフルバックアップを週次で実行しています。処理内容としてはmysqldumpを実行してバックアップを取得した後、圧縮・暗号化してAWSのS3バケットにアップロードしています。

構成図2.png

ちなみに、運用バッチが失敗した場合は運用スクリプトが直接Slackにメッセージを送り、通知するようにしています。はじめ、ログ収集コンテナの章で記載する、CloudWatch Logsで運用バッチのログを監視し、アラート機能で通知するようにしようかと考えていたのですが、CloudWatch Logsは"error"や"warning"などの文字列を拾って、閾値を超えたことを通知することはできても、失敗内容を通知することはできないため、自分の中でボツになりました。また、Mackerelプラグインのcheck-aws-cloudwatch-logsを使えばこの辺りの問題を解決してCloudWatch Logsの監視ができるはずなのですが、自分の環境ではなぜか上手く監視文字列を拾うことができず、現在調査中です。


ログ収集コンテナ(fluentd)

Dockerのfluentd logging driverを使い、各コンテナのログをfluentdコンテナに集約し、AWSのCloudWatchLogsに送付しています。ログの収集後の分析などは行っておらず、有事の際の確認用というスタンスで集めています。

構成図4.png

fluentdのフィルターでdockerから流れてきたログを、環境ごと、ログの種類(stdout、stderr)ごと、コンテナの種類ごとと分解してタグ付けしていき、下記のような形で保存しています。

ap-northeast-1.console.aws.amazon.com_cloudwatch_home_region=ap-northeast-1 (1).png

ログの収集方法は下記の三案の中から決めました。


  1. 各コンテナを永続化ボリュームにアタッチして、ホスト側にログを保存する。

  2. Dockerのawslogs driverを使い、CloudWatch Logsにログを送付する。

  3. fluentdにログを集約し、CloudWatch Logsにログを送付する。

案1についてはホスト側のディスク容量にそこまで余裕がないことと、今後のことを考えたときコンテナをスケールしにくいことからボツになりました。

案2についてはログの送付先を気軽に変えられないこと、各コンテナのstdoutとstderrに出力されたログが、Cloudwatch Logsの同じストリームに出力されてしまうのが個人的に気に入らないためボツになりました。


さいごに

コンテナの運用方法を一通り考えてみて感じたのは、(特にオートスケール等を考慮する場合)ログ周りの運用が難しいなということです。単純にホスト側に保管するのならば別ですが、fluentdやクラウドの知識は必須だと感じました。今回ログ監視周りがおざなりになってしまったので、今後そのあたりの構成の検討をしていきたいと思っています。