Magentoにおけるブルーグリーンデプロイの利点と注意点

takeda
2024-04-18
2024-04-18

こんにちは!

今回はMagentoおよびAdobe Commerce(以下まとめてMagentoと呼びます)のブルーグリーンデプロイにまつわるお話を書いてみようと思います。

ブルーグリーンデプロイメントとは

稼働中の運用サーバーへのリリースを行う際、運用中のサーバーと別にデプロイ用の新しいサーバーを用意し、そちらにデプロイや検証を行ってからトラフィックを切り替えてリリースする手法です。

運用中の環境をブルー系
準備側の環境をグリーン系
と呼びます。

ダウンタイムを最小限にとどめることができ、デプロイで問題が発生した場合でもロールバックを行う必要が無い(または切り戻しが容易)などのメリットがあります。

Magentoにおけるブルーグリーンデプロイの利点

ブルーグリーンデプロイでは、サービスを継続させたままリリースが可能となるため、MagentoのようなECシステムにおいては、非常に有効なデプロイ手法と言えます。

production modeで稼働しているMagento環境ではソースコードを置くだけでそれをシステムに反映できる事はできず、殆どの場合アップデートの実行やファイルの再構築の実行などを伴うため、ちょっとしたソースコード変更でも反映には非常に時間がかかります。更新中はサイトへのアクセスが出来ない状態となるため通常はサイトをメンテインして作業を行います。そのような特徴を持つMagentoにとって、無停止でのリリースが可能となるブルーグリーンデプロイはまさにうってつけのデプロイ手法です。

Magentoにおけるブルーグリーンデプロイの注意点

Magentoに限ったことではないですが、ブルーグリーンデプロイする際に注意しなければならないのは共有しているリソースについてです。DBのようなリソースをブルー系とグリーン系のどちらからも参照している場合。グリーン系で更新するとブルー系にもそのまま影響するため、スキーマ更新やデータの大幅な更新が行われる場合はそれをよく考慮しておかないとブルー系WEBサーバーでシステムダウンを引き起こす可能性があります。

特にMagetnoはソースコードとデータベースの関係性が非常に強いシステムです。EAVモデルに関する情報やモジュールのスキーマバージョン情報など、データベース内で管理されているシステム情報が非常に多く、アップデートの際にこれらが更新される場合は、デプロイ実行中にブルー系に及ぼす影響に注意しておく必要があります。

注意が必要なモジュールアップデートの一例

  • EAVの属性の削除
  • Magento設定項目の変更や削除
  • モジュールのsetup_versionの変更

属性の削除等を伴うモジュールアップデートの場合

EAV属性やシステムの設定項目を新たに追加する場合はあまり問題になることはありませんが、運用環境で既に存在しているものを削除する場合は注意が必要です。モジュールアップデートにおいてソースコードの削除と共に関連するEAV属性の削除を一緒に行うようなとき、アップデートが走った時点でブルー系がその影響を受けてエラーを起こす可能性があります。

このようなケースの回避方法としては、デプロイ作業を2段階にする等が考えられます。
先にソースコードの対応のみを行ってリリースし、システムがその属性を使用しない状態にします。その後でデータベースの更新(属性の削除)をデプロイします。

モジュールのsetup_versionに注意

データベース上の重要な変更が行われる場合には注意が必要ですが、その中でも気を付けておきたいポイントとして、モジュールのsetup_version(schema_versionの更新があります。

モジュールアップデート時におけるデータ更新やスキーマ更新の実装方法にはいくつか方法がありますが、古い実装手法にUpgradeSchemaやUpgradeDataといったアップデート実装があります。この方法ではバージョン管理のためにモジュールのsetup_versionを用いる事があり、それがブルーグリーンデプロイで問題になることがあります。

グリーン系でモジュールのアップデートが実行されたときモジュールのsetup_versionが変更になると、データベースに記録されているモジュールのバージョン管理テーブルが更新されます。(setup_moduleテーブルにschema_versionとして記録されます)
例えばグリーン系でsetup_versionを"1.0.0"→"1.1.0"に変更したとします。それにより管理テーブルのレコードも"1.1.0"に更新されますが、この時のブルー系のモジュールは"1.0.0"のソースコードで稼働しているので、クラスが呼び出されたときにバージョンチェックにひっかかり、クリティカルなエラーが発生します。
モジュールとデータベース定義の互換性を保つ事は重要なのでsetup_versionには一定の意味はありますが、ブルーグリーンデプロイにとっては不利な管理方法です。

そこでモジュールアップデートにおけるデータ更新はData Patch(DataPatchInterface)による実装手法を用いるようにします。この手法はMagento2.3から採用されている新しい実装手法です。モジュールアップデート時のDBのアップデート適用判断においてsetup_versionを用いる必要がありません。個々のData Patchが適用済みかどうかの判断はpatch_listテーブルでMagentoによって管理されており、その判定自体がブルー系に影響を与えることはありません。依存関係を指定することもできるのでバージョン番号で管理するよりも便利で合理的です

setup_versionを使用している古い実装例(UpgradeDataInteface実装)

module.xml に、setup_versionを記述

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="FutureSpirits_Catalog" setup_version="1.2.0">
    </module>
</config>

UpgradeDataInterfaceでクラスを実装し、setup_versionを判定をして処理を行う

<?php

namespace FutureSpirits\Catalog\Setup;

use Magento\Framework\Setup\UpgradeDataInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\ModuleContextInterface;

class UpgradeData implements UpgradeDataInterface
{

    public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        if (version_compare($context->getVersion(), '1.1.0', '<')) {
            /**
             *  アップデートに必要な更新処理 - その1
             */
        }
        if (version_compare($context->getVersion(), '1.2.0', '<')) {
            /**
             *  アップデートに必要な更新処理 - その2
             */
        }
    }

setup_versionを使用しない新しい実装例(DataPatchInterface実装)

module.xml に、setup_versionの記述は不要

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="FutureSpirits_Catalog">
    </module>
</config>

DataPatchInterfaceでクラスを実装し、applyメソッド内に更新処理を記述。


<?php

namespace FutureSpirits\Catalog\Setup\Patch\Data;

use Magento\Framework\Setup\Patch\DataPatchInterface;

class UpdateA implements DataPatchInterface
{
    public function apply()
    {
        /**
         * アップデートに必要な更新処理 - その1
         */
    }

パッチに依存関係が必要な場合はgetDependenciesに記述可能。

<?php 

namespace FutureSpirits\Catalog\Setup\Patch\Data;

use Magento\Framework\Setup\Patch\DataPatchInterface;

class UpdateB implements DataPatchInterface
{
    public function apply()
    {
        /**
         * アップデートに必要な更新処理 - その2
         */
    }
    public static function getDependencies()
    {
        // 依存するパッチをここに列挙する(この例ではUpdateAの適用を必須とする)
        return [
            \FutureSpirits\Catalog\Setup\Patch\Data\UpdateA::class
        ];
    }

事前の検証も大事

大幅なデータベース更新を伴うアップデートをする際は、ブルーグリーンデプロイで問題が起きないかを事前に検証してみることも大事です。本番のブルーグリーンを再現できる環境を用意し、グリーン系でアップデートを実行した時のブルー系の挙動を確認しておくと安心です。

運用中のシステムに対して安全に無停止リリースが出来るのがブルーグリーンデプロイの良いところなので、そのための事前の確認はしっかりしておきたいですね。