はじめに
こんにちは。
株式会社エブリーの開発本部データ&AIチーム(DAI)でデータエンジニアをしている吉田です。
今回は、Redashのアップグレードについてのお話です。
背景
デリッシュキッチンではデータ分析のための可視化ツールとしてRedashを利用しており、ECS上にRedashをデプロイして運用しています。
RedashはOSS版の更新が長らく停止していましたが、昨年プロジェクトが再始動され(参考)、先日v25.1.0がリリースされました。
今回、Redash v10.0.0 から v25.1.0 へのアップグレード試験を実施しました。
現在のRedashの運用状況については、以下の記事で詳しく解説しています。
https://tech.every.tv/entry/2024/03/06/160148
アップグレード手順
v10.0.0 から v25.1.0 へのアップグレードは、v10.1.0 を経由する必要があります。
v10.0.0 から v10.1.0 はイメージの差し替えのみで、DBマイグレーションは不要です。
v10.1.0 から v25.1.0 はDBマイグレーションが必要です。
具体的な手順は以下の通りです。
- 事前準備
- Redash v25.1.0でビルドしたDockerイメージをECRに登録します
- マイグレーションタスク用のECSタスク定義とサービス定義を作成します
- Redash DBのバックアップを作成します
- 作業
- 古いRedashコンテナを停止します
- マイグレーションタスクを実行します
- 新しいRedashコンテナを起動します
- 確認
- Redashにログインし、データが正常に表示されることを確認します
マイグレーションタスクの作成
Redashのデプロイにはecspressoを利用しており、ecspresso run
コマンドでマイグレーションタスクを実行できるようにマイグレーション用定義ファイルを作成します。
タスク定義ファイルは以下のように作成します。(一部抜粋)
{ "family": "redash-migration", "containerDefinitions": [ { "name": "redash-migrate", "image": "ECR/Custom-Redash:25.1.0", "command": [ "manage", "db", "upgrade" ] } ] }
手順2.1で古いRedashコンテナを停止した後、ecspresso run --wait-until stopped
のようなコマンドを実行することで、マイグレーションタスクを実行できます。
このとき、ある程度の時間がかかるのでecspressoのタイムアウト設定を適切に行う必要があります。
ハマりどころ
v10.1.0からv25.1.0へのアップグレードにおいて、以下のようなハマりどころがありました。
エラーDETAIL: \u0000 cannot be converted to text.
が発生する
マイグレーションタスクを実行中に、"change type of json fields from varchar to jsond" ステップで以下のエラーが発生しました。
DETAIL: \u0000 cannot be converted to text.
これはIssueでも報告されており、以下のSQLを実行することで対応できます。
UPDATE visualizations SET options = replace(options::text, '\u0000', '')::json WHERE strpos(options::text, '\u0000') > 0;
エラーTypeError: 'NoneType' object is not iterable
が発生する
マイグレーションタスクを実行中に、"fix_hash"ステップで、以下のエラーが発生しました。(一部抜粋)
2025/02/12 14:38:32 File "/app/migrations/env.py", line 85, in run_migrations_online 2025/02/12 14:38:32 context.run_migrations() 2025/02/12 14:38:32 File "<string>", line 8, in run_migrations 2025/02/12 14:38:32 File "/usr/local/lib/python3.10/site-packages/alembic/runtime/environment.py", line 948, in run_migrations 2025/02/12 14:38:32 self.get_context().run_migrations(**kw) 2025/02/12 14:38:32 File "/usr/local/lib/python3.10/site-packages/alembic/runtime/migration.py", line 627, in run_migrations 2025/02/12 14:38:32 step.migration_fn(**kw) 2025/02/12 14:38:32 File "/app/migrations/versions/9e8c841d1a30_fix_hash.py", line 55, in upgrade 2025/02/12 14:38:32 new_hash = update_query_hash(record) 2025/02/12 14:38:32 File "/app/migrations/versions/9e8c841d1a30_fix_hash.py", line 29, in update_query_hash 2025/02/12 14:38:32 parameters_dict = {p["name"]: p.get("value") for p in record['options'].get('parameters', [])} if record.options else {} 2025/02/12 14:38:32 TypeError: 'NoneType' object is not iterable
コードの該当箇所を確認したところ、取得されたparameters_dict
は利用されていなかったためコメントアウトすることで対応しました。
https://github.com/getredash/redash/blob/master/migrations/versions/9e8c841d1a30_fix_hash.py#L29-L31
def update_query_hash(record): should_apply_auto_limit = record['options'].get("apply_auto_limit", False) if record['options'] else False query_runner = get_query_runner(record['type'], {}) if record['type'] else BaseQueryRunner({}) query_text = record['query'] # parameters_dict = {p["name"]: p.get("value") for p in record['options'].get('parameters', [])} if record.options else {} # if any(parameters_dict): # print(f"Query {record['query_id']} has parameters. Hash might be incorrect.") return query_runner.gen_query_hash(query_text, should_apply_auto_limit)
最後に
Redash v10.0.0 から v25.1.0 へのアップグレードが完了しました。
一部暫定的な対応を行いましたが、試験環境でのアップグレードは成功しました。
現在、既存クエリとダッシュボードが正常に動作するかどうか、試験環境で確認を行っています。
これらに問題がないことを確認次第、本番環境へのアップグレードを進める予定です。