emahiro/b.log

Drastically Repeat Yourself !!!!

gokzen/redis-cluster を使って protected mode "no" で Redis Cluster を起動するまで

※ このエントリはある特定の Docker Iamge を利用して Github Actions で Redis Cluster を起動してアクセスできるようにするものです。他の Image を使っていたりする場合には特に有益な情報はありません。

Overview

  • grokzen/redis-cluster を利用して Redis Cluster にアクセスし、Go のテストができるようにします。
  • Go のテストには go-redis を利用します。

hub.docker.com

背景・前提

商用環境/検証環境を除く local 環境と test (CI込)環境において、ずっと Redis のコンテナと Redis Cluster を両方立ち上げていたのですが、すでに商用環境を始め remote の環境では Redis が Cluster mode で利用されており、すべての環境で統一して Redis Cluster を利用する方向に統一するために既存の Redis コンテナを削除したかったことが背景です。
ただし、前提として local 及び test 環境においては Redis Cluster を立ち上げておきながら、通常モードの Redis (Master1本構成)に接続しており、CIがこの通常モードの Redis に依存していたので、通常モードの Redis を引き剥がす際に CI の環境でも Redis Cluster を利用するように設定し直す必要がありました。

はまったところ

大まかに2つです。

  1. Redis Cluster の protected mode の問題。
  2. Redis Cluster 利用に合わせて Go のコードを修正。

Redis Cluster の protected mode の問題

  • Redis の protected-mode の設定 grokzen san の作ったイメージでは環境変数等でアクセスできず、GitHub Actions 上でこのイメージをベースとした Redis Cluster を立ち上げても Redis コマンドの実行を拒否されてしまう。
  • 以下の discussions でも話にはあがっているものの、ワークアラウンドがあるだけで、現状このイメージを使い続ける場合、自前でこの protected mode を off にする必要がある。

github.com

以下で issue も起票はされているが対応は未定らしい。
作者自身もイメージコピーして独自で対応してほしいとコメントしている。

github.com

対応Log

  • grokzen/redis-cluster を指定して GitHub Actions を起動するときに、 protected mode を no にする方法を調べる => 環境変数などは用意されておらず、issues でも対応予定はないっぽくワークアラウンドが提示されていた。
  • 他の image を使うことを検討する => 不思議なことに grokzen/redis-cluster 以外に割と使い勝手のいい image が存在しない。いくつか redis-cluster のコンテナを起動できるイメージはあるものの、どれも既存の設定を大きく変更する必要があり、作業量的にちょっとめんどくさかった。 grokzen/redis-cluster がそこまで利用しやすいのかと言われるとそうじゃないのかもしれませんが、Actions の設定項目の少なさはやはり魅力的で(他の docker hub に公開されている Redis Cluster を立ち上げる image 類は Actions にいくつか Redis のコンテナを立ち上げる必要があり、全部を記述するのが若干面倒。
  • groken/redis-cluster が立ち上がるときに実行してる設定ファイル (*.tmpl ファイル)を protected mode を no にするファイルを自前で用意して Volume をマウントする。=> GitHub Actions で service のコンテナにリポジトリのファイルをマウントしようとするとエラーになる で書かれてる内容と同じエラーに遭遇してマウントできなかったので諦める。
  • Redis Cluster のコンテナのコンテナを立ち上げてそのコンテナに向けて Redis のコマンドで操作することを試みる => GitHub Actions の環境そのままでは Redis Cluster の中に入れない + 仮に protected mode を更新できたとしても立ち上げてる Cluster 分設定を更新する必要があるのでめんどい(手順として壊れやすい ex ポート番号が変わったときに CI が全死)
  • Actions の内部で Redis Cluster のコンテナを操作することは難しかったので、取りうる方法としては以下の2つに限定される。
    • GitHub Actions の内部で Docker Image をビルドする => かなり時間がかかる。
    • grokzen/redis-cluster を fork して protected mode を on にして Redis Cluster を立ち上げる image を 自前でビルドする (結果としてこれを採用) => なお、そのまま M1 で Docker Image をビルドすると arm64 向けの Image がビルドされ GitHub Actions では動かない(GitHub Actions は何も設定しないと amd64 で動いているため)ので M1 でビルドするときは Platform を指定することで対応(Redis をそのままビルドするので M1 Max でも10minくらいかかりました。)
      • 実際に叩いたコマンドはこちら -> docker build --platform linux/amd64 . -t ${image_name}:${image_tag}
    • ビルドするときに最初は脳死で Redis バージョンを 7系にしてビルドしていましたが、6系と7系で API の互換がなく、コマンドの実行でエラーになる事がわかったのでビルドするときの大本の Redis のバージョンを 6系にしてビルドして利用しています。実際に自分が遭遇したエラーは issues にも記載されてます(ここで 6系にするワークアラウンドの話が出てるのが面白い...。)

github.com

そして出来上がったのが以下。
基本的な使い方は本家の設定と同じなので設定方法は割愛。

hub.docker.com ref: https://hub.docker.com/repository/docker/emahiro/redis-cluster/general

※業務で利用するものでもあるので、ちゃんとメンテをし続けるものは業務で使用している ECR に移行予定。特にこのイメージをちゃんとメンテしていくモチベーションは有りません。

ちなみに最後の最後で気づきましたが、 protected mode は Redis 7 系以降の機能なので、最初から Cluster mode で起動する Redis を 6 系にしていればよかったかもしれません。(つまい grokzen/redis-cluster の version を最新にしない、という選択肢です。)

go-redis の実装修正

大した話では有りませんが、もともと CI の環境では Cluster mode ではない Redis を使っていたので、Redis を利用してる実装のテストをする際にはテスト前後で Redis の中データを Flush する処理を追加しました。
ただし、Redis Cluster を起動するようになったので、ある node に対して FlushAll コマンドとを実行してもその node 上でデータをフラッシュしたことにしかならず、Cluster に所属する node 全体に FlushAll を実行しているわけではなかったので、 あるテストに置いてデータを事前に削除しても他のテストではまだ削除がされていない Node を引き当てて、データが残ってる状態でテストが実行されて既存のテストが壊れる、という事象が発生。
そのためもともと FlushAll を実行していた Go のテストのヘルパー関数の中で Node 全体のデーターを削除するように変更しました。すべての node に対してコマンドを実行する場合には https://pkg.go.dev/github.com/go-redis/redis/v8#ClusterClient.ForEachMaster を利用します。
ちなみにこのコマンドは以下の issues ではなされてる内容から生まれたもののようです。

github.com

まとめ

ただの備忘録ですが、Redis の最新バージョンでデフォルト ON になるセキュリティ系の設定を OFF にしたいだけのために結構回り道をしました。特に誰の約にも立つことはないと思いますが自分がいつか思い出したときのために書き残しておきます。