主题
Azure Terraform 架构
在 AKS 上自托管 LangSmith 的平台层、服务、Workload Identity、网络、ingress 选项,以及模块依赖。
了解 Azure Terraform 模块预配什么以及各部分如何组合,以便你在运行 make apply 之前为你的 LangSmith 部署做容量规划、加固和定制。
把本页当作规划一次推行或排查现有推行时的参考。它涵盖:
- 平台层和部署层级(light 与 production)。
- 应用部署路径(Helm 与 Terraform)。
- 网络、Workload Identity 和密钥流。
- 附加组件:LangSmith Deployment、Agent Builder、Insights 和 Polly。
- ingress 控制器、资源规格和可选模块。
如果你已准备好安装,从部署演练开始。
平台层
LangSmith 在 Azure 上分阶段部署。每个阶段在前一层之上增加一个能力层。所有层共享同一个 AKS 集群和 langsmith 命名空间。

| 阶段 | 层 | 它增加什么 |
|---|---|---|
| 基础设施 | Azure 基础设施 | VNet、AKS、Postgres、Redis、Blob、Key Vault、cert-manager、KEDA、ingress 控制器 |
| 应用 | LangSmith 基础 | frontend、backend、platform-backend、queue、ingest-queue、ace-backend、clickhouse、playground |
| LangSmith Deployment 附加组件 | LangSmith Deployment | host-backend、listener、operator + 每个部署的 pod |
| Agent Builder 附加组件 | Agent Builder | agent-builder-tool-server、agent-builder-trigger-server + deep-agent LGP |
| Insights + Polly 附加组件 | Insights + Polly | Clio 分析(ClickHouse 支撑)、Polly 评估 agent(operator 管理,动态) |
应用部署路径
| 路径 | 方式 | 何时使用 |
|---|---|---|
| Helm 路径 | make init-values && make deploy | 默认。Shell 脚本,交互式,动态读取 TF 输出。最适合首次部署和第 2 天起的重新部署。 |
| Terraform 路径 | make init-app && make apply-app | 声明式。Kubernetes Secrets + langsmith-ksa SA + Terraform 状态中的 Helm release。最适合 GitOps 和 CI/CD 流水线。 |
Terraform 路径使用 app/ 模块。make init-app 调用 app/scripts/pull-infra-outputs.sh 读取所有 infra 输出并写入 app/infra.auto.tfvars.json。
部署层级
Light 部署(全部在集群内)
txt
AKS Cluster
├── langsmith namespace
│ ├── frontend, backend, platform-backend, playground, queue, ace-backend
│ ├── clickhouse (in-cluster pod)
│ ├── postgres (in-cluster pod)
│ └── redis (in-cluster pod)
├── ingress-nginx (Azure Load Balancer → NGINX)
└── cert-manager (Let's Encrypt TLS)
Azure
├── Azure Blob Storage (trace payloads, always external)
└── Azure Key Vault (secrets)在 terraform.tfvars 中设置:
hcl
postgres_source = "in-cluster"
redis_source = "in-cluster"
clickhouse_source = "in-cluster"有关完整的集群内演练(NGINX 配合 Let's Encrypt HTTP-01 TLS、集群内 DB),参见 Azure 模块仓库中的 BUILDING_LIGHT_LANGSMITH.md。
Production(外部托管服务)
txt
AKS Cluster
├── langsmith namespace
│ ├── frontend, backend, platform-backend, playground, queue, ingest-queue, ace-backend
│ └── clickhouse (in-cluster; use LangChain Managed for production scale)
└── ingress-nginx + cert-manager
Azure Managed Services
├── Azure DB for PostgreSQL Flexible Server (private VNet)
├── Azure Managed Redis (private VNet)
├── Azure Blob Storage (Workload Identity, no static keys)
└── Azure Key Vault网络
Light 部署
txt
langsmith-vnet<identifier>
└── subnet-0 (AKS nodes only)
No Postgres/Redis subnets; chart-managed pods handle both生产
txt
langsmith-vnet<identifier>
├── subnet-0 (AKS nodes)
├── subnet-postgres (Azure DB for PostgreSQL Flexible Server)
└── subnet-redis (Azure Managed Redis)所有子网都是私有的。Postgres 和 Redis 没有公共端点;两者只能通过私有 DNS 解析从 VNet 内部访问。
应用核心服务
| 服务 | 目的 | 端口 | HPA | Workload Identity |
|---|---|---|---|---|
langsmith-frontend | React UI | 3000 | 2 到 10 | 否 |
langsmith-backend | 主 API(追踪、运行、项目、API 密钥、反馈) | 1984 | 3 到 10 | 是(Blob) |
langsmith-platform-backend | 组织与用户管理、身份验证、计费、设置 | 1986 | 2 到 10 | 是(Blob) |
langsmith-playground | LLM 提示 playground UI | 3001 | 1 到 5 | 否 |
langsmith-queue | 追踪摄取 worker(Redis → ClickHouse + Blob) | — | 3 到 10 + KEDA | 是 |
langsmith-ingest-queue | 专用高吞吐摄取 worker | — | 3 到 10 + KEDA | 是 |
langsmith-ace-backend | 异步计算(数据集运行、评估、后台作业) | — | 1 到 5 | 否 |
langsmith-clickhouse | 列式存储(追踪 span、运行元数据、评估结果) | — | StatefulSet,单副本,500Gi PVC | 否 |
WARNING
集群内 ClickHouse 仅供开发/POC(单 pod,无复制,无备份)。对于生产,使用 LangChain Managed ClickHouse 或一个自管理的外部集群。
NOTE
SmithDB 是 LangSmith 专为其构建的可观测性后端,自托管版本 0.16.0 起可用于自托管(参见自托管支持)。这些 Terraform 模块预配 ClickHouse,因此前面各节中的指引适用于当前的部署。
一次性作业
| 作业 | 目的 |
|---|---|
langsmith-backend-migrations | PostgreSQL schema 迁移 |
langsmith-backend-ch-migrations | ClickHouse schema 迁移 |
langsmith-backend-auth-bootstrap | 用 langsmith-config-secret 中的 initial_org_admin_password 创建初始组织和 admin 账户 |
LangSmith Deployment 附加组件
| 服务 | 目的 | Workload Identity |
|---|---|---|
langsmith-host-backend | LangGraph 控制平面 API。管理部署生命周期,服务部署元数据。 | 是 |
langsmith-listener | 监视 host-backend 的状态变化,创建并更新 LangGraphPlatform CRD。 | 是 |
langsmith-operator | Kubernetes operator。Azure 专属:注入 azure.workload.identity/use: "true" + langsmith-ksa,让每个 agent pod 通过 Workload Identity 访问 Blob 存储。 | 否 |
Agent Builder 附加组件
| Pod | 类型 | 角色 | Workload Identity |
|---|---|---|---|
langsmith-agent-builder-tool-server | 静态 | MCP 工具执行服务器 | 是 |
langsmith-agent-builder-trigger-server | 静态 | Webhook 接收器和计划触发引擎 | 是 |
langsmith-agent-bootstrap | Job | 注册随附的 Agent Builder agent | — |
agent-builder-<hash> + queue + redis + lg-<hash>-0 | 动态 | Agent Builder 部署,operator 管理 | 继承 |
Insights 与 Polly 附加组件
Insights/Clio: 没有静态 pod。它作为动态 LangGraph 部署,在首次 UI 调用时经 operator 惰性部署。从 langsmith-config-secret 读取 insights_encryption_key。切勿轮换此密钥:它会永久破坏现有的 Insights 数据。
Polly: 作为动态 LangGraph 部署运行,由 operator 管理。从 langsmith-config-secret 读取 polly_encryption_key。与 Insights 相同的轮换警告。
Azure 托管服务
当 postgres_source = "external" 且 redis_source = "external"(推荐的生产设置)时,Terraform 预配:
Azure DB for PostgreSQL Flexible Server
- 存放组织、用户、项目、API 密钥、设置。
- 需要 PostgreSQL ≥ 14。
postgres模块默认将postgres_version设为14。 - 由
postgres模块自动启用的扩展:btree_gin、btree_gist、pgcrypto、citext、pg_trgm。 - 仅私有 VNet(
subnet-postgres),SSL 端口 5432。 - 机密:
langsmith-postgres-secret,由k8s-bootstrapTerraform 模块创建。
Azure Managed Redis
- 追踪摄取队列、pub/sub、短期缓存。
- Azure Managed Redis 管理引擎版本;没有可设置的版本变量。
- 每个 LangSmith 安装必须使用它自己专属的 Redis。共享实例会导致部署任务路由错误。
- 仅私有 VNet(
subnet-redis),TLS 端口 10000。 - 机密:
langsmith-redis-secret,由k8s-bootstrapTerraform 模块创建。
Azure Blob Storage
- 追踪负载:大的输入和输出、附件。
- 通过
k8s-app-identityManaged Identity 使用 Workload Identity(无静态密钥)。 - 始终必需。禁用 blob 存储会在大负载下使集群崩溃。
- 前缀:
ttl_s/(14 天 TTL)、ttl_l/(400 天 TTL)。
Azure Key Vault
- 所有 LangSmith 机密的集中式机密存储。
- 密钥流:
az keyvault secret show→kubectl create secret generic langsmith-config-secret。
Workload Identity
Azure AD 令牌交换通过 AKS OIDC 颁发者进行。Pod 无需静态密钥即可访问 Blob 存储。
txt
AKS OIDC issuer
→ Federated credential on Azure Managed Identity (one per Kubernetes ServiceAccount)
→ Kubernetes ServiceAccount annotated with azure.workload.identity/client-id
→ Pod labeled with azure.workload.identity/use: "true"
→ Azure AD issues a short-lived token; no storage keys in any Secret or env varWorkload Identity 与托管身份和 OIDC 颁发者一起集中在 modules/k8s-cluster/ 中,这避免了循环依赖并简化了新增 ServiceAccount 的工作。
哪些 pod 需要 Workload Identity
每个读取 blob 存储环境变量的 pod 都必须有:
- 在 Terraform(
modules/k8s-cluster/main.tf)中注册的一个联合凭据。 - Deployment 上的
azure.workload.identity/use: "true"标签。 - ServiceAccount 上的
azure.workload.identity/client-id注解。
| Pod | 阶段 | 需要 WI |
|---|---|---|
langsmith-backend | 应用 | 是 |
langsmith-platform-backend | 应用 | 是 |
langsmith-queue | 应用 | 是 |
langsmith-ingest-queue | 应用 | 是 |
langsmith-host-backend | LangSmith Deployment 附加组件 | 是 |
langsmith-listener | LangSmith Deployment 附加组件 | 是 |
langsmith-agent-builder-tool-server | Agent Builder 附加组件 | 是 |
langsmith-agent-builder-trigger-server | Agent Builder 附加组件 | 是 |
langsmith-frontend | 应用 | 否 |
langsmith-playground | 应用 | 否 |
langsmith-ace-backend | 应用 | 否 |
langsmith-clickhouse | 应用 | 否 |
langsmith-operator | LangSmith Deployment 附加组件 | 否 |
所有联合凭据都注册在 modules/k8s-cluster/main.tf 的 service_accounts_for_workload_identity 下。添加一个访问 blob 存储的新 pod,需要把它的 ServiceAccount 名加入那个列表并运行 terraform apply -target=module.aks。
如果一个 pod 的 ServiceAccount 没有注册的联合凭据,Azure AD 会拒绝令牌交换,pod 会在启动时 panic:
txt
panic: blob-storage health-check failed: get container properties failed:
DefaultAzureCredential: failed to acquire a token.
WorkloadIdentityCredential authentication failed.
AADSTS700213: No matching federated identity record found for presented assertion subject密钥流
txt
Infrastructure stage
./setup-env.sh (read-only against Key Vault; never writes to KV directly)
First run: prompts for postgres password, license key, admin password, admin email.
Generates api_key_salt, jwt_secret, Fernet keys locally.
Key Vault does not exist yet → writes to local dot-files + secrets.auto.tfvars.
Subsequent: Key Vault exists → reads the six generated secrets (api_key_salt,
jwt_secret, four Fernet keys) from KV. Re-prompts for postgres password,
license key, admin password, and admin email unless LANGSMITH_PG_PASSWORD,
LANGSMITH_LICENSE_KEY, LANGSMITH_ADMIN_PASSWORD, and LANGSMITH_ADMIN_EMAIL
are set. Writes secrets.auto.tfvars. No generation, no KV writes.
Output: secrets.auto.tfvars (gitignored, chmod 600)
Terraform picks this up automatically; no shell session coupling.
terraform apply
Reads: terraform.tfvars (non-sensitive config)
secrets.auto.tfvars (sensitive values; sole input for KV secret creation)
Creates: Azure Key Vault + all secrets as KV secrets (Terraform is the sole KV writer)
Application stage
./setup-env.sh (re-run on any machine; reads generated secrets from Key Vault,
re-prompts for user-provided ones unless LANGSMITH_* env vars are set)
kubectl create secret generic langsmith-config-secret
Reads: Key Vault secrets + Terraform outputs (postgres/redis URLs, blob account)
Writes: K8s secrets: langsmith-config-secret, langsmith-postgres-secret,
langsmith-redis-secret
helm upgrade --install langsmith ...
Chart reads config.existingSecretName = "langsmith-config-secret".
No secrets inline in any YAML file.关键规则: secrets.auto.tfvars 从不被提交。在任何机器上运行 ./setup-env.sh 都会恢复它:生成的密钥来自 Key Vault,而用户提供的密钥会重新提示输入,除非通过 LANGSMITH_* 环境变量提供。Terraform 是 Key Vault 的唯一写入者;setup-env.sh 只在首次 apply 之后从中读取。
Ingress 选项
| 控制器 | 变量 | DNS 标签支持 | 备注 |
|---|---|---|---|
nginx (默认) | ingress_controller = "nginx" | 是 | 经 Helm 的 NGINX,标准 Kubernetes Ingress。 |
istio-addon | ingress_controller = "istio-addon" | 是 | AKS 托管的 Istio 服务网格。用 istio_addon_revision 固定修订版。 |
istio | ingress_controller = "istio" | 是 | 经 Helm 的自管理 Istio。对修订版和配置的完全控制。 |
agic | ingress_controller = "agic" | 是 | Azure Application Gateway v2 + AKS 托管的 ingress_application_gateway 附加组件。原生 L7 WAF。仅 HTTP 或 dns01 + 自定义域名。 |
envoy-gateway | ingress_controller = "envoy-gateway" | 是 | Gateway API 原生。使用 envoyproxy/gateway-helm。 |
none | ingress_controller = "none" | — | 自带 ingress。 |
Azure 公共 IP DNS 标签(dns_label)适用于所有控制器。deploy.sh 会根据所选控制器,把 service.beta.kubernetes.io/azure-dns-label-name 注解应用到正确的 LoadBalancer 服务。
有关完整的 TLS 兼容性矩阵和逐控制器设置,参见 Azure 模块仓库中的 INGRESS_CONTROLLERS.md。
资源规格
有四个规格配置可用。
| 配置 | 用例 | 通过何设置 |
|---|---|---|
minimum | 成本占位、CI 冒烟测试、单用户演示 | sizing_profile = "minimum" in terraform.tfvars |
dev | 开发者使用、集成测试、POC | sizing_profile = "dev" |
production | 真实流量、多副本 + HPA | sizing_profile = "production" (推荐) |
production-large | ~50 用户、~1000 追踪/秒 | sizing_profile = "production-large" |
AKS 节点池
| 池 | VM 大小 | vCPU | 内存 | 最小 | 最大 | 目的 |
|---|---|---|---|---|---|---|
| default | Standard_D8s_v3 | 8 | 32 GB | 1 | 10 | 核心 LangSmith、系统 pod(生产设最小 3) |
| large | Standard_D16s_v3 | 16 | 64 GB | 0 | 2 | ClickHouse(集群内)、LGP agent pod |
NOTE
ClickHouse(在集群内时)根据配置请求 1 到 4 CPU 和 2 到 16 GB 内存。使用 LangChain Managed ClickHouse 时,large 池仅在 LGP operator 生成的 agent pod 时才需要。
可选模块
每个模块都由 count 控制(0 禁用,1 启用)。启用任意组合;核心部署(Passes 1 到 5)无需它们也能工作。
| 模块 | 变量 | 用例 |
|---|---|---|
waf | create_waf = true | Azure WAF 策略(OWASP 3.2 + 机器人防护)。附加到 Application Gateway。 |
diagnostics | create_diagnostics = true | AKS、Key Vault 和 PostgreSQL 的 Log Analytics 工作区 + 诊断设置。推荐用于生产可观测性。 |
bastion | create_bastion = true | 带静态公共 IP 的跳板 VM,用于通过 az ssh vm 和 Entra ID SSH 进行私有 AKS 访问。 |
dns | create_dns_zone = true | Azure DNS 区域 + A 记录。对使用自定义域名的 DNS-01 证书签发是必需的。 |