
K3s ArgoCD 中的密码管理Kubernetes 中的密码管理不只是创建一个Secret对象还要明确密码的真实来源、读取权限、注入方式、轮换流程以及集群重建后如何恢复。本文只讨论当前 LiteLLM 项目的密码管理方案。1. 当前需要管理的凭证Phase 1 只有三类运行时敏感信息凭证Kubernetes 环境变量用途Gemini API KeyOPENAI_API_KEY_FREE_1LiteLLM 访问上游 Gemini APILiteLLM Master KeyLITELLM_MASTER_KEY客户端访问 LiteLLM ProxyRedis 密码REDIS_PASSWORDLiteLLM 访问 Redis三者属于不同的身份体系Gemini API Key 只能用于上游模型 APILiteLLM Master Key 用于客户端访问 LiteLLMRedis 密码只用于 Redis 认证OCI API Signing Key 用于 ESO 访问 OCI Vault。这些凭证不能互相替代。比如Gemini API Key 不能访问 OCI VaultOpenAI API Key 也不能访问 GCP Secret Manager。Phase 1 暂不管理 OCI MySQL、Prisma、LiteLLM Virtual Key 和用户级预算凭证。2. ConfigMap 与 Kubernetes Secret2.1 ConfigMap 保存非敏感配置可以放入 ConfigMap 的内容包括LITELLM_PORT4000 REDIS_HOSTredis.redis.svc.cluster.local REDIS_PORT6379 NO_PROXYlocalhost,127.0.0.1,10.0.0.0/8,.svc,.cluster.localLiteLLM 的config.yaml也可以挂载为 ConfigMap但只能引用环境变量model_list:-model_name:gemini-3.6-flash-freelayerlitellm_params:model:gemini/gemini-3.6-flashapi_key:os.environ/OPENAI_API_KEY_FREE_1ConfigMap 不能保存 Gemini API Key、LiteLLM Master Key、Redis 密码、OCI 私钥、TLS 私钥或数据库密码。2.2 Kubernetes Secret 不是自动加密Kubernetes Secret 的data通常只是 Base64 编码data:REDIS_PASSWORD:base64-valueBase64 不是加密。Secret 的实际安全性依赖于 Kubernetes RBAC、API Server、etcd 加密、节点权限和备份权限。因此不能把 Base64 后的 Secret YAML 当作安全文件提交到 Git。3. 密码保存方案3.1.env文件本地测试可以使用uv run --env-file .env litellm--configconfig.yaml.env适合开发机不适合集群长期运行。它没有集中权限、自动轮换和灾备能力也容易误提交到 Git。.env必须被.gitignore排除。3.2 手工创建 Kubernetes Secret可以在集群外手工创建kubectl-nllm-system create secret generic litellm-secrets\--from-literalLITELLM_MASTER_KEY...\--from-literalOPENAI_API_KEY_FREE_1...\--from-literalREDIS_PASSWORD...优点是密码不进入 Git缺点是集群重建时需要人工重新创建密码轮换需要人工执行创建过程不在 Git 历史中密码可能进入 shell history 或进程信息ArgoCD 不知道这个 Secret 的声明状态。它适合临时测试或 Bootstrap不适合作为长期密钥来源。3.3 把原生 Secret YAML 提交到 Git不应该把明文或 Base64 编码后的原生 Secret 提交到 GitapiVersion:v1kind:Secretmetadata:name:litellm-secretsstringData:LITELLM_MASTER_KEY:real-secretGit 会永久保留旧版本。即使删除当前文件旧 commit、fork、CI 日志和备份中仍可能存在密码。3.4 Sealed SecretsSealed Secrets 在集群外使用公钥加密密码把加密后的SealedSecret提交到 Git集群内 controller 使用私钥解密并生成普通 Kubernetes Secret。明文 Secret ↓ 公钥加密 SealedSecret 密文 ↓ Git / ArgoCD Sealed Secrets Controller ↓ 私钥解密 Kubernetes Secret优点密文可以进入 GitArgoCD 可以恢复SealedSecret对象不依赖云厂商。风险controller 私钥丢失后旧密文无法解密私钥泄露后密文可能被解密。因此 controller 私钥需要独立备份和保护。Sealed Secrets 解决的是“如何把密文放进 Git”不等于外部 Secret Manager。3.5 External Secrets OperatorExternal Secrets Operator简称 ESO是运行在 Kubernetes 中的 controller。它从外部 Secret Manager 读取密码再生成 Kubernetes Secret。外部 Secret Manager ↓ ESO provider ExternalSecret ↓ ESO Kubernetes Secret ↓ LiteLLM PodExternalSecret只保存引用和字段映射不保存真实密码apiVersion:external-secrets.io/v1kind:ExternalSecretmetadata:name:litellm-secretsnamespace:llm-systemspec:refreshInterval:1hsecretStoreRef:name:oci-litellm-vault-storekind:SecretStoretarget:name:litellm-secretscreationPolicy:Ownerdata:-secretKey:LITELLM_MASTER_KEYremoteRef:key:litellm/master-keyESO 的优势是密码保存在外部系统Git 只保存引用密码轮换后可以自动同步但 ESO 自己必须先拥有访问外部系统的身份。4. 当前方案OCI Vault ESO当前项目使用 OCI Secret Management Service也就是 OCI Vault作为运行时密码的真实来源。计划的资源结构Tenancy └── litellm-prod └── LiteLLM Vault ├── litellm/openai-api-key-free-1 ├── litellm/master-key └── litellm/redis-password映射关系OCI SecretKubernetes Secret 字段Pod 环境变量litellm/openai-api-key-free-1OPENAI_API_KEY_FREE_1OPENAI_API_KEY_FREE_1litellm/master-keyLITELLM_MASTER_KEYLITELLM_MASTER_KEYlitellm/redis-passwordREDIS_PASSWORDREDIS_PASSWORDGit 中只保存名称和映射真实值保存在 OCI Vault 和运行时 Kubernetes Secret 中。4.1 OCI Compartment 与最小权限LiteLLM 的 OCI 资源计划放在独立 CompartmentCompartment: litellm-prod Region: ap-singapore-1ESO 使用专用读取身份User: litellm-vault-reader Group: litellm-vault-readersPolicy 只允许读取目标 Compartment 中的 SecretAllow group litellm-vault-readers to read secret-bundles in compartment litellm-prod该身份不应拥有创建、删除或修改 Vault、Secret、加密密钥或其他 OCI 资源的权限。4.2 OCI API Signing Key当前集群运行在 Tencent K3s不是 OCI OKE因此不能直接假设 OCI Workload Identity 可用。Phase 1 使用 OCI User Principal 和 API Signing Key。ESO 官方 OCI provider 支持UserPrincipal、InstancePrincipal和Workload当前固定使用UserPrincipal。准确的SecretStore格式为apiVersion:external-secrets.io/v1kind:SecretStoremetadata:name:oci-litellm-vault-storenamespace:llm-systemspec:provider:oracle:vault:VAULT_OCIDregion:ap-singapore-1principalType:UserPrincipalauth:user:USER_OCIDtenancy:TENANCY_OCIDsecretRef:privatekey:name:oci-litellm-vault-readerkey:privateKeyfingerprint:name:oci-litellm-vault-readerkey:fingerprintBootstrap Secret 格式为apiVersion:v1kind:Secretmetadata:name:oci-litellm-vault-readernamespace:llm-systemtype:OpaquestringData:privateKey:|-----BEGIN PRIVATE KEY----- OCI_API_SIGNING_PRIVATE_KEY -----END PRIVATE KEY-----fingerprint:OCI_API_KEY_FINGERPRINTprivateKey和fingerprint放在 Kubernetes Bootstrap Secret 中user、tenancy、region和vault放在SecretStoreprovider 配置中。5. Bootstrap Secret 与循环依赖ESO 必须先拥有 OCI API Signing Key才能访问 OCI Vault。如果 API Signing Key 也放在 OCI Vault就会形成循环依赖ESO 需要 API Signing Key ↓ API Signing Key 位于 OCI Vault ↓ 读取 OCI Vault 又需要 API Signing Key所以 API Signing Key 是 Bootstrap Secret必须由集群外安全流程提前写入 KubernetesOCI API Signing Key ↓ 集群外安全创建 llm-system/oci-litellm-vault-reader ↓ ESO ↓ OCI Vault ↓ llm-system/litellm-secretsBootstrap Secret不进入 Git、ConfigMap、镜像或 CI 日志不由 ExternalSecret 创建需要通过独立安全流程备份和重新创建。6. Namespace 设计计划使用external-secrets └── ESO Controller llm-system ├── oci-litellm-vault-reader ├── oci-litellm-vault-store ├── litellm-secrets └── LiteLLM Pod当前使用命名空间级SecretStore因此 Bootstrap Secret 必须和SecretStore位于同一个 NamespaceSecretStore: llm-system/oci-litellm-vault-store Bootstrap Secret: llm-system/oci-litellm-vault-reader不能把 Bootstrap Secret 只放在external-secrets再让llm-system中的SecretStore直接引用它。ClusterSecretStore是集群级对象可以被多个 Namespace 使用但权限范围更大。当前 Phase 1 使用SecretStore不增加跨 Namespace 共享身份的复杂度。7. ArgoCD 的恢复边界ArgoCD 能恢复 Git 中声明的 Kubernetes 对象例如SecretStoreExternalSecretSealedSecret普通 Kubernetes Secret前提是它确实声明在 Git 中。例如ExternalSecret对象被删除后ArgoCD 可以根据 Git 重新创建这个对象。ESO 看到对象后会重新从 OCI Vault 读取数据并生成目标 Kubernetes Secret。这里的“对象”指 Kubernetes API 中的资源对象不是 OCI Vault 中的 Secret也不是 Secret 明文。ArgoCD 不能凭空恢复没有提交到 Git 的原生 Kubernetes Secret集群外手工创建的 Bootstrap SecretOCI Vault 中已经删除且没有备份的 SecretSealed Secrets controller 的解密私钥OCI API Signing Key 私钥。恢复边界是Git 中的 ExternalSecret → ArgoCD 可以恢复 OCI Vault 中的真实密码 → OCI Vault 负责保存和恢复 Bootstrap Secret → 外部安全流程负责备份和重新创建selfHeal只表示 ArgoCD 可以把被手工修改或删除的 Git 管理对象恢复为 Git 中的状态它不等于能够恢复 Git 之外的密码也不能替代 OCI Vault 备份。8. 为什么不选择 GCP Secret ManagerESO 支持 GCP provider但 GCP 的典型配置需要 GCP Service Account JSONauth:secretRef:secretAccessKey:name:gcp-authkey:credentials.json这个 JSON 是访问 GCP Secret Manager 的 IAM 身份不是 Gemini API Key。当前 K3s 不运行在 GKE 上不能直接假设 GCP Workload Identity 可用项目已经选择 OCI Vault因此不额外引入 GCP Service Account。9. Master Key 与 Virtual KeyLITELLM_MASTER_KEY是 LiteLLM Proxy 的主访问凭证用于受控的管理和联调请求。它不是每位同事的独立账号不适合长期多人共享。Phase 1 暂不接入 MySQL、Prisma 和 LiteLLM Virtual Key因此先使用受控的 Master Key。后续具备数据库和 Key 管理能力后再为每位用户创建独立 Virtual Key并设置预算、权限、过期时间和轮换策略。10. 最终职责边界OCI Vault ├── Gemini API Key ├── LiteLLM Master Key └── Redis Password ↓ OCI IAM Policy External Secrets Operator ↑ llm-system/oci-litellm-vault-reader ↓ llm-system/oci-litellm-vault-store ↓ llm-system/litellm-secrets ↓ LiteLLM Pod组件负责内容OCI Vault保存真实密码、版本和轮换后的值OCI IAM限制谁能读取 OCI SecretBootstrap Secret让 ESO 获得第一次访问 OCI Vault 的能力ESO从 OCI Vault 同步 Kubernetes SecretExternalSecret声明外部 Secret 到 Kubernetes Secret 的映射ArgoCD恢复 Git 中的ExternalSecret和SecretStore对象LiteLLM Pod使用环境变量不负责保存密码来源最终原则是Git 管理引用和映射OCI Vault 管理真实敏感值ESO 负责同步Kubernetes Secret 只作为 Pod 的运行时对象存在。