akiyoko blog

akiyoko の IT技術系ブログです

Mezzanine の本番設定(その4:Mezzanine の運用設定)〜AWS 環境構築から運用設定まで〜

こんにちは、akiyoko です。

Mezzanine は、まだまだ日本での認知度はイマイチですが、知る人ぞ知る Python製の WordPress風フルスタックCMSフレームワークです。

akiyoko.hatenablog.jp


今年の 7月に、Mezzanine を使った某ブログサイト(将来的に ECサイトを増設予定)の本番運用を開始しました。*1 その備忘録として、AWS の初期設定から Mezzanine テーマのカスタマイズ、Mezzanine の本番デプロイ、ちょっとした運用設定までの記録をまとめておくことにしました。

全ての記録を一つの記事にすると長くなり過ぎるので、テーマごとに、

の 4本に記事を分割することにしました。

今回はラスト 4本目、「その4:Mezzanine の運用設定」について説明します。


Mezzanine の運用設定として実施した内容としては、

  • Mezzanine 本体のカスタム設定
  • Mezzanine サイトのページ設定
  • バックアップの設定
  • sitemap の定期更新
  • Google Search Console の設定
  • CloudWatch の監視設定

となります。



【目次】



 

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

f:id:akiyoko:20161029182952p:plain



Twitter 側の設定

f:id:akiyoko:20161030115540p:plain


(参考)Twitter REST APIの使い方


Akismet 側の設定

f:id:akiyoko:20161030115703p:plain


Google Analytics 側の設定

f:id:akiyoko:20161030122212p:plain


 

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

f:id:akiyoko:20161030124441p:plain


 

2.3. Users

「akiyoko」ユーザを作成して、「Blog user」権限グループを付与します。

f:id:akiyoko:20161030124507p:plain


ここで、新しく追加したユーザで 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

お問い合わせページの作成方法。こんな感じのページです。

f:id:akiyoko:20161030130048p:plain

[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 Email
Fields > Message Multi line text


f:id:akiyoko:20161029183251p:plain


実際にフォームへの問い合わせがあれば、[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]を選択。
f:id:akiyoko:20161030201246p:plain

バケット内の「media/」ディレクトリ以下のオブジェクトの有効期限を10日間(有効期限を過ぎたものは削除)に設定します。
f:id:akiyoko:20161030201305p:plain

f:id:akiyoko:20161030201323p:plain

f:id:akiyoko:20161030201340p:plain

「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


(参考)

 

(2017/3/6 追記)

f:id:akiyoko:20170307012941p:plain:w450
「/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 のデフォルトではディスク使用量の監視が利用できないようで、ディスク使用量の監視をするには、

あたりの対応が必要そうです。面倒なので一旦保留ということで。。



 

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 の監視については、無料枠内で最低限の監視ができればよいという方針で運用しています。


(参考)


 

6.1. 監視通知用の SNS 作成

SNS の通知先に、監視用のメールアドレスを指定します。


まず、[Topics]から[Create new topic]を選択してトピックを作成します。

f:id:akiyoko:20161102004922p:plain

トピック名は「akiyokoproject-notification」としました。 *6

f:id:akiyoko:20161102004949p:plain

作成されたトピックの ARN をクリックして、[Create subscription]をクリックします(あるいは[Subscription]から[Create subscription]をクリックしてから ARN を直接指定します)。

f:id:akiyoko:20161102005016p:plain
f:id:akiyoko:20161102005041p:plain

Protocol Email
Endpoint 管理者のメールアドレス

を設定して、[Create subscription]をクリックします。

f:id:akiyoko:20161102005103p:plain

確認メールが届くので、メール本文の「Confirm subscription」をクリックします。

f:id:akiyoko:20161102005128p:plain

f:id:akiyoko:20161102005141p:plain

「Subscription ID」が「PendingConfirmation」から ARN に変われば、設定完了となります。

f:id:akiyoko:20161102005156p:plain


 

6.2. メトリクスを設定

[Metrics]から[EC2]をクリックします。
f:id:akiyoko:20161102011342p:plain
[Per-Instance Metrics]をクリック。
f:id:akiyoko:20161102011417p:plain


「CPUUtilization」(CPU使用率)および「StatusCheckFailed」(インスタンスステータス異常あるいはシステムステータス異常)を選択します。
f:id:akiyoko:20161102011447p:plain

(参考)【小ネタ】CloudWatchの「StatusCheckFailed_Instance」と「StatusCheckFailed_System」について | Developers.IO



続けて、作成したメトリクスをダッシュボードに保存します。


[Actions]から、[Add to dashboard]を選択します。
f:id:akiyoko:20161102082216p:plain

ダッシュボード名を入力して、[Add to dashboard]ボタンをクリック。
f:id:akiyoko:20161102082310p:plain

[Save dashboard]ボタンをクリックして完了です。
f:id:akiyoko:20161102082349p:plain




 

6.3. アラームを設定

  • EC2 インスタンスの平均 CPU 使用率が 70% を超える状態が 10分以上継続
  • EC2 インスタンスのインスタンスステータス異常あるいはシステムステータス異常が 10分以上継続

を閾値として、アラームを作成します。 *7


まずは、「CPUUtilization」(CPU使用率)のアラームから。


「Graphed metrics」タブから、「CPUUtilization」の右側のベルアイコンをクリックします。
f:id:akiyoko:20161102011732p:plain

以下のようにアラームの設定をします。
f:id:akiyoko:20161102013453p:plain


(参考)E メールを送信する CPU 使用率アラームの作成 - Amazon CloudWatch



引き続き、「StatusCheckFailed」(インスタンスステータス異常あるいはシステムステータス異常)の右側のベルアイコンをクリックして、アラームを以下のように設定します。
f:id:akiyoko:20161102012644p:plain


 

TODO

その他の運用設定として、

  • logrotate の設定が不完全(application.log とか)

について、今後対応していく予定です。



 

まとめ

今回は、「Mezzanine の本番設定」と銘打った連続記事の最後を締めくくる「Mezzanine の運用設定」として、

  • Mezzanine 本体のカスタム設定
  • Mezzanine サイトのページ設定
  • バックアップの設定
  • sitemap の定期更新
  • Google Search Console の設定
  • CloudWatch の監視設定

を実施した内容を記載しました。


Mezzanine の本番サイトを運用し始めて 3ヶ月ほど経ちますが、やりたいこと、やらなければいけないことがまだまだ盛り沢山です。

今後も定期的に、Mezzanine の記事をアップしていこうと思います。



 

参考本

運用についてはまだまだ勉強不足です。。

Amazon Web Services 定番業務システム12パターン 設計ガイド

Amazon Web Services 定番業務システム12パターン 設計ガイド

Amazon Web Services パターン別構築・運用ガイド  一番大切な知識と技術が身につく

Amazon Web Services パターン別構築・運用ガイド  一番大切な知識と技術が身につく

  • 作者: NRIネットコム株式会社,佐々木拓郎,林晋一郎,小西秀和,佐藤瞬
  • 出版社/メーカー: SBクリエイティブ
  • 発売日: 2015/03/25
  • メディア: Kindle版
  • この商品を含むブログを見る

Amazon Web Servicesクラウドサーバ構築ガイド コストを削減する導入・実装・運用ノウハウ

Amazon Web Servicesクラウドサーバ構築ガイド コストを削減する導入・実装・運用ノウハウ

*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回連続で異常が検知された場合を指す