前回は、RoDで作成したWordPress環境をKUSANAGI環境にコピーする方法を説明しました。今回は、KUSANAGI RoDを本番環境で使う際のノウハウについて考えます。
KUSANAGI RoDをスケールアウトする
RoDは、httpサーバ、php-fpm、DBが一つになったパッケージです。スケールする際に問題となるのは、PVとなるDocumentRoot以下のファイルとDBです。
PVの分散
DocumentRoot以下のファイルは一度読み込めばファイルキャッシュされますが、読み込むまでの動作が遅くなります。そのためコンテナホスト上のボリュームを使用するのが一番早いのですが、そうするとスケールアウトする際の阻害条件になりやすいです。
DBも同様に、ただDBのコンテナを増やすだけではなく、データも動機させなければなりません。一つの解決策はDBコンテナを分け、Gallera Clusterとして扱うことです。ただしこの場合、DBのコンテナ数を3つ以上奇数にするという制限が発生します。
管理用と公開用コンテナの分離
多くの場合スケールアウトする対象は一番負荷が高くなる、httpとphp-fpmです。ただし、スケールする対象全てで管理者権限アクセスする必要はありません。むしろ、公開サーバでは管理者画面にログインできなくすべきでしょう。
管理者画面にログインさせない一番簡単な方法は、管理者が使用するIPアドレスを制限することです。OAuth等を使ったSingle Sign Onも有効でしょう。
公開用コンテナでの書き込み禁止
公開サーバ側でDocumentRootやDBに読み込みできなくさせるという方法も、セキュリティ上有効です。WordPressの脆弱性の殆どはプラグインによるものなので、公開用サーバで書き込みさせないことにより、マルウェア等の感染を防ぐことができます。KUSANAGIではhttpおよびphpの設定により、書き込み出来る場所の制限や不正な箇所でのphp実行を制限しています。しかし、最近はシェルスクリプトの実行によるマルウェアなどもあるため、安心できません。
コンテナでは、書き込みが必要な箇所(/tmp、/var/cashe、/run など)をtmpfs としてマウントし、それ以外のボリュームをリードオンリーマウントにする方法があります。公開用コンテナではこの方法を利用して書き込み不能とし、なおかつPVをリードオンリーマウントとすれば、より安全となります。
ただし、この方法ではWordPressのコメント機能や、DB書き込みを伴うプラグインを使用することが出来ません。何が出来なくるかを検証し、実現可能かどうかを検証しましょう。
公開方法のまとめ
以上をまとめると、以下のようになります。公開用コンテナと投稿・管理用コンテナを分けています。下記例ではロードバランサを用意して、参照者と管理者を分離します。また、TLS証明書の管理もロードバランサに任せています。DBに関しては、マネージドDBを使用する方法などもありますので、色々検討してください。
RoD今後の課題
現在のRoDには課題がいくつかあります。
- Certbotの実用化
現行のDocker-composeでの使用は諦め、上位のロードバランサで実施 - PHPの高速化
現在のAlpine Linuxベースのイメージは、動作が遅く性能劣化した状態 - Kubernetesへの組み込み
RoD をコンテナオーケストレーションのデファクトスタンダードである kubernetes へ組み込み
1番、2番に関しては、近日中に修正する予定です。
kubernetes組み込みは、現在配布しているDockerイメージでも構成可能です。使用するWordPressデータ(プラグイン、テーマ、投稿など)をRoDで作成し、PVへは前回まで説明したコピー方法でデータのみをデプロイすれば良いと考えています。モデルは以下のような感じです。ロードバランサとしてIngressを使用することを前提としています。
- ロードバランサで、PHPのコードはPHPコンテナに処理を転送する
- PHPコンテナは、PVをリードオンリーマウント、DBの読み込みのみを行う
- ロードバランサで、PHP以外のコードはキャッシュを参照する
- キャッシュサーバは、Redis、memcached などで画像、CSS、JSファイルなどをキャッシュし、高速にロードバランサでコンテンツを配布する
- 投稿・管理用コンテナを同梱させてもいいし、ローカルの環境からデータコピーしても良い
この構成では、KUSANAGIのようにメモリキャッシュなどをうまく活かせない可能性が高いです。そのため以下のような施策で高速化することを考えます。
- PHPコンテナにDBキャッシュサーバ(MaxScaleやMySQL Router)などを用意し、DBのデータをメモリにキャッシュする
- DBのReplcaサーバコンテナを、KubernetesのDaemonSetで各コンテナノードに配置し、PHPコンテナはDBとしてコンテナホスト上のレプリカサーバを使用する
- KubernetesのDaemonSetで、各コンテナホスト上のローカルPVに本PVの内容をコピーするコンテナを用意し、PHPやRedisはコピーしたローカルPVを使用する
終わりに
今回は、RoDを本番環境で使う際のノウハウについて考えてみました。実環境は常に攻撃にさらされます。コンテナは外部からの攻撃には比較的強いですが、内部からの攻撃(プラグイン経由や、内部の操作ミスなど)には弱い環境です。コンテナのデプロイは、コンテナ単位で行えるため影響範囲の少ない範囲だけをデプロすることも可能です。できるだけ手作業ではなく、何度もテストした手順通りにデプロイしましょう。
今回で、KUSANAGI RoDの連載は終了となります。またどこかでお会いしましょう。