こんにちは、技術本部研究開発部ML Platformチームのジャン(a.k.a jc)です。 本記事は Sansan Advent Calendar 2023 の19日目、および【R&D DevOps通信】の連載記事のひとつです。
今年6月にData DirectionチームからML Platformチームに異動し、全社横断データ基盤の開発から離れて、研究開発部内のアプリケーション基盤「Circuit」の開発に従事しています。 研究開発部の2大基盤に関する知見を有していることを誇りに思っています。
全社横断データ基盤
全社横断データ基盤とは、2022年に研究開発部で導入した全社のデータ意思決定を支えるデータ基盤です。
研究開発部のアプリケーション基盤「Circuit」
Circuitとは、同じく2022年に研究開発部で導入したアプリケーション基盤です。 AWS EKSを用いたKubernetesで動いています。
CircuitにAirbyteを載せる
Data Directionチームに所属していた頃、より低いコスト(運用・費用)で素早くデータソースを連携できるようにするため、AirbyteというELTツールを調査・検証していました。
TerraformによるAirbyteを利用したデータ基盤へのデータ連携とCI/CD - Sansan Tech Blog
Airbyteは、多数のデータソース同士を連携させることができる OSS のデータコネクタです。ELT 処理によりデータソースから AWS や BigQuery などのディスティネーションへデータの抽出を行うことができます。データソースと連携先の種類が多い、dbtを経由できる、短時間で連携できるなどといった特長があり、現在勢いのあるELTツールのひとつです。
チーム内で検討した結果、コスト・セキュリティ面の理由からSaaS版のAirbyteの導入を見送り、社内の技術本部設計レビューを受けた上でアプリケーション基盤「Circuit」に載せることを決定しました。
構築時に遭遇した問題
最初はHelmを使用してAirbyteをインストールしようと考えていましたが、うまくいきませんでした。
具体的には、Airbyte v0.50.31 以前のバージョンでは、api-serverの一部のendpointを呼び出すとUnexpected error occurred: Read Timeout
のエラーが発生します
*1。
api-serverが使えないと、webappからデータインジェストの設定をすることも可能ですが、TerraformなどのIaCで設定を管理できなくなります。
v0.50.31 以降ではこのバグが修正されたようですが、api-serverで任意のendpointを呼び出すと {"type":"about:blank","status":500}
のエラーが発生します*2。
原因として.env
ファイル(docker-composeによるインストールの場合)には INTERNAL_API_URL
という新しい環境変数が追加されていますが*3、Helm Chartは最新の環境変数に追いつかず、ConfigMapにこの環境変数がまだ追加されていません*4(2023年12月11日時点)。
また、2023年10月上記のバグを修正するためのPRが出されていますが、まだマージの見込みがありません。
まとめると
- Airbyteのバージョンをv0.50.31以上に更新するとapi-serverが正常に動作しなくなる
- 更新しないと
Read Timeout
エラーが頻発する
というデッドロック状態になってしまいました。
解決法
上記の問題に対処するために、helm template
を使用してマニフェストを出力し、それをKustomizeを使ってAirbyteをインストールする方法を採用しました。
マニフェストを出力する
特定のchartとバージョンを指定して、以下のhelm template
を実行し、マニフェストをairbyte.yaml
に出力します。
AIRBYTE_CHART_VERSION=0.50.2 echo "## DON'T EDIT THIS FILE. This is an auto-generated file from the airbyte helm chart." > airbyte.yaml helm template --release-name airbyte --namespace airbyte --version $AIRBYTE_CHART_VERSION airbyte/airbyte >> airbyte.yaml
これにより、Airbyteのインストールに必要なKubernetesのマニフェストがairbyte.yaml
に保存されます。
Helm hookを書き換える
生成されたマニフェストはHelmのhookによって依存関係が管理されているため、Kustomizeを使用してインストールする場合、適切に動作しなくなります。
また、ドキュメントを読むと
Argo CD supports many (most?) Helm hooks by mapping the Helm annotations onto Argo CD’s own hook annotations
つまり、Argo CDがHelm annotationsをArgo CD annotationsにマッピングしてくれるようです。しかし検証した結果、Argo CDのApplicationによってHelmインストールをする場合のみ、マッピングが行われることがわかりました(Argo CD v2.8.0
)。どうやらKustomizeは守備範囲外のようです。
この問題を解決するために、インストールする前にHelm hookをArgo CDのhookで置き換えます。
# replace helm hook with argo hook sed -i '' 's$helm.sh/hook-weight$argocd.argoproj.io/sync-wave$g' base/airbyte.yaml sed -i '' 's$helm.sh/hook: pre-install,pre-upgrade$argocd.argoproj.io/hook: PreSync$g' base/airbyte.yaml sed -i '' 's$"helm.sh/hook": post-install$argocd.argoproj.io/hook: PostSync$g' base/airbyte.yaml sed -i '' 's$"helm.sh/hook-delete-policy": hook-succeeded$argocd.argoproj.io/hook-delete-policy: HookSucceeded$g' base/airbyte.yaml
kustomize
を使用しても同様の置換が可能ですが、Airbyteのバージョンによってリソースが変わることので、sed
を使用することで運用コストを抑えられるでしょう。
バグ修正用のpatchを適用する
airbyte.yamlと同じディレクトリに、環境変数INTERNAL_API_URL
をConfigMapに追加するpatchと、api-serverの環境変数名を修正するpatchを追加します。
fix-config-map.yaml
- op: add path: /data/INTERNAL_API_URL value: http://airbyte-airbyte-server-svc:8001
fix-development-api-server.yaml
- op: replace path: /spec/template/spec/containers/0/env/0/valueFrom/configMapKeyRef/key value: INTERNAL_API_URL
kustomizationでこれらのpatchを当てます。
namespace: airbyte resources: - airbyte.yaml patches: # fix bugs https://github.com/airbytehq/airbyte/issues/29506#issuecomment-1775527850 - target: kind: Deployment name: airbyte-airbyte-api-server path: fix-development-api-server.yaml - target: kind: ConfigMap name: airbyte-airbyte-env path: fix-config-map.yaml
これにより、修正が加えられたpatchを含むマニフェストが生成されます。なお、割愛していますが、resourcesのlimitsとrequestsの追加や不要なDeploymentの削除などを行うと良いでしょう。
アプリケーションをインストールする
最後はArgo CDのApplicationにインストールされたAirbyteの動作確認です。 インストールが問題なく完了すると、Argo CDのGUIから状態を確認できます。
また、v0.50.31
以上でありながら、api-server
が動作していることも確認できます。
curl https://airbyte-api.yourdomain.com/v1/workspaces # response # {"data":[{"workspaceId":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx","name":"Default Workspace","dataResidency":"auto"}]}
まとめ
Airbyte公式はConnectorの開発を優先させており、Helm Chartを含めたOSS版インストールの提供が十分ではありません。 これはビジネスモデルの制約からくるもの理解しています。
バグに対処するために、helm template
を使用して出力したマニフェストを自前で管理する方法を採用しました。これにより、機会損失を最小限に抑えつつ、今後のバグ修正などにも迅速に対応できるようになりました。
ただし、自前でマニフェストを管理しているのでバージョン更新時の手間は避けられません。Helmのvalues.yaml
やparameters
のように、リソースのyaml構造を意識せずに設定を変更することができなくなる点にも留意すべきでしょう。
おわりに
Helmを使用せずにKustomizeでAirbyteをKubernetes上に構築する手法について紹介しました。ご参考になれば幸いです。 今後も「Circuit」に関連する情報を積極的にシェアしていきますので、お楽しみにしていてください。
研究開発部ではMLOps/DevOpsエンジニアを募集しています。
*1: Timeout error has occurred when creating connection by terraform via local AirByte API Server
*2:https://github.com/airbytehq/airbyte/issues/29506#issuecomment-1775527850
*3:https://github.com/airbytehq/airbyte-platform/blob/d7161f7800e4e1b3fd3b9967a79b83096621fec0/.env#L61
*4:https://github.com/airbytehq/airbyte-platform/blob/d7161f7800e4e1b3fd3b9967a79b83096621fec0/charts/airbyte/templates/env-configmap.yaml#L27