Redashをv10.1にバージョンアップしました
こんにちは、こんばんは、おはようございます。LAPRASでエンジニアのような何かをしているdenzow です。この記事はLAPRAS Advent Calendar 2023 17日目の記事です。
またLAPRAS Advent Calendar 2021 12日目の記事でもあります。
まとめると
LAPRAS社では長らくRedashを利用しており、クエリも先程7000を超えた程度に活用されています。導入当初はv3をEC2で動かしていたRedashが、気がつけばv8 + ECSの構成に変わり、そのままEKSに引っ越しをしていましたが、この度漸くv10.1の最新(Release 2021/11/24)に移行しました。色々踏んだので、そこを書いておきますので誰かの検索に引っかかればと思います。
バージョンアップのモチベ
運用上、実はv8でもそれほど困ってるところはなかったので中々重い腰があがりませんでしたが、アドカレネタになるかなということで勢い良くv10.1にしました。
LAPRASのRedashの構成
LAPRASではプライベートリポジトリに登録したRedashのDocker Imageを元にEKS上にPodをデプロイしています。メタデータはPostgreSQLのRDSを使用しています。直接パブリックのredashのイメージを使っていないのは以下の点からです。
- docker hubの制限や障害の影響に引きずられたくない
- 一部独自の拡張を利用したいため、イメージ作成時点でコードにパッチしたい
- gevent等を追加したい(もしかしてもう不要かも…?)
バージョンアップ手順
まずは、v10.1用のイメージを作りますが、これはプライベートリポジトリのDockerファイルを更新するだけなので割愛します。
v10.1化は本家を参考に進めます。
簡素なものですが、v10にする際にservices
やscheduler
コンテナから不要になったQUEUES
やWORKERS_COUNT
を削除し、 worker
の QUEUES
に"periodic emails default" を指定するようにあります。また、Redashのバージョンアップ時はメタデータのDBのスキーマを更新するためにpython ./manage.py db upgrade
を実行する必要があります。
メタデータDBのバックアップ
とても大事。DBのマイグレーションが走るので戻すの面倒なので。
manage.py db upgrade の実行
こちらはEKSなのでk8sのjobで実行しました。kube-job というショットでJOBを実行するOSSを利用しました。LAPRASではkube-jobは各所で使われています。job.yamlを作成し引数として渡して実行しています。
apiVersion: batch/v1
kind: Job
metadata:
name: redash-adhoc-migrate-job
namespace: XXXX
labels:
app: redash-adhoc-migrate-job
spec:
:
spec:
containers:
- name: redash
image: XXXX
imagePullPolicy: Always
args: ["python ./manage.py db upgrade"]
envFrom:
:
resources:
:
restartPolicy: Never
backoffLimit: 0
こちらは問題なく実行されました。
deploymentの変更
基本的にはimageをv10.1のものに入れ替えて、ドキュメント通りにWORKERS_COUNT
やQUEUES
を変更しました。
containers:
- name: redash
- image: v8なimage
+ image: v10なimage
args: ["/usr/local/bin/gunicorn", "-b", "0.0.0.0:XXXX", "--name", "redash", "-w", "4", "-k", "gevent", "-t", "180", "redash.wsgi:app"]
ports:
@@ -122,7 +122,7 @@ spec:
- "node"
containers:
- name: redash
- image: v8なimage
+ image: v10なimage
args: ["worker"]
envFrom:
- secretRef:
@@ -137,7 +137,7 @@ spec:
- name: WORKERS_COUNT
value: "2"
- name: QUEUES
- value: "queries,scheduled_queries,celery,schemas"
+ value: "queries,periodic emails default"
@@ -195,7 +195,7 @@ spec:
- "node"
containers:
- name: redash
- image: v8なimage
+ image: v10なimage
args: ["scheduler"]
- - name: WORKERS_COUNT
- value: "1"
- - name: QUEUES
- value: "celery"
- name: REDASH_THROTTLE_LOGIN_PATTERN
value: "50/second"
正常にアクセスできるようになりました。
起動後の問題
勝ったな、と思ったのですがRefresh Schemaが終わらず、スキーマ一覧が一生取得されません。 当たり前といえばそうなのですがキューに積まれたスキーマのリフレッシュを行うWokerがいないからです。ドキュメント通りなのにこれは、、とは思いますがきっと意図を読み違えているのでしょう。QUEUES
にschemas
を追加することで解消します。
また、スケジュールされたクエリも実行されていないことに気が付きました。こちらも同様にscheduled_queries
を見ているWorkerがいないためなのでQUEUES
に追加して解消しました。(なんかscheduler
コンテナ何してんだろって気持ちになるけどいいのかな)
- name: QUEUES
- value: "queries,scheduled_queries,celery,schemas"
+ value: "scheduled_queries,schemas,queries,periodic emails default"
いくつかのバグ
ダッシュボードのソートでInternal Server Error
ここをクリックするとInternal Server Errorになります。
サーバ側ではこんなエラーが記録されています。
e, statement, parameters, cursor, context
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1473, in _handle_dbapi_exception
util.raise_from_cause(sqlalchemy_exception, exc_info)
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 398, in raise_from_cause
reraise(type(exception), exception, tb=exc_tb, cause=cause)
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 152, in reraise
raise value.with_traceback(tb)
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1249, in _execute_context
cursor, statement, parameters, context
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/default.py", line 580, in do_execute
cursor.execute(statement, parameters)
sqlalchemy.exc.ProgrammingError: (psycopg2.errors.InvalidColumnReference) SELECT DISTINCT ON expressions must match initial ORDER BY expressions
LINE 2: FROM (SELECT DISTINCT ON (dashboards.created_at, dashboards....
PostgreSQLが受け取れない構文のSQLが発行されているためで、Redashのバグです。すでにBUGFIX: Fixing dashboard order by name #5645 で修正されています。v10.1の次が長らく出てないですが、最近動きがありそうなのですし影響も軽微なバグなのでリリースを待ちます。
内部APIの戻り型の変更
redasql というredashに対してクエリを実行するCLIツールを作って仕事でも使ってるのですが、PostgreSQLデータソースに接続した際にクラッシュするようになりました。確認したところ、/api/data_sources/ID/schema
というスキーマ一覧を戻すAPIの戻り値が、PostgreSQLの場合以下のように変更されていました。
{
'schema': [
{
'name': 'city',
'columns': ['ID', 'Name', 'CountryCode', 'District', 'Population']
},
]
}
{
'schema': [
{
'name': 'city',
'columns': [
{'name': 'id', 'type': 'integer'},
{'name': 'created_at', 'type': 'timestamp without time zone'},
]
},
]
}
他にも形式変更があったデータソースはあるかもしれませんが、少なくともMySQLではそうなっておらず一部だけ変更されたようです。
カラム名に加えてデータ型も取得するように変更されていることがわります。
データ型がAPIから取れる分には嬉しいのですが一部データソースだけなので、一旦redasql
はデータ型を無視する方向で修正しています。
アラートのカスタムテンプレートの変数名変更
リリース後、Slackに通知されるアラートの内容がおかしくなっているという報告で気が付きました。
v8時点ではテスト的に導入されていたアラートのカスタムテンプレート機能ですが、v10(v9時点で)から変数名が変更されていたためでした。
こちらの記事 を参考にさせていただきました。
なぜか、現在のredashでv8.0.0
とタグが打たれているコードではrows
ではなくQUERY_RESULT_VALUE
で実装されているのでソースを見てるときには気がつけなかったので助かりました…
原因がわかったので直していくかとアラート一覧を開くと71件もあった上に、画面を開いても設定済みのテンプレートが表示されず、心が折れたのでメタデータDBの中身を直接更新します。
v8(いつのかわからない)の時点ではカスタムテンプレートはalert
テーブルのoptions
カラムにJSONとしてtemplate
属性に保存されています。しかし以降はcustom_subject
と custom_body
という属性に保存されるように変更されていました。まずはここを変更しないと、RedashのUI上からテンプレートを更新することができません。
update
alerts
set
options = (options::jsonb||jsonb_build_object(
'custom_subject', to_jsonb(options::jsonb->'subject'),
'custom_body', to_jsonb(options::jsonb->'template')
))::text
where
options::jsonb ? 'template';
そもそも弊社はSlack連携しか使っていないのでsubject属性が参照されていないのですが、一応移植しました。また、optionsカラムはJSONが入っているもののDBの型としてはText型なのでjsonにキャストしながら組み換えをしています。
この時点でUI上からは設定済テンプレートが更新可能になっています。さらに変数名の変更を行います。幸い弊社ではrows
しか使われていなかったため、そのままQUERY_RESULT_ROWS
に置き換えを行います。
update
alerts
set options = replace(options, 'rows', 'QUERY_RESULT_ROWS')
where options like '%row%
仮にrow
という文字列が入っていても置き換えられてしまうので、実際はもう少し丁寧にやったほうがいいと思いますが、問題になりそうな箇所もなかったためこちらで済ませました。今の所、アラートの内容に関して問題も見つかっていないので正しく置き換えができているようです。
まとめ
今更ながら無事にv10.1にアップグレードできて良かったです。v11なのかRedash 2024なのかわかりませんが、ぼちぼち次のリリースもでるような気がしていますので来年も新しいバージョンのRedashでお会いできれば幸いです。
Discussion