LiteLLM Terraform Provider 的 litellm_budgets 数据源:以基础设施即代码方式读取代理中的全部预算
【免费下载链接】litellmThe fastest, litest AI Gateway. Rust core with Python SDK. Call 100+ LLM APIs in OpenAI (or native) format with cost tracking, guardrails, load balancing, and logging [Bedrock, Azure, OpenAI, Anthropic, OpenAI, VertexAI, vLLM, Nvidia NIM]项目地址: https://gitcode.com/GitHub_Trending/li/litellm
本篇技术指南聚焦 LiteLLM Terraform Provider 中的litellm_budgets数据源(对应文档 budgets.md),讲清它如何在 Terraform 中一次性拉取 LiteLLM Proxy 上配置的全部预算(budget),返回budgets列表与ids两个核心属性。读完本文,你可以直接在 HCL 中枚举、审计和消费 Proxy 上的预算配置,并理解该数据源从 Terraform 到 Proxy REST API 的完整实现链路。
什么是 litellm_budgets 数据源
LiteLLM 支持在代理(proxy)层面创建"预算"对象,将其应用到 team、组织、用户或 API key 上,统一约束美元额度、TPM/RPM 速率与并发请求数。当预算已经由其他流程(控制台、litellm_budget资源或其他 IaC 栈)创建后,litellm_budgets数据源提供了一种只读的读取方式:
Retrieves all budgets configured on the LiteLLM proxy.
它与litellm_budget单数数据源(按budget_id查询单个预算,见 budget.md)配对使用,两者共同覆盖"查单个"与"列全部"两类只读场景。
前置条件:配置 Provider
数据源依赖 Provider 完成鉴权。Provider 的根 Schema 定义在 provider.go,包含三个参数,均支持同名环境变量作为默认值:
| 参数 | 类型 | 必填 | 环境变量 | 说明 |
|---|---|---|---|---|
api_base | string | 是 | LITELLM_API_BASE | LiteLLM API 的基础 URL |
api_key | string | 是 | LITELLM_API_KEY | 用于鉴权的 API key(标记为 Sensitive) |
insecure_skip_verify | bool | 否 | LITELLM_INSECURE_SKIP_VERIFY | 跳过 TLS 证书校验,仅建议开发环境或自签证书使用 |
一个最小可用的 Provider 声明:
terraform { required_providers { litellm = { source = "BerriAI/litellm" version = "~> 1.99.0" # 与你 proxy 运行的 LiteLLm 版本保持一致 } } } provider "litellm" { api_base = var.litellm_api_base api_key = var.litellm_api_key }注意 terraform/provider/README.md 强调的版本策略:Provider 版本与 LiteLLM 版本一一对应,每次 proxy 发布会同步发布同版本的 Provider,因此required_providers中的版本约束应与 proxy 实际运行的版本行对齐。
使用示例与属性参考
完整用法
继承自 budgets.md 的官方示例:
data "litellm_budgets" "all" {} output "budget_ids" { value = data.litellm_budgets.all.ids }该数据源不接收任何参数("This data source takes no arguments"),terraform plan阶段即会调用代理接口读取全量预算并填充输出。
Attribute Reference
| 属性 | 类型 | 说明 |
|---|---|---|
budgets | list of object | 代理上配置的全部预算列表,每个条目包含下表字段 |
ids | list of string | 全部预算的 ID 列表(等价于budgets[*].budget_id的扁平化) |
budgets列表中每个条目的字段:
| 字段 | Terraform 类型 | 说明 |
|---|---|---|
budget_id | string | 预算 ID |
max_budget | float | 硬预算上限(USD),超出后请求会失败 |
soft_budget | float | 软预算上限(USD),超出仅触发告警,不拦截请求 |
max_parallel_requests | int | 该预算允许的最大并发请求数 |
tpm_limit | int | 该预算的每分钟 token 上限 |
rpm_limit | int | 该预算的每分钟请求数上限 |
budget_duration | string | 预算重置周期,如1hr、1d、28d |
model_max_budget | string | 按模型的预算配置,JSON 字符串格式,例如{"gpt-4o": {"max_budget": 10.0}} |
budget_reset_at | string | 预算重置的时间(datetime) |
以上类型并非文档惯例,而是与源码 Schema 逐一对应——data_source_budget.go 中budgets为TypeList(元素是嵌套 Resource),ids为元素TypeString的TypeList,max_budget/soft_budget为TypeFloat,max_parallel_requests/tpm_limit/rpm_limit为TypeInt。
实战:按预算迭代消费
由于返回的是结构化列表,可以直接驱动for_each做审计或二次编排,例如把预算 ID 导出给合规报表,或为某个预算下的 key 做交叉校验:
data "litellm_budgets" "all" {} # 仅输出设置了硬预算上限的条目 output "budgets_with_hard_limit" { value = [ for b in data.litellm_budgets.all.budgets : b if b.max_budget > 0 ] } # 用预算 ID 作为 for_each 键,逐个拉取单预算详情 data "litellm_budget" "each" { for_each = toset(data.litellm_budgets.all.ids) budget_id = each.value }源码实现解析:从 HCL 到 /budget/list
读取流程
litellm_budgets数据源的实现位于 data_source_budget.go 的dataSourceLiteLLMBudgetsRead,核心链路为:
- 通过
MakeRequest(client, "GET", endpointBudgetList, nil)发起GET /budget/list请求(端点常量endpointBudgetList = "/budget/list"定义在 data_source_budget.go); - 用
handleResponse校验响应状态; - 将响应体反序列化为
[]budgetResponse切片——该结构体定义在 resource_budget.go,除BudgetID外所有字段均为指针类型(*float64、*int、*string),用于区分"未设置"与"零值"; - 遍历切片,通过
budgetListEntry组装每个预算 map,同时收集ids; - 执行
d.SetId("budgets")并d.Set("budgets", ...)、d.Set("ids", ...)写入 state。
字段映射与可空语义
budgetListEntry(data_source_budget.go)对每个可选字段都做了判空:只有当对应指针非 nil 时才写入条目。这意味着代理上未设置的限额不会出现在返回的条目中,HCL 侧消费时应使用coalescelist/条件判断等防御式写法,而不是假设九个字段必然齐全。
model_max_budget 的 JSON 归一化
model_max_budget是数据源中最容易踩坑的字段:Proxy 接口返回时它可能是嵌套对象(dict)而非字符串,而 Terraform Schema 要求 string。源码通过budgetModelMaxBudgetString(data_source_budget.go)做了归一化——若已是 string 直接透传,若是 map 则json.Marshal成字符串(空 map 视为未设置)。因此你在 HCL 中拿到的始终是合法 JSON 字符串,如需在 Terraform 内解析,应配合jsondecode(data.litellm_budgets.all.budgets[0].model_max_budget)使用。
测试用例对行为的印证
单元测试 data_source_budget_test.go 中的TestDataSourceBudgetsRead_MapsList用一个httptest假服务器覆盖了上述关键行为,可作为行为契约:
- 断言请求必须是
GET /budget/list(与单数数据源的POST /budget/info形成对比); - 返回两个预算(
bud-1带max_budget/tpm_limit/model_max_budget对象,bud-2仅带soft_budget),验证budgets列表长度、各字段映射,以及model_max_budget被转为可json.Unmarshal的字符串且包含gpt-4o键; - 验证
ids精确为[bud-1 bud-2]。
后端 API:/budget/list 的服务端约束
数据源调用的后端接口定义在 budget_management_endpoints.py 的list_budget,有三个直接决定可用性的前提:
- 必须连接数据库:
prisma_client is None时接口返回 400(db not connected error)。也就是说纯配置 YAML 启动、未接入数据库的 proxy 无法提供该列表; - 需要 admin 视角:接口经过
user_api_key_auth依赖鉴权后,还会调用_user_has_admin_view(user_api_key_dict)校验角色,非 admin/proxy admin 角色会得到 400 权限错误。因此provider "litellm"使用的api_key应是一个具备管理员角色的 master key; - 数据源实现:服务端通过
BudgetRepository(prisma_client).table.find_many()全量拉取预算表记录后原样返回。
同一文件头部注释列出了完整的预算管理端点集合(/budget/new、/budget/info、/budget/update、/budget/delete、/budget/settings、/budget/list),其中读写端点分别对应 Provider 中的litellm_budget资源(resource_budget.go 定义了对应的四个端点常量)与两个数据源。
单数与复数数据源的差异对比
| 维度 | litellm_budget(单数) | litellm_budgets(复数,本篇) |
|---|---|---|
| 参数 | budget_id(必填) | 无 |
| 后端请求 | POST /budget/info,body 为{"budgets": ["<id>"]} | GET /budget/list |
| 未命中行为 | 返回budget '<id>' not found错误 | 空列表(budgets/ids为空) |
| 典型用途 | 依赖已知预算 ID 的精确引用 | 枚举、审计、for_each驱动 |
两个实现细节值得注意:单数数据源在 404 或空响应时直接报错(data_source_budget.go),而资源侧的resourceLiteLLMBudgetRead遇到预算消失时会执行d.SetId("")将其移出 state,二者在漂移处理策略上并不相同。
小结
litellm_budgets数据源用零参数设计换来了最简的枚举体验:一条data "litellm_budgets" "all" {}声明即可在 state 中获得全量预算对象与 ID 列表。从源码看,其字段判空映射、model_max_budget的 JSON 归一化均有单元测试固化;使用时需牢记三件事——proxy 必须接入数据库、调用 key 必须具有 admin 视角、Provider 版本应与 proxy 版本保持一致。对于预算的创建与变更,则应使用 resource_budget 相关文档 同系列的litellm_budget资源,配合本篇的数据源完成"写-读-校验"的完整 IaC 闭环。
【免费下载链接】litellmThe fastest, litest AI Gateway. Rust core with Python SDK. Call 100+ LLM APIs in OpenAI (or native) format with cost tracking, guardrails, load balancing, and logging [Bedrock, Azure, OpenAI, Anthropic, OpenAI, VertexAI, vLLM, Nvidia NIM]项目地址: https://gitcode.com/GitHub_Trending/li/litellm
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考