既存クラウド環境を Alibaba Cloud に移行した話

# はじめに

こんにちは、新卒4年目のバックエンド（？）エンジニアです。
この1年で結構大変だったなぁって感じた案件があったのでさらっと書いてみます。

# 移行の話

オークファンでは様々なサービスを様々なクラウドサービス上で構築しています。
今回は Azure 上に構築されたサービスを Alibaba Cloud に移行した話についてざっくりと書いていきたいと思います。

## 背景

今回移行の対象となったサービスは Azure 環境上に構築されており、リリースされておおよそ 10 年が経過していました。
システムコストが膨れ上がっており、社内でちょこちょことコスト削減についての話が挙がり始めていました。

そんな時、 Alibaba Cloud であれば（諸々を踏まえて）コスト削減の見通しが得られることが分かりました。
また、現状の構成がコストに対して最適化されていない部分もあったため、移行に合わせてコスト削減できる箇所を洗い出し、 Alibaba Cloud にサービスを移行しようという案件が立ち上がりました。

## プロジェクト規模

- メンバー
    - フロントエンドエンジニア
        - 1 名
    - バックエンドエンジニア
        - 2 名
    - インフラエンジニア
        - 2 名
- 期間
    - おおよそ 3 ヵ月


## システム構成（ざっくり）

今回の対象は Azure の枠内のすべてのコンポーネントとなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200155/3580ece6-2d6b-6428-fb7f-5f616c336609.png)


## やったこと（主観）

### API サーバ

- 移行先のサービスとして Alibaba Cloud ECS を利用
    - プログラム自体はステートレスでそのままプログラムを持ってきても動いたので特段手を付けず、そのままプログラムを配置しました。

### バッチサーバ

- 移行先のサービスとして Alibaba Cloud ECS を利用
    - バッチの管理は Jenkins を利用していたため、 Azure 環境同様に ECS インスタンスに Jenkins をインストールしてバッチプログラムを配置しました。
- バッチプログラムの改修
    - Azure 環境ではバッチプログラムから Blob Storage にファイルのアップロード/ダウンロードがあったため、Alibaba Cloud 環境で同様のストレージサービスを利用することになりました。
    - 今回は Object Storage Service (以下、OSS) を利用するため、バッチプログラム内で OSS 向けの SDK を利用する形に改修しました。

### SQL Server

- 移行先のサービスとして Alibaba Cloud RDS for SQL Server を利用
    - Azure SQL Server のデータ構成や設定等を Alibaba Cloud RDS for SQL Server インスタンスに反映しました。
- データ移行
    - データ自体はバッチプログラムで集計された結果を保持していたのですが、バッチプログラムで 0 からデータを作成するのは時間がかかるため、SQL Server 間でデータを直に移行しました。
    - 使用したツールは SQL Server インポートおよびエクスポートです。

### Blob Storage

- 移行先のサービスとして Alibaba Cloud OSS を利用
- データ移行
    - これまで蓄積されたデータを全て Alibaba Cloud OSS に移行しました。
    - データ移行は Alibaba Cloud 上で提供されているストレージサービス間のデータ移行をサポートする Data Online Migration を利用しました。

### その他

- Alibaba Cloud のサービスへの理解
    - Alibaba Cloud のサポートの方が親身に聞いてくださり、とてもスムーズでした。
- システムテスト
- 負荷検証試験

## Blob Storage のデータ移行で気を付けたこと

- 移行にかかるコストを抑える。
    - 実はこのタイミングで気づいたんですが Azure データセンターからデータを引っ張り出すときにネットワーク帯域のアウトバウンド（GB 単位）で結構な料金がかかることがわかりました。。。
    - このコストを抑えるために以下を実施。
        1. Blob Storage にアップロードされたファイルを gzip 圧縮して移行時のデータ容量を削減する。
        2. 移行後、 OSS 側で Cold Archive を利用して保持コストを削減する。
            - ちなみに、この作業で移行前の保持コストからおおよそ 1/10 ほどコストを削減できました。

- 移行後の Azure Blob Storage のコストを削減する。
    - 上記にあるように生データがそのまま Blob Storage に流し込まれていたので結構な保持コストがかかっていました。
    - そのため移行が完了した範囲から削除して Azure のコストを削減しながら進めていきました。

# 移行後の話

## 私「あれ、特定のページが返ってこない。。。」

実は Azure 側で運用していた SQL Server には、過去に記録の無いインデックスが貼られており、移行時に確認漏れがありました。
DDL や ER 図は A5:SQL Mk-2 で管理していたのですが、そこに書いてあるものだけを信じてしまってました。。

### 反省点

- 特定の条件下でデータベースの負荷が上がった際に上記問題が発生しており、リリース前に負荷検証を実施していたが、そのパターンが漏れていた。
- インデックスの貼り忘れについて、 SQL Server の設定値を丸々引っ張ってきてリスト化する必要があった。
    - ER図等にまとめられているといっても、運用の過程で変更は合ってしかるべき、という意識が足りていなかったです。

## 私「あれれ、メンテナンス用のバッチが重すぎる。。。」

これはおおよそ半年に 1 回の頻度で実行されるメンテナンス用のバッチなのですが、移行時の検証から漏れていました。
なので、一度実行したら集計用バッチの稼働時間が爆増して全然終わる気配がない、なんてことをやらかしました。

### 反省点

- 例えメンテナンス用のバッチでも、同じような状況を準備して検証するべき。
    - ちなみに原因はこれまた SQL Server の設定が Azure 環境時と比較して差分があったからでした。。。
    - 具体的には以下の設定値で差分がありました。
        - 並列数: `max degree of parallelism`
        - トランザクション分離レベル: 
            - 移行前: `READ_COMMITTED_SNAPSHOT `
            - 移行後: `READ_COMMITTED`
        - ただし、Azure SQL Server と Alibaba Cloud RDS for SQL Server では構成が違うのかトランザクション分離レベルを変更すると性能が劣化したため、他の設定値もいじらないといけないのかもしれません。（この時は代替案としてバッチの並列数を下げたり、バッチの稼働時間帯を調整する、などで対応する方針となりました。）

# まとめ

ざっくりと書きましたが、学んだことは以下の通りです。

- 既存資料だけでなく、現環境の設定値を丸々引っ張り出してきてリスト化する。
    - 特に長く運用されてきたサービスについては、資料だけがすべてではないという意識が必要だと感じます。
- 検証はリリース直後だけでなく、運用中のメンテナンスも手順を準備して行う。

あと、今回のプロジェクトではこれまでやったことの無いようなプロジェクト運営（WBSやタスクの割り振り）にちょっとだけ挑戦することができました。
プロジェクトの立ち上げから参加して、自分で考えながら移行を進めていきましたが、結構な抜け漏れがあったことが悔しかったです。
どうすればスムーズに抜け漏れなく進めることができるのかを常日頃考えとかないと、いざというときにうまく立ち回れないなと感じた案件でした。

以上