# prefect overview 基本和`puppemon` 想做的事有關,但複雜很多,機制也不同。 * `prefect` 一樣有 ETL assets 的 idea,只是不像 `dagster` 更強制。 official document 分成 * concept * 使用前 * how-to * 基本使用 * advanced * 完整設定 basic command * `uv tool install prefect[docker]` * `uv run python xxx.py` 單次的 run on server. (no deploy, worker...) ## working * flow 需要 worker 執行 * worker 需要在 work pool 裡 * --> flow 需要指定 work pool。 * `prefect worker start --pool "my-process-pool" --type process` 建立 worker 和 work pool * 這的 worker 的 process 是 blocking 的。 * worker 和 prefect 的 UI server 無關, prefect 只負責公告 work 存在,實際的執行依賴 worker 自己去 poll then execute。說是 work broker 都可以。 * "distributed execution" * I actually think this is unnecessary, and will casue problem especially for file storage. 可能變成只能用 cloud DB。 * mount docker volume to NAS * block e.g. AWS S3, that's why prefect need AWS block。 * `prefect worker` 可以在 `docker-compose.yml` 找隨便容器 called 就好。 * [prefect Workers](https://docs.prefect.io/v3/concepts/workers) * [How to daemonize worker processes](https://docs.prefect.io/v3/advanced/daemonize-processes) * `prefect worker start --pool docker-pool --type docker --install-policy always` worker in docker 天生就有sandbox 的能力。 * 綜合來說,只要有**持久化**的需求難度就會上升不少。 ## deploy * `prefect.yaml` 是重點,[How to define deployments with YAML](https://docs.prefect.io/v3/how-to-guides/deployments/prefect-yaml#how-to-define-deployments-with-yaml) * > Deploying a prefect.yaml without a worker pool in a self-hosted Prefect environment is not possible for standard execution. * 如果serve only 1 flow, 願意直接執行 python 用 flow.serve 是可以沒有 worker。 * [Static infrastructure](https://docs.prefect.io/v3/concepts/deployments#static-infrastructure) * 以下主要 以 dynamic infrastructure 為主,也就是需要 work pool。 * build, push, pull, deployment 裡,`pull`, `deployment` 是必要的。 * `pull` defines how Prefect pulls your deployment in remote execution environments. * `deployements` block define 每一個 deployment * `prefect deploy --all` 就啟動全部 deployment。 * `work_pool/job_variables` 是所執行的 work pool 的設定 * image 表示 `Execute flow runs within Docker containers` * `push` * 能不能在這個階段把 code 上傳到 prefect server? * `deployed flow` 需要 worker + work flow 才會變成 ready 的狀態。 * `deployed flow` run 以後,才會有 `flow run`(work) 真的執行。甚至是 completed. * 點擊 quick run 等效 `prefect deployment run 'main/01-getting-started'` * 注意 deploy 只有保證把 deploy 的事件傳到 prefect server, e.g. 時間、work pool、名字等上傳。不含 腳本 (code) * 正確設定了話,可以把腳本送到遠端 prefect server 能夠access 的 store e.g. S3 or git。 * 之後腳本會再被 worker 從這些 store,fetch 並執行。worker 所 fetch 的server 取決於 `PREFECT_API_URL` 。 * `prefect init` will show more detail * 見下 code persistence ### code persistence code 可存在 S3, git repo. * [Create the deployment](https://docs.prefect.io/v3/how-to-guides/deployment_infra/docker#create-the-deployment) * `Automatically bake your code into a Docker image` 是把 code 放在image ,整個推到 dockerhub * `Automatically build a custom Docker image with a local Dockerfile` 多做一點客制化 * docker based 的 deploy 算是最難保證環境穩定。 * git 是最推薦的方式。 * 也有版本管理。 * 存在 S3 的方法沒怎麼講,理論上在`prefect.yaml` 的 `pull` 設定存code 的位置是可以做到的。 * 好處是在離線環境也能用,且 container 元件數量最少。 #### github 有個很不好的弱點,正在改的code 還沒push。所以 worker pull 的不是正在修改的版本。 當然可以開獨立的 branch,改完再merge。但現在要求的 git branch 目的更像是file storage,而非 source code,就像 `gh-pages`。 --> orphan branch * [Access flow code stored in a private GitHub repository in a deployment](https://docs-3.prefect.io/integrations/prefect-github#access-flow-code-stored-in-a-private-github-repository-in-a-deployment) * [The pull action](https://docs.prefect.io/v3/how-to-guides/deployments/prefect-yaml#the-pull-action) ### action local 開發完成後,可以單靠 github action 就完成 code push。而不需要手動下command deploy to prefect。 * [actions-prefect-deploy](https://github.com/PrefectHQ/actions-prefect-deploy) * `examples/docker` 是 build 含 prefect cli 的 docker image 並執行 deploy 動作 到 某一 prefect server。 * `examples/simple`, `examples/multi-deployment` 都是 pull from github source then deploy in docker image ## persistent prefect 的執行,是以 flow based programming 為中心思想。所以它更傾向user 以無狀態,單純靠 parameter pass in 的 方式去寫。 然後 最終結果 及 中間資料則透過 assets 去記錄。declare as assets 則會 自動儲存,不需要明確儲存,且儲存 介質,路徑... 的設定也是由 prefect global 設定。 prefect 內的 logger 也是如此。 其它如果真的需要獨立存檔,建議都直接存進 S3 bucket。 configuration 則if and only if 用 block,可以處理 distributed execution 和 secret 的問題。 [How to persist workflow results](https://docs.prefect.io/v3/advanced/results) ### [Assets](https://docs.prefect.io/v3/concepts/assets) #### artifacts ### prefect variable variable 是明碼顯示的,一般是希望多個 workflow 有共同設定時使用。 * [How to share configuration between workflows](https://docs.prefect.io/v3/how-to-guides/configuration/variables) * [Variables](https://docs.prefect.io/v3/concepts/variables) ### [prefect block](https://docs.prefect.io/v3/concepts/blocks) * > Prefect blocks store typed **configuration** that can be used across workflows and deployments. The most common use case for blocks is storing credentials used to access external systems such as AWS or GCP. * block 的用途是**設定**,不要拿來做其它用途。 * 基本是為了 fix "distributed execution",處理**持久化** 的問題時,避免 file system token 之類 secret 寫在 code 裡,且讓secret 能在 worker間共用。 * file system 本身的 resource url 在 worker 間必須具有唯一共通的意思。 * 有 database, Remote File System, [Local File System](https://reference.prefect.io/prefect/filesystems/) ... 界面。 * LocalFileSystem 還是 save on work computer, 基本 only for 暫存檔 `/tmp/` * RFS 是用 fsspec。沒有 nfs。 * aws s3 --> MinIO * [boto3-AWS-S3 SDK for Python保姆级入门](https://zhuanlan.zhihu.com/p/539375418) * aws s3 其實也是像 disk mount,並非魔法。 * 如果 db, MinIO... 之類 service 的 url,在 worker 和 prefect server 間不同,會導致failed。 * 這對 self host 的服務有些問題,LAN 內外可能不同。 * 算是 aws s3 的很難取代的好處。 * 如果 worker & prefect 對 NAS 有不同 mount point,一樣會failed. * prefect server 應該要有 proxy file system 的能力。才能輕易解決這個問題。要求全體 worker 設定正確很不現實。大部分的 user 只先要簡單的 file system 功能而已。 * 也有對接 3rd service e.g. discord webhook * [Variables](https://docs.prefect.io/v3/concepts/variables) * 用來 init global distributed variable, e.g. json * [ Serverless is a Scam. ](https://dev.to/code42cate/serverless-is-a-scam-5fc0) * 想要用 `S3Bucket` * `AwsCredentials` block 可以取 credential,然後再將其設定入 `S3Bucket` 。 * minIO credentials 一樣用 aws credentials 設定,minIO credentials 是 * prefect 也有提供 S3 bucket block,內含 bucket name 的設定。直接 load 就能產生 s3 bucket 供讀寫。 * `prefect` block 的 error message 蠻差的(2025),基本完全看不出來到底是什麼error。 #### secret Secret 是特別重要的 block,因為要求 prefect support 所有廠商的 token type 不可能,沒必要。甚至是負優化,因為有一堆 class。 json ```python @dataclass class DiscordChatExport: """ decode from JSON secret block """ channel_id: int # DISCORD_CHANNEL_ID token: str # DISCORD_TOKEN secret_block = Secret.load("discord-chat-export") secret_value = secret_block.get() discord_chat_export = DiscordChatExport(**secret_value) ``` #### custom * [< Marvin> Can create a Secret storage block in JSON ...](https://linen.prefect.io/t/18883816/ulva73b9p-can-create-a-secret-storage-block-in-json-format-i) 理論上可以custom block,但要事先執行註冊。所以我暫時更傾向簡單的 secret + json 如果有 python 的 regist 加入 .env ,透過 env var 去設定 custom block 了話,可能能夠更簡化。 ## flow with 3rd lib * [ Day14 - LLMOps Pipeline 自動化實戰:用 Prefect 與 Dagster,拯救你的睡眠時間 ](https://ithelp.ithome.com.tw/articles/10389635) * 這篇的其實還是有很多點沒實作。沒有考慮 host on VPS的情況。 * vector db 應該 outside flow define,因為docker 內部存不了東西。 * 這也對worker 很尷尬,如果workder 不在localhost,且用 embeded db,就會存錯地方。 * that's why need AWS S3 * 這也顯示 純 docker host service 沒啥用 (render.com),正常都至少都要 docker compose 起跳。 * 其實file watch 還是額外一個 process 達成的,這對 deploy 造成一定的影響。 * 但另一個角度就是 可以把 local 的file change trigger 到遠端的 prefect server。更有彈性。 * ## excercise ## what Prefect lack 應用範圍 * 我們把 self host 的 prefect 視為單人 * 單人多個 app * 或是 一個 project 使用 * 單一 project 希望有統一的界面去 trace 所有相關的工作,尤其是在純內網環境下。 * 不是一個團隊/企業。--> 這當然會需要多租戶。 * 一個 project 多個 app,如果 token, secret 統一是個別 project ,權限均質那沒問題。 * 但實際上,不同團隊做一個 project 很有可能想要控管 source code 的權限,且token 的來源不同。 * 姑且可以假設 flow source code 都是 script,都可以 open。但 token 總是要分開結算的,除非業主開共用 token。 * global 的 secret block 完全就會洩漏 token,缺乏 flow specific secret block。 code push * worker 需要分佈式 parallel workload 可以理解。 * 但 存 code 也分佈式就很怪了。因為存code 沒有 workload 問題。 * 但不存code 就需要額外的 service 。這無疑增加麻煩。 * 再加上 上面的 global block 設計,額外 service 能夠提昇的效果 也被直接抹平。 直接限制 * [Webhooks](https://docs.prefect.io/v3/concepts/webhooks) * 只有 prefect cloud 才能用? 這刀太狠。 * [Beyond Scheduling: Event-Driven Flows with Prefect](https://medium.com/the-prefect-blog/beyond-scheduling-event-driven-flows-with-prefect-b072edd06833) * [Is there a way for self-hosted (not cloud) to use ...](https://linen.prefect.io/t/26890318/is-there-a-way-for-self-hosted-not-cloud-to-use-webhooks-i-g) * > For self-hosted Prefect, you might need to implement custom solutions to handle webhook-like behavior, such as setting up an external service to listen for events and trigger Prefect flows via the Prefect API. * [Create Events](https://docs.prefect.io/v3/api-ref/rest-api/server/events/create-events) * 其他app 直接 call prefect API send event 是否可行? * 必定是會有割裂的。除非把整個前端重做。 [microservice critical probelm](/9_EKsb8FSxqn1RgQ3xlUBA) [git based automation](/TvCJnACwTFiTMNiiRYlR6Q) ## TODO * store deploy code in local S3