
Windows Server
イベント
マガジン
該当するコンテンツが見つかりませんでした
技術ブログ
はじめに こんにちは。EC基盤開発本部 SRE部 カート決済SREの遠藤です。 普段はカート決済に関連する機能のリプレイスや保守運用をメインに、ZOZOTOWNのDBREとして活動しています。 近年、ランサムウェア攻撃が世界中で猛威を振るっており、企業のデータ保護は喫緊の課題となっています。特にデータベースは企業活動の根幹を支える重要な資産であり、万が一の攻撃に備えた対策が不可欠です。 本記事では、Everpure社(旧Pure Storage社)のストレージ製品「FlashArray」を活用したランサムウェア対策をご紹介します。対象はZOZOTOWNの基幹データベースであるMicrosoft SQL Serverです。 はじめに 概要 前提:Everpure FlashArrayとSafeMode FlashArrayの主な特徴 主な特徴・機能 スナップショットの容量効率と多世代保持 SafeModeによる不変スナップショット SafeModeのランサムウェア対策の仕組み 課題:FlashArray標準スナップショットによる運用上の問題 解決策:VSS連携によるSQL Serverスナップショットの取得 VSS連携の仕組み VSS連携の流れ VSSの3つのコンポーネント 検証:I/Oフリーズによるサービス影響 検証方法 検証結果 実装:スナップショット取得バッチの作成 全体構成 事前設定 クレデンシャルの登録 バックアップジョブの登録 バッチ実装 スナップショットの実行 運用:構成とモニタリング Protection Group と Snapshot Schedule の設計 実行タイミングの最適化 日常運用とモニタリング 展望:T-SQLスナップショットへの移行 各方式の比較 SQL Server 2022:VSSに依存しないスナップショットバックアップ SQL Server 2025:T-SQLで完結したスナップショットバックアップ まとめ 本取り組みのポイント 今後の展望 最後に 概要 本取り組みでは以下を行いました。 Everpure FlashArrayの「SafeMode」機能を利用した不変スナップショット運用の導入 データベースの整合性を担保したスナップショット取得の設計実装 今後のSQL Serverのバージョンアップに伴うFlashArrayとの連携強化の調査と検証 これらの取り組みにより、万が一ランサムウェア攻撃を受けた場合にデータを復旧できる体制を強化しました。 前提:Everpure FlashArrayとSafeMode FlashArrayは、ストレージベンダーであるEverpure社が提供するオールフラッシュストレージです。 ZOZOTOWNの基幹データベースは、オンプレミス環境のWindows Server上で稼働するMicrosoft SQL Serverです。そのデータを保存するストレージとして、Everpure FlashArrayを採用しています。 Everpure社は、2026年2月にPure Storage社からの社名変更を発表しました。本記事ではSDKなど一部の名前に「Pure Storage」という名前が残っていることをご了承ください。 www.everpuredata.com FlashArrayの主な特徴 主な特徴・機能 FlashArrayは、データベース運用において有用な特徴や特性を備えています。 機能・特性 説明 データベース運用上のメリット 重複排除・データ圧縮 同一ブロックの集約とリアルタイム圧縮 ストレージ容量を効率化し、多世代スナップショットを低コストで保持できる 高速なスナップショット ボリュームの瞬間的なコピーを作成 高速なバックアップ・復元が可能 SafeMode機能 データやスナップショットの物理削除を不可能にする ランサムウェア対策に有効 スナップショットの容量効率と多世代保持 FlashArrayのスナップショットは元データの参照情報を記録した軽量データです。スナップショット作成時にはデータの物理的なコピーは行わず、その後書き換えられたデータの旧版のみが容量を消費します。保持されるデータにも重複排除と圧縮が適用されます(弊社環境のアレイ全体では平均5:1程度のデータ削減率を実現しています)。 管理画面上では最新以外のスナップショットは数GB程度と小さく表示される一方、最新のスナップショットだけが数百GB規模で表示される場合があります。これは複数世代で共有しているデータが最新のスナップショットにまとめて計上されるためで、実際の消費量はスナップショット全体の合計で見る必要があります。この合計容量は、データの増加量ではなく既存データの書き換え量で決まります。追記中心のDBでは小さく収まりますが、インデックスの再構築や大量の更新・削除、集計テーブルの洗い替えなど、既存ページを広く書き換える処理があると大きくなります。 いずれの場合も、世代ごとに全量のコピーを持つわけではないため、ストレージ内に多世代のスナップショットを容量効率良く保持し続けられます。 SafeModeによる不変スナップショット FlashArrayによってランサムウェア対策を実現するためには、SafeMode機能 *1 の有効化が必要です。 SafeModeが有効なスナップショットは、事前に設定された保持期間の間は削除・変更できなくなります。前述の容量効率の高さにより、この不変スナップショットも多世代にわたって保持できるため、ランサムウェア被害時に確実に復旧できます。 SafeModeのランサムウェア対策の仕組み 昨今のランサムウェア攻撃はデータを暗号化するだけでなく、バックアップやスナップショットを削除して復旧手段を奪おうとするケースが増えています。通常のストレージであれば、管理者の認証情報まで取られた場合、攻撃者はスナップショットを削除できます。 しかし、SafeModeで保護されたスナップショットは、管理者権限でも物理削除できないため、攻撃前の正常なデータを確実に保持し続けます。仮に攻撃者がホストサーバー(Windows Server等)の管理者権限を取得し、FlashArrayのボリューム上のデータを暗号化したとしても、スナップショット自体は守られます。 万が一、SafeModeの無効化や設定変更を行いたい場合は、事前に登録された複数の管理者がEverpureのサポートと連絡を取り本人確認する必要があります。この多要素・多人数の認証により、内部犯行や認証情報の漏洩があった場合でも、攻撃者が単独でSafeModeを無効化できないようになっています。 以下の図は、ランサムウェア攻撃に対してSafeModeがどのように機能するかを示しています。 攻撃を受けた場合は、FlashArrayの管理画面やREST APIから攻撃前の正常なSafeModeスナップショットを特定し、ボリュームをリストアすることで復旧できます。 課題:FlashArray標準スナップショットによる運用上の問題 ここからは、FlashArrayのSafeModeによる不変スナップショットを導入するにあたり判明した課題と解決へのアプローチを紹介します。 ZOZOTOWNの基幹データベースでは、以前からFlashArrayを採用していました。 FlashArray導入時からSafeModeも有効化しスナップショットを取得していました。しかし、ランサムウェア対策の運用を見直す中で、FlashArrayの標準設定ではSQL Serverの運用に適したスナップショットが取得できていないことが判明しました。 FlashArrayをはじめとするストレージ製品の標準的なスナップショットは、「クラッシュ整合性」と呼ばれる整合性レベルのスナップショットです。 SQL Serverなどのトランザクションを持つデータベースでは、書き込みI/Oを一時停止して静止点を確保し、復元可能な状態を保証する「アプリケーション整合性」レベルのスナップショットが求められます。 それぞれの整合性の違いは下記の通りです。 比較項目 クラッシュ整合性 アプリケーション整合性 データ状態 突然の電源断と同じ状態。メモリ上のバッファキャッシュや未コミットのログはディスクに書き込まれていない。 書き込みI/Oが停止された状態。書き込み中断によるページ破損のリスクがなく、復元可能な状態が保証されている。 復旧プロセス 起動時にクラッシュリカバリが走る。不整合な箇所を自動修復する。 リカバリ処理は不要。バックアップ時点の状態ですぐに起動・利用可能。 復旧時間 (RTO) 時間がかかる。未処理のログ量が多いほど、起動時のロールフォワード/ロールバックに時間を要する。 極めて短い。修復プロセスをスキップできるため、即座にサービスを再開できる。 データ破損リスク 稀にページ破損(Partial Write)が起きるリスクがある。 リスクは極めて低い。 実現方法 ストレージやハイパーバイザのスナップショット機能のみで実行。 DBのI/Oを一時的に凍結し、静止点を作れる機能と連携して実行 本番への影響 負荷が無い。DB側での処理が不要なため、スナップショット作成時のパフォーマンス低下はない。 一時的な負荷あり。メモリのフラッシュやI/Oの一時凍結(フリーズ)により、レスポンスの瞬断や遅延が発生する場合がある。 クラッシュ整合性スナップショットから復元するとクラッシュリカバリが必ず走ります。ログ量や実行中のトランザクションの状況によって復旧にかかる時間は大きく変動するため、RTOを見通せないことが問題となります。 また、MicrosoftはSQL Serverのスナップショットバックアップの取得方法としてVSSとの連携を案内しており *2 、ストレージ単独でのスナップショット取得は推奨されていません。 解決策:VSS連携によるSQL Serverスナップショットの取得 この課題を解決するための方法として、Windows VSS *3 (Volume Shadow Copy Service、以下VSS)と連携しスナップショットを取得する必要があります。 しかし、過去に別のバックアップソリューションでVSSと連携したスナップショットを取得した際、深刻な障害へと発展した経験がありました。 VSS連携時にはディスクに対して瞬間的にI/Oフリーズを発生させる必要がありますが、このI/Oフリーズが長時間続いた場合、クエリタイムアウトが発生し、大量のエラーを引き起こすことにつながります。 この経験から、VSSの利用は慎重なアプローチが必要でした。 VSS連携の仕組み ここでFlashArrayとVSSの連携方法を解説します。VSSはある瞬間の整合性が取れたデータスナップショットを取得するためのサービスで、Windows OSに組み込まれている機能です。 VSS連携の流れ 以下がVSSによるFlashArrayの不変スナップショットの全体フローです。 VSSの3つのコンポーネント VSSを使ったスナップショットは、以下の3つのコンポーネントを連携することで実現します。 (1) VSS Requester VSSによるボリュームのスナップショットを取得するためにはVSS Requesterによる実行指示が必要です。 Backup SDKによってインストールされるPure Storage Requesterがこれに該当します。PowerShellのスクリプトを定期実行し、SDKの Invoke-PfaBackupJob コマンドによりPure Storage Requesterに対してスナップショット取得を要求します。 (2) VSS Writer SQL Serverなどのアプリケーション側と連携するためのコンポーネントです。今回はSQL Server VSS Writerがこれに該当し、SQL Server構築時に自動でインストールされています。VSSからの指示を受けて、静止点が取れる状態に準備します。その後データベースへの書き込みI/Oの一時停止(Freeze)と再開(Thaw)をします。 (3) VSS Hardware Provider ストレージ側と連携するためのコンポーネントです。今回はPure Storage VSS Hardware Providerがこれに該当します。VSSからの指示を受けて、FlashArrayのREST APIを呼び出し、スナップショットを作成します。 検証:I/Oフリーズによるサービス影響 前述の通り、過去にVSSのI/Oフリーズを原因とした障害を経験しており、今回のVSS連携も慎重に検討する必要がありました。 検証方法 以下の2つの検証を実施しました。 STG環境で過去に障害となったバックアップツールを起動し、VSSによるI/Oフリーズの発生時間を確認 商用環境でI/Oフリーズを再現し、段階的にフリーズ時間を延長してサービス影響が出ないか確認 検証2では以下のクエリをSQL Serverに実行しI/Oフリーズを再現しました。 DBCC FREEZE_IO ( ' DB名 ' ) WAITFOR DELAY ' 00:00:00.100 ' ; --(例)100msの間I/Oフリーズを発生させる DBCC THAW_IO ( ' DB名 ' ) DBCC FREEZE_IOコマンドはMicrosoft公式サポート対象外(Undocumented)です。本来は本番環境での利用は推奨されませんが、問題がないことを確認した上で利用しています。 検証結果 2つの検証を通じて、VSSのI/Oフリーズの与えるサービス影響が許容範囲であることを確認し、VSS連携によるSafeMode導入は問題ないと判断しました。 また、検証のなかで、VSSによるI/Oフリーズ発生時の具体的な影響範囲も判明しました。 Insert/Update/Deleteは全て影響を受ける Selectについてはメモリにデータが載っていないときだけ影響を受ける メモリに余裕がある場合Select句で影響を受ける可能性は少なくなる 実装:スナップショット取得バッチの作成 全体構成 今回は、VSSと連携してスナップショットを取得するために、Pure Storage Backup SDKを利用したバッチスクリプトを実装しました。このSDKはPowerShellモジュールのため、バッチもPowerShellで実装しています。 バッチから呼び出される各機能の関連は下記の通りです。 このうち、SQL Server VSS WriterとVSSはSQL Server構築時とWindows OSに標準で含まれているため、追加インストールは不要です。Pure Storage Requesterについても、初回のバックアップジョブ実行時にBackup SDKが自動でインストールしてくれました。手動でのインストールが必要なのは、バッチ実行サーバーのSSMS Extension(Backup SDKが同梱されています)と、DBサーバーのVSS Hardware Providerの2つです。 FlashArrayへのREST API接続は2経路あります。1つはVSS Hardware Providerからのもので、VSSからの指示を受けてスナップショットを作成します。もう1つはBackup SDKからのもので、こちらはスナップショット取得そのものではなく、バックアップ構成と取得履歴の管理に使われます。 なお、DBサーバーとFlashArrayの間はFC Switch経由のFC接続で、SQL Serverのデータファイル・ログファイルはFlashArray上のボリュームに配置されています。 事前設定 設定にはPure Storage Backup SDKのPowerShellモジュールに含まれるコマンドレットを使用します。 クレデンシャルの登録 バッチ実行サーバーから、SQL ServerとFlashArrayのREST APIに接続するためのCredentialを登録します。 # SQL Serverへの接続情報(Windows認証) Add-PfaBackupCred -CredentialName "<任意の名前>" ` -Address "<SQL Server IP>" ` -CredentialType "Windows" ` -Credential ( Get-Credential ) # FlashArrayへの接続情報 Add-PfaBackupCred -CredentialName "<任意の名前>" ` -Address "<FlashArray IP>" ` -CredentialType "FlashArray" ` -Credential ( Get-Credential ) バックアップジョブの登録 同様に、バッチ実行サーバーからスナップショット取得先の設定を登録します。 Add-PfaBackupJob -ConfigName "<設定名>" ` -Component "<インスタンス名>\<データベース名>" ` -ComputerName "<SQL Server名>" ` -FAName "<FlashArrayクレデンシャル名>" ` -VolumeType "Physical" ` -MetadataDir "<メタデータ保存先>" ` -CopyOnly SQL Serverのバックアップ運用と併用する場合は -CopyOnly を指定します。未指定の場合、スナップショットが差分バックアップの基点としてリセットされ、既存のフルバックアップ+差分バックアップの復元手順に影響が出てしまいます。 バッチ実装 スナップショットの実行 バッチから Invoke-PfaBackupJob コマンドを実行しスナップショットを取得できます。ConfigNameには Add-PfaBackupJob コマンドで事前に設定したジョブ設定名を指定します。 $result = Invoke-PfaBackupJob -ConfigName "<設定名>" if ( $result [ "Status" ] -ne "Succeeded" ) { throw "スナップショット取得に失敗しました" } 運用:構成とモニタリング VSS連携によるスナップショット運用を安定して回すため、Protection Groupの設計、実行タイミング、日常的なモニタリングの観点で運用ルールを整理しました。 Protection Group と Snapshot Schedule の設計 Protection Groupは、FlashArrayにおけるスナップショットの管理単位です。複数のボリュームをグループ化し、まとめてスナップショットを取得・管理できます。 同じProtection Group内にある複数ボリュームのスナップショット取得や復元は、まとめて処理されます。しかし、VSS連携をした今回のスナップショットは指定したボリュームのみに適用されます。また、SafeModeを有効化するためには、Protection GroupにSnapshot ScheduleというFlashArray標準のスナップショットも有効化する必要があります。 この仕様を理解し、以下のようにProtection Groupの設計を見直しました。 SystemDBとUserDBをそれぞれ独立してリストアできるよう、Protection GroupとVSS連携をDBごとに分ける Protection GroupのSnapshot Scheduleは必ず有効化する(SafeMode有効化の前提条件) 弊社環境での具体的なProtection Group構成は以下の通りです。 ProtectionGroupA :DBではないその他の複数ボリューム ProtectionGroupB :SQL ServerのSystemDBが存在する単一ボリューム。VSS連携によるスナップショット対象 ProtectionGroupC :SQL ServerのUserDBが存在する単一ボリューム。VSS連携によるスナップショット対象 ProtectionGroupD :SQL ServerのTempDBが存在する単一ボリューム(SQL Server起動時に自動再作成されるため、VSS連携の対象外) 実行タイミングの最適化 他の処理との競合を避けるため、実行タイミングを慎重に設計しました。考慮事項としては以下が挙げられます。 他の処理のピーク時間帯を避ける 通常のSQL Serverバックアップ(BACKUP DATABASE)とVSSスナップショットを同時に実行すると、ロック競合を起こす可能性があるため起動時間をずらす 同一のFlashArray内で複数のデータベースが稼働している場合はそれらの起動時間が被らないようにずらす 日常運用とモニタリング 日常的なモニタリング項目としては以下が挙げられます。 I/Oフリーズ時間の監視 スナップショットストレージ容量の推移監視 I/Oフリーズは負荷やDBの特性によって変化が大きく、数十msから1500ms程度かかるDBも存在しました。データの更新量やキャッシュ容量の大きいDBではスナップショットの所要時間が伸びる傾向にあります。許容できるフリーズ時間をあらかじめ見積もり、フリーズ時間が徐々に延びていないかを監視する必要があります。 また、FlashArrayのスナップショットは、重複排除の仕組みにより非常に小さいサイズで済みます。しかし、データの更新量や重複率によってサイズが大きく変わるため、正確な見積もりは困難です。そのためスナップショットを含めたFlashArrayの容量監視は重要です。 なお、万が一ランサムウェアに感染しデータを改ざんされた場合、重複排除が効かなくなりデータ容量の肥大化を起こすと考えられます。その際の早期発見としても容量推移のモニタリングは有効です。 展望:T-SQLスナップショットへの移行 ここからは、今後のバージョンアップに備えて調査・検証した最新の連携方法を整理します。 今回導入したVSS方式は安定して運用できていますが、SQL Server外部のWindows VSSがI/Oフリーズを制御する仕組みです。そのため、VSS WriterやVSS Hardware Provider、Backup SDKなどの依存コンポーネントが多い構成となっています。また、VSS方式のスナップショットはLSN情報を持たないため、スナップショット復元後に既存のトランザクションログバックアップを適用したポイントインタイムリストア(PITR)ができないという制約もあります。ランサムウェア被害時はサーバー上のデータが信用できないためSafeModeスナップショットから復元しますが、VSS方式ではその後のPITRに対応できません。 SQL Server 2022で追加された「T-SQLスナップショットバックアップ」はSQL Server自身が静止点を制御する方式で、VSSへの依存がない構成です。加えて、 .bkm メタデータファイルによってスナップショット後のログバックアップを適用したPITRも可能になります。さらにSQL Server 2025ではFlashArrayのAPI呼び出しまでT-SQLで行えるようになり、外部スクリプトを排した運用が可能になりそうです。 各方式の比較 項目 VSS連携方式 T-SQL方式 (2022) T-SQL方式 (2025) SQL Serverバージョン 2016以降 2022以降 2025以降 I/Oフリーズの制御 VSS(Windows OS側) SQL Server自身 SQL Server自身 ストレージ呼び出し VSS Hardware Provider PowerShell + Backup SDK T-SQLから直接(REST API) 外部スクリプト 必要(PowerShell等) 必要(PowerShell等) 不要 ポイントインタイム復旧 困難 可能(.bkmファイル) 可能(.bkmファイル) 各方式の構成は以下のようになります。バージョンが上がるにつれて依存コンポーネントが段階的に削減されます。 SQL Server 2022:VSSに依存しないスナップショットバックアップ SQL Server 2022では、VSSを介さずSQL Server自身がI/Oフリーズを直接制御します *4 。 VSS WriterやVSS Hardware Providerへの依存がなくなり、構成がシンプルになります。 スナップショット取得後に出力される .bkm メタデータファイルにはLSN(Log Sequence Number)情報が記録されます。これにより、スナップショットから復元後にトランザクションログバックアップを適用したポイントインタイム復旧が可能になります。VSS方式では実現が難しかった任意時点への復旧が、標準的な手順で行えるようになる点が大きな改善です。 なお、FlashArrayのREST API呼び出しはPowerShell *5 で行う必要があります。 SQL Server 2025:T-SQLで完結したスナップショットバックアップ SQL Server 2025では、T-SQLからFlashArrayのREST APIを直接呼び出せるようになります( sp_invoke_external_rest_endpoint ) *6 。 これにより外部PowerShellスクリプトが不要になり、認証情報の管理を含めたスナップショット運用をSQL Server内部に完全に閉じることができます。スナップショットへのタグ付けやカタログ機能も提供され、T-SQLのみでバックアップ運用を完結できます。 このように、今後SQL ServerとFlashArrayの連携が強化され、よりシンプルな運用が可能になる予定です。 まとめ 本取り組みのポイント 本記事では、Everpure FlashArrayのSafeModeとVSS連携を組み合わせ、SQL Serverの確実なリストア体制を整えた取り組みを紹介しました。 FlashArray SafeModeによる不変性の確保 :導入当初から有効化し、攻撃者による削除・改ざんを防止 VSS連携の導入(今回の対応) :Microsoftが推奨するVSS連携を導入し、クラッシュリカバリなしに確実に復旧できる体制を整えた 重複排除による容量効率 :多世代のスナップショットを効率的に保持 段階的な導入 :過去のVSS障害の教訓を活かし、影響を最小限に抑えながら展開 今後の展望 今後も様々な改善を検討中です。 SQL Server 2022環境でVSSに依存しない方式への移行 SQL Server 2025でのT-SQLで完結したスナップショットへの移行 異なる環境へのスナップショットの転送。多層防御化 定期的な復旧訓練の実施 最後に ランサムウェア対策は単一の施策で完結するものではありません。多層的な防御を構築し、継続的に改善していくことが重要です。本記事が同様の課題を抱える方々の参考になれば幸いです。 ZOZOでは、一緒にサービスを作り上げてくれる方を募集中です。ご興味のある方は、以下のリンクからぜひご応募ください。 corp.zozo.com *1 : https://www.everpuredata.com/jp/solutions/cyber-resilience/ransomware/safemode.html *2 : https://learn.microsoft.com/ja-jp/sql/relational-databases/backup-restore/create-a-transact-sql-snapshot-backup *3 : https://learn.microsoft.com/ja-jp/windows-server/storage/file-server/volume-shadow-copy-service *4 : https://learn.microsoft.com/ja-jp/sql/relational-databases/backup-restore/create-a-transact-sql-snapshot-backup *5 : https://github.com/PureStorage-Connect/PowerShellSDK2 *6 : https://techcommunity.microsoft.com/blog/sqlserver/reimagining-data-excellence-sql-server-2025-accelerated-by-pure-storage/4470810
AWS Systems Manager (SSM) の Fleet Manager を使用して、カスタムAMIから起動したWindows Serverインスタンスに接続できない事象の原因と解決策について解説します。Sysprep未実行によるSID重複などの問題を回避するための正しいAMI作成手順を紹介します。
はじめに こんにちは、EC基盤開発本部SRE部でテックリードを務めている杉山です。 ZOZOでは、長年運用してきた基幹システムを新しいアーキテクチャへリプレイスする取り組みを進めています。新システムではAPIにJava、フロントエンド+BFFにReact(TypeScript / Node.js)を採用し、インフラはKubernetes上に構築しています。 2025年11月に開催されたファインディ株式会社主催の「アーキテクチャConference 2025」では、「巨大モノリスのリプレイス──機能整理とハイブリッドアーキテクチャで挑んだ再構築戦略」と題して発表しました。基幹システムの課題と、アーキテクチャの方向性を紹介した内容です。 findy-tools.io その中で、基幹フロントエンドリプレイスについても触れています。既存システムと新システムを共存させながら、Kubernetes上で機能ごとにパスルーティングし、段階的に置き換えていく構想です。 しかし、当時このアーキテクチャはまだ「予定」でした。実現するためには、既存システムが長年抱えてきたある制約を取り除く必要があったためです。 それが、Webサーバーがユーザーセッションを保持する「ステートフル」な構成です。 本記事では、既存システムのIISが保持していたセッションをRedisへオフロードし、Webサーバーをステートレス化するまでの取り組みを紹介します。それによって基幹システムの段階的なフロントエンドリプレイスを進められるようになった背景にも触れます。 目次 はじめに 目次 基幹フロントエンドリプレイスの構想 新アーキテクチャを用意するだけでは移行できない 段階的リプレイスを阻んだIISセッション 認証だけではないIISセッションへの依存 認証をOIDC化するだけでは解決できない リプレイスの前に「状態」を切り離す IISセッションをRedisへオフロードする Before / After 独自フレームワークを変更した理由 セッションIDの引き回し シリアライズ方式と互換性 更新タイミングとエラー時のロールバック セッション期限管理の設計 Redis障害時の考え方 Redis Clusterの障害対策とキー設計 段階的な切り替えとフォールバック ステートレス化によって何が変わったのか いよいよ基幹フロントエンドのリプレイスへ まとめ 基幹フロントエンドリプレイスの構想 まず、ZOZOの基幹システムとリプレイスの背景について簡単に紹介します。 既存の基幹システムはClassic ASP(VBScript)/ IISを中心に構築され、長年にわたって機能追加を続けてきました。ZOZOは自社で倉庫を持っており、基幹システムには事業部が利用する業務機能だけでなく、ECサイトで取り扱う商品の物流機能も含まれています。非常に巨大なシステムで、長期間の運用によってモノリス化が進み、保守性・拡張性の低下や技術的負債の蓄積が課題となっています。 そこで現在、既存システムを新しいアーキテクチャへリプレイスする取り組みを進めています。 ただし、巨大な基幹システムを一度にすべて置き換えることは現実的ではありません。 ドメイン分離が容易な部分のマイクロサービス化やデータベースアクセス部分のマイクロサービスAPI化は進んでいますが、基幹システムのメインのフロントエンドのリプレイスはまだこれからです。 既存システムと新システムを一定の期間共存させ、機能単位で徐々に切り替えていく方針を考えました。 具体的には、次のような構成を目指しています。 Kubernetes基盤上にIngress + Istioによるルーティングの仕組みを構築し、URLのパスなどに応じてリクエストを振り分けます。これにより、既存システムを稼働させたまま一部の機能から置き換えていく、いわゆるストラングラーパターンによる段階的なリプレイスを目指しました。 「アーキテクチャConference 2025」でこの構想を紹介した2025年11月時点では、まだ「ステートレス化後のフロントアーキテクチャ(予定)」という位置づけでした。 では、なぜすぐにこの構成へ移行できなかったのでしょうか。 新アーキテクチャを用意するだけでは移行できない 構成図だけを見ると、新システムをKubernetes上に構築し、Ingressなどでパスルーティングすれば、既存システムから少しずつ移行できるように思えるかもしれません。 しかし、実際の既存システムには大きな制約がありました。 Webサーバー自身が状態を持っていた ことです。 既存システムでは、IISのセッション管理やサーバー上の作業用データファイルなど、動作に必要な状態をWebサーバー内部に保持していました。このような構成では、リクエストを処理するサーバーを自由に切り替えられません。 例えば、あるユーザーからの最初のリクエストをWebサーバーAが処理し、そのサーバーのメモリ上にセッションを作成したとします。次のリクエストがWebサーバーBへ送られると、WebサーバーBにはそのセッションが存在しません。 これは単純なスケールアウトだけでなく、Kubernetesへの移行でも問題になります。KubernetesではPodが作成・削除されることを前提としており、特定のWebサーバーやPodのローカルな状態に依存しない、ステートレスなアプリケーションが扱いやすい構成となります。 そして今回、もう1つ大きな問題となったのが 段階的リプレイス でした。 段階的リプレイスを阻んだIISセッション 今回目指しているのは、既存システムをあるタイミングですべて停止し、新システムへ一斉に切り替えるリプレイスではありません。既存システムと新システムを共存させながら、ページや機能単位で少しずつ移行していく、ストラングラーパターンによる段階的なリプレイスです。 この構成を実現するうえで、大きな壁となったのが、既存システムのIISセッションへの依存でした。 認証だけではないIISセッションへの依存 既存の基幹システムでは、IISのインメモリセッションをさまざまな用途で利用しています。代表的なものがユーザーの認証情報ですが、セッションの用途は認証だけではありません。 基幹システムには、複数の画面を遷移しながら1つの業務を完了する機能が数多く存在します。その過程で入力・選択した情報など、画面をまたいで引き継ぐ必要がある一時的なデータの保持にもセッションを利用しています。 そのため、既存システムの画面遷移は、同じIISセッションを継続して参照できることを前提としていました。 ここで、ページ単位の段階的なリプレイスを考えてみます。 既存画面(Classic ASP / IIS) ↓ 新画面(新システム) ↓ 既存画面(Classic ASP / IIS) IngressやIstioを利用すれば、URLのパスに応じてリクエストを振り分けること自体は可能です。しかし、ルーティングだけを切り替えても、画面間で利用しているセッション情報まで引き継げるわけではありません。 例えば、既存画面で保持した認証情報や一時データを後続の画面で必要とする場合を考えます。遷移先がKubernetes上の新システムになると、IISのメモリ上に保持していたセッションをそのまま参照できません。 つまり、ログイン状態の維持だけが問題ではありません。既存システムにおける 画面間の状態の引き継ぎそのものが、IISのインメモリセッションに依存している ことが、段階的リプレイスの障壁でした。 認証をOIDC化するだけでは解決できない この問題に対して、認証方式そのものを変更するアプローチも考えられます。例えば認証をOIDC(OpenID Connect)化し、ID Tokenを利用する構成に変更したとします。認証情報を特定のIISサーバーのインメモリセッションに依存させず、新旧システムの双方でユーザーを識別できるようになります。 認証だけが課題であれば、この方法で解決できる可能性があります。しかし今回の基幹システムでは、OIDC化だけでは要件を満たせません。既存システムがIISセッションに保持しているのは認証情報だけではないこと、そして拠点専用のサーバー構成を脱却しALBによるロードバランシングを実現することも目的としていたためです。 仮にOIDC化によって「誰がログインしているのか」を新旧双方で識別できるようになったとします。それでも、画面で入力・選択した情報など、画面間で引き継いでいる業務上の一時データまでID Tokenで引き継げるわけではありません。 例えば、既存画面でセッションに保存した情報を、次の新システムの画面で必要とするケースを考えます。 既存画面 │ │ 認証情報 │ + │ 画面間で引き継ぐ業務データ ↓ IIS Session │ × │ 新画面(新システム) 認証方式だけを切り替えても、この「×」は残ります。 つまり、今回解決する必要があったのは、認証をステートレスにすることだけではありませんでした。必要だったのは、認証情報や画面間で引き継ぐ一時データを含め、 既存WebアプリケーションがIISに保持している状態そのものを、特定のWebサーバーから切り離すこと でした。 リプレイスの前に「状態」を切り離す このままでは、Kubernetes上に新しいアプリケーションを構築しても、ページ単位の段階的な置き換えは実現できません。 言い換えると、セッションの保存場所という既存システムの実装上の制約が、リプレイスできる単位まで制約していました。 そこで、新システムへの移行を本格化する前に、まず特定のIISサーバーに閉じていたセッションを外部へ切り離すことにしました。認証情報だけでなく、画面をまたいで利用される状態もWebサーバーの外部で管理します。これにより、既存システムと新システムが共存しながら、ページ・機能単位で段階的に移行できる状態を作ります。 そのために採用したのが、IISのインメモリセッションをRedisへオフロードする 「セッションオフロード」 という手法です。 次章では、このセッションオフロードをどのような構成で実現したのかを紹介します。 IISセッションをRedisへオフロードする 目指したのは、Webサーバー自身がユーザーセッションを保持しない構成です。そこで、これまでIISのインメモリに保持していたセッションを、外部のRedisへオフロードすることにしました。 Before / After ポイントは、単純にRedisを追加することではありません。既存アプリケーションから見たセッションの扱いを大きく変えずに、セッションの保存先だけをWebサーバーのメモリから外部へ移す必要があります。 ZOZOの既存基幹システムでは独自フレームワークを利用しています。今回、この独自フレームワークをバージョンアップして、セッションの読み書きをRedisへオフロードできる仕組みを導入しました。これによって、Webサーバー自身はユーザー固有のセッションを保持せず、必要なセッション情報を外部から取得する構成へ変更します。 サーバー内部に保持していたデータファイルも、読み書き先をファイルサーバーへ移行しました。 Webサーバーとセッションのライフサイクルを分離することが、この取り組みの重要なポイントです。 独自フレームワークを変更した理由 既存の基幹システムでは、Classic ASPの各ページから直接IISのSessionオブジェクトを操作するのではなく、独自フレームワークを通じてセッションを読み書きしています。このフレームワークが、セッションへのアクセスを一元的に管理する役割を担っています。 この構成であったことが、今回のセッションオフロードを実現するうえで大きな助けとなりました。 アプリケーションを1つずつ改修して保存先を変更するアプローチでは、膨大な画面数を持つ基幹システムにおいて現実的な工数で対応しきれません。しかし、セッションへのアクセスがフレームワーク層に集約されていたため、そのレイヤーでRedisへの読み書きを吸収すれば、個々のアプリケーションコードを変更せずにセッションの保存先を切り替えられます。 つまり、フレームワーク側を変更することで、 既存アプリケーションへの変更を最小限に抑えながら、セッション管理だけを差し替える ことが可能になりました。 セッションIDの引き回し 新旧システム間でセッションを共有するためには、同一ユーザーのリクエストに対して同じセッションIDでRedisにアクセスする必要があります。 セッションIDはCookieを通じてクライアントに保持させます。リクエストごとにCookieから取得したセッションIDをキーとしてRedisからセッション情報を取得します。この仕組みにより、振り分け先がIIS上の既存システムでもKubernetes上の新システムでも、同じセッションを参照できます。 シリアライズ方式と互換性 IISのインメモリセッションでは、VBScript固有のオブジェクト形式でデータが保持されています。Redisへオフロードするにあたっては、このデータをシリアライズ可能な形式に変換する必要があります。 フレームワーク層でシリアライズ・デシリアライズ処理を実装し、既存のセッションデータとの互換性を維持しながらRedisへの永続化を実現しました。シリアライズフォーマットにはJSONを採用し、VBScript固有の型情報も保持するスキーマ設計としています。これにより、新システム側でも同じフォーマットで正しくデータを読み書きできます。 更新タイミングとエラー時のロールバック セッションデータのRedisへの更新タイミングも、重要な設計ポイントです。 今回は、スクリプトの実行開始時にセッションデータをまとめて取得し、処理中はインメモリで扱い、実行完了時にまとめてRedisへ書き戻す方式を採用しました。この方式には、スクリプト処理中のセッションアクセスを高速化できること、そしてエラー発生時のロールバックを兼ねられることという2つの利点があります。 処理の途中でエラーが発生した場合、Redisへの更新は実行されません。つまり、セッションが中途半端に更新された状態を防ぐことで、セッションデータの自動ロールバックを実現しています。 仮に、スクリプト実行中に都度Redisを更新する方式にすると、エラー発生時点で一部だけ更新が反映された状態となり、ロールバックが難しくなります。更新タイミングをまとめることで、この問題を回避しています。 セッション期限管理の設計 IISのインメモリセッションには、一定時間アクセスがなければ自動的に破棄されるタイムアウトの仕組みがあります。既存システムでは、セッション破棄時にSession_OnEndイベントで業務処理を実行していました。Redisへオフロードするにあたり、このセッション終了時の処理をどう再現するかが課題となりました。 RedisにはKeyspace Notificationsという仕組みがあり、キーの期限切れを検知した際にexpiredイベントを通知できます。ただし、このイベントはTTL満了時刻ちょうどではなく、Redisがキーの期限切れを検知・削除した時点で発行されるため、通知タイミングや時刻の厳密さは保証されません。また、Keyspace Notificationsは永続キューではなく、購読者が停止している間のイベントを後から取得する仕組みもありません。したがって、取りこぼしが許容されない業務処理のトリガーには適さないと判断しました。 そこで、別途、期限管理のサブシステムを稼働させる方式を採用しています。このサブシステムがセッションの期限切れを能動的に検知し、従来Session_OnEndで実行していた業務処理を代替したうえでセッションを削除します。定期スキャンによって確実に処理を実行でき、イベントの取りこぼしがないため安定性に優れます。 この仕組みは、ZOZOTOWNでのセッションオフロード時の仕様を踏襲したものです。 Redis障害時の考え方 セッションの保存先をRedisに一本化することで、Redis障害がシステム全体に影響するリスクが生まれます。 この点については、Amazon ElastiCache for Redisのクラスタモードを採用し、3AZにまたがるレプリケーショングループによる自動フェールオーバー構成としています。さらに、1シャードの障害影響を局所化するために複数シャード構成を採用しました。特定のシャードに障害が発生しても、影響を受けるのはそのシャードに割り当てられたセッションのみです。たとえば、1シャード構成では1ノード障害の影響が100%に及びますが、5シャード構成であればハッシュスロットが均等に分散していると仮定して1ノード障害の影響は20%にとどまります。実際にはハッシュスロット分散の偏りによって上下し、ここはランニングコストと可用性のバランスになります。そのうえで、SLOで定義した可用性や試験で計測したMTTRなども考慮して、最終的なシャード数を決定しました。 Redis Clusterの障害対策とキー設計 Redis Clusterでは、キーのハッシュ値に基づいてデータが各シャードに分散されます。しかし、1つのセッションに関連する複数のキーが異なるシャードに散ると、以下の問題が生じます。 複数シャードをまたいだ読み書きによるレイテンシー悪化。 multi-key commandは同一hash slot内のキーに制限されるため、別slotのキーにはCROSSSLOTエラーが発生する。 single-slot operationの方がパフォーマンスに優れる。 シャード障害時に、同一セッションのキーの一部だけが取得できず、データ不整合を引き起こす。 Redis Clusterには「ハッシュタグ」という仕組みがあります。キーに {...} パターンを含めると、波括弧内の文字列のみをもとにハッシュスロットが計算されます。これにより、同じハッシュタグを持つキーは必ず同一シャードに配置されます。 今回のセッション管理では、1ユーザーの複数のキーにセッションIDをハッシュタグとして埋め込む設計を採用しました。 機能によってHash・String・List・Setなど適したRedisのデータ型が異なるため、セッションを1つのキーにまとめず、ユーザーの認証情報とは別に機能や画面の単位でキーを分けています。これらのキーが別シャードに散らないよう、セッションIDをハッシュタグとして共通で埋め込んでいます。 例: data:{session-id}:<FEATURE_KEY_1> # Hash data:{session-id}:<FEATURE_KEY_2> # String data:{session-id}:<FEATURE_KEY_3> # List data:{session-id}:<FEATURE_KEY_4> # Set このキー設計により、同一ユーザーのセッションに属するすべてのデータが同じシャードに格納されます。これにより、前述の問題を回避しつつ、Redis Clusterによるシャーディングの恩恵を受けられる構成としました。 参考: Redis Cluster Specification - Hash tags 段階的な切り替えとフォールバック セッションオフロードの適用は、全拠点を一斉に切り替えるのではなく、段階的に進めています。 まず、セッションオフロードに対応した環境を構築し、全倉庫拠点での動作確認を事前に実施しました。その後、影響度が小さい拠点から順にアクセス先をセッションオフロード環境へ切り替え、ロングランで安定稼働を確認しながら対象拠点を広げていく方式を採用しています。 問題が発生した場合は、影響のあるユーザー単位で旧ドメインへ切り戻すフォールバックを用意しています。拠点全体を巻き戻す必要がなく、影響範囲を限定した復旧が可能です。 2026年9月現在、この段階的な切り替えを進行中です。 ステートレス化によって何が変わったのか セッションオフロードで得られた一番大きな変化は、「Redisを使えるようになったこと」ではありません。 Webサーバーとユーザーセッションの紐付きを切り離せたこと です。 これまでWebサーバーの中にあった状態を外部へ移しました。その結果、リクエストをどのWebサーバーが処理するかと、ユーザーがどのセッションを利用するかを分離して考えられるようになりました。 これによって、アーキテクチャ上の選択肢が大きく広がります。 特定のWebサーバーにユーザーを固定する前提がなくなる。 ALBによるリクエストの均等な負荷分散が可能になる。 Webサーバーの増減や入れ替えと、ユーザーセッションのライフサイクルを分離できる。 Podが入れ替わることを前提とするKubernetesへの移行にも対応しやすくなる。 従来のステートフルな構成では、拠点ごとに接続先のWebサーバーが固定されていました。「アーキテクチャConference 2025」でもこの点を課題として紹介しています。セッションがサーバーに紐付いているため、リクエストを別のサーバーへ振り分けられず負荷が偏りやすい構造でした。ステートレス化によってこの制約がなくなり、ALBで均等にリクエストを分散できるようになりました。 しかし、今回の基幹リプレイスにおいて最も重要なのは、その先です。既存システムと新システムをまたいだ、段階的なフロントエンドリプレイスを進めるための前提条件が整いました。 これまで、 Webサーバー = アプリケーション + ユーザーの状態 だったものを、 Webサーバー = アプリケーション Redis = ユーザーの状態 へ分離したことで、フロントエンドのルーティングとセッション管理を独立して考えられるようになります。 これは単なるインフラ変更ではなく、基幹システムをどの単位で、どの順番でリプレイスできるかを変えるための アーキテクチャ変更 です。 いよいよ基幹フロントエンドのリプレイスへ ここで、2025年11月の「アーキテクチャConference 2025」で紹介した構成に戻ります。 当時紹介したのは、Kubernetes基盤上にIngress + Istioを配置し、ストラングラーパターンによって既存システムと新システムを共存させる構成でした。そして、機能ごとのパスルーティングによって、既存のClassic ASPから新しいアプリケーションへ段階的に切り替えていくことを予定していました。 当時はまだ「予定」だったこのアーキテクチャに対して、今回のセッションオフロードによって、その前提となるステートレス化を進めることができました。 巨大な基幹システムのリプレイスでは、新しいシステムを作ることだけが課題になるわけではありません。既存システムが長年の運用の中で持つようになった前提や制約を1つずつ解きほぐし、新旧システムが共存できる状態を作ることも、段階的なリプレイスには必要です。 今回取り組んだセッションオフロードは、そのための1つのステップでした。Webサーバーから状態を切り離したことで、既存システムを稼働させたまま、新アーキテクチャへページ・機能単位で移行していくための土台が整いました。 まとめ 本記事では、ZOZOの基幹システムにおけるWebサーバーのステートレス化について紹介しました。 2025年11月の「アーキテクチャConference 2025」では、基幹システムのリプレイスを進めるうえで「ステートフル」であることを課題として挙げました。あわせて、IISセッションをRedisへオフロードする方針と、Kubernetes上での段階的なフロントエンドリプレイス構想を紹介しました。 その構想を実現するため、既存システムで利用している独自フレームワークをバージョンアップし、IISのインメモリに保持していたユーザーセッションをRedisへオフロードしました。 今回の取り組みで重要だったのは、Redis導入そのものではありません。既存システムから「状態」という制約を切り離し、リプレイスの自由度を上げることでした。 長年稼働してきた基幹システムを、一度にすべて刷新できません。だからこそ、新しいアーキテクチャを作るだけではなく、既存システムを少しずつ「置き換えられる状態」に変えていくことが重要だと考えています。 2025年に「予定」として紹介していた基幹フロントエンドの新しいアーキテクチャは、今回のステートレス化によって実現に向けた準備が整いました。ここから、基幹フロントエンドの段階的なリプレイスを進めていきます。 ZOZOでは、一緒にサービスを作り上げてくれる仲間を募集中です。ご興味のある方は、以下のリンクからぜひご応募ください。 corp.zozo.com
動画
該当するコンテンツが見つかりませんでした










