はじめに
こんにちは。データ戦略室データエンジニアリンググループでリーダーをしている森下です。
データエンジニアリンググループでは、全社のデータ活用をエンジニアリングの側面から加速させることをミッションとし、誰でも簡単にデータ分析を行える環境の整備及びその活用を推進しています。
今回は、先日発生したEmbulkのプラグインを起因とする障害およびその復旧作業についてお話しします。
レバレジーズのデータ活用基盤について
BigQuery を中心としたデータ活用基盤の導入及び保守運用を行っています。レバレジーズはインハウスの組織として、提供しているサービスや社内の営業支援システムを自社で開発しています。それらのDBからデータを取得して BigQuery へアップロードする処理を、Digdag と Embulk を活用して実装しています。Digdag がワークフロー全体のスケジュールとタスクを管理し、Embulk がデータ更新のバッチ処理を行う構成です。Embulk の実行は、Digdag の Docker オプションを使用して Docker コンテナ上で実行させています。また、Digdag も Docker コンテナ上で実行させています。
データ更新は1日1回を基本とし、業務開始時刻までに前日のデータが全て更新されるようにワークフローを組んでいます。データ活用基盤のユーザーは社内に限られますが、セールス・マーケター・エンジニア・経営層まで、社内のあらゆる職種が使用するデータ活用環境です。
障害発生〜対応完了までの時系列
朝起きてスマホを見ると、データ活用基盤の ETL 処理が全てコケていると Slack 通知が入っていました。Slack への通知では、「〜〜DBのETL処理が失敗しました」という内容のみを投稿しており、具体的に何が原因で失敗しているのかはわからないので、出社して Digdag のログを直接確認しないといけません。朝から憂鬱です。
出社後、Digdag のログを確認してみると、”output plugin bigquery not found” というエラーで ETL 処理が失敗していることが分かりました。 とりあえずエラーメッセージで Google 検索してみても、これといった対処方法は見当たりません。いくつか思いついた方法を試しても一向にエラー内容が変わらないので、ローカルに調査用の Dockerfile を作成してそちらで検証することにします。
そうすると以下のエラーに変わります。
🤔 (Ruby 2.4.0?? Embulk は Java で動いているはずでは・・・??)
エラーがより具体的になり調査が少し先に進んだものの、どうやって対応したら良いかわかりません。そこで、障害発生時の頼もしい味方である Twitter で検索してみると似たような事象に対するツイートを発見しました。それによると、依存関係が発生しない前のバージョンをあらかじめインストールすることで今回のエラーは回避可能とのことです。そこで representable 3.0.4 を先にインストールしてから embulk-output-bigquery をインストールすると無事にインストールできました。ありがとう Twitter、さすがだよTwitter。 embulk-output-bigquery がインストールでき、データの更新もうまくいっています。詳細な原因調査は後々行うことにして、まずはデータ更新作業を優先させます。
午前中に原因を特定しデータ更新処理を開始しましたが、BigQuery へ ETL 処理しているテーブルは1,000近くあるため、全テーブルの更新処理完了は夕方までかかりました。
原因と対応
Ruby gem のバージョン違いによるコンフリクトが発生していたことが原因でした。embulk-output-bigquery について詳細に調べてみると、このようにいくつかの RUNTIME 依存性があることがわかります。
https://rubygems.org/gems/embulk-output-bigquery/versions/0.4.11?locale=ja
ここで、google-api-client -> google-apis-core -> representable と確認していくと、representable は2021年4月に入ってからバージョンが上がり、2.4.0以上が必要 Ruby バージョンになっていることが確認できます。embulk-output-bigquery をインストールする際には、必要な gem の最新版をインストールしようとしますが、他の gem と必要 Ruby バージョンが異なるため、結果的に embulk-output-bigquery のインストール失敗につながっていました。embulk-output-bigquery のインストールに失敗しても、Docker コンテナのビルド自体は成功してしまうので、Digdag は通常通り ETL 処理を開始します。そして、BigQuery へロードする段階でembulk-output-bigquery がないというエラーが発生したようです。今回のような場合には、embulk-output-bigquery をインストールする前に、コンフリクトが発生しないバージョンの gem を予めインストールしておくことで対処可能です。
なぜ representable のアップデートが入った直後に障害が発生しなかったのか
Digdag のタスクで Docker オプションを指定する場合、初回ビルド時以外はキャッシュを使用してコンテナを作ります。キャッシュを使用して ETL 処理をしている間は新規に embulk-output-bigquery をインストールしません。そのため、キャッシュがなくなるタイミング(Digdag コンテナのビルド時)までは障害が発生しませんでした。
今後について
Ruby の gem が原因となる障害は、データ活用基盤の構築を開始してから約1年半の間で初めて発生しました。今回の原因による障害の発生は、頻度自体は高くないはずなので、構成変更の工数とリスクを鑑みて、ETL 処理の構成は変更しない予定です。ただ、今回のような障害が頻発するようであれば、Digdag と Embulk を同じ環境に入れることを検討しないといけません。現状は Java8 上で両方とも動きますが、Digdag と Embulk はそれぞれ随時アップデートされていくので、Java のバージョン違いが発生する可能性があります。そうなると環境構築がやや面倒なことになりそうです。
おわりに
今回は Embulk のプラグインを起因とするデータ更新失敗についてお話ししました。ここまで大規模な障害発生は初めてと言うこともあり、調査や対応で手間取った部分がありましたが、なんとか障害発生したその日に収束させることができてよかったです。今回のこの記事が、Digdag や Embulk を使って構築している(もしくはしようとしている)データエンジニアやインフラエンジニアの方にとってためになる記事になれば幸いです。