news 2026/9/25 2:54:49

使用 Helm 在裸金属 Kubernetes 集群上部署 Nginx 应用:Chart 模板、占位符与 Ingress 暴露全流程实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用 Helm 在裸金属 Kubernetes 集群上部署 Nginx 应用:Chart 模板、占位符与 Ingress 暴露全流程实战
  • 云原生
  • CI/CD
  • 运维

【免费下载链接】DevOps-Guide

DevOps Guide - Development to Production all configurations with basic notes to debug efficiently.

项目地址:https://gitcode.com/gh_mirrors/de/DevOps-Guide
点击查看免费下载

导读

本文以 package-managers/helm/helm-demo.md 中的实战演示为核心,完整还原「用 Helm 将 Nginx 应用部署到裸金属 Kubernetes 集群」的端到端流程:从Chart.yaml元数据、templates/三件套(Deployment、Service、Ingress)的编写,到helm install一键发布、{{ .Values.scale }}占位符实现配置化、helm upgrade --set动态扩缩容,以及helm list/helm uninstall的发布管理。场景使用 Nginx Ingress Controller 与 MetalLB 在裸金属环境暴露服务,读完本文你将具备用 Helm 封装并管理一个可复现、可配置 Kubernetes 应用发布的最小工程能力。

实战背景:裸金属集群上的「Helm + Ingress + MetalLB」组合

本演示面向裸金属(bare-metal)Kubernetes 集群:没有云厂商托管的负载均衡器,因此需要借助两个组件打通外部访问链路:

  • MetalLB:为裸金属集群提供 LoadBalancer 类型的 Service 支持,分配外部 IP;
  • Nginx Ingress Controller:作为集群入口,根据 Ingress 规则将外部流量路由到内部 Service。

而 Helm 的作用则是把 Deployment、Service、Ingress 这些原本需要逐个kubectl apply的资源,打包成一个可版本化、可参数化的 Chart,实现「一条命令部署整个应用」。

整个工程位于helm-demo目录,结构如下:

k8s-master@master:~/helm-demo$ ls Chart.yaml templates values.yaml

一个标准 Chart 由三部分构成:描述自身的Chart.yaml、渲染资源模板的templates/目录、以及提供默认参数值的values.yaml。关于 Chart 文件结构的基本约定,可参考仓库中的 helm 概念文档。

第一步:用 Chart.yaml 描述发布元数据

Chart 的元数据集中在Chart.yaml中,它定义了 Chart 的名称、版本、用途说明和维护者信息,是 Helm 识别和版本化管理每个发布的基础:

# helm-demo/Chart.yaml name: my-first-demo version: 1.0.0 description: easy helm demo maintainers: - name: Siwar

各字段含义:

字段作用
nameChart 名称,同时也是安装后 Release 默认名称的一部分
versionChart 版本号,遵循语义化版本,升级 Chart 时递增
description对该 Chart 的简要说明
maintainers维护者列表,帮助使用者了解该 Chart 的负责人

这份元数据不仅用于描述,还会在模板渲染阶段通过内置对象Chart暴露给模板使用——例如{{ .Chart.Name }}-{{ .Chart.Version }}会渲染出my-first-demo-1.0.0。更多内置对象说明见 Helm 模板内置对象清单。

第二步:编写 templates/ 下的三类核心资源

templates/目录是 Chart 的灵魂,里面每个 YAML 文件都会被 Helm 渲染后提交到集群。本演示包含三个文件:

k8s-master@master:~/helm-demo/templates$ ls deployment.yaml ingress.yaml service.yaml

2.1 deployment.yaml:声明 Nginx 工作负载

# helm-demo/templates/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: my-nginx-deployment spec: selector: matchLabels: app: nginx replicas: 3 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80

关键点:

  • selector.matchLabels与template.metadata.labels必须一致(此处均为app: nginx),这是 Deployment 关联 Pod 的依据;
  • replicas: 3声明期望副本数,由 ReplicaSet 保证任何时刻都有 3 个 Pod 可用(若 Pod 意外死亡会自动重建,相关机制可参考 Kubernetes 概念文档 中的 Deployment / ReplicaSet 说明);
  • 容器镜像固定为nginx:1.14.2,暴露容器端口 80。

2.2 service.yaml:为 Pod 提供稳定访问入口

# helm-demo/templates/service.yaml apiVersion: v1 kind: Service metadata: name: my-nginx-service spec: selector: app: nginx ports: - name: main protocol: TCP port: 80

Service 通过selector: app: nginx收集后端 Pod,为它们提供一个稳定的 ClusterIP 与 DNS 名称。注意:Pod 会随调度变动 IP,而 Service 的访问入口是固定的——这正是 Kubernetes Service 抽象的核心价值。

2.3 ingress.yaml:将流量按路径路由进集群

# helm-demo/templates/ingress.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-nginx-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / http.port: "443" spec: ingressClassName: nginx rules: - http: paths: - path: /testpath pathType: Prefix backend: service: name: my-nginx-service port: number: 80

Ingress 是集群外部流量进入内部 Service 的「路由表」,本示例要点:

  • ingressClassName: nginx指定由Nginx Ingress Controller处理该 Ingress(对应裸金属环境的入口组件);
  • path: /testpath+pathType: Prefix表示所有以/testpath开头的请求都会被转发到后端my-nginx-service的 80 端口;
  • 注解nginx.ingress.kubernetes.io/rewrite-target: /会把请求路径重写为/后再转发,这样后端 Nginx 就能正确响应根路径;
  • 演示中通过http.port: "443"注解在 Ingress 上暴露了443 端口(HTTPS 入口),这也是裸金属场景下由 MetalLB 分配外部 IP、Nginx Ingress Controller 监听对外端口完成流量接入的体现。

至此,三个模板文件已经构成了「Deployment(运行)→ Service(内部寻址)→ Ingress(外部路由)」的完整链路,Helm 将按模板逐个创建这些资源。

第三步:helm install 一键部署并验证

3.1 执行安装

模板写好后,无需逐个kubectl apply,一条命令即可完成整套资源的创建:

k8s-master@master:~$ helm install --generate-name helm-demo/ NAME: helm-demo-1660310990 LAST DEPLOYED: Fri Aug 12 06:29:50 2022 NAMESPACE: default STATUS: deployed REVISION: 1 TEST SUITE: None

--generate-name会为 Release 自动生成唯一名称(此处为helm-demo-1660310990)。输出信息解读:

输出项含义
NAMERelease 名称,后续upgrade/uninstall/rollback都以它为目标
NAMESPACE部署到的命名空间(默认default)
STATUSdeployed表示发布成功
REVISION发布修订号,首次安装为 1,每次 upgrade/rollback 递增
TEST SUITE若 Chart 定义了测试钩子会显示,本示例为None

上述REVISION等字段也对应模板内置对象Release.Revision的取值来源,详见 Helm 模板内置对象清单。

3.2 用 kubectl get all 核对集群状态

部署后立刻检查集群内的全部资源:

k8s-master@master:~$ kubectl get all NAME READY STATUS RESTARTS AGE pod/my-nginx-deployment-9456bbbf9-c74rs 0/1 ContainerCreating 0 11s pod/my-nginx-deployment-9456bbbf9-k4cdb 0/1 ContainerCreating 0 11s pod/my-nginx-deployment-9456bbbf9-mm7dm 0/1 ContainerCreating 0 11s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 22m service/my-nginx-service ClusterIP 10.100.146.193 <none> 80/TCP 11s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/my-nginx-deployment 0/3 3 0 11s NAME DESIRED CURRENT READY AGE replicaset.apps/my-nginx-deployment-9456bbbf9 3 3 0 11s

可以看到 Helm 已一次性创建出:

  • 3 个 Pod(状态ContainerCreating,正在拉取 nginx 镜像);
  • 1 个 Servicemy-nginx-service(ClusterIP10.100.146.193,暴露 80/TCP);
  • 1 个 Deployment(期望 3、当前 3);
  • 1 个 ReplicaSetmy-nginx-deployment-9456bbbf9(由 Deployment 自动生成)。

待 Pod 变为Running后,就可以通过 Ingress 分配到的外部 IP(示例中为192.168.1.240)在浏览器中访问http://192.168.1.240/testpath验证 Nginx 页面。

3.3 对比传统方式:kubectl apply 逐个提交

回顾整个部署过程:如果不用 Helm,就需要对 Deployment、Service、Ingress 三个 YAML 文件分别执行kubectl apply -f deployment.yaml、kubectl apply -f service.yaml、kubectl apply -f ingress.yaml,且没有版本管理与回滚能力。而 Helm 用一个 Chart 封装了「一组相关资源」,一次helm install即可完成发布——这正是「Helm 是 Kubernetes 的包管理器」这一说法的直观体现。

第四步:用 values.yaml 与占位符实现配置化

4.1 {{ .Values.scale }} 占位符

Helm 最实用的能力之一就是模板占位符:把写死在 YAML 里的数值替换为模板表达式,运行时由values.yaml或命令行参数注入。改造后的 Deployment 模板如下:

# helming-once-more/templates/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: my-nginx-deployment spec: selector: matchLabels: app: nginx replicas: {{.Values.scale}} template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80

{{ .Values.scale }}表示「取 values.yaml 中scale键的值」,其效果是:修改配置时无需改动模板文件本身,只要调整values.yaml即可改变最终生成的清单。

对应的values.yaml内容:

k8s-master@master:~/helming-once-more$ cat values.yaml scale: 3

4.2 占位符背后的内置对象体系

Values只是 Helm 模板内置对象之一。完整的可用对象还包括:

  • Release:描述当前发布,如Release.Name(发布名)、Release.Namespace(目标命名空间)、Release.IsUpgrade/Release.IsInstall(当前操作类型)、Release.Revision(修订号)、Release.Service(固定为 Helm);
  • Values:来自values.yaml与用户-f/--set传入的值,默认空;
  • Chart:Chart.yaml的全部内容;
  • Files:访问 Chart 内非模板文件,提供Get、GetBytes、Glob、Lines、AsSecrets、AsConfig等方法;
  • Capabilities:探测集群能力,如Capabilities.KubeVersion.Version、Capabilities.APIVersions.Has;
  • Template:当前模板信息(Name、BasePath)。

详细字段说明见 Helm 模板内置对象清单。

4.3 用新值重新安装

带占位符的 Chart 安装方式与之前一致:

k8s-master@master:~$ helm install another-demo helming-once-more/ NAME: another-demo LAST DEPLOYED: Fri Aug 12 11:48:53 2022 NAMESPACE: default STATUS: deployed REVISION: 1 TEST SUITE: None

验证 Pod 数量是否与values.yaml中的scale: 3一致:

k8s-master@master:~$ kubectl get pods NAME READY STATUS RESTARTS AGE my-nginx-deployment-9456bbbf9-mx45n 1/1 Running 0 3m9s my-nginx-deployment-9456bbbf9-rqkmw 1/1 Running 0 3m9s my-nginx-deployment-9456bbbf9-tl4wj 1/1 Running 0 3m9s

正如预期,由于values.yaml中scale: 3,集群中正好运行着3 个 Pod——模板与配置解耦的价值在此体现:同一套模板,改一个参数即可复用。

第五步:helm upgrade --set 动态扩缩容

当业务需要调整规模时,不必改文件、更不必卸载重装,使用helm upgrade配合--set直接覆盖参数:

k8s-master@master:~$ helm upgrade --set scale=5 another-demo ./helming-once-more/ Release "another-demo" has been upgraded. Happy Helming! NAME: another-demo LAST DEPLOYED: Fri Aug 12 11:55:14 2022 NAMESPACE: default STATUS: deployed REVISION: 2 TEST SUITE: None

注意REVISION已从 1 变为2——这是一次新的发布修订。随后查看 Pod:

k8s-master@master:~$ kubectl get pod NAME READY STATUS RESTARTS AGE my-nginx-deployment-9456bbbf9-7ddlm 1/1 Running 0 95s my-nginx-deployment-9456bbbf9-mx45n 1/1 Running 0 8m9s my-nginx-deployment-9456bbbf9-rqkmw 1/1 Running 0 8m9s my-nginx-deployment-9456bbbf9-tl4wj 1/1 Running 0 8m9s my-nginx-deployment-9456bbbf9-tpsqv 1/1 Running 0 96s

Pod 数量由 3 平滑扩容到5(新 Pod7ddlm、tpsqv已就绪),全程无需人工编辑任何 YAML。--set的优先级高于values.yaml,适合临时性调整;若要固化配置,应把值写回values.yaml再升级。

模板层面对这类动态渲染还提供了配套能力:quote函数用于给从Values注入的字符串加引号以避免类型歧义,if/else、with、range分别用于条件渲染、作用域限定与循环遍历,lookup函数可查询集群中已存在的资源。这些语法细节可继续阅读 Helm 模板指南。

第六步:helm list 与 helm uninstall 清理

发布管理同样围绕 Release 展开。先列出集群中已安装的 Release:

k8s-master@master:~$ helm list NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION another-demo default 2 2022-08-12 11:55:14.913503686 -0700 PDT deployed another-demo-1.0.0

可以看到another-demo当前为修订 2、状态deployed。不再需要该应用时,一条helm uninstall即可连同其管理的全部资源一并删除:

k8s-master@master:~$ helm uninstall another-demo release "another-demo" uninstalled

对比手工方式——若用kubectl删除,需要分别找到 Deployment、ReplicaSet、Service、Pod 逐个清理且容易遗漏;而 Helm 通过 Release 记录「这个发布创建了哪些资源」,卸载时按记录统一回收,这也是 Helm 管理应用生命周期的核心优势。

附录:围绕本演示的 Helm 生态延伸

A. 前置:安装 Helm CLI

本演示假设环境已具备helm命令。若尚未安装,可参考仓库中的 Helm 安装指南,支持多种方式:下载官方二进制 release 解压后放入PATH(如tar -zxvf helm-v3.x.x-linux-amd64.tar.gz后mv linux-amd64/helm /usr/local/bin/helm)、使用官方安装脚本(curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3后执行),以及brew install helm(macOS)、choco install kubernetes-helm(Windows)、Apt/Snap(Linux)等包管理器途径。

B. 进阶:Chart Hooks 介入发布生命周期

生产环境往往需要在发布的关键节点执行额外动作(如备份数据库、迁移数据、优雅下线)。Helm 通过Hooks机制支持在 Release 生命周期的特定时点介入,常用钩子如下(完整列表见 helm 概念文档):

Hook触发时机
pre-install模板渲染后、资源创建前
post-install所有资源加载进集群后
pre-delete删除请求发起后、资源删除前
post-delete所有资源删除后
pre-upgrade升级请求模板渲染后、资源更新前
post-upgrade所有资源升级完成后
pre-rollback回滚请求模板渲染后、资源回滚前
post-rollback回滚完成后
test执行helm test子命令时

例如:升级前执行一个 Job 备份数据库、删除前优雅摘除服务流量,都是 Hooks 的典型用法。它们与普通模板写法一致,仅通过特殊注解让 Helm 以不同方式调度。

C. 原理延伸:模板渲染与内置对象

本演示中的{{ .Values.scale }}只是 Helm 模板引擎的冰山一角。深入 Helm 模板指南 可系统掌握:内置对象(Release / Values / Chart / Files / Capabilities / Template)、lookup运行时查询、quote引用、以及if/else、with、range三类流程控制结构。理解这些机制后,你就能把本演示的最小 Chart 演进为可处理条件分支、循环渲染与动态配置的完整生产级 Chart。


至此,从 Chart 骨架搭建、三模板编写、一键安装、参数化占位、动态升级到最终卸载,一条完整的 Helm 发布流水线已在裸金属集群上跑通。你可以基于helm-demo目录结构(Chart.yaml+templates/+values.yaml)把它复制为任何新应用的起点:替换镜像、调整values.yaml参数、增加 Hooks,即可获得一套可版本化、可回滚、可参数化的 Kubernetes 发布方案。

  • 云原生
  • CI/CD
  • 运维

【免费下载链接】DevOps-Guide

DevOps Guide - Development to Production all configurations with basic notes to debug efficiently.

项目地址:https://gitcode.com/gh_mirrors/de/DevOps-Guide
点击查看免费下载
上一篇:WireMock JSON模式匹配:验证请求数据结构
下一篇:告别繁琐标注:Sketch Measure与Runner集成的3分钟效率革命

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/25 2:54:43

MySQL报错only_full_group_by:原因、排查与SQL改写实战

最近群里一位老同事贴了张报错截图&#xff0c;红彤彤一行英文&#xff1a;this is incompatible with sql_modeonly_full_group_by。这大概是 MySQL 5.7 之后后端同学最常撞见的“老朋友”了。很多人第一反应是“SQL 哪里写错了”&#xff0c;但把 SQL 翻来覆去看&#xff0c;…

作者头像 李华
网站建设 2026/9/25 2:54:35

USB转I2C适配器实现400KHz总线扫描与Excel导出实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 2:52:33

HHO-LSBoost多输入回归预测:哈里斯鹰优化与Matlab实现

做预测建模这些年&#xff0c;我最深刻的体会就是&#xff1a;调参的功夫往往比跑模型本身还多。尤其是用集成学习做回归预测时&#xff0c;弱学习器的数量、学习率、树深这些超参数&#xff0c;直接决定了模型的上限&#xff0c;可手动一个个试又费时又费力。所以当我尝试把哈…

作者头像 李华