🎉

[備忘録]ElastiCache(Redis)のサービス更新時の瞬断を調査した

に公開

ElastiCacheのサービス更新の対応した際の、DEV環境での調査内容を備忘録として残します🫡

構成

本番のElastiCacheは以下の構成になっていました。

  • エンジン:Redis
  • ノード数:2
  • クラスターモード:無効
  • マルチAZ:有効
  • 自動フェイルオーバー:有効

結論

サービス更新適用時の瞬断の時間

DEVでの検証では0.2秒以下だった
ただし検証環境が本番とまったく同じ環境にできなかったため、本番での適応時と多少誤差があったように思える(環境差分の詳細は後述)

サービス更新適用時にシステムが正常に稼働しているか

プライマリノードとレプリカノードの入れ替わりが発生したが、問題なく稼働していることが確認できた

サービス更新適用にかかるトータルの時間

DEVでの検証では20分程度だった
ただし検証環境が本番とまったく同じ環境にできなかったため、本番では30分ほどだった(環境差分の詳細は後述)

やったこと

本番とDEV環境の差分を確認

terraformでリソース管理しているので、ElastiCacheの各設定値をコードで確認
以下の差分があった

  • ノード数
    • 本番:2
    • DEV:1
  • マルチAZ
    • 本番:有効
    • DEV:無効
  • 自動フェイルオーバー
    • 本番:有効
    • DEV:無効

AWSコンソールで差分を揃える

DEV環境のRedisクラスターにレプリカノードを追加

マルチAZと自動フェイルオーバーを有効にする

Redis接続確認用のスクリプトを作成する

redis-cliをインストール

こちらを参考にしました

# パッケージインストール
sudo yum -y install openssl-devel gcc
# ユーザーのホームディレクトリに移動
cd
# redisのソースコード取得(安定版)
wget http://download.redis.io/redis-stable.tar.gz
# 解凍
tar xvzf redis-stable.tar.gz
# 階層移動
cd redis-stable
# Redis公式ソースからTLS/SSL対応のredis-cliを手動でビルドする
make distclean # ビルド環境の完全クリーンアップ
make redis-cli BUILD_TLS=yes # TLS対応redis-cliのビルド
# パスを通す(コンパイルパッケージをインストール)
sudo install -m 755 src/redis-cli /usr/local/bin/
# 動作確認 PONGが返ってくればOK
redis-cli -h ${エンドポイント} -p ${port} ping

スクリプト作成

スクリプトの内容は以下。
AIに作成してもらいました。

#!/bin/bash

# --- 設定 ---
mykey="test_key_$(date +%s)" # 実行ごとにユニークなキーを生成
host="xxxcache.amazonaws.com"   # あなたのプライマリエンドポイントに置き換える
interval=0.2  # 0.2秒間隔で実行

echo "--- Redis Ping Test Start ---"

# 初期値設定 (エラーが出たら終了)
if ! redis-cli -h ${host} set ${mykey} "0"; then
    echo "$(date "+%Y-%m-%d %H:%M:%S") [FATAL] Initial connection failed."
    exit 1
fi
echo "$(date "+%Y-%m-%d %H:%M:%S") [INFO] Initial key set successful."

# 3600回 (約60分間) ループ
for i in $(seq 1 18000); do

    # incrコマンド実行(書き込み検証)
    # 2>&1 で標準エラー出力を標準出力にリダイレクトし、変数に格納
    result=$(redis-cli -h ${host} incr ${mykey} 2>&1)

    # 戻り値チェック
    if [[ "$result" == *"Error"* || "$result" == *"Could not connect"* ]]; then
        # 接続失敗時
        timestamp=$(date "+%Y-%m-%d %H:%M:%S.%3N")
        echo "${timestamp} [FAIL] Command: INCR. Error: ${result}"
    else
        # 接続成功時(結果を定期的に表示し、動作確認)
        if (( i % 50 == 0 )); then # 50回に1回のみ表示
            echo "$(date "+%H:%M:%S") [OK] Current value: ${result}"
        fi
    fi

    sleep ${interval}
done

echo "--- Redis Ping Test End ---"

上記のスクリプトをRedisにアクセス可能なEC2に作成する

# ユーザーのホームディレクトリに移動
cd
# スクリプト作成
vi redis_test.sh
# 権限付与
chmod +x redis_test.sh
# 試しに実行
./redis_test.sh > redis_ping_log.txt 2>&1 &
# 出力ファイル確認し、出力されていればOK
vi redis_ping_log.txt

スクリプトを停止したいときはps aux | grep redis_test.shして、結果に表示されたプロセスIDを指定してkillすればOK

サービス更新を適用する

  • スクリプトを実行しておく
    • ./redis_test.sh > redis_ping_log.txt 2>&1 &
      
  • 任意のサービスのページで、自分のクラスターを選択して「今すぐ適用」を押下
  • 「クラスターの更新ステータス」がCompleteになるのを待つ

結果の確認

  • redis_ping_log.txtの出力内容を確認
    • エラーログがでていたらその間瞬断していたことになる
    • 今回はひとつもエラーログが出ていなかった
  • システムが正常に稼働していることを確認
    • Redisとの接続を必要する機能を実行して問題ないかを確認する

後片付け

  • ec2の不要なものを削除
rm -rf redis-stable
rm redis-stable.tar.gz
rm redis_ping_log.txt
sudo rm /usr/local/bin/redis-cli

# redis-cliが削除されたことを確認(redis-cli: command not foundになればOK)
redis-cli --version
  • マルチAZ、自動フェイルオーバーを無効化
  • 不要なノードの削除
    • 追加したノードはレプリカからプライマリに昇格しているので、レプリカになっている元のノードを削除する

注意:検証時のDEV環境と本番環境の差分

DEV環境にノードを追加することで本番環境とノード数を揃えましたが、DEVに追加したノードはサービス更新が適用された状態でした。
そのためDEV環境でのサービス適用は対象ノード数が1つ、本番は2つといった差分が発生してしまいました。
ただ瞬断が発生するのはプライマリノードとレプリカノードが入れ替わるタイミングだと思うので、瞬断の時間の検証にはなると思いこの状態で検証を進めました🫡

補足

サービスの更新とバージョン管理は何が違うのか?が気になったので調べてみました🤔

感想

すでにネットに上がっている情報でしたが、自分の手で確認することに価値があると思い調査しました🫡
環境をまったく同じにすることはできませんでしたが、本番も問題なく適用することができたのでよかったです-_-b

参考

Discussion