Qiita の TORICO Advent Calendar 2019 の記事として書きました
社内での実績閲覧のツールとして Re:dash を使っています。
最初に導入した Re:dash v2 のまましばらくアップデートを行っていなかったので、v8 にアップデートを行いました。
アップデート方針
v8 は dockerコンテナで提供され、 docker-compose
で起動させることができます。提供されている docker-compose.yml は、Postgres や redis コンテナの起動も自動でされますし、インストールスクリプトも良くできており、初期状態の ubuntu サーバであればコマンド一発で docker エンジンのインストールも含めアプリの起動まで行うことができます。
従来の EC2イメージの Redash から、スクリプトでアップデートできたら楽なのですが、少し試したところ Postgres の DB のスキーマ名が変わっていたり、Postgresのサーバのバージョンも 9.3 -> 9.6 への大きなアップデートとなることもあり、今回は「Redash v8 を新規EC2で起動し、旧サーバからDBのレコードをコピーする」という方針としました。
Redash V8 サーバの構築
https://github.com/getredash/setup/ こちらのスクリプトを使うことで、非常に簡単に起動させることができます。
1. EC2 で Ubuntu18 サーバを起動
2. ホームディレクトリで、
git clone git@github.com:getredash/setup.git
3.
cd setup
bash setup.sh
あとは、スクリプトの中で docker エンジンのインストール、postgres のデータファイル構築や ランダムなDBパスワードの作成、初期スキーマの構築などすべて行ってくれます。スクリプト終了時に docker-compose up -d
まで行うため、ブラウザでアクセスすれば Redash のサインインページが表示されます。
postgres コンテナへの接続
インポートするために、Postgres の Docker コンテナに外部から接続できるようにします。
上記スクリプトで Redash をインストールした場合、/opt/redash/docker-compose.yml
が作成されますので、この postgres サービスの箇所に
postgres:
image: postgres:9.6-alpine
env_file: /opt/redash/env
volumes:
- /opt/redash/postgres-data:/var/lib/postgresql/data
restart: always
# 追加
ports:
- "5432:5432"
ports項目を追加し、ホストマシンの5432ポートをコンテナに接続します。/opt/redash/env
の POSTGRES_PASSWORD
に作成されているパスワードと、ユーザー名 postgres
でコンテナの postgres に接続できます。
旧サーバの暗号キー等の設定のコピー
旧サーバの、/opt/redash/.env
の設定値を新サーバにコピーします。
REDASH_COOKIE_SECRET
REDASH_COOKIE_SECRET
は、DBの data_sources テーブルにある暗号化フィールドの復号化に使われますので、テーブル内容をそのままコピーする場合は一致させる必要があります。
これを一致させない場合、Redash 起動時の data source の選択の際にローディングスピナーがぐるぐる回り続けることになります。APIレスポンス自体はHTTP500が返ってきており、docker-compose のログには Pythonの例外が、暗号化内容を復号できない旨のメッセージと共に出力されます。肝心のトレースバック(スタックトレース)は保存し忘れました。
実際のDBの復号化には settings.
DATASOURCE_SECRET_KEY
が暗号キーとして使われ、settingsを読んでみると
COOKIE_SECRET = os.environ.get("REDASH_COOKIE_SECRET", "c292a0a3aa32397cdb050e233733900f")
SECRET_KEY = os.environ.get('REDASH_SECRET_KEY', COOKIE_SECRET)
DATASOURCE_SECRET_KEY = os.environ.get('REDASH_SECRET_KEY', SECRET_KEY)
このようになっており、DBの暗号キーとクッキーの暗号キーは個別に設定できるようですが、旧Redashの場合はそれぞれ同じ値を使っていると思いますので、新サーバの /opt/redash/env
には 旧サーバの /opt/redash/.env
から REDASH_COOKIE_SECRET
の内容だけコピーしておきます。REDASH_SECRET_KEY
ができていたら項目ごと消しておきます。
その他の設定
Google (Gsuite ) を使っている場合は、
REDASH_GOOGLE_APPS_DOMAIN
REDASH_GOOGLE_CLIENT_ID
REDASH_GOOGLE_CLIENT_SECRET
をコピーすることで新サーバでもGoogle 認証が行えるようになります。そのほか、REDASH_MAIL_*
など、旧サーバの設定内容はそのままコピーします。
REDASH_GOOGLE_CLIENT_ID="1xxxxxxxx.apps.googleusercontent.com"
このように、ダブルクォーテーションで囲っているとV8ではうまく動作しませんので、envファイル内でダブルクオーテーションは書かないようにします。
テーブル内容のコピー
おそらく、慣れてる方であれば pg_dump
を使うのが良いと思うのですが、私は postgres や pg_dump の経験があまり無いため、datagrip を使ってSELECT 結果から INSERT 文を生成し、それをコピペで流し込むことにしました。
旧Redash からの変更点として、データベーススキーマ名が redash から postgres に変更されたこと、また旧版の queries テーブルや dashboards にあった user_email フィールドが無くなっていることなどあり、pg_dump での対応が難しそうだと思ったためです。
データ量として 700クエリー、30ダッシュボード、60ユーザー程度の規模ですので、コピペで十分対応できました。なお、query_results
テーブルに過去のSQL結果が入ってますが、2GB程度のストレージを使っており、不要だと思ったため今回は query_results は移行しませんでした。
旧サーバの postgres に接続し、以下のテーブル内容をコピーしていきます。
organizations
users
data_sources
groups
data_source_groups
queries
visualizations
dashboards
widgets
外部キー制約があるため、流し込む順番が違うと失敗しますが、上記の順番で INSERT できると思います。
queries , dashboards には user_email
という不要フィールドがあり、queries にはさらに query_results への参照があるのですが、それらは不要なため下記のようなSELECT 文で datagrip 上で検索し、INSERT 文としてコピーして 新DBに INSERT します。
SELECT id, updated_at, created_at, org_id, data_source_id, name, description, query, query_hash, api_key, user_id, last_modified_by_id, is_archived, options, version, is_draft, schedule_failures, search_vector, tags, schedule
FROM public.queries
ORDER BY id;
SELECT id, updated_at, created_at, org_id, slug, name, user_id, layout, dashboard_filters_enabled, is_archived, version, is_draft, tags
FROM public.dashboards
ORDER BY id;
ついでに、MySQL データソースは RDS用のものが新たに出来ていたため、 data_sources の type フィールドは mysql から rds_mysql 変更しました。
シーケンスの更新
INSERT しただけではオートインクリメントPKに使われるシーケンス番号が1から始まり、新しいクエリを保存する時エラーになってしまうので、シーケンスも更新しておきます。
SELECT * FROM users_id_seq;
SELECT MAX(id) + 1 FROM users;
ALTER SEQUENCE users_id_seq RESTART WITH 61;
SELECT * FROM groups_id_seq;
SELECT MAX(id) + 1 FROM groups;
ALTER SEQUENCE groups_id_seq RESTART WITH 6;
SELECT * FROM data_sources_id_seq;
SELECT MAX(id) + 1 FROM data_sources;
ALTER SEQUENCE data_sources_id_seq RESTART WITH 24;
SELECT * FROM data_source_groups_id_seq;
SELECT MAX(id) + 1 FROM data_source_groups;
ALTER SEQUENCE data_source_groups_id_seq RESTART WITH 22;
SELECT * FROM dashboards_id_seq;
SELECT MAX(id) + 1 FROM dashboards;
ALTER SEQUENCE dashboards_id_seq RESTART WITH 37;
SELECT * FROM queries_id_seq;
SELECT MAX(id) + 1 FROM queries;
ALTER SEQUENCE queries_id_seq RESTART WITH 699;
SELECT * FROM visualizations_id_seq;
SELECT MAX(id) + 1 FROM visualizations;
ALTER SEQUENCE visualizations_id_seq RESTART WITH 1230;
SELECT * FROM widgets_id_seq;
SELECT MAX(id) + 1 FROM widgets;
ALTER SEQUENCE widgets_id_seq RESTART WITH 695;
このように、MAX(id) の結果をコピペしてALTER SEQUENCE していきました。1行で書けそうなのですが、経験が無く書き方がわからなかったため、愚直に書いてます。
これで、新サーバで旧サーバの状態が再現されていると思います。
nginx に SSL証明書を組み込む
自己認証局のSSL証明書がありますので、使います。
参考: dockerでredashのnginxをssl化したら思いの外ハマった
mkdir -p /home/ubuntu/nginx/certs
certs に、証明書 ( my-awesome.crt, my-awesome.key )を入れる
/home/ubuntu/nginx/default.conf を作成
upstream redash {
server redash:5000;
}
server {
listen 80 default;
return 301 https://$host$request_uri;
}
server {
listen 443;
ssl on;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1.2;
ssl_ciphers "ECDHE+RSAGCM:ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:!EXPORT:!DES:!3DES:!MD5:!DSS";
gzip on;
gzip_types *;
gzip_proxied any;
ssl_certificate /etc/nginx/certs/my-awesome.crt;
ssl_certificate_key /etc/nginx/certs/my-awesome.key;
error_log /var/log/nginx/nginx_error.log;
access_log /var/log/nginx/nginx_access.log;
location / {
proxy_ssl_server_name on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_pass http://redash;
}
}
/opt/redash/docker-compose.yml を修正
nginx:
image: redash/nginx:latest
ports:
- "80:80"
- "443:443"
depends_on:
- server
links:
- server:redash
restart: always
volumes:
- /home/ubuntu/nginx/default.conf:/etc/nginx/conf.d/default.conf
- /home/ubuntu/nginx/certs:/etc/nginx/certs
最後に
繰り返しとなりますが、データソース選択ビューで、INSERTしたはずのデータソースが表示されず、ぐるぐるとローディングスピナーが回り続ける場合、旧サーバと settings.DATASOURCE_SECRET_KEY が一致していません。/opt/redash/env の REDASH_COOKIE_SECRET を旧サーバと同じにして、REDASH_SECRET_KEY 設定を消すとデータソースが見れるようになると思います。