Sansan Tech Blog

Sansanのものづくりを支えるメンバーの技術やデザイン、プロダクトマネジメントの情報を発信

Helmを使用せずにKustomizeでAirbyteをKubernetes上に構築する

こんにちは、技術本部研究開発部ML Platformチームのジャン(a.k.a jc)です。 本記事は Sansan Advent Calendar 2023 の19日目、および【R&D DevOps通信】の連載記事のひとつです。

adventar.org

今年6月にData DirectionチームからML Platformチームに異動し、全社横断データ基盤の開発から離れて、研究開発部内のアプリケーション基盤「Circuit」の開発に従事しています。 研究開発部の2大基盤に関する知見を有していることを誇りに思っています。

全社横断データ基盤

全社横断データ基盤とは、2022年に研究開発部で導入した全社のデータ意思決定を支えるデータ基盤です。

speakerdeck.com

研究開発部のアプリケーション基盤「Circuit」

Circuitとは、同じく2022年に研究開発部で導入したアプリケーション基盤です。 AWS EKSを用いたKubernetesで動いています。

speakerdeck.com

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.yamlparametersのように、リソースのyaml構造を意識せずに設定を変更することができなくなる点にも留意すべきでしょう。

おわりに

Helmを使用せずにKustomizeでAirbyteをKubernetes上に構築する手法について紹介しました。ご参考になれば幸いです。 今後も「Circuit」に関連する情報を積極的にシェアしていきますので、お楽しみにしていてください。

研究開発部ではMLOps/DevOpsエンジニアを募集しています。

open.talentio.com

© Sansan, Inc.