使用 Helm Chart 在 Kubernetes 上部署 Tandoor Recipes:values 配置、Secret 管理与流量接入实战
2026/9/16 17:25:15 网站建设 项目流程

使用 Helm Chart 在 Kubernetes 上部署 Tandoor Recipes:values 配置、Secret 管理与流量接入实战

【免费下载链接】recipesApplication for managing recipes, planning meals, building shopping lists and much much more!项目地址: https://gitcode.com/GitHub_Trending/re/recipes

Tandoor Recipes(即本仓库的recipes应用)是一款用于管理菜谱、规划膳食、生成购物清单的开源食谱管理应用。本文将基于仓库中社区贡献的 docs/install/helmChart.md 指南,完整讲解如何通过第三方 Helm Chart(csg33k/helm-charts中的tandoorchart)在已有 PostgreSQL 的 Kubernetes 集群上快速部署 Tandoor Recipes,包括values.yaml的每一项核心配置、环境变量与启动脚本的对应关系、Secret 的安全注入方式,以及用 Gateway API 的HTTPRoute完成流量接入的完整流程。读完本文,你将获得一份可直接复制落地、并理解其底层原理的 Helm 部署方案。

指南性质与适用前提

该指南由社区贡献,既非官方支持,也不会被官方持续更新或测试。使用时请结合 docs/install/helmChart.md 和 chart 发布方的最新values.yaml核对版本差异。

在开始之前,需要明确两个前提假设:

  1. 你已有一个可访问的 PostgreSQL 数据库。本 chart 的初始版本不负责创建数据库,只负责部署应用本身,数据库连接参数全部通过环境变量注入。
  2. chart 初始版本不内置 LoadBalancer。应用流量需要你自己通过 Ingress 清单或 Gateway API 的HTTPRoute指向 chart 创建出的 Service。

另外需要特别注意 Tandoor 2 的兼容性变化:根据 docs/install/kubernetes.md 的警告,Tandoor 2 已将 nginx 服务集成进默认 Docker 容器,并把服务端口从 8080 改为 80。本仓库的 Dockerfile 中EXPOSE 80 8080与 boot.sh 中的 nginx 启动逻辑印证了这一演进,因此在配置路由或 Ingress 时,请以你所使用镜像版本实际暴露的端口为准。

核心配置:values.yaml 逐项解析

社区指南给出了一个"基础最小化可运行"的示例values.yaml,本节逐段拆解,并结合仓库源码解释每个参数的实际作用。

命名空间与资源名称覆盖

namespaceOverride: food fullnameOverride: "recipes"
  • namespaceOverride: food:强制 chart 内所有资源(包括下方extraResources中定义的 Secret)都部署在food命名空间。后续的helm installHTTPRoute都基于该命名空间编写。
  • fullnameOverride: "recipes":覆盖 chart 自动生成的应用资源名称前缀,最终应用 Service 名为recipes,这也是后面HTTPRoutebackendRefs.name必须对齐的值。

指南注明这两项"并非必需",只是为了保证与作者环境的命名一致,使路由示例开箱可用。如果你的环境命名不同,请同步修改HTTPRoute中的 backend 名称。

global 段:镜像与版本

# Change to latest version if out of date. #global: # create_namespace: false # image: vabene1111/recipes # tandoor_version: 2.3

global段整体被注释掉,表示全部采用 chart 内置默认值:

  • create_namespace:是否由 chart 自动创建命名空间,默认为关闭(false),需提前手动建好food命名空间,或由helm install -n food在目标集群策略允许时创建。
  • image/tandoor_version:镜像仓库地址与 Tandoor 版本标签。当前仓库主镜像为vabene1111/recipes,解注释后按需调整版本(例如2.3)。建议显式锁定版本号以提升稳定性、避免意外迁移,这一点与 docs/install/k8s/50-deployment.yaml 中"建议显式指定 tag"的建议一致。

env 段:应用环境变量

env: ## Values below will get you to a basic working installation - name: DB_ENGINE value: django.db.backends.postgresql - name: POSTGRES_HOST value: shared-rw.postgres-operator.svc.cluster.local - name: POSTGRES_PORT value: "5432" - name: POSTGRES_DB value: fooddb - name: SECRET_KEY valueFrom: secretKeyRef: name: recipes-secrets key: secret-key - name: POSTGRES_USER valueFrom: secretKeyRef: name: recipes-secrets key: username - name: POSTGRES_PASSWORD valueFrom: secretKeyRef: name: recipes-secrets key: password ## I skipped email support but feel free to add it as well.

这些环境变量会被注入应用容器,其消费逻辑可以直接在仓库启动脚本 boot.sh 中找到:

  • DB_ENGINE:固定为 Django 的 PostgreSQL 后端django.db.backends.postgresqlboot.sh依据该值(或DATABASE_URLpostgres开头)判断是否进入"等待数据库就绪"与POSTGRES_PASSWORD校验分支。
  • POSTGRES_HOST/POSTGRES_PORT/POSTGRES_DB:数据库地址、端口与库名。boot.sh会用pg_isready --host=${POSTGRES_HOST} --port=${POSTGRES_PORT} --user=${POSTGRES_USER}轮询等待数据库可用,最多尝试 20 次、每次间隔 5 秒;超时会打印诊断信息并以非零码退出容器。
  • SECRET_KEY/POSTGRES_USER/POSTGRES_PASSWORD:推荐通过secretKeyRef从 Kubernetes Secret 中引用,避免明文写在values.yaml中。boot.sh会校验SECRET_KEYPOSTGRES_PASSWORD是否为空,缺失时打印[WARNING]并继续启动(但后续应用将无法正常工作),因此务必正确注入。

补充说明:boot.sh还支持*_FILE形式的变量(如SECRET_KEY_FILEPOSTGRES_PASSWORD_FILE),容器启动时会自动读取文件内容填充对应变量。若你的 Secret 以文件卷形式挂载,同样适用。

persistence 段:数据持久化

persistence: enabled: true volumes: - name: staticfiles mountPath: /opt/recipes/staticfiles size: 1Gi - name: mediafiles mountPath: /opt/recipes/mediafiles size: 1Gi
  • enabled: true:启用持久化声明(PVC)。
  • 两个卷分别挂载到容器内的/opt/recipes/staticfiles(Django 静态文件)与/opt/recipes/mediafiles(用户上传的图片等媒体文件)。这两个路径与 boot.sh 中的默认值MEDIA_ROOT=/opt/recipes/mediafilesSTATIC_ROOT=/opt/recipes/staticfiles完全对应。

指南特别强调:虽然持久化"并非严格必需",但强烈建议创建,否则每次 Pod 重启都会丢失已收集的静态文件与用户上传的媒体文件。boot.sh在启动时执行python manage.py collectstatic --noinput --clear重新收集静态文件,媒体文件则不可再生,必须落盘保存。

extraResources 段:一次性注入 Secret

## In Production, use a different way of getting the secrets in. unless this code never leaves your server. ## In a "Prod" like homelab you should use ESO or Sealed Secrets, etc populate these values. extraResources: - apiVersion: v1 kind: Secret metadata: name: recipes-secrets namespace: food type: Opaque stringData: password: superSecretDBPass secret-key: ## output of openssl rand -base64 32 | tr -d '/+=' | head -c 32 username: db_username

extraResources允许在安装 chart 的同时附带创建额外 Kubernetes 资源。这里用它直接声明了env段引用的recipes-secretsSecret(Opaque 类型,包含passwordsecret-keyusername三个键):

  • secret-key生成方式openssl rand -base64 32 | tr -d '/+=' | head -c 32,即取 32 字节随机数并裁剪为 32 字符的 Django SECRET_KEY。
  • 安全提醒(原指南原文语义):直接把 Secret 写进values.yaml仅适用于"这份代码不会离开你的服务器"的场景;在类生产环境(如 Homelab 生产)应改用External Secrets Operator(ESO)Sealed Secrets等方案来注入这些值,不要把明文密钥提交到代码仓库。

安装 Chart

配置好values.yaml(文件名可自定义,如myvalues.yaml)后,执行:

helm install recipe-manager -n food oci://ghcr.io/csg33k/helm-charts/tandoor --version 0.0.1 -f myvalues.yaml

参数含义:

参数说明
recipe-manager本次 Helm Release 的名称
-n food安装到food命名空间(与namespaceOverride保持一致)
oci://ghcr.io/csg33k/helm-charts/tandoor以 OCI 方式拉取 chart,无需手动添加 repo
--version 0.0.1指定 chart 版本,官方提示"若过期请更新到最新版本"
-f myvalues.yaml覆盖默认值的自定义配置文件

流量接入:HTTPRoute 示例

Chart 本身不创建 LoadBalancer,安装完成后应用 Service(名为recipes,端口 80)已就绪,剩下就是如何把外部流量引进来。指南给出了基于Gateway APIHTTPRoute示例:

apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: food-https namespace: food spec: parentRefs: - name: http-gateway ## Change this namespace: default ## Change this sectionName: https hostnames: - food.domain.tld ## Change this rules: - backendRefs: - name: recipes ## If the name is different for your env, update it accordingly. port: 80

需要修改的占位项:

  • parentRefs.name/parentRefs.namespace:指向你集群中已部署的 Gateway 资源(示例假定它名为http-gateway、位于default命名空间)。
  • parentRefs.sectionName:Gateway 监听器名称,示例为https
  • hostnames:替换为你的真实域名,如food.domain.tld
  • backendRefs.name:必须与fullnameOverride生成的 Service 名一致(此处为recipes),端口 80。

如果你使用的是传统 Ingress 控制器而非 Gateway API,也可以参考仓库自带的 docs/install/k8s/70-ingress.yaml:它展示了将/media/static路径路由到 nginx 容器(端口 80)、其余流量路由到 gunicorn(端口 8080)的路径拆分写法,并预留了 cert-manager 的 TLS 注释模板(默认注释状态)。

与 Manifest 部署方式的对照参考

除了 Helm Chart,本仓库还维护了一套可直接kubectl apply的清单文件,位于 docs/install/k8s/,对应指南为 docs/install/kubernetes.md。两套方案的架构思路高度一致,可互为印证:

关注点Helm Chart(本文)Manifest 方式
数据库复用外部 PostgreSQL40-sts-postgresql.yaml 自带 Bitnami PostgreSQL StatefulSet(数据卷 2Gi、runAsUser: 1001低权限运行,init 容器以 root 准备目录)
静态/媒体文件persistence声明两个 1Gi 卷30-pvc.yaml 声明recipes-mediarecipes-static两个 1Gi PVC
初始化流程chart 内置逻辑50-deployment.yaml 的init-chmod-datainit 容器执行migratecollectstatic并修正媒体目录属主,与 boot.sh 的启动流程对应
SecretextraResources注入15-secrets.yaml 预置明文(必须替换),或用kubectl create secret generic recipes --from-file=...生成
流量入口HTTPRoute(Gateway API)70-ingress.yaml(recipes.local占位域名,需修改)

Manifest 方式还给出了一些 Helm 指南未展开的运维细节,可作为补充参考:应用主容器recipesrunAsUser: 65534(nobody)低权限运行,gunicorn 绑定:8080,配置了 liveness/readiness 探针;nginx 容器通过 ConfigMap 10-configmap.yaml 提供/static//media/的静态文件服务。如果你需要按需微调探针、资源配额或安全上下文,直接阅读并修改这些清单会比改写 chart 更直观。

安装后的检查要点

  • 数据库连通性boot.sh会在启动时轮询pg_isready,失败 20 次后容器会打印Database not reachable. Maximum attempts exceeded.并退出,此时优先核对POSTGRES_HOST/POSTGRES_PORT/POSTGRES_USER是否正确。
  • 静态文件:容器启动时执行collectstatic --noinput --clear,首次启动耗时较长属正常现象;若通过 nginx 独立服务静态文件,需确认挂载的staticfiles卷内容完整。
  • Secret 一致性env段与extraResources中的 Secret 键名必须一一对应(secret-keyusernamepassword),拼写不一致会导致应用启动时读取不到凭据。
  • 版本锁定:建议像 docs/install/k8s/50-deployment.yaml 强调的那样显式固定镜像 tag,避免latest在升级时触发不必要的数据库迁移。

完成以上步骤后,你的 Tandoor Recipes 就已通过 Helm Chart 运行在 Kubernetes 集群中,外部流量经由HTTPRoute到达recipesService。Happy cooking!

【免费下载链接】recipesApplication for managing recipes, planning meals, building shopping lists and much much more!项目地址: https://gitcode.com/GitHub_Trending/re/recipes

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询