いかに GKE で Magento2 をホスティングするか。その背景。

LIFULL 社長室で事業開発エンジニアをしているカズキック2（@kzkiq2nd）です。

LIFULL の社長室は、LIFULL HOME'S 事業ではなく、例えば以下の様な新規事業領域を扱う部署です。

- 花の定期便「[LIFULL FLOWER](https://flower.lifull.jp/)」
- 規格外野菜からつくる福利厚生飲料「[Clean Smoothie](https://smoothie.lifull.net/)」
- スポーツトレーナー向け動画学習サービス「[Sufu](https://sufu.lifull.net/)」
- 出張家族写真サービス「[famphoto](https://famphoto.lifull.net/)」
- 半蔵門本社ビルの施設である「[Table](https://table.lifull.com/)」「[Hub](https://hub.lifull.com/)」「[Fab](https://fab.lifull.com/)」
- [不動産権利移転記録パブリックチェーン](https://lifull.com/news/15396/)
- ビジネスプランコンテスト「[OPEN SWITCH](https://lifull.net/openswitch/)」

社長室事業開発エンジニアは経営、商品開発、マーケティング、ブランディング、デザイン、各種調達、渉外など WEB が関わるビジネスを扱う全方位の能力に加え、多くの開発領域でエンジニアリングの専門性を必要に応じて発揮することが求められます。そのため開発運用保守をローコストに抑えようと常に NoOps（面倒な運用はいらない）、さらにいえば NoDev（無用な開発はしない）を志向しています。

こういった背景がある中、巨大システムである EC をどう扱っていくかが焦点となり、本記事で取り扱う Magento2 を GKE ホスティングすることに挑戦しました。

## 柔軟な EC 開発環境としての Magento2 on GKE
Adobe Magento2 は Nike.com に代表される大型 EC を柔軟に開発できるように設計された、世界でもっともシェアがあり高品質な、オープンソース EC システムです。

[Online Selling Platform | Magento Commerce](https://www.adobe.com/commerce/magento.html)

新規事業領域は EC そのものが必要な場面は多くありますが、Magento2 を利用してカバーするのはサービスの価値提供の根幹に込み入った実装が存在する、例えばバックエンドとして商材と決済と会員のエンドポイントを扱いながら、各部で他のシステムへの連携機能を組み込むなど、フルスペックでありながら柔軟に機能拡張が可能な EC システムが必要になる場面です。

この様な領域のために、保守運用を含めた 2019 年時点での Magento2 構成のベタープラクティスの研究を行い、GKE ホスティングにたどりつきました。

## Magento2 ホスティングの論点
Magento2 は乱暴に言えば500万行のコードと400弱のテーブルを持つ巨大な WordPress、つまりモノリシックな LAMP ソフトウェアの文脈に属します。

ホスティングする際は EC2 などのインスタンスを秘伝の IaC 等で立てるのが一般的です。しかし Magento2 自体ホスティング要件の変化が多く、年4回ほどのアップデートでのミドルウェア依存の変更はもとより、年一度ほどは OS レベルで依存関係が変化する場合も多く、IaC もすぐ腐るか、なかなか割にあいません。

そもそも IaaS での運用は大変なのでコンテナ化できないかと 2015 年の Magento2 発表時からコミュニティ内でも課題感を共有していました。

Magento2 発表後から現在まで、公式含む数多くのコントリビューターが、まず開発環境のコンテナ化を模索していました。しかし LAMP 文脈のステートフルなシステムを素直にコンテナ化していくと Laradock 的な文脈で肥大化したコンテナに到達してしまうなど、ホスティングを前提としたコンテナデザインにたどり着かないまま（公式も半ばあきらめモードとなり）Kubernetes 時代に入りました。

Kubernetes をもって改めてどうホスティングしていくか、いくのがよいかの発表が 2017 年から各都市のカンファレンスでポツポツと出てくるなか、私もついに 2019年11月の東京カンファレンスに登壇し GKE 構成を日本初で発表しました。

## 仮想的なロール、単一プロセス
Magento2 をホスティング前提でコンテナ化するのが難しい理由は、その巨大なモノリシックさから来ます。

通常モノリシックなアプリケーションをコンテナ化していく際は、機能を役割ずつ分割した API として切り出していくのが正攻法と思いますが、Magento2 においては独自開発を行えば行うほどアップデートに追従できず、 Adobe Magento 社の1000人超のフルタイム開発者がメンテナンスしているという大きな利点を手放してしまうことになります。

どうモノリシックなシステムと、コンテナと、スケーラブルさを折り合わせて Kubernetes の利点を享受するのか。この点は過去に Kubernetes ホスティング化にトライした各地カンファレンススピーカー達も GCP の公式ベストプラクティス構成においてもぼやかしており、ベストプラクティスが定まらない課題が残る領域です。

[アーキテクチャ: Magento のデプロイ  |  アーキテクチャ  |  Google Cloud](https://cloud.google.com/solutions/architecture/magento-deployment)

私のコンテナデザインにおいても満足いかない無理やりな出来ではありますが、Magento2 シングルイメージを、ロールに分けて部分的な機能だけ使うという手法で、仮想的に機能を分解して利用する手法をとりました。以下が構成図です。

![M2K-Architecture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/752/511bb2c0-93ec-30ca-80a3-62a0cfb36bff.png)

この構成図では DB はもとより、ユーザーが利用する「ストアフロント」をスケールアウトできる様に Redis と NFS でつなぎ、ジョブ管理専用で Cron を利用したコンテナを独立させ（余りにも初期化が重くCronJob化は断念）管理者が利用する「管理画面」を分割したコンテナのみで利用できる様に Magento2 の既存機能を利用して仕込んでいます。

この構成で過去に比べ特徴的となったのは、一つのイメージコンテナをルーティングによって役割分割するというアイデアです。（まるでモノリシックな Rails アプリをスケールさせていく途中で現れそうな構成です）

さらに Magento2 は早くから半ば SPA 的な構造を取り入れているため、ストアフロントと管理画面の分割から始めて、API 通信に対するルーティングベースで「商品検索のみ」「マイページのみ」「購入遷移のみ」とさらに分割し専用コンテナ化する事が可能です。ただし完全な機能分割ではないため、分割をすればするほどマシンリソースにオーバーヘッドが伴うのは留意しなければなりません。

モノリシックなコンテナイメージに対し、ルーティングで仮想的なロールを振る舞わせるアイデアに伴うオーバーヘッドを許容することにより、GKE の多くの利点を享受して Magento2 を開発運用できるようにしたのがトレードオフとなっています。開発運用の効率化を考えれば悪くない取引だと判断しています。

## さらに Magento2 モジュール単位での分解へ
GKE のメリットは享受できたとしても仮想的なロール分割の筋がベストとは考えていません。

今後さらに Magento2 のコンテナホスティングをすすめるにあたり突破口となりそうなポイントは、実は Magento2 自体は完全に独立したモジュール、機能郡、composer packages の集合体として設計されている点です。そのため PHP アプリケーションでありながらコンパイルを必要とするシステムとなっています。

もしモジュールそれぞれをモジュール郡に分類し、各コンテナとして動かす事が成功すれば、オーバーヘッドのない実際的なロールを与えられる可能性があります。

LIFULL 社長室では、ビジネスも育てる。必要とあれば Magento2 を GKE に乗せる。そんな事業開発エンジニアを募集しております。ご連絡は @kzkiq2nd まで。