🤖

Prefectでトラブルシューティングした話

2024/10/25に公開

はじめに

こんにちは、D2Cエンジニアの原尻です。
D2Cには社内のデータサイエンティストのためのデータ分析基盤があります。
その分析基盤でワークフローの管理ツールの一つとして、Prefectを提供しています。
トラブルシューティングの経験が少なく今回の経験を通じて学びが多かったため、
Prefectでjobのエラーが出た際にしたトラブルシューティングの様子をまとめます。

前提

Prefect: 2.14.12
環境: Kubernetes on EKS
HelmChart(2023.12.20): https://github.com/PrefectHQ/prefect-helm
実行しているnamespace名: prefect
デプロイ方法: ArgoCD

エラー内容

Prefect内のいくつかのjobで以下のエラーが発生しました。

HTTP response body: {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"namespaces \"kube-system\" is forbidden: User \"system:serviceaccount:prefect:prefect-worker\" cannot get resource \"namespaces\" in API group \"\" in the namespace \"kube-system\"","reason":"Forbidden","details":{"name":"kube-system","kind":"namespaces"},"code":403}

このエラーはprefect-workerというkubernetesのサービスアカウントがkube-systemというnamespaceへのアクセスができないという内容です。

ValuesにclusterUidの設定が無い場合、helmfile templateを実行した時点でkube-systemのメタデータを見にいくように設定されています。
https://github.com/PrefectHQ/prefect-helm/blob/2023.12.20/charts/prefect-worker/templates/_helpers.tpl
ここでアクセスできなかった場合には空の値として設定されてしまいます。
今回はArgoCDでリリースしておりArgoCDが何らかの原因でメタデータにアクセスできなくなったため、空の値が設定されるようになってしまったものだと思われます。

関連する問題は、PrefectのHelm Chartに関するissuesにも記載されています。
https://github.com/PrefectHQ/prefect/issues/9851

解決方法

configの設定ファイルにてworker.clusterUidを追加し、エラーを解決しました。

その後起こったエラー

解決後、prefectで別のエラーが出ました。

Process for flow run 'test-flow' exited with status code: 1

Prefectのpodのログを見ると以下のような記述がありました。

 Attempting uninstall: prefect
    Found existing installation: prefect 2.14.12
    Uninstalling prefect-2.14.12:
      Successfully uninstalled prefect-2.14.12
Successfully installed (中略) prefect-3.0.2 prefect_aws-0.5.0 (中略)
08:06:19.111 | INFO    | prefect.flow_runs.runner - Opening process...
08:06:25.654 | ERROR   | prefect.engine - Engine execution of flow run 'xxxxx' exited with unexpected exception
(以下略)

prefect-2.14.12がアンインストールされ、prefect-3.0.2がインストールされてしまっています。

解決方法

WebUIでprefectのバージョンを明示的に指定することで、解消できました。

トラブルシューティングの中で学んだこと

ここからは、トラブルシューティングに慣れていない私が解決までに右往左往していた様子を書こうと思います。

1:安易にClusterRoleを作成しようとしていた

最初は現在のnamespaceではないnamespaceへのアクセスできるようにすることが問題解決になると考えていました。
KubernetesのRBAC認可にはRoleとClusterRole, RoleBindingとClusterRoleBindingが存在します。
現在はRole(とRoleBinding)を用いていますが、ClusterRole(とClusterRoleBinding)を用いることによってprefect名前空間からkube-system名前空間へのアクセスが可能になると考えました。

RoleとClusterRoleはいずれかである必要があります。
しかし、Prefectのhelmfile(23.12.20)ではRoleの作成をしない設定ができない状態になっています。
そのためclusterRoleのマニフェストを作成することはできません。
この問題を解決するには、別のアプローチが必要でした。

2:その場しのぎのためにバージョンアップを行おうとしてしまった

それならばと、Roleの作成の可否を設定できる最新のhelmfile(2024.9.13174400)を用いることを考えました。
https://github.com/PrefectHQ/prefect-helm/blob/2024.9.13174400/charts/prefect-worker/templates/role.yaml

{{- if .Values.role.create }}

しかし、DBのマイグレーションにより、一度バージョンを上げると元に戻すことができないというリスクがあり、トラブルシューティングのために一時的にバージョンアップをすることはできません。
また、バージョンアップには他にも多くの要素を考慮する必要があるため、問題の解決のために安易にバージョンアップを行うべきではありませんでした。

おわりに

今回のトラブルシューティングでは、既存の知識に頼ってすぐにClusterRoleの作成やバージョンアップを試みるのではなく、実際に発生しているエラーに焦点を当てて適切に対応することの重要性を学びました。最終的には有識者の方にアドバイスをいただきながら解決に辿り着くことができましたが、一人でトラブルシューティングの検証を行う時も慎重に行い、その場しのぎの解決策に飛びつかないように心がけるべきだと感じました。

トラブルシューティングは多くの学びを得られる貴重な機会でした。今後も様々な経験を積み、素早く効果的に対応できる勘所を掴めるように精進していきたいと思います。

D2C m-tech

Discussion