---
# System prepended metadata

title: prefect overview
tags: [MIS, SDK]

---

# 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

