こんにちは、akiyoko です。
Mezzanine は、まだまだ日本での認知度はイマイチですが、知る人ぞ知る Python製の WordPress風フルスタックCMSフレームワークです。
今年の 7月に、Mezzanine を使った某ブログサイト(将来的に ECサイトを増設予定)の本番運用を開始しました。*1 その備忘録として、AWS の初期設定から Mezzanine テーマのカスタマイズ、Mezzanine の本番デプロイ、ちょっとした運用設定までの記録をまとめておくことにしました。
全ての記録を一つの記事にすると長くなり過ぎるので、テーマごとに、
の 4本に記事を分割することにしました。
今回はラスト 4本目、「その4:Mezzanine の運用設定」について説明します。
Mezzanine の運用設定として実施した内容としては、
- Mezzanine 本体のカスタム設定
- Mezzanine サイトのページ設定
- バックアップの設定
- sitemap の定期更新
- Google Search Console の設定
- CloudWatch の監視設定
となります。
【目次】
- 1. Mezzanine 本体のカスタム設定
- 2. Mezzanine サイトのページ設定
- 3. バックアップの設定
- 4. sitemap の定期更新
- 5. Google Search Console の設定
- 6. CloudWatch の監視設定
- TODO
- まとめ
- 参考本
1. Mezzanine 本体のカスタム設定
config/settings.py の設定を変更して、Mezzanine 本体のカスタム設定をおこないます。
本来この設定変更は本番デプロイ時(fab all コマンド実行時)かその直後におこなうべきですが、運用に関わる設定なのでここに記しておきます。
1.1. ブログ記事のフィーチャー・イメージ設定
ブログ記事にフィーチャー・イメージを付けるかどうかの設定です。
なお、画像は必須ではありません。
--- a/config/settings.py +++ b/config/settings.py @@ -79,7 +79,7 @@ from django.utils.translation import ugettext_lazy as _ # Setting to turn on featured images for blog posts. Defaults to False. # -# BLOG_USE_FEATURED_IMAGE = True +BLOG_USE_FEATURED_IMAGE = True # If True, the django-modeltranslation will be added to the # INSTALLED_APPS setting.
1.2. レーティング設定
レーティング機能をオフにします。
--- a/config/settings.py +++ b/config/settings.py @@ -85,6 +85,9 @@ BLOG_USE_FEATURED_IMAGE = True # INSTALLED_APPS setting. USE_MODELTRANSLATION = False +# Comment settings +COMMENTS_USE_RATINGS = False + ######################## # MAIN DJANGO SETTINGS #
2. Mezzanine サイトのページ設定
Django Admin(/admin/)にログインして、Mezzanine サイトの各種設定を行います。
2.1. Settings
[Site]>[Settings]から Mezzanine サイト全体の設定を行います。
項目 | 内容 | 設定例 |
---|---|---|
Comments > Accounts required for commenting | コメントするのにアカウントが必要か | チェックしない |
Comments > Auto-approve comments | コメントを自動承認するか | チェック |
Comments > Show removed comments | 削除済みのコメントを表示するか | チェックしない |
Comments > Show unapproved comments | 未承認のコメントを表示するか | チェック |
Twitter > Twitter OAuth access token | Twitter 連携で必要 | Twitter 側の設定 ① を参照 |
Twitter > Twitter OAuth access token secret | 同上 | Twitter 側の設定 ② を参照 |
Twitter > Twitter OAuth consumer key | 同上 | Twitter 側の設定 ③ を参照 |
Twitter > Twitter OAuth consumer secret | 同上 | Twitter 側の設定 ④ を参照 |
Twitter > Default Number of Tweets | Tweet の表示数 | 5 |
Twitter > Default Twitter Query | Twitter 検索のキー | aki_yok (*2) |
Twitter > Default Twitter Query Type | Twitter 検索キーの種類 | User |
Miscellaneous > Akismet API Key | Akismet 連携で必要 | Akismet 側の設定を参照 |
Miscellaneous > Blog posts per page | ブログ一覧の表示数 | 6 |
Miscellaneous > Google Analytics ID | Google Analytics 連携で必要 | Google Analytics 側の設定を参照 |
Miscellaneous > Max paging links | ブログ一覧のページ表示数 | 10 |
Miscellaneous > Accounts required for rating | レーティングするのにアカウントが必要か | Yes |
Miscellaneous > Rich Text filter level | Rich Text ページのフィルタリングレベル | No filtering (*3) |
Twitter 側の設定
Akismet 側の設定
Google Analytics 側の設定
2.2. Groups
ブログ投稿しかできない「akiyoko」ユーザを作成するため、まず、ブログ投稿関連のパーミッションのみを許可した「Blog user」という権限グループを作成します。
以下のパーミッションを選択します。
- blog | Blog Category | Can add Blog Category
- blog | Blog Category | Can change Blog Category
- blog | Blog Category | Can delete Blog Category
- blog | Blog post | Can add Blog post
- blog | Blog post | Can change Blog post
- blog | Blog post | Can delete Blog post
- galleries | Gallery | Can add Gallery
- galleries | Gallery | Can change Gallery
- galleries | Gallery | Can delete Gallery
- galleries | Image | Can add Image
- galleries | Image | Can change Image
- galleries | Image | Can delete Image
2.3. Users
「akiyoko」ユーザを作成して、「Blog user」権限グループを付与します。
ここで、新しく追加したユーザで Django Admin サイトにログインしようとすると「You don't have permission to access the admin for this site.」というエラーが出てログインできない問題が発生(2016年7月時点)。 *4
関連するデータを見てみると、
mysql> select * from core_sitepermission; +----+---------+ | id | user_id | +----+---------+ | 1 | 2 | +----+---------+ 1 row in set (0.00 sec) mysql> select * from core_sitepermission_sites; Empty set (0.00 sec)
となっていたのですが、本事象が発生しなかった開発環境(Vagrant)では、
mysql> select * from core_sitepermission; +----+---------+ | id | user_id | +----+---------+ | 1 | 2 | +----+---------+ 1 row in set (0.00 sec) mysql> select * from core_sitepermission_sites; +----+-------------------+---------+ | id | sitepermission_id | site_id | +----+-------------------+---------+ | 1 | 1 | 1 | +----+-------------------+---------+ 1 row in set (0.00 sec)
となっていて、結局原因はよく分からなかったのですが、
mysql> insert core_sitepermission_sites(id,sitepermission_id,site_id) values(1,1,1);
と実行して core_sitepermission_sites レコードを作成してやると、事象は発生しなくなりました。
2.4. Contact
お問い合わせページの作成方法。こんな感じのページです。
[Content]>[Pages]から[Add Form]を選択して、Form ページを作成。
項目 | 内容 |
---|---|
Title | Contact |
Content | Please fill out the form below and submit for your inquiry. |
Button text | Submit |
Email > Send email to user | チェックしない |
Email > From address | no-reply@akiyoko.com |
Email > Send email to others | xxx@gmail.com, xxx@gmail.com |
Email > Subject | [akiyoko.com] New contact |
Email > Message | 問い合わせフォームからコンタクトがありました。対応をお願いします。 |
Fields > Name | Single line text |
Fields > Email | |
Fields > Message | Multi line text |
実際にフォームへの問い合わせがあれば、[Email > Send email to others]に設定したメールアドレス宛に、以下のような内容のメールが届きます。
問い合わせフォームからコンタクトがありました。対応をお願いします。 Name: xxx Email: xxx@xxx.com Message: メッセージの内容 http://akiyoko.com
3. バックアップの設定
Mezzanine サイトでアップロードした画像ファイルは、
/home/webapp/mezzanine/akiyokoproject/static/media/ └── uploads └── blog └── test.png
というパスに配置されるので、以下のように media ディレクトリ以下を圧縮してバックアップします。
$ tar czvf <出力ファイル名> <対象ファイル or 対象ディレクトリ> $ tar czvf /tmp/media_backup_`date +%y%m%d%H%M`.tar.gz /home/webapp/mezzanine/akiyokoproject/static/media
圧縮したファイル名は「media_backup_1610301815.tar.gz」などとなります。
また、MySQL のバックアップは以下のようにして実行します。
$ mysqldump --single-transaction -u root -p akiyokoproject > /tmp/mysql_backup_`date +%y%m%d%H%M`.dump
こちらは今のところ圧縮しない方針です(ファイルがもっと大きくなれば圧縮した方がよさそうですが)。
以下、バックアップファイルを cron で毎日深夜に S3 にアップロードするまでの手順です。
3.1. S3 バケットの準備
バックアップ用バケット(バケット名は「akiyokoproject」とします)を作成し、有効期限ルールを設定します。
バケットの Properties の[Lifecycle]から、[Add rule]を選択。
バケット内の「media/」ディレクトリ以下のオブジェクトの有効期限を10日間(有効期限を過ぎたものは削除)に設定します。
「db/」ディレクトリ以下のオブジェクトの有効期限についても同様に設定します。
(参考)Amazon S3でオブジェクトの有効期限を設定できるようになりました | Developers.IO
3.2. AWS CLI のインストール
AWS CLI を pip でインストールします。
(akiyokoproject)$ pip install awscli (akiyokoproject)$ pip list | grep awscli awscli (1.11.10)
3.3. 実行シェルの作成
media ディレクトリ以下のファイルと MySQL のバックアップを行う、シェルを作成します。
/home/webapp/mezzanine/akiyokoproject/scripts/backup.sh
#!/bin/sh MEDIA_BACKUP_FILE=media_backup_`date +%y%m%d%H%M`.tar.gz DB_BACKUP_FILE=mysql_backup_`date +%y%m%d%H%M`.dump DB_PASS=TODO(FIX ME) # Create backup file tar czvf /tmp/$MEDIA_BACKUP_FILE /home/webapp/mezzanine/akiyokoproject/static/media mysqldump --single-transaction -u root -p$DB_PASS akiyokoproject > /tmp/$DB_BACKUP_FILE # Copy file to S3 . /home/webapp/.virtualenvs/akiyokoproject/bin/activate aws s3 cp /tmp/$MEDIA_BACKUP_FILE s3://akiyokoproject/media/ aws s3 cp /tmp/$DB_BACKUP_FILE s3://akiyokoproject/db/ # Delete old files find /tmp -name 'media_backup_*.tar.gz' -mtime +10 -exec rm {} \; find /tmp -name 'mysql_backup_*.dump' -mtime +10 -exec rm {} \;
(mysqldump のパスワード「TODO(FIX ME)」の部分は、適宜設定してください。)
$ sudo chmod 755 /home/webapp/mezzanine/akiyokoproject/scripts/backup.sh
(参考)
- AWS CLIのS3コマンドまとめ - TASK NOTES
- s3 — AWS CLI 1.11.100 Command Reference
- [Ubuntu][Shell]Ubuntuの/bin/shでsourceコマンドが効かない件 | aoshiman.org
(2017/3/6 追記)
「/tmp」以下のゴミファイルが溜まり過ぎて、「/dev/xvda1」がディスクフルになってしまうという不具合が発生してしまったので、
# Delete old files find /tmp -name 'media_backup_*.tar.gz' -mtime +10 -exec rm {} \; find /tmp -name 'mysql_backup_*.dump' -mtime +10 -exec rm {} \;
10日前より古いファイルを削除する処理を加えました。
Traceback (most recent call last): File "/usr/lib/python2.7/runpy.py", line 162, in _run_module_as_main "__main__", fname, loader, pkg_name) File "/usr/lib/python2.7/runpy.py", line 72, in _run_code exec code in run_globals File "/usr/local/lib/python2.7/dist-packages/virtualenvwrapper/hook_loader.py", line 223, in <module> main() File "/usr/local/lib/python2.7/dist-packages/virtualenvwrapper/hook_loader.py", line 145, in main output.close() IOError: [Errno 28] No space left on device -bash: cannot create temp file for here-document: No space left on device $ df Filesystem 1K-blocks Used Available Use% Mounted on udev 502984 12 502972 1% /dev tmpfs 101636 352 101284 1% /run /dev/xvda1 8115168 7679972 0 100% / none 4 0 4 0% /sys/fs/cgroup none 5120 0 5120 0% /run/lock none 508160 0 508160 0% /run/shm none 102400 0 102400 0% /run/user
なお、CloudWatch のデフォルトではディスク使用量の監視が利用できないようで、ディスク使用量の監視をするには、
- Amazon EC2 Linux インスタンスのメモリとディスクのメトリクスのモニタリング - Amazon Elastic Compute Cloud
- AWS CloudWatchでディスク容量チェック - Septeni Engineer's Blog
- AWSのCloud Watchでディスク使用量を監視 - Qiita
あたりの対応が必要そうです。面倒なので一旦保留ということで。。
3.4. cron ファイルの編集
デプロイ時に Fabric スクリプトを実行すると、「/etc/cron.d/」配下に「akiyokoproject」という cron ファイルが用意されるので、このファイルに定期バックアップルールを追記します。
$ ls -al /etc/cron.d/ total 16 drwxr-xr-x 2 root root 4096 Oct 30 19:52 . drwxr-xr-x 92 root root 4096 Aug 11 21:59 .. -rw------- 1 root webapp 306 Oct 30 19:52 akiyokoproject -rw-r--r-- 1 root root 102 Feb 9 2013 .placeholder
/etc/cron.d/akiyokoproject
# Poll Twitter every 5 minutes # Comment-out if you don't use Mezzanine's Twitter app */5 * * * * webapp /home/webapp/.virtualenvs/akiyokoproject/bin/python /home/webapp/mezzanine/akiyokoproject/manage.py poll_twitter
(poll_twitter を5分ごとに実行する設定が既に書き込まれています。)
毎日深夜 0時5分に定期バックアップのためのシェルが実行されるような設定を、末尾に追加します。
# Daily backup 5 0 * * * webapp /home/webapp/mezzanine/akiyokoproject/scripts/backup.sh
(参考)cron設定をもっとわかりやすく説明! - こまけぇこたぁいんだよ
3.5. cron 実行ログの出力先を変更
Ubuntu はデフォルトで、cron の実行ログが「/var/log/syslog」に出力されるようになっているのですが、「/var/log/cron.log」に出力されるように rsyslog の設定を変更しておきます。
/etc/rsyslog.d/50-default.conf
・ ・ (略) # First some standard log files. Log by facility. # auth,authpriv.* /var/log/auth.log *.*;auth,authpriv.none -/var/log/syslog #cron.* /var/log/cron.log #daemon.* -/var/log/daemon.log kern.* -/var/log/kern.log #lpr.* -/var/log/lpr.log mail.* -/var/log/mail.log #user.* -/var/log/user.log (略) ・ ・
となっているのを、「cron.*」のコメントを外して、
cron.* /var/log/cron.log
と修正します。
最後に、
$ sudo service rsyslog restart
を実行して、rsyslog を再起動します。
これで、/var/log/cron.log にログが出力されるようになりました。
(参考)ubuntu14.04 cronログ出力設定 - Qiita
4. sitemap の定期更新
Mezzanine には、Google Search Console の設定に必要な「sitemap.xml」を Google に送信するためのコマンドが用意されています。 *5
(akiyokoproject)$ python manage.py ping_google System check identified some issues: WARNINGS: ?: (1_8.W001) The standalone TEMPLATE_* settings were deprecated in Django 1.8 and the TEMPLATES dictionary takes precedence. You must put the values of the following settings into your default TEMPLATES dict: TEMPLATE_DIRS.
WARNING が出ているのは無視するとして、何も反応が無いのが気になります。。
先述の cronファイルの末尾に、以下のルールを追加します。
/etc/cron.d/akiyokoproject
# Hourly ping google 0 * * * * webapp /home/webapp/.virtualenvs/akiyokoproject/bin/python /home/webapp/mezzanine/akiyokoproject/manage.py ping_google
5. Google Search Console の設定
ここでは細かく書きませんが、Google Search Console の各種設定を行い、SEO 対策をしておきます。
(参考)
6. CloudWatch の監視設定
CloudWatch で以下の監視を実施し、異常を検知した場合に管理者用のメールアドレスに通知をするように設定をおこないます。
- EC2 インスタンスの CPU使用率監視
- EC2 インスタンスの死活監視
なお、CloudWatch の監視については、無料枠内で最低限の監視ができればよいという方針で運用しています。
(参考)
- AWS環境での監視について調べる CloudWatchとZabbixの比較 | Developers.IO
- [CloudWatch]グラフの確認方法と確認できるグラフ一覧(EC2/ELB/RDS) | Developers.IO
6.1. 監視通知用の SNS 作成
SNS の通知先に、監視用のメールアドレスを指定します。
まず、[Topics]から[Create new topic]を選択してトピックを作成します。
トピック名は「akiyokoproject-notification」としました。 *6
作成されたトピックの ARN をクリックして、[Create subscription]をクリックします(あるいは[Subscription]から[Create subscription]をクリックしてから ARN を直接指定します)。
Protocol | |
Endpoint | 管理者のメールアドレス |
を設定して、[Create subscription]をクリックします。
確認メールが届くので、メール本文の「Confirm subscription」をクリックします。
「Subscription ID」が「PendingConfirmation」から ARN に変われば、設定完了となります。
6.2. メトリクスを設定
[Metrics]から[EC2]をクリックします。
[Per-Instance Metrics]をクリック。
「CPUUtilization」(CPU使用率)および「StatusCheckFailed」(インスタンスステータス異常あるいはシステムステータス異常)を選択します。
(参考)【小ネタ】CloudWatchの「StatusCheckFailed_Instance」と「StatusCheckFailed_System」について | Developers.IO
続けて、作成したメトリクスをダッシュボードに保存します。
[Actions]から、[Add to dashboard]を選択します。
ダッシュボード名を入力して、[Add to dashboard]ボタンをクリック。
[Save dashboard]ボタンをクリックして完了です。
6.3. アラームを設定
- EC2 インスタンスの平均 CPU 使用率が 70% を超える状態が 10分以上継続
- EC2 インスタンスのインスタンスステータス異常あるいはシステムステータス異常が 10分以上継続
を閾値として、アラームを作成します。 *7
まずは、「CPUUtilization」(CPU使用率)のアラームから。
「Graphed metrics」タブから、「CPUUtilization」の右側のベルアイコンをクリックします。
以下のようにアラームの設定をします。
(参考)E メールを送信する CPU 使用率アラームの作成 - Amazon CloudWatch
引き続き、「StatusCheckFailed」(インスタンスステータス異常あるいはシステムステータス異常)の右側のベルアイコンをクリックして、アラームを以下のように設定します。
TODO
その他の運用設定として、
- logrotate の設定が不完全(application.log とか)
について、今後対応していく予定です。
まとめ
今回は、「Mezzanine の本番設定」と銘打った連続記事の最後を締めくくる「Mezzanine の運用設定」として、
- Mezzanine 本体のカスタム設定
- Mezzanine サイトのページ設定
- バックアップの設定
- sitemap の定期更新
- Google Search Console の設定
- CloudWatch の監視設定
を実施した内容を記載しました。
Mezzanine の本番サイトを運用し始めて 3ヶ月ほど経ちますが、やりたいこと、やらなければいけないことがまだまだ盛り沢山です。
今後も定期的に、Mezzanine の記事をアップしていこうと思います。
参考本
運用についてはまだまだ勉強不足です。。
Amazon Web Services 定番業務システム12パターン 設計ガイド
- 作者: 川上明久
- 出版社/メーカー: 日経BP社
- 発売日: 2016/06/15
- メディア: 単行本
- この商品を含むブログを見る
Amazon Web Services パターン別構築・運用ガイド 一番大切な知識と技術が身につく
- 作者: NRIネットコム株式会社,佐々木拓郎,林晋一郎,小西秀和,佐藤瞬
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2015/03/25
- メディア: Kindle版
- この商品を含むブログを見る
Amazon Web Servicesクラウドサーバ構築ガイド コストを削減する導入・実装・運用ノウハウ
- 作者: アロマネット株式会社中村義和
- 出版社/メーカー: 翔泳社
- 発売日: 2015/11/13
- メディア: 大型本
- この商品を含むブログを見る
*1:Mezzanine を採用したのは、個人の趣味です。
*2:「@」は付けない
*3:「No filtering」に設定すると、Rich Text ページ内のタグが無効化されなくなる
*4:(関連)https://groups.google.com/forum/#!topic/mezzanine-users/RSoPDeDrnaw
*5:正確には Django の機能です。(参考)django/ping_google.py at 1.9.7 · django/django · GitHub
*6:管理者のメールアドレスに通知する系の SNS は、「akiyokoproject-notification」を使い回す予定です。
*7:10分以上継続というのは、5分間の監視インターバルを 2回連続で異常が検知された場合を指す