[Redash] Redashの別AWS VPC環境への移行手順

# [Redash] Redashの別AWS VPC環境への移行手順

## 目的

AWS VPC上に本家AMIから構築したRedashを別VPC上に移行する手順の共有、および移行時発生したトラブルについての対処法の記録

## 背景

AWS上に本家のAMIから構築したRedashだが、都合により別VPC上へリプレイスする必要がでた。

参照するデータソースについても新VPC上のものへ変更になるが、そこらへんは後から何とでもなるだろうと考え、
巷に溢れるバックアップ/レストア手順を元に移行作業を実施した。

しかし、移行後RedashのUIへアクセスすると既存のデータソースを参照できないどころか、新規データソースも作成できない問題が発生した。

## 環境/名称

- Redash

Redash Version: 8.0.0+b32245 (a16f551e) 
Redash AMI: ami-060741a96307668be

- 移行元環境名称

|Item|Name|
|---|---|
|VPC|src_vpc|
|Redash Instance|i-src-redash|
|DataSource DB Host|srcdb.example.ap-northeast-1.rds.amazonaws.com|
|DataSource DB|migration_db_a|
|DataSource DB|migration_db_b|

- 移行先環境名称

|Item|Name|
|---|---|
|VPC|dst_vpc|
|Redash Instance|i-dst-redash|
|DataSource DB Host|dstdb.example.ap-northeast-1.rds.amazonaws.com|
|DataSource DB|migration_db_a|
|DataSource DB|migration_db_b|

## 移行手順

### 移行データの取得

1. RedashのDBのdump

    何はともあれ移行データの取得

    ```
    $ cid=$(sudo docker ps -qf "name=redash_postgres_1")
    $ docker exec -t ${cid} pg_dumpall -c -U postgres | gzip > redash_dump.sql.gz
    ```

2. dumpのS3 upload

    移行先インスタンスからデータを取得できるようにS3にデータアップロード

    1. 移行データ受け渡し用のS3 bucketを用意

        AWS Web Consoleからredash-migrationという名でS3 bucketを用意しておく

    1. i-src-redashに対しIAM RoleのS3 Full Accessを付与

        AWSのWeb Consoleを利用して権限を付与する

    1. i-src-redashへaws cliのインストール

        `python-pip`ではなく`python3-pip`

        ```
        $ sudo apt install python3-pip
        $ sudo pip3 install awscli
        ```

        動作確認でS3 bucket(redash-migration)が参照できることを確認

        ```
        $ aws s3 ls
        ```

    1. 移行データのS3アップロード

        ```
        $ aws s3 cp redash_dump.sql.gz s3://redash-migration/
        $ aws s3 ls s3://redash-migration/
        →ファイルがアップロードされたことを確認
       ```

### 新規Redashサーバ(i-dst-redash)の構築

@hujuu さんの [AWSにRedashを設置](https://qiita.com/hujuu/items/8e8d6b61b03860302e51) を参考に本家AMIを利用してRedashを立ち上げ。

### 移行データのレストア

dst_vpc上のi-dst-redashにsrc_vpc上のi-src-redashから取得した移行用データをレストアする

1. 移行データをS3からダウンロード

    1. i-dst-redashに対しIAM RoleのS3 Full Accessを付与(Read Only Accessのみでもよい)

        AWSのWeb Consoleを利用して権限を付与する

    1. i-dst-redashへaws cliのインストール

        ```
        $ sudo apt install python3-pip
        $ sudo pip3 install awscli
        ```

        動作確認でS3 bucket(redash-migration)が参照できることを確認

        ```
        $ aws s3 ls
        ```

    1. 移行データをS3からダウンロード

        ```
        $ aws s3 cp s3://redash-migration/redash_dump.sql.gz ./
        $ ls -l
        →ファイルがダウンロードされたことを確認
       ```

2. 移行データのレストア

    1. 起動しているredashコンテナの停止

        ```
        $ sudo docker-compose --file /opt/redash/docker-compose.yml down --remove-orphans
        ```

    2. PostgreSQLコンテナのみ起動

        ```
        $ sudo docker-compose --file /opt/redash/docker-compose.yml up --detach postgres
        $ cid=$(sudo docker ps -qf "name=redash_postgres_1")
        ```

     3. 移行データをPostgreSQLコンテナへ展開

        ```
        $ sudo docker container cp redash_dump.sql.gz ${cid}:/usr/local/redash_dump.sql.gz
        $ sudo docker container exec ${cid} /bin/bash -c 'psql -c "drop database if exists postgres" -U postgres template1'
        $ sudo docker container exec ${cid} /bin/bash -c 'psql -c "create database postgres" -U postgres template1'
        $ sudo docker container exec ${cid} /bin/bash -c 'zcat /usr/local/redash_dump.sql.gz | psql -U postgres -d postgres'
        ```

     4. PostgreSQLコンテナを停止し、Redash全体を起動

        ```
        $ sudo docker-compose --file /opt/redash/docker-compose.yml down --remove-orphans
        $ sudo docker-compose --file /opt/redash/docker-compose.yml up --detach
        ```

### Redashへの接続確認

i-dst-redashのPublic IPを確認しブラウザでアクセスすると、Redashのログイン画面が表示されるので、i-src-redashで利用していたアカウントとパスワードでログインできることを確認する。

正常動作が確認できない場合は以下を再度確認する。

- AWS上のセキュリティグループ
- AWS上のネットワークACL
- AWS上のルーティングテーブル(インターネットGWへのルートは適切か)

ログインすると、Dashboardのデータなどが表示されるが、ドリルダウンしてもデータは参照できない。
なぜなら、データソースのDataSource DB Hostが変更になっているため。

また、ここでデータソースを変更しようとSettings > Data Sources へアクセスしても、以下のエラーが出力され新規データソースの追加もできない状態となる

```
Sorry, we couldn't find anything.
```

### データソースの復旧

一旦、既存のデータソース情報をDBから削除すると新規にデータソースを追加できるようになる。
そのため、以下の流れでデータソースを復旧させる。

(1). 既存データソース情報の確認
(2). データソース削除
(3). Web/UIからデータソースの作成
(4). 新規データソースとqueryが参照するデータソースの紐づけ


1. 既存データソース情報の確認

    1. PostgreSQLへpsqlを利用しログイン

        ```
        $ cid=$(sudo docker ps -qf "name=redash_postgres_1")
        $ sudo docker container exec -it ${cid} /bin/bash
        →PostgreSQLコンテナへログインしたことを確認
        # psql -U postgres postgres
        ```

    2. 既存の data_sources, data_source_groups テーブルのデータを確認

        data_sources の id が query テーブルで参照されている。
        「(4).新規データソースとqueryが参照するデータソースの紐づけ」作業で必要となるので必ずメモっておく

        ```
        # select * from data_sources;
         id | org_id |      name      |   type    |  encrypted_options  | queue_name | scheduled_queue_name |          created_at    
        ----+--------+----------------+-----------+---------------------+------------+----------------------+-------------------------------
          1 |      1 | migration_db_a | rds_mysql | \x67413d3d(snippet) | queries    | scheduled_queries    | 2019-11-27 02:20:13.635035+00
          2 |      1 | migration_db_b | rds_mysql | \x67415f42(snippet) | queries    | scheduled_queries    | 2019-11-28 04:07:50.333332+00
        (2 rows)

        postgres=# select * from data_source_groups;
         id | data_source_id | group_id | view_only
        ----+----------------+----------+-----------
          1 |              1 |        2 | t
          2 |              1 |        1 | f
          3 |              2 |        2 | f
          4 |              2 |        1 | f
        (4 rows)
        ```

2. データソース削除

    data_sourcesのレコードは他のテーブルのレコードと依存関係(FOREIGN KEY CONSTRAINT)があるので、そのまま削除するとエラーになる。
    一旦、DISABLE TRIGGERで依存を切ってから削除する。
    DISABLEした依存関係の復旧は「(4). 新規データソースとqueryが参照するデータソースの紐づけ」の中で実施する。

    ```
    # delete from data_source_groups;
    DELETE 4
    # delete from data_sources;
    ERROR:  update or delete on table "data_sources" violates foreign key constraint "queries_data_source_id_fkey" on table "queries"
    # ALTER TABLE data_sources DISABLE TRIGGER ALL;
    ALTER TABLE
    # delete from data_sources;
    DELETE 2
    ```

3. Web/UIからデータソースの作成

    i-src-redashに設定したときと同様にRedashのWeb/UIから`dstdb.example.ap-northeast-1.rds.amazonaws.com`上の`migration_db_a`, `migration_db_b`をデータソースとして登録する。

    正常にデータソースにconnectできない場合は以下を確認する

- AWS上のセキュリティグループ
- AWS上のネットワークACL
- AWS上のルーティングテーブル
- DBのアカウント設定(特にアクセス元ホストのIPが変更になっているのでその点をチェック)

4. 新規データソースとqueryが参照するデータソースの紐づけ

    1. 新規データソースの data_sources, data_source_group テーブル上のレコードを確認

        ```
        # select * from data_sources;
         id | org_id |      name      |   type    |  encrypted_options  | queue_name | scheduled_queue_name |          created_at    
        ----+--------+----------------+-----------+---------------------+------------+----------------------+-------------------------------
          3 |      1 | migration_db_a | rds_mysql | \x67413d3d(snippet) | queries    | scheduled_queries    | 2020-01-06 07:31:34.455437+00
          4 |      1 | migration_db_b | rds_mysql | \x67415f42(snippet) | queries    | scheduled_queries    | 2020-01-06 07:33:56.520092+00
        (2 rows)

        # select * from data_source_groups;
         id | data_source_id | group_id | view_only
        ----+----------------+----------+-----------
          5 |              3 |        2 | f
          6 |              4 |        2 | f
        ```

    2. data_sourcesのidと、data_source_groupsのid, data_source_idを修正する

        「(1). 既存データソース情報の確認」で確認したものに合わせるよう、修正する

        ```
        # update data_sources set id = 1  where id = 3;
        UPDATE 1
        # update data_sources set id = 2  where id = 4;
        UPDATE 1
        # select * from data_sources;
         id | org_id |      name      |   type    |  encrypted_options  | queue_name | scheduled_queue_name |          created_at    
        ----+--------+----------------+-----------+---------------------+------------+----------------------+-------------------------------
          1 |      1 | migration_db_a | rds_mysql | \x67413d3d(snippet) | queries    | scheduled_queries    | 2020-01-06 07:31:34.455437+00
          2 |      1 | migration_db_b | rds_mysql | \x67415f42(snippet) | queries    | scheduled_queries    | 2020-01-06 07:33:56.520092+00
        (2 rows)

        # update data_source_groups set id = 1, data_source_id = 1 where id = 5;
        UPDATE 1
        # update data_source_groups set id = 3, data_source_id = 2 where id = 6;
        UPDATE 1
        # select * from data_source_groups;
         id | data_source_id | group_id | view_only
        ----+----------------+----------+-----------
          1 |              1 |        2 | f
          3 |              2 |        2 | f
        (2 rows)

        # insert into data_source_groups (id, data_source_id, group_id, view_only) values (2, 1, 1, true);
        INSERT 0 1
        # insert into data_source_groups (id, data_source_id, group_id, view_only) values (4, 2, 1, true);
        INSERT 0 1
        # select * from data_source_groups;
         id | data_source_id | group_id | view_only
        ----+----------------+----------+-----------
          1 |              1 |        2 | f
          3 |              2 |        2 | f
          2 |              1 |        1 | t
          4 |              2 |        1 | t
        (4 rows)
        ```

    3. DISABLEしたdata_sourcesテーブルの依存関係を復元する

        ```
        # ALTER TABLE data_sources ENABLE TRIGGER ALL;
        ALTER TABLE
        ```

### Redashの動作確認

データソースが参照できるようになり、queryの結果が確認できることをRedashのWeb/UIから確認する