Help us understand the problem. What is going on with this article?

dockerで稼働するredashのトラブルと対策

More than 1 year has passed since last update.

概要

redashは複数のコンテナによって構成されている。
ざっくり役割は以下の通り。

redash_worker_1

データの結果取得に時間がかかる場合が多いので、
実際のクエリーを実行する処理はこのコンテナが行う。
celeryというPythonのjob queue処理を行うためのフレームワークが使われている。

以下の2種類存在している

adhoc workers

アドホックに実行したクエリーを処理する

scheduled queries workers

スケジュールされた通りにクエリーを実行する

切り替えはcelery worker起動時に-Qオプションで制御される。
1つのworkerで両方の機能を担うことも、 別々のworkerに分けることも可能。

redash_nginx_1

webサーバ リバースプロキシとして稼働

redash_server_1

Pythonで実装されたWeb console画面。
基本的にこの画面を利用して ユーザはクエリーの発行やデータの可視化を行う。
Application Serverとしてgunicornが使われている。

redash_redis_1

celeryではクエリーを貯めておく場所としてredisを利用することができる。
このredis内にserverからjobがqueueに登録され、 workerが引き出して実行を行う。

redash_postgres_1

ユーザ情報や作成したQuery/Dashboardの情報が格納される。

トラブルシューティング

コンテナのリソース状況を確認したい

redashというか、dockerでの管理の話しになるが、
ctopというコマンドを使うと、管理しやすい

https://qiita.com/S-T/items/d5a43076a51f5814ee32
image-20180322014156917.png

クエリが返って来ない

test connectionはOKでもクエリーを発行すると戻って来ない時がある。
コンテナの一つ一つ見ていくと、workerで処理が来ていないことがわかった。

スケジュールに登録されているクエリが多すぎるのでは?という仮説に至った。
考えてみればスケジュールされていなければいけない必要性もない。
QUEUESごとにworkerプロセスを分けて見ることにした。
をオフにすることにした。

https://github.com/getredash/redash/blob/master/setup/ubuntu/files/supervisord.conf

appears only in the queue list of "redash_celery_scheduled"

before

  worker:
    image: redash/redash:latest
    command: scheduler
    environment:
      PYTHONUNBUFFERED: 0
      REDASH_LOG_LEVEL: "INFO"
      REDASH_REDIS_URL: "redis://redis:6379/0"
      REDASH_DATABASE_URL: "postgresql://postgres@postgres/postgres"
      QUEUES: "queries,scheduled_queries,celery"
      WORKERS_COUNT: 1
    restart: always

after

workerコンテナを3分割した

  worker-queries:
    image: redash/redash:latest
    command: scheduler
    environment:
      PYTHONUNBUFFERED: 0
      REDASH_LOG_LEVEL: "INFO"
      REDASH_REDIS_URL: "redis://redis:6379/0"
      REDASH_DATABASE_URL: "postgresql://postgres@postgres/postgres"
      QUEUES: "queries"
      WORKERS_COUNT: 1
    restart: always
  worker-scheduled_queries:
    image: redash/redash:latest
    command: scheduler
    environment:
      PYTHONUNBUFFERED: 0
      REDASH_LOG_LEVEL: "INFO"
      REDASH_REDIS_URL: "redis://redis:6379/0"
      REDASH_DATABASE_URL: "postgresql://postgres@postgres/postgres"
      QUEUES: "scheduled_queries"
      WORKERS_COUNT: 1
    restart: always
  worker-celery:
    image: redash/redash:latest
    command: scheduler
    environment:
      PYTHONUNBUFFERED: 0
      REDASH_LOG_LEVEL: "INFO"
      REDASH_REDIS_URL: "redis://redis:6379/0"
      REDASH_DATABASE_URL: "postgresql://postgres@postgres/postgres"
      QUEUES: "celery"
      WORKERS_COUNT: 1
    restart: always

コンテナを分けた後、ctopで再度リソースを確認したところ
worker-celeryが極端にCPUを使い始めた
スクリーンショット 2018-03-29 14.34.25.png

celeryというPythonのjob queue処理で何かか詰まっていたようだ。
しばらくしたら解消した。

redashのversionUP

以下の流れで実施する
0. Postgressのデータをバックアップする
1. コンテナを止め、削除
2. docker-composeファイルを修正する
3. DBのスキーマ変更処理をする
4. redash起動

Postgressのデータをバックアップする

docker ps
docker exec -it redash_postgres_1 /bin/bash
pg_dump -U postgres postgres | gzip > /tmp/redash_backup.gz
exit
docker cp redash_postgres_1:/tmp/redash_backup.gz .

コンテナを止め、削除

docker stop redash_worker-scheduled_queries_1 redash_worker-celery_1 redash_worker-queries_1 redash_server_1
docker rm redash_worker-scheduled_queries_1 redash_worker-celery_1 redash_worker-queries_1 redash_server_1

docker-composeファイルを修正する

    #image: redash/redash:latest
    image: redash/redash:4.0.0-rc.1

DBのスキーマ変更処理をする

https://gitter.im/getredash/redash/archives/2017/03/26
@arikfr氏が提案してくれているコマンドを実施したが、
エラーが出るわけでもなく、何が起こったのかわからない。
しかし、ブラウザで画面を確認すると500errorになっている。

# docker-compose run --rm server manage db upgrade
Starting redash_redis_1
[2018-03-29 05:52:16,551][PID:1][INFO][root] Generating grammar tables from /usr/lib/python2.7/lib2to3/Grammar.txt
[2018-03-29 05:52:16,586][PID:1][INFO][root] Generating grammar tables from /usr/lib/python2.7/lib2to3/PatternGrammar.txt
[2018-03-29 05:52:17,848][PID:1][INFO][alembic.runtime.migration] Context impl PostgresqlImpl.
[2018-03-29 05:52:17,848][PID:1][INFO][alembic.runtime.migration] Will assume transactional DDL.
#

よくよく考えたら、
composeを起動する時のymlファイルを指定してなかった。。

# docker-compose -f docker-compose.production.yml run --rm server manage db upgrade
[2018-03-29 06:05:30,551][PID:1][INFO][root] Generating grammar tables from /usr/lib/python2.7/lib2to3/Grammar.txt
[2018-03-29 06:05:30,585][PID:1][INFO][root] Generating grammar tables from /usr/lib/python2.7/lib2to3/PatternGrammar.txt
[2018-03-29 06:05:32,423][PID:1][INFO][alembic.runtime.migration] Context impl PostgresqlImpl.
[2018-03-29 06:05:32,424][PID:1][INFO][alembic.runtime.migration] Will assume transactional DDL.
[2018-03-29 06:05:32,433][PID:1][INFO][alembic.runtime.migration] Running upgrade d1eae8b9893e -> 7671dca4e604, empty message
[2018-03-29 06:05:32,439][PID:1][INFO][alembic.runtime.migration] Running upgrade 7671dca4e604 -> 5ec5c84ba61e, Add Query.search_vector field for full text search.
[2018-03-29 06:05:32,565][PID:1][INFO][alembic.runtime.migration] Running upgrade 5ec5c84ba61e -> 6b5be7e0a0ef, Re-index Query.search_vector with existing queries.
[2018-03-29 06:05:32,661][PID:1][INFO][alembic.runtime.migration] Running upgrade 6b5be7e0a0ef -> 969126bd800f, Update widget's position data based on dashboard layout.
Updating dashboards position data:
  Updating dashboard: 1
    Building widgets map:
    Widget: 1
    Widget: 2
    Iterating over layout:
      Row: 0 - [1, 2]
      Column: 0 - 1
      Column: 1 - 2
  Updating dashboard: 2
    Building widgets map:
    Widget: 3
    Iterating over layout:
      Row: 0 - [3]
      Column: 0 - 3
  Updating dashboard: 4
    Building widgets map:
    Widget: 18
    Iterating over layout:
      Row: 0 - [18]
      Column: 0 - 18
  Updating dashboard: 5
    Building widgets map:
    Widget: 21
    Widget: 22
    Widget: 31
    Widget: 32
    Widget: 41
    Widget: 42
    Widget: 82
    Widget: 93
    Iterating over layout:
      Row: 0 - [93]
      Column: 0 - 93
      Row: 1 - [21]
      Column: 0 - 21
      Row: 2 - [22]
      Column: 0 - 22
      Row: 3 - [31]
      Column: 0 - 31
      Row: 4 - [32]
      Column: 0 - 32
      Row: 5 - [41]
      Column: 0 - 41
      Row: 6 - [42]
      Column: 0 - 42
      Row: 7 - [82]
      Column: 0 - 82
  Updating dashboard: 9
    Building widgets map:
    Widget: 53
    Widget: 94
    Iterating over layout:
      Row: 0 - [94]
      Column: 0 - 94
      Row: 1 - [53]
      Column: 0 - 53
  Updating dashboard: 7
    Building widgets map:
    Widget: 38
    Widget: 40
    Widget: 95
    Iterating over layout:
      Row: 0 - [95]
      Column: 0 - 95
      Row: 1 - [38]
      Column: 0 - 38
      Row: 2 - [40]
      Column: 0 - 40
  Updating dashboard: 11
    Building widgets map:
    Widget: 71
    Widget: 67
    Widget: 70
    Iterating over layout:
      Row: 0 - [67]
      Column: 0 - 67
      Row: 1 - [70]
      Column: 0 - 70
      Row: 2 - [71]
      Column: 0 - 71
  Updating dashboard: 3
    Building widgets map:
    Widget: 5
    Widget: 11
    Widget: 13
    Widget: 14
    Widget: 15
    Widget: 16
    Widget: 17
    Widget: 28
    Widget: 51
    Widget: 77
    Widget: 78
    Widget: 80
    Iterating over layout:
      Row: 0 - [14, 15]
      Column: 0 - 14
      Column: 1 - 15
      Row: 1 - [17, 16]
      Column: 0 - 17
      Column: 1 - 16
      Row: 2 - [11, 13]
      Column: 0 - 11
      Column: 1 - 13
      Row: 3 - [28]
      Column: 0 - 28
      Row: 4 - [5]
      Column: 0 - 5
      Row: 5 - [77, 78]
      Column: 0 - 77
      Column: 1 - 78
      Row: 6 - [51, 80]
      Column: 0 - 51
      Column: 1 - 80
  Updating dashboard: 13
    Building widgets map:
    Widget: 83
    Iterating over layout:
      Row: 0 - [83]
      Column: 0 - 83
  Updating dashboard: 14
    Building widgets map:
    Iterating over layout:
  Updating dashboard: 12
    Building widgets map:
    Iterating over layout:
      Row: 0 - [
      Column: 0 - [
      Row: 1 - ]
      Column: 0 - ]
  Updating dashboard: 16
    Building widgets map:
    Widget: 102
    Widget: 103
    Widget: 104
    Widget: 105
    Iterating over layout:
      Row: 0 - [102, 103]
      Column: 0 - 102
      Column: 1 - 103
      Row: 1 - [104, 105]
      Column: 0 - 104
      Column: 1 - 105
  Updating dashboard: 6
    Building widgets map:
    Widget: 25
    Widget: 26
    Widget: 29
    Widget: 30
    Widget: 33
    Widget: 34
    Widget: 43
    Widget: 45
    Widget: 46
    Widget: 47
    Widget: 48
    Widget: 91
    Iterating over layout:
      Row: 0 - [91, 48]
      Column: 0 - 91
      Column: 1 - 48
      Row: 1 - [47, 45]
      Column: 0 - 47
      Column: 1 - 45
      Row: 2 - [46]
      Column: 0 - 46
      Row: 3 - [43]
      Column: 0 - 43
      Row: 4 - [25]
      Column: 0 - 25
      Row: 5 - [26]
      Column: 0 - 26
      Row: 6 - [29]
      Column: 0 - 29
      Row: 7 - [30]
      Column: 0 - 30
      Row: 8 - [33]
      Column: 0 - 33
      Row: 9 - [34]
      Column: 0 - 34
  Updating dashboard: 10
    Building widgets map:
    Widget: 57
    Widget: 59
    Widget: 61
    Widget: 63
    Widget: 65
    Widget: 62
    Widget: 92
    Iterating over layout:
      Row: 0 - [92]
      Column: 0 - 92
      Row: 1 - [62]
      Column: 0 - 62
      Row: 2 - [57]
      Column: 0 - 57
      Row: 3 - [63]
      Column: 0 - 63
      Row: 4 - [59]
      Column: 0 - 59
      Row: 5 - [65]
      Column: 0 - 65
      Row: 6 - [61]
      Column: 0 - 61
  Updating dashboard: 17
    Building widgets map:
    Widget: 108
    Widget: 107
    Widget: 109
    Widget: 110
    Widget: 111
    Iterating over layout:
      Row: 0 - [108]
      Column: 0 - 108
      Row: 1 - [109]
      Column: 0 - 109
      Row: 2 - [107]
      Column: 0 - 107
      Row: 3 - [110, 111]
      Column: 0 - 110
      Column: 1 - 111
  Updating dashboard: 15
    Building widgets map:
    Widget: 98
    Widget: 99
    Widget: 100
    Widget: 101
    Iterating over layout:
      Row: 0 - [99, 100]
      Column: 0 - 99
      Column: 1 - 100
      Row: 1 - [98, 101]
      Column: 0 - 98
      Column: 1 - 101
  Updating dashboard: 18
    Building widgets map:
    Widget: 112
    Widget: 113
    Widget: 114
    Iterating over layout:
      Row: 0 - [112, 113]
      Column: 0 - 112
      Column: 1 - 113
      Row: 1 - [114]
      Column: 0 - 114
  Updating dashboard: 8
    Building widgets map:
    Widget: 68
    Widget: 85
    Widget: 86
    Widget: 87
    Widget: 88
    Widget: 89
    Widget: 115
    Widget: 116
    Iterating over layout:
      Row: 0 - [68, 116]
      Column: 0 - 68
      Column: 1 - 116
      Row: 1 - [115]
      Column: 0 - 115
      Row: 2 - [85]
      Column: 0 - 85
      Row: 3 - [86, 89]
      Column: 0 - 86
      Column: 1 - 89
      Row: 4 - [87]
      Column: 0 - 87
      Row: 5 - [88]
      Column: 0 - 88
  Updating dashboard: 20
    Building widgets map:
    Iterating over layout:
  Updating dashboard: 21
    Building widgets map:
    Widget: 122
    Iterating over layout:
      Row: 0 - [122]
      Column: 0 - 122
  Updating dashboard: 19
    Building widgets map:
    Widget: 120
    Widget: 121
    Widget: 124
    Widget: 118
    Iterating over layout:
      Row: 0 - [118]
      Column: 0 - 118
      Row: 1 - [124]
      Column: 0 - 124
      Row: 2 - [120]
      Column: 0 - 120
      Row: 3 - [121]
      Column: 0 - 121

作業前と、作業後でスキーマを見比べて見たが、
今回新しく追加されたカラムが結構あったので、本処理は必須。

スクリーンショット 2018-03-29 15.24.27.png
無事アップデートが完了した。

参考情報

http://tech.curama.jp/entry/2018/03/02/120000

S-T
10年続けたフリーランスのシステムエンジニアを経て、オンライン英会話会社のインフラにジョイン。金髪のおねーさんが道で迷った時のために英語勉強してます。
https://tsukada.sumito.jp/
rarejob
明治神宮にあるオンライン英会話サービスを提供するベンチャー
https://www.rarejob.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away