
DatahubのUIベースによるメタデータ取り込み機能でRedshiftのメタデータを取り込んでみた
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
どーも データアナリティクス事業本部のsutoです。
LinkedIn製のOSSデータカタログ「DataHub」は、メタデータ取り込みの際は、レシピというConfigパラメータをyamlで記述し、Datahub CLIによるコマンドベースで取り込みを実施します。
ですが、アップデートによりv0.8.25以降はUI画面上でメタデータ取り込みができるようになったとのことで検証していきたいと思います。
Datahub実行環境は以前の記事に紹介したAWS EKSサービス上にDatahubをデプロイする記事を参考に検証環境を構築します。
上記記事を参考に作業環境のインストールが完了したらEKSクラスターを作成していきましょう。
EKSクラスター作成
eksctlコマンドを使用してクラスターを作成します。今回は以下のパラメータで作成します。
- VPC:CIDRを指定して新規作成(10.1.0.0/16)
- クラスター名:datahub-test
- リージョン:ap-northeast-1
- インスタンスタイプ:m5.large
- ノード数:3
※Datahubのストレージレイヤを含むすべてのコンポーネントをEKSクラスター内のpodでデプロイさせるには少なくともm5.large以上が3ノード必要となります。
eksctl create cluster \ --vpc-cidr 10.1.0.0/16 \ --name datahub-test \ --region ap-northeast-1 \ --with-oidc \ --node-type m5.large \ --nodes 3
実行するとCloudformationスタックが実行され、完了後にkubectl get nodesを実行することで以下例のように3ノードが表示されます。
% kubectl get nodes NAME STATUS ROLES AGE VERSION ip-10-1-12-57.ap-northeast-1.compute.internal Ready <none> 17m v1.20.11-eks-f17b81 ip-10-1-60-101.ap-northeast-1.compute.internal Ready <none> 17m v1.20.11-eks-f17b81 ip-10-1-72-207.ap-northeast-1.compute.internal Ready <none> 16m v1.20.11-eks-f17b81
UIベース取り込みのためのIAMポリシー作成
UIベース取り込みの機能はacryl-datahub-actionsというPodを実装するので、そのPodにアタッチするIAMロールを作成します。
まず、必要なデータソースにアクセスできるためのIAMポリシーを作成します。今回はとりあえずRedshiftにアクセスできるようなポリシー(arn:aws:iam::<アカウントID>:policy/datahub-ingection-policy)を用意します。
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "redshift-data:*",
                "redshift:*"
            ],
            "Resource": "*"
        }
    ]
}
次に、以下のコマンドでポリシーが添付されたサービスアカウントを作成します。
eksctl create iamserviceaccount \
    --name acryl-datahub-actions \
    --namespace datahub \
    --cluster datahub-test \
    --attach-policy-arn arn:aws:iam::<<account-id>>:policy/atahub-ingection-policy \
    --approve \
    --override-existing-serviceaccounts
Helmを使用してEKSクラスターにDataHubをセットアップ
- DatahubのリポジトリをHelmに追加します。
helm repo add datahub https://helm.datahubproject.io/
- クラスター上にデプロイするMySQLデータベースとNeo4jのパスワードを格納したkubernetesシークレットを作成します。
kubectl create secret generic mysql-secrets --from-literal=mysql-root-password=datahub kubectl create secret generic neo4j-secrets --from-literal=neo4j-password=datahub
- 以下を実行してDatahubのストレージレイヤ部分を先にデプロイします
% helm install prerequisites datahub/datahub-prerequisites NAME: prerequisites LAST DEPLOYED: Wed Dec 1 01:31:18 2021 NAMESPACE: default STATUS: deployed REVISION: 1
- kubectl get podsを実行して、以下のように依存関係のすべてのポッドが実行されているかどうかを確認します。
% kubectl get pods NAME READY STATUS RESTARTS AGE elasticsearch-master-0 1/1 Running 0 2m6s elasticsearch-master-1 0/1 Running 0 2m6s elasticsearch-master-2 1/1 Running 0 2m6s prerequisites-cp-schema-registry-cf79bfccf-hxw5g 2/2 Running 0 2m6s prerequisites-kafka-0 1/1 Running 0 2m6s prerequisites-mysql-0 1/1 Running 0 2m6s prerequisites-neo4j-community-0 1/1 Running 0 2m6s prerequisites-zookeeper-0 1/1 Running 0 2m6s
- Helmチャートのvalues.yamlを作成します。acryl-datahub-actionsに先ほど作成したserviceAccountの名前を追記します。
- ※本記事では、2022年5月10日時点の最新バージョンv0.8.34で作成しています。
- 【参考】デフォルト構成はこちら
datahub-gms:
  enabled: true
  image:
    repository: linkedin/datahub-gms
    tag: "v0.8.34"
datahub-frontend:
  enabled: true
  image:
    repository: linkedin/datahub-frontend-react
    tag: "v0.8.34"
  # Set up ingress to expose react front-end
  ingress:
    enabled: false
acryl-datahub-actions:
  enabled: true
  image:
    repository: public.ecr.aws/datahub/acryl-datahub-actions
    tag: "v0.0.1-beta.13"
  resources:
    limits:
      memory: 512Mi
    requests:
      cpu: 300m
      memory: 256Mi
  serviceAccount:
    name: acryl-datahub-actions
datahub-mae-consumer:
  image:
    repository: linkedin/datahub-mae-consumer
    tag: "v0.8.34"
datahub-mce-consumer:
  image:
    repository: linkedin/datahub-mce-consumer
    tag: "v0.8.34"
datahub-ingestion-cron:
  enabled: false
  image:
    repository: acryldata/datahub-ingestion
    tag: "v0.8.34"
elasticsearchSetupJob:
  enabled: true
  image:
    repository: linkedin/datahub-elasticsearch-setup
    tag: "v0.8.34"
  podSecurityContext:
    fsGroup: 1000
  securityContext:
    runAsUser: 1000
kafkaSetupJob:
  enabled: true
  image:
    repository: linkedin/datahub-kafka-setup
    tag: "v0.8.34"
  podSecurityContext:
    fsGroup: 1000
  securityContext:
    runAsUser: 1000
mysqlSetupJob:
  enabled: true
  image:
    repository: acryldata/datahub-mysql-setup
    tag: "v0.8.34"
  podSecurityContext:
    fsGroup: 1000
  securityContext:
    runAsUser: 1000
postgresqlSetupJob:
  enabled: false
  image:
    repository: acryldata/datahub-postgres-setup
    tag: "v0.8.34"
  podSecurityContext:
    fsGroup: 1000
  securityContext:
    runAsUser: 1000
datahubUpgrade:
  enabled: true
  image:
    repository: acryldata/datahub-upgrade
    tag: "v0.8.34"
  noCodeDataMigration:
    sqlDbType: "MYSQL"
  podSecurityContext: {}
    # fsGroup: 1000
  securityContext: {}
    # runAsUser: 1000
global:
  graph_service_impl: neo4j
  datahub_analytics_enabled: true
  datahub_standalone_consumers_enabled: false
  elasticsearch:
    host: "elasticsearch-master"
    port: "9200"
  kafka:
    bootstrap:
      server: "prerequisites-kafka:9092"
    zookeeper:
      server: "prerequisites-zookeeper:2181"
    ## For AWS MSK set this to a number larger than 1
    # partitions: 3
    # replicationFactor: 3
    schemaregistry:
      url: "http://prerequisites-cp-schema-registry:8081"
      # type: AWS_GLUE
      # glue:
      #   region: us-east-1
      #   registry: datahub
  neo4j:
    host: "prerequisites-neo4j-community:7474"
    uri: "bolt://prerequisites-neo4j-community"
    username: "neo4j"
    password:
      secretRef: neo4j-secrets
      secretKey: neo4j-password
  sql:
    datasource:
      host: "prerequisites-mysql:3306"
      hostForMysqlClient: "prerequisites-mysql"
      port: "3306"
      url: "jdbc:mysql://prerequisites-mysql:3306/datahub?verifyServerCertificate=false&useSSL=true&useUnicode=yes&characterEncoding=UTF-8&enabledTLSProtocols=TLSv1.2"
      driver: "com.mysql.cj.jdbc.Driver"
      username: "root"
      password:
        secretRef: mysql-secrets
        secretKey: mysql-root-password
  datahub:
    gms:
      port: "8080"
      nodePort: "30001"
    mae_consumer:
      port: "9091"
      nodePort: "30002"
    appVersion: "1.0"
    encryptionKey:
      secretRef: "datahub-encryption-secrets"
      secretKey: "encryption_key_secret"
      # Set to false if you'd like to provide your own secret.
      provisionSecret: true
    managed_ingestion:
      enabled: true
      defaultCliVersion: "0.8.34.1"
    metadata_service_authentication:
      enabled: false
      systemClientId: "__datahub_system"
      systemClientSecret:
        secretRef: "datahub-auth-secrets"
        secretKey: "token_service_signing_key"
      tokenService:
        signingKey:
          secretRef: "datahub-auth-secrets"
          secretKey: "token_service_signing_key"
      # Set to false if you'd like to provide your own auth secrets
      provisionSecrets: true
- 以下のコマンドを実行してDatahubをデプロイします。
helm upgrade --install datahub datahub/datahub --values <yamlファイルを保存したフォルダパス>/values.yaml
- デプロイ完了後、podの一覧が以下のようになるはずです。
% kubectl get pods NAME READY STATUS RESTARTS AGE datahub-acryl-datahub-actions-f87bbf4cb-j2vh4 1/1 Running 0 2m49s datahub-datahub-frontend-5f57bc485b-967vw 1/1 Running 0 2m49s datahub-datahub-gms-7dbcd8d77d-rv2hx 1/1 Running 0 2m49s datahub-datahub-upgrade-job--1-ggzcb 0/1 Error 0 2m49s datahub-datahub-upgrade-job--1-s7td2 0/1 Completed 0 104s datahub-elasticsearch-setup-job--1-9wqk2 0/1 Completed 0 3m52s datahub-kafka-setup-job--1-5vcbs 0/1 Completed 0 3m50s datahub-mysql-setup-job--1-6wn2l 0/1 Completed 0 2m52s elasticsearch-master-0 1/1 Running 0 24m elasticsearch-master-1 1/1 Running 0 24m elasticsearch-master-2 1/1 Running 0 24m prerequisites-cp-schema-registry-cf79bfccf-5q5kf 2/2 Running 1 (23m ago) 24m prerequisites-kafka-0 1/1 Running 1 (23m ago) 24m prerequisites-mysql-0 1/1 Running 0 24m prerequisites-neo4j-community-0 1/1 Running 0 24m prerequisites-zookeeper-0 1/1 Running 0 24m
- Frontend用ELB(http://xxxxxxxx.ap-northeast-1.elb.amazonaws.com:9002)にブラウザでアクセスしてみると以下のようにログイン画面が表示されます。

実際にUI上からメタデータ取り込みをやってみた
- 今回はRedshiftを例にデータ取り込みを実施します。Redshift内のデータは以下ブログで使用したサンプルと同じです。
- デフォルトユーザとパスワード(datahub:datahub)でログインし、右上の「Ingection」をクリックします。
- 
まずはRedshiftに接続するユーザー名とパスワードをUI上のシークレットに登録します。「Secrets」タブをクリックして「Create new secret」をクリックします。 

- Name:REDSHIFT_USERNAME、Value:「Redshiftのユーザー名」を入力してOKをクリックします

- 画面を更新すると一覧にシークレットが表示されます。同様に、Name:REDSHIFT_PASSWORD、Value:「Redshiftのパスワード」も作成します。

- 次に「Sources」タブをクリックし、「Create new source」をクリックして取り込みジョブを作成していきます。
- 
ソースタイプはRedshiftを選択します。 

- 次の画面でレシピを記入して「次へ」。(書き方は従来のDatahub CLIと同様です。)
- 
ログインユーザーとパスワードは先ほど作成したシークレットのNameを以下のように記入します。 
※例では、「schema_pattern」で取り込むスキーマを指定するためのフィルタリングをしていますが、この部分はオプション設定となります。
source:
  type: redshift
  config:
    # Coordinates
    host_port: <<Redshiftのエンドポイント>>:5439
    database: <<Redshiftデータベース名>>
    # Credentials
    username: '${REDSHIFT_USERNAME}'
    password: '${REDSHIFT_PASSWORD}'
    schema_pattern:
      allow: 
        - '^cm_suto*'
    include_views: True # ビューを取り込むかどうか選択可能、defaultはTrue
    include_tables: True # テーブルを取り込むか選択可能、defaultsはTrue
sink:
  type: "datahub-rest"
  config:
    server: "http://<<GMSサーバのエンドポイント>>:<<GMSサーバのポート番号>>"
- 次の画面ではcronによるスケジュール設定ができます。ここはオプションなので今回は設定しません、よって「Skip」で次へ進みます。

- 最後にワークフローの名前を付けます
- Executor idは今回はデフォルト設定とするので空欄にしています
- CLI VersionはデプロイしたDatahubサーバのバージョンと合わせるように設定してください。今回はサーバ、CLIどちらも最新バージョンで検証しているので空欄(自動的に最新バージョンに設定)でいきます。
- 最後に「Done」をクリックして設定完了です。

- すると一覧に表示されますので「EXECUTE」をクリックして取り込みジョブを実行してみます。

- ステータスは「Succeeded」になったら成功です。(画面ではレシピの記入ミスで何度かFailedになっていますが)

- 実際にメタデータの取り込みも問題なくできていました。

以上、Datahub CLIを作業端末にインストールすることなくUI画面上でメタデータの取り込みができました。
まとめ
UIベースの取り込み機能を実装しているフリーのOSSソフトは少ないので、Datahubはかなり開発が進んでいて多くのユーザーが扱いやすくなっている印象があります。
また、cronベースのスケジューリング機能も追加されていて、簡易なジョブワークフローならばDatahub画面上で管理できるようになったのもとても良いアップデートがされていると思います。
【2022年5月15日時点】この後、ストレージ部分をAWSサービス(RDS,MSK,Opensearch等)にした構成でこのUIベース取り込みを検証してみましたが、実行時に「acryl-datahub-actions」のPodがクラッシュしてしまい、ジョブが実行されないエラーが発生していて現在調査中です。











