Hosted Redash(app.redash.io) から Self-Hosted Redash(GKE) への移行

こんにちは。Platform チームの飯迫 (@minato128)です。

CADDi ではこれまで Hosted Redash(app.redash.io) を利用していたのですが、残念ながら 2021/11/30 に End of Life になるので、10 月末に Self-Hosted Redash 環境を構築して移行しました。今回はそのときやったことを紹介します。

移行の流れ

  1. 新しい Redash 環境を v10 で構築する
  2. 公式の移行ツールを利用してデータ移行する
  3. 監視を追加する

新しい Redash 環境を v10 で構築する

まず、移行ツールは移行先として v10 を前提としているので、新しい環境は v10 である必要があります。ちなみに、v10 は 10/2 にリリースされた現時点の最新版です。

v10 であればどんな方法で構築しても問題ないのですが、今回は社内用 GKE Cluster に入れることにしました。監視もリソースも集約でき、Helm Chart を使うことで初期導入コストも低そうだったからです。

移行対象 GKE Cluster は、このような構成となっており、

  • 基幹システム(社内システム)のほとんどをマルチテナントで運用している
  • ArgoCD で GitOps している
  • Secret は External Secrets + GCP Secret Manager で管理している
  • Datadog で監視、ログを参照できるようにしている

次のように進めていきました。

(1) Terraform に必要な GCP リソースを追加してデプロイ

  • GKE に新しい Node pool の追加
    • 基幹システムに出来る限り影響を与えないようにしたかったので、いったん Node pool ごと分離
    • 移行後のリソース状況をみながら見直す想定
  • CloudSQL(PostgreSQL) の追加
    • DB の管理はできるだけしたくなかったため
    • バックアップもおまかせ

(2) Redash Helm Chart の ArgoCD Application Manifest を追加してデプロイ

現在の Chart version は 2.3.1 で Redash version は v8 となっています。ほしいのは v10 だったため、まず v10 に対応する PR を作成しました。(Redash ほど有名なツールの Chart が最新バージョンに対応してないとは思っておらず、これは想定外の作業でした)

追加したファイルの一覧はこれらで、

├── applications
│   ├── redash-assets
│      └── overlays
│          └── prod
│              ├── kustomization.yaml
│              ├── redash-postgres-secret.yaml
│              └── redash-secret.yaml
├── argocd
│   ├── overlays
│       ├── prod
│           ├── pj-name
│               ├── helm-redash.yaml

以下が helm-redash.yaml のイメージです。(実際のものではなくいろいろ端折っています)

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: redash
  namespace: argocd
  finalizers:
    - resources-finalizer.argocd.argoproj.io
spec:
  project: project-name
  source:
    repoURL: "https://minato128.com/contrib-helm-chart/"
    chart: redash
    targetRevision: 2.4.1
    helm:
      valueFiles:
        - values.yaml
      values: |-
        # env -- Redash global envrionment variables - applied to both server and worker containers.
        env:
          PYTHONUNBUFFERED: 0
          REDASH_RATELIMIT_ENABLED: "false"
          REDASH_MAIL_SERVER: "smtp.sendgrid.net"
          REDASH_MAIL_PORT: "587"
          REDASH_MAIL_USE_TLS: "true"
          REDASH_MAIL_USERNAME: "apikey"
          REDASH_MAIL_DEFAULT_SENDER: "redash@caddi.jp"

        ## Redash application configuration
        redash:
          # -- REQUIRED `REDASH_SECRET_KEY` value. Secret key used for data encryption. Stored as a Secret value.
          # helm template 通らないので入れているが、実際はexistingSecretが採用される
          secretKey: "DUMMY"
          # -- `REDASH_STATSD_HOST` value.
          # @default -- 127.0.0.1
          statsdHost: "datadog-statsd-service.datadog"
          # -- `REDASH_GOOGLE_CLIENT_ID` value.
          googleClientId: "XXXXXXXXXX"
          # -- REQUIRED `REDASH_COOKIE_SECRET` value. Stored as a Secret value.
          # helm template 通らないので入れているが、実際はexistingSecretが採用される
          cookieSecret: "DUMMY"
          # redash.existingSecret -- Name of existing secret to use instead of either the values above
          ## This secret must contain keys matching the items marked "Stored as a Secret value" above.
          existingSecret: "redash-secret"

        # we dont use ingress
        ingress:
          # ingress.enabled -- Enable ingress controller resource
          enabled: false

        # CloudSQL
        # externalPostgreSQLSecret -- Read external PostgreSQL configuration from a secret. This should point at a secret file with a single key which specifyies the connection string.
        externalPostgreSQLSecret:
          name: redash-postgres-secret
          key: connectionString

        ## we dont use this postgresql
        postgresql:
          # postgresql.enabled -- Whether to deploy a PostgreSQL server to satisfy the applications database requirements. To use an external PostgreSQL set this to false and configure the externalPostgreSQL parameter.
          enabled: false
          # helm template 通らないので入れているが、実際はexternalPostgreSQLSecretが採用される
          postgresqlPassword: "DUMMY"

        ## Configuration values for the redis dependency. This Redis instance is used by default for caching and temporary storage [ref](https://github.com/kubernetes/charts/blob/master/stable/redis/README.md)
        redis:
          # redis.enabled -- Whether to deploy a Redis server to satisfy the applications database requirements. To use an external Redis set this to false and configure the externalRedis parameter.
          enabled: true
  destination:
    server: "https://kubernetes.default.svc"
    namespace: redash
  syncPolicy:
    syncOptions:
      - CreateNamespace=true
  • v10 対応の PR はまだマージできていないので、fork した Repository の Package を参照している
    • v10 のスキーマに対応した DB で運用していれば、あとで Chart を入れ替えても問題ない
      • 移行のブロック要因にはならない
  • 移行データが多いと API 制限に当たってしまうのでREDASH_RATELIMIT_ENABLEDを false にする
  • Secret は existingSecretexternalPostgreSQLSecret で指定する
    • redash-assets という名前で、ArgoCD Application を追加して External Secrets をデプロイ
    • REQUIRED な設定には、実際には使わなくても空でない値を入れておかないと helm template コマンドが通らない
  • Redash は Statsd に対応しているが、現在の Chart では REDASH_STATSD_HOSTstatus.hostIP を指定できないので、Proxy Service を作って指定している

公式の移行ツールを利用してデータ移行する

概要は @ariarijp さんのスライドがわかりやすいです。

https://speakerdeck.com/ariarijp/you-should-know-about-hosted-redash-eol-and-redash-migrate

基本的には 公式ドキュメントに書いてある通りにやっただけです。

  1. redash-toolbelt をインストールする
  2. redash-migrate init
    • 移行に必要な設定が meta.json として生成される
  3. redash-migrate --help の結果のコマンドを上から順に実行していく
    • データに依存関係があるため
    • 移行の from/to 情報が meta.json に蓄積される

こちらが実行後の meta.json の一部抜粋で、データタイプごとに移行元と移行先の id が状態管理されていることがわかります。

    "queries": {
        "233300": 1,
        "233440": 2,
        "234065": 3,
    }

以下がポイントです。

  • redash-migrate は最新バージョンを使う
  • セキュリティ上の都合で、Data Source の Secret は移行されない
    • Redash UI 上で再設定が必要
  • 冪等性があり何度でも実行可能
    • リソースの id 単位で移行するため、移行済みリソースを origin 側で変更しても再同期はできない
  • Origin 側も Destination 側も Redash 本体の Web API でアクセスする
    • 接続周りに気を使う必要がない
  • 移行量が多い場合は、Destination 側の API Limit を変えておく

監視を追加する

モニタリングのためにこれらを追加しました。

  • Datadog Logs の Pipeline 追加
    • 一部 Parse しづらいログがあるので手動で Parser を書いてレベル(status)を正しく Remap する
  • Datadog Monitor の追加
    • GKE や CloudSQL は既存の監視を利用
      • Terraform で管理しており、Module を参照
    • Error log 数
    • Synthetics(外形監視)
    • Queue 監視
      • 前提として、Redash v10 は RQ(Redis Queue) を利用しており、job(message)を処理できているか監視する必要がある
      • 個人的に Queue は Message Age で監視する派ですが、既存 metrics にはないので、message がたまり続けてないか観測することにした
      • redash.rq.jobs.created が enqueue 時、redash.rq.jobs.started が処理開始時に記録されている ので、created - started が n (正の整数)より大きい状態が一定期間続くと worker が message をさばけていないことになる
        • n は traffic や worker count に依るが 0 に近いほうがよい
  • Datadog Dashboard の追加
    • 俯瞰して状況把握できるように

まとめとポイント

  • 新しい環境は v10 で作る
    • 移行ツールが v10 しかサポートしていないため
    • Redash Helm Chart は現時点では Redash v8
  • データ移行は、公式の移行ツールで簡単にできる
    • 移行データに依存関係があるので、help コマンドの順番通りに実行していく
    • セキュリティ上の都合で、Data Source の Secret は移行されないので UI 上で再設定が必要
    • 冪等性があり何度でも実行可能
    • Origin 側も Destination 側も Redash 本体の Web API でアクセスするので、接続周りに気を使う必要がない
    • 移行量が多い場合は、Destination 側の API Limit を変えておく