主题
Azure Terraform 故障排除
用 LangChain Terraform 模块部署、在 Azure AKS 上自托管 LangSmith 的常见问题、修复和诊断命令。
本页记录用 Azure Terraform 模块预配的 LangSmith 部署的常见问题、修复和诊断命令。
TIP
升级之前,查阅 LangSmith 自托管变更日志了解破坏性变更和必需的变量更新。在运行任何 kubectl 命令之前,先运行 az aks get-credentials --name <cluster> --resource-group <rg>。
有关本页各处所用 kubectl、helm 和 az 调用的可复制粘贴参考,跳到诊断命令。
基础设施阶段
K8sVersionNotSupported:版本仅限 LTS
症状
Error: creating Kubernetes Cluster ... unexpected status 400
"code": "K8sVersionNotSupported"
"message": "Managed cluster ... is on version 1.32.x, which is only available for Long-Term Support (LTS).
If you intend to onboard to LTS, please ensure the cluster is in Premium tier ..."原因: Azure 会周期性地从 Standard 层支持中退役小版本并把它们移到仅限 LTS。截至 2026 年 4 月,在 eastus 中 1.32 及以下是仅限 LTS 的。Standard 层集群必须用 1.33+。
修复: 把 kubernetes_version 更新为一个带 KubernetesOfficial 支持的版本:
bash
az aks get-versions --location eastus -o table
# Versions with KubernetesOfficial in SupportPlan column work on Standard tier移除或更新 terraform.tfvars 中任何 kubernetes_version 锁定,然后 make apply。在 1.32 上的现有集群继续运行;这仅阻塞新的集群创建。
vCPU 配额超出
症状(自动伸缩器退避、pod Pending):
Warning FailedScheduling pod/langsmith-backend-xxx 0/1 nodes are available: 1 Too many pods.
Normal NotTriggerScaleUp pod/langsmith-backend-xxx pod didn't trigger scale-up: 2 in backoff after failed scale-up症状(节点池轮换):
Error: creating temporary Agent Pool ... "code": "ErrCode_InsufficientVCPUQuota",
"message": "Insufficient vcpu quota requested 8, remaining 2 for family standardDSv3Family for region eastus."原因: 每 VM 系列的按区域 vCPU 配额。standardDSv3Family 在 eastus 的默认值常为 10 核。一个 Standard_D8s_v3 节点用 8;只剩 2。
为何 max_pods = 30 会触发它: AKS 默认每节点 30 pod。仅 LangSmith 基础安装就部署 ~37 个 pod。自动伸缩器试图添加第二个节点、撞上配额、进入退避。修复:在 terraform.tfvars 中设 default_node_pool_max_pods = 60,使所有 pod 落在一个节点上。
多 dataplane(3 个 dataplane)的推荐配额:32 核。
请求一次配额增加:
bash
# Azure portal usually auto-approves within minutes:
# Portal → Subscriptions → <sub> → Usage + Quotas → search "DSv3" → eastus → Request increase → 32
# Or via CLI
az quota update \
--resource-name "standardDSv3Family" \
--scope /subscriptions/<sub-id>/providers/Microsoft.Compute/locations/eastus \
--limit-object value=32 limit-type=Independent \
--resource-type dedicated
az vm list-usage --location eastus --query "[?contains(name.value,'DSv3')]" -o table替代方案,若 DSv3 配额耗尽则切换 VM 系列: 用 Standard_DS4_v2(基线)+ Standard_DS5_v2(大)。同样的 vCPU,略少的 RAM。已针对完整 LangSmith 安装加所有附加组件验证。
NOTE
max_pods 在一个现有节点池上不可变。在首次 terraform apply 之前就设置它。
Istio 附加组件修订版不受支持
症状: terraform apply 拒绝该 Istio 修订版(Revision asm-1-XX is not supported)。Azure 会定期退役旧的 ASM 修订版。
修复: 查看当前可用的修订版并更新 istio_addon_revision:
bash
az aks mesh get-revisions --location eastus -o table在 terraform.tfvars 中设值并重新 apply。
Key Vault 清除保护一旦启用便无法禁用
症状
Error: updating Key Vault "langsmith-kv-dz":
once Purge Protection has been Enabled it's not possible to disable it原因: 当一个 Key Vault 通过 terraform destroy 删除时,Azure 会软删除它 90 天。下一次用同名的 terraform apply 会静默恢复旧的 Key Vault,包括它原来的 purge_protection_enabled = true。清除保护是单向的(启用 → 无法禁用)。
修复(接受清除保护,测试环境):
hcl
keyvault_purge_protection = true修复(需要 purge_protection = false):
bash
# 1. Remove KV from Terraform state (does not delete from Azure)
terraform -chdir=infra state rm module.keyvault.azurerm_key_vault.langsmith
# 2. Permanently purge the soft-deleted KV (irreversible)
az keyvault purge --name langsmith-kv<identifier> --location eastus
# 3. Re-apply
make applyKey Vault 机密已存在但不在 Terraform 状态中
症状
Error: a resource with the ID "https://langsmith-kv-<id>.vault.azure.net/secrets/.../..."
already exists - to be managed via Terraform this resource needs to be imported into the State.原因: 较旧的 setup-env.sh 版本会把 Fernet 密钥直接写入 Key Vault。当前的 setup-env.sh 对 Key Vault 是只读的;Terraform 是唯一写入者。
修复: 导入冲突的机密:
bash
terraform import \
'module.keyvault.azurerm_key_vault_secret.deployments_encryption_key[0]' \
"$(az keyvault secret show --vault-name langsmith-kv<id> --name langsmith-deployments-encryption-key --query id -o tsv)"
terraform import \
'module.keyvault.azurerm_key_vault_secret.agent_builder_encryption_key[0]' \
"$(az keyvault secret show --vault-name langsmith-kv<id> --name langsmith-agent-builder-encryption-key --query id -o tsv)"
terraform import \
'module.keyvault.azurerm_key_vault_secret.insights_encryption_key[0]' \
"$(az keyvault secret show --vault-name langsmith-kv<id> --name langsmith-insights-encryption-key --query id -o tsv)"
terraform apply应用阶段
dns_label 子域不解析:TLS 证书卡在 pending
症状: nslookup langsmith-demo.eastus.cloudapp.azure.com 返回 NXDOMAIN。cert-manager 的 ACME 质询无法完成;TLS 证书停在 READY: False。
原因: service.beta.kubernetes.io/azure-dns-label-name 注解必须设在 NGINX LoadBalancer 服务上,好让 Azure 把 DNS 标签分配给公共 IP。make deploy 通过 deploy.sh 自动设置它。如果你直接运行了 helm upgrade,那个注解从未被设置。
修复
bash
kubectl annotate svc ingress-nginx-controller -n ingress-nginx \
service.beta.kubernetes.io/azure-dns-label-name=<dns_label> \
--overwrite
# Wait 1-2 minutes, verify DNS resolves
nslookup <dns_label>.eastus.cloudapp.azure.com
# Delete the stuck cert to trigger re-issue
kubectl delete certificate langsmith-tls -n langsmithistio-addon:端口 80/443 超时,TLS 握手被重置
症状: 用 ingress_controller = "istio-addon" 执行 make deploy 后站点不可达。端口 80 超时,端口 443 重置。ACME 质询停在 pending。
原因(三个叠加问题):
- 错误的网关标签。 带
ingressClassName: istio的 Kubernetes Ingress 针对标为istio: ingressgateway的 pod。AKS 管理的外部网关用istio: aks-istio-ingressgateway-external。 ClusterIssuer以class: nginx创建。 ACME HTTP-01 求解器 ingress 拿到 classnginx而非istio。- TLS secret 在错误的命名空间。 Istio SDS 从网关 pod 命名空间(
aks-istio-ingress)而非应用命名空间(langsmith)读取。
修复: 在当前脚本里,make deploy 会自动处理全部三点。若手动部署,创建一个针对 istio: aks-istio-ingressgateway-external 的 Istio Gateway,把 ClusterIssuer 求解器 patch 成 ingressClassName: istio,把 langsmith-tls 同步到 aks-istio-ingress 命名空间,并创建一个路由到 LangSmith 前端的 VirtualService。完整 YAML 见 TROUBLESHOOTING.md 源。
letsencrypt-prod ClusterIssuer 缺失
症状: kubectl describe certificate langsmith-tls -n langsmith 显示 clusterissuers.cert-manager.io "letsencrypt-prod" not found。
原因: 对 tls_certificate_source = "letsencrypt"(HTTP-01),letsencrypt-prod ClusterIssuer 由 apply-cluster-issuers.sh 创建,而 make deploy 通过 kubectl apply 运行它。Terraform 的 k8s-bootstrap 模块不创建 HTTP-01 发行者;它只为 dns01 创建发行者。直接运行 helm upgrade 而非 make deploy 会跳过发行者。
手动修复:
bash
kubectl apply -f - <<EOF
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: you@example.com
privateKeySecretRef:
name: letsencrypt-prod-account-key
solvers:
- http01:
ingress:
ingressClassName: nginx # use "istio" with istio-addon or istio
EOF
kubectl delete certificate langsmith-tls -n langsmithdatabase "langsmith" does not exist:后端 pod 崩溃循环
症状: 后端 pod 立即崩溃:FATAL: database "langsmith" does not exist。
原因: Azure DB for PostgreSQL Flexible Server 不会自动创建应用数据库。Terraform 的 postgres 模块现在通过 azurerm_postgresql_flexible_server_database 创建数据库。这个错误意味着你在一个缺该资源的较旧模块版本上。
修复
bash
terraform apply
kubectl rollout restart deployment -n langsmithlangsmith-backend-auth-bootstrap 卡在 CreateContainerConfigError
原因: 该 Job 用键 initial_org_admin_password 读 admin 密码。如果那个 Secret 是用另一个键名创建的(例如 admin_password),容器无法启动。
修复
bash
kubectl delete secret langsmith-config-secret -n langsmith
make k8s-secrets # recreates with correct key names
make deploy无法回滚到一个较旧的 chart 版本
原因: LangSmith 数据库迁移是仅向前的。降级 chart 会让数据库停在一个较旧应用镜像找不到的修订版上。
修复: 向前滚到你原来的版本(或更新)。在 terraform.tfvars 中设 langsmith_helm_chart_version 并重新部署。在升级生产之前,始终在一个独立环境里测试新的 chart 版本。
Helm 安装超时
原因: langsmith-backend-auth-bootstrap 在每次 helm upgrade 都运行数据库迁移;首次安装最多耗时 5 分钟。没有 --timeout 20m,Helm 会报告失败,即使安装最终会成功。
修复: make deploy 已用 --timeout 20m。手动运行 Helm 时,始终包含 --timeout 20m。
附加组件
pod 停在 DEPLOYING,从不达到 HEALTHY
原因: 在 TLS 启用时 config.deployment.url 为空,或 config.deployment.tlsEnabled 为 false。operator 用这些值构建 agent 端点 URL。
修复: init-values.sh 在从 examples 复制之后会自动注入 url 和 tlsEnabled。若手动部署:
yaml
config:
deployment:
enabled: true
url: "https://langsmith-demo.eastus.cloudapp.azure.com" # must include https://
tlsEnabled: true # must be true when tls_certificate_source = letsencrypt or dns01Insights 附加组件:backend-ch-migrations 处于 CreateContainerConfigError
症状: 启用 enable_insights = true 后多个 pod 以 CreateContainerConfigError 失败。日志:secret "langsmith-clickhouse" not found。
原因: 示例 langsmith-values-insights.yaml 设 clickhouse.external.enabled: true 配 existingSecretName: langsmith-clickhouse。这覆盖了集群内 ClickHouse 配置并期望一个并不存在的外部机密。
修复: 当 clickhouse_source = "in-cluster" 时,init-values.sh 现在会生成一个最小 Insights 文件。对一个有这个问题的现有部署:
bash
cat > helm/values/langsmith-values-insights.yaml << 'EOF'
insights:
enabled: true
EOF
make deployPolly 显示 "Unable to connect to LangGraph server"
症状: Polly 聊天小组件显示连接错误。浏览器控制台:POST http://localhost:8123/threads net::ERR_FAILED 和一个 CORS 错误。
原因 A,前端在 langsmith-polly-config 被创建之前启动。 bootstrap job 在 Polly 注册后用 VITE_POLLY_DEPLOYMENT_URL 创建 ConfigMap。来自 ConfigMap 的环境变量在 pod 启动时加载,而非动态加载。
修复
bash
kubectl rollout restart deployment langsmith-frontend -n langsmith
kubectl exec -n langsmith deploy/langsmith-frontend -- env | grep POLLY
# expect: VITE_POLLY_DEPLOYMENT_URL=https://<hostname>/lgp/smith-polly-<hash>原因 B,LANGCHAIN_ENDPOINT 设在 polly.agent.extraEnv 里。 LANGCHAIN_ENDPOINT 是保留的。设置它会让 bootstrap job 以 400 Bad Request: 'LANGCHAIN_ENDPOINT' is reserved 失败。Polly 从不被创建。
修复: 完全移除 polly.agent.extraEnv 块。operator 会自动注入 LANGCHAIN_ENDPOINT。
启用 LangSmith Deployment 后 listener 和 operator pod 从不出现
原因: 设了 config.deployment.url 但省略了 config.deployment.enabled: true。当 enabled 为 false(默认)时,chart 会静默跳过创建 listener 和 operator。
修复: 在 deployment 块内添加 enabled: true:
yaml
config:
deployment:
enabled: true # required; url alone is not enough
url: "https://<your-hostname>"重复的顶层 config: 键静默丢弃值
原因: YAML 不允许重复的顶层键。第二个 config: 块会静默丢弃其中一个。
修复: 始终把新的 config 块添加在现有的 config: 键之内。用 helm get values langsmith -n langsmith 验证。
加密密钥在首次部署后不得更改
在 deployments_encryption_key、agent_builder_encryption_key 或 insights_encryption_key 首次使用之后更改它们,会永久损坏它们所保护的数据。没有恢复。
- 不要轮换这些密钥。
- 不要在
values-overrides.yaml里内联设config.agentBuilder.encryptionKey或config.insights.encryptionKey。chart 通过existingSecretName从langsmith-config-secret读它们。内联设置会覆盖机密引用。
agent-builder-tool-server 或 polly 处于 CrashLoopBackOff
症状: pod 无限重启。无回溯。日志反复显示 "Child process died"。
原因: lc_config.settings.SharedSettings 在 uvicorn worker 内于模块导入时实例化。那里抛出的一个 pydantic ValidationError 会以退出码 0 退出 worker;uvicorn 的父进程会打印 "Child process died" 但吞掉回溯。常见诱因:BASIC_AUTH_ENABLED = true 但 BASIC_AUTH_JWT_SECRET 为空,或一个必需的功能标志键在 langsmith-config 中缺失。
诊断:用一个 envFrom 指向 langsmith-config、带 PYTHONUNBUFFERED=1 的调试 pod 运行服务器。修复:把缺失的键添加到 Key Vault,重跑 make k8s-secrets,重启 deployment。
Workload Identity
pod 崩溃:AADSTS700213: No matching federated identity record found
症状
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
'system:serviceaccount:langsmith:langsmith-<service>'原因: 该 pod 的 Kubernetes ServiceAccount 在 Azure 托管身份上没有联合凭据。每个访问 Blob 存储的 pod 都需要一个。
修复: 把缺失的 ServiceAccount 添加到 modules/k8s-cluster/main.tf 中的 service_accounts_for_workload_identity:
hcl
service_accounts_for_workload_identity = [
"${var.langsmith_release_name}-backend",
"${var.langsmith_release_name}-platform-backend",
"${var.langsmith_release_name}-queue",
"${var.langsmith_release_name}-ingest-queue",
"${var.langsmith_release_name}-host-backend", # LangSmith Deployment add-on
"${var.langsmith_release_name}-listener", # LangSmith Deployment add-on
"${var.langsmith_release_name}-agent-builder-tool-server", # Agent Builder add-on
"${var.langsmith_release_name}-agent-builder-trigger-server", # Agent Builder add-on
]bash
terraform apply -target=module.aks
kubectl rollout restart deployment/langsmith-<service> -n langsmith完整的 pod 到 WI 映射,见架构页。
拆除与清理
make clean 在 make destroy 之前会使基础设施孤立
症状: make clean 之后的 make destroy 以 No state file was found! 失败。Azure 资源仍在运行,但 Terraform 已丢失跟踪。
原因: make clean 会移除 terraform.tfvars 和 secrets.auto.tfvars。没有它们,Terraform 无法初始化后端。
正确的拆除顺序
txt
1. make uninstall ← Helm + namespace
2. make destroy ← Azure infra (needs tfstate + tfvars)
3. make clean ← local secrets and generated files (LAST)当 tfstate 丢失时的恢复
bash
az group delete --name langsmith-rg<identifier> --yes --no-wait
az group show --name langsmith-rg<identifier> 2>&1 | grep -E "provisioningState|ResourceGroupNotFound"如果你之后复用同一个 identifier,Azure 可能会在下一次 terraform apply 恢复被软删除的 Key Vault。带 keyvault_purge_protection = false 时,先清除:az keyvault purge --name langsmith-kv<identifier> --location <region>。
terraform destroy 卡在 VNet/子网删除上
原因: 由 ingress-nginx-controller 预配的 Azure 负载均衡器不被 Terraform 跟踪。当 LB 持有一个子网引用时,Azure 会阻止 VNet 删除。
修复: 先运行 make uninstall。
bash
make uninstall
kubectl delete namespace langsmith --timeout=60s
make destroylangsmith-agent-bootstrap 钩子超时
症状: Helm post-upgrade 钩子超时(context deadline exceeded)。agent 依次经过 QUEUED → AWAITING_DEPLOY → DEPLOYING 但在 20 分钟内达不到 HEALTHY。
原因: 在一个冷集群上,三个 LGP agent(agent-builder、clio、smith-polly)首次镜像拉取可能耗时超过 20 分钟。Helm 钩子同步等待。
修复: 其实不是失败。资源已被应用;agent 继续部署。等到 pod 稳定,然后重跑 make deploy。
listener pod 被 OOMKilled
原因: listener 内存上限由规格 overlay 在 listener.deployment.resources 下设定。在 dev 配置上那个上限是 2Gi,持续的 Deployments 负载可能超出它。
修复: 在 listener.deployment.resources 下(chart 读的那个键)调高上限,要么移到一个更大的规格配置,要么把覆盖加到一个在规格 overlay 之后加载的 values 文件,然后重跑 make init-values 和 make deploy。
NOTE
chart 读 listener.deployment.resources 作为容器上限,而非扁平的 listener.resources。langsmith-values-agent-deploys.yaml 示例设的是 listener.resources,chart 会静默忽略它,所以那个值不会改变上限。
陈旧的 HPA 把 listener 或 host-backend 扩到最大副本数
原因: 一个先前的 Helm 修订版创建了一个 HPA。Helm 在钩子失败时不清理它。带 enabled: false 重新部署时,陈旧的 HPA 仍在并覆盖 replicas。
修复
bash
kubectl delete hpa langsmith-listener langsmith-host-backend -n langsmith 2>/dev/null || true
kubectl scale deployment langsmith-listener -n langsmith --replicas=1
kubectl scale deployment langsmith-host-backend -n langsmith --replicas=1
make deployAGIC(Application Gateway Ingress Controller)
AGIC pod CrashLoopBackOff:AGW GET 上 403
症状: ingress-appgw-deployment 是 CrashLoopBackOff。日志:ErrorApplicationGatewayForbidden: does not have authorization to perform action Microsoft.Network/applicationGateways/read。
原因: AKS 为 AGIC 附加组件创建一个托管身份(在 MC_ 资源组中的 ingressapplicationgateway-<cluster>)。该身份在集群预配期间创建,但要 ~5 分钟才在 Azure AD 中注册,之后角色指派才生效。
修复: k8s-cluster 模块在集群创建后等待 300 秒(time_sleep.agic_identity_propagation)并自动创建三个所需的角色指派。如果 make apply 之后 AGIC 仍 403:
bash
az aks update --name <CLUSTER> --resource-group <RG> --yes
kubectl delete pod -n kube-system -l app=ingress-azure关于手动角色指派(RG 上的 Reader、AGW 上的 Contributor、VNet 上的 Network Contributor),见 TROUBLESHOOTING.md 源。
AGIC:ApplicationGatewayInsufficientPermissionOnSubnet
原因: AGIC 附加组件身份在 VNet 上缺少 Network Contributor。
修复
bash
AGIC_OID=$(az aks show -g <RG> -n <CLUSTER> \
--query "addonProfiles.ingressApplicationGateway.identity.objectId" -o tsv)
VNET_ID=$(az network vnet show -g <RG> -n <VNET> --query id -o tsv)
az role assignment create --role "Network Contributor" --scope "$VNET_ID" \
--assignee-object-id "$AGIC_OID" --assignee-principal-type ServicePrincipal
kubectl rollout restart deployment/ingress-appgw-deployment -n kube-systemAGIC:TLS secret 的 SecretNotFound
原因: AGIC 在 cert-manager 签发 TLS 证书之前看到了 Ingress。
修复: 触碰 Ingress 以触发重新同步:
bash
kubectl get certificate langsmith-tls -n langsmith # verify cert is ready
kubectl annotate ingress langsmith-ingress -n langsmith touch="$(date +%s)" --overwriteAGIC 拒绝 ingressClassName: azure/application-gateway
原因: 旧式注解 kubernetes.io/ingress.class: azure/application-gateway(带斜杠)不是一个有效的 ingressClassName。AKS 把 IngressClass 创建为 azure-application-gateway(连字符)。
修复: 用 ingressClassName: azure-application-gateway。make init-values 会自动设置这个。
Istio(自管理 Helm)
Istio 站点返回连接被拒 / 无路由
症状: 连接被拒。pilot-agent request GET config_dump 显示 LDS: PUSH resources:0。
根因(三者都必须修复):
meshConfig.ingressControllerMode未设。默认为DEFAULT,它会忽略ingressClassName。必须是STRICT。istioIngressClass 资源缺失。meshConfig.ingressClass未设为istio。
修复: 三者都自动化。meshConfig 在 istiod Helm release(Terraform)中设置,deploy.sh 创建 IngressClass。手动修复:创建 IngressClass 并重启 istiod。
Istio HTTPS 返回 "no peer certificate available"
原因: istiod 通过 SDS(kubernetes://langsmith-tls)读 TLS secret。该 secret 必须存在于 istio-system(网关 pod 命名空间)。cert-manager 把它签发到 langsmith 命名空间;它不会被自动复制。
修复: deploy.sh 在部署后同步该 secret。手动修复:把该 secret 复制到 istio-system。
来自 istio-addon 的残留 CRD 阻止自管理 Helm 安装
症状: terraform apply 失败:CustomResourceDefinition "wasmplugins.extensions.istio.io" exists and cannot be imported into the current release: invalid ownership metadata。
修复
bash
kubectl get crd | grep "istio.io" | awk '{print $1}' | xargs kubectl delete crd
terraform apply诊断命令
集群访问
bash
az aks get-credentials --name <cluster> --resource-group <rg>
kubectl config current-context
kubectl get nodes -o widePod
bash
kubectl get pods -n langsmith
kubectl get pods -n langsmith -w
kubectl describe pod <pod-name> -n langsmith
kubectl logs <pod-name> -n langsmith --tail=100 -f
kubectl logs <pod-name> -n langsmith --previous --tail=50Ingress 与 TLS
bash
kubectl get ingress -n langsmith
kubectl get svc ingress-nginx-controller -n ingress-nginx
kubectl get certificate -n langsmith
kubectl get challenges -n langsmith
kubectl get clusterissuerWorkload Identity
bash
kubectl get serviceaccount langsmith-ksa -n langsmith \
-o jsonpath='{.metadata.annotations.azure\.workload\.identity/client-id}'
kubectl get pod <pod> -n langsmith \
-o jsonpath='{.metadata.labels.azure\.workload\.identity/use}'Helm
bash
helm status langsmith -n langsmith
helm history langsmith -n langsmith
helm get values langsmith -n langsmithLangSmith Deployment
bash
kubectl get pods -n langsmith | grep -E "host-backend|listener|operator"
kubectl get lgp -n langsmith
kubectl get crd | grep langchainKey Vault 与 Kubernetes Secrets
bash
./infra/scripts/manage-keyvault.sh list
./infra/scripts/manage-keyvault.sh validate
./infra/scripts/manage-keyvault.sh diff
kubectl get secrets -n langsmith
kubectl get secret langsmith-config-secret -n langsmith -o jsonpath='{.data}' | jq 'keys'快速健康检查
bash
make status # 10-section automated check
make status-quick # skip Key Vault + K8s secret queries