部署本地 Helm Chart

KubernetesBeginner
立即练习

介绍

之前的部署实验直接使用了原始的 Kubernetes 清单(manifests)。Helm 在这些清单之上增加了一个打包层。Helm chart 将相关的 Kubernetes 模板存储在一起,通过 values.yaml 暴露可重用的设置,并将渲染后的对象安装为一个命名的发布版本(release)。

在本实验中,你将构建一个小型本地 chart,而不是从仓库下载。你将编写 chart 元数据、配置值、Deployment 模板和 Service 模板,在安装前渲染 chart,然后通过更改配置值来升级发布版本。这有助于你专注于 CKAD 的核心技能:理解本地 chart 如何转化为普通的 Kubernetes 对象。

准备 Helm 工作空间

在此步骤中,你将准备一个命名空间,并确认本地 Helm chart 工作流所需的工具。

从 /home/labex/project 开始。本实验将 chart 目录、生成的清单以及所有命令都保存在此工作空间中。

mkdir -p /home/labex/project
cd /home/labex/project

检查 Kubernetes API 服务器是否可达。如果虚拟机刚启动且节点尚未就绪,请等待几秒钟后再次运行该命令。

kubectl get nodes --request-timeout=5s

预期输出包括:

NAME         STATUS   ROLES           AGE   VERSION
labex-v135   Ready    control-plane   ...   v1.35...

等待集群网络 Pod 变为就绪状态。由于 chart 将创建一个 Service,因此在进行流量测试之前,应用程序 Pod 需要集群网络支持。

kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s

预期输出:

pod/calico-node-... condition met

创建一个名为 ckad-prep-helm 的命名空间,并将其设置为当前命名空间:

kubectl create namespace ckad-prep-helm
kubectl config set-context --current --namespace=ckad-prep-helm

确认当前命名空间和 Helm 客户端。Helm 3 使用当前的 kubeconfig 直接与 Kubernetes 交互;不再有独立的服务器端 Tiller 组件。

kubectl config view --minify --output 'jsonpath={..namespace}'; echo
helm version --short

预期输出包括:

ckad-prep-helm
v...

创建并渲染本地 Chart

在此步骤中,你将创建一个最小化的本地 Helm chart,并在安装前对其进行渲染。

chart 目录包含几个重要部分。Chart.yaml 描述了 chart 本身。values.yaml 包含默认设置。templates/ 下的文件是带有模板表达式(如 {{ .Values.replicaCount }})的 Kubernetes 清单。当 Helm 渲染或安装 chart 时,它会将这些表达式替换为具体的值。

创建 chart 目录:

mkdir -p local-web-chart/templates

编写 Chart.yaml。chart 名称与发布名称不同;发布名称是在安装 chart 时选择的。

cat > local-web-chart/Chart.yaml <<'EOF'
apiVersion: v2
name: local-web
description: A small local chart for CKAD deployment practice
type: application
version: 0.1.0
appVersion: "1.0"
EOF

编写 values.yaml。这些默认值控制 Pod 数量、容器镜像、Service 端口以及应用程序提供的消息。

cat > local-web-chart/values.yaml <<'EOF'
replicaCount: 2
image:
  repository: busybox
  tag: "1.36"
service:
  port: 80
  targetPort: 8080
message: helm-v1
EOF

创建 Deployment 模板。该模板在对象名称和标签中使用发布名称,因此同一个 chart 可以以不同的发布名称安装多次。

cat > local-web-chart/templates/deployment.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-web
  labels:
    app.kubernetes.io/name: {{ .Chart.Name }}
    app.kubernetes.io/instance: {{ .Release.Name }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app.kubernetes.io/name: {{ .Chart.Name }}
      app.kubernetes.io/instance: {{ .Release.Name }}
  template:
    metadata:
      labels:
        app.kubernetes.io/name: {{ .Chart.Name }}
        app.kubernetes.io/instance: {{ .Release.Name }}
    spec:
      terminationGracePeriodSeconds: 0
      containers:
      - name: web
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        imagePullPolicy: IfNotPresent
        command:
        - /bin/sh
        - -c
        - |
          mkdir -p /www
          echo {{ .Values.message | quote }} > /www/index.html
          httpd -f -p {{ .Values.service.targetPort }} -h /www
        ports:
        - containerPort: {{ .Values.service.targetPort }}
        readinessProbe:
          httpGet:
            path: /
            port: {{ .Values.service.targetPort }}
          initialDelaySeconds: 1
          periodSeconds: 2
EOF

创建 Service 模板。注意,Service 选择器使用了与 Pod 模板相同的标签。

cat > local-web-chart/templates/service.yaml <<'EOF'
apiVersion: v1
kind: Service
metadata:
  name: {{ .Release.Name }}
  labels:
    app.kubernetes.io/name: {{ .Chart.Name }}
    app.kubernetes.io/instance: {{ .Release.Name }}
spec:
  selector:
    app.kubernetes.io/name: {{ .Chart.Name }}
    app.kubernetes.io/instance: {{ .Release.Name }}
  ports:
  - port: {{ .Values.service.port }}
    targetPort: {{ .Values.service.targetPort }}
EOF

运行 helm lint 来检查 chart 结构和模板问题:

helm lint ./local-web-chart

预期输出包括:

1 chart(s) linted, 0 chart(s) failed

在本地渲染 chart。helm template 会打印出 Helm 将发送给 API 服务器的 Kubernetes YAML,但不会创建任何对象。

helm template local-web ./local-web-chart | sed -n '1,120p'

预期输出包括一个名为 local-web 的 Service 和一个名为 local-web-web 的 Deployment。

将 Chart 安装为发布版本

在此步骤中,你将把本地 chart 安装到 ckad-prep-helm 命名空间中。

安装 chart 会创建一个 Helm 发布版本。在本实验中,发布名称为 local-web。Helm 会记录发布元数据,而 Kubernetes 会接收到普通的 Deployment 和 Service 等对象。

安装 chart:

helm install local-web ./local-web-chart

预期输出包括:

NAME: local-web
STATUS: deployed

等待 chart 创建的 Deployment 就绪:

kubectl rollout status deployment/local-web-web --timeout=120s

预期输出:

deployment "local-web-web" successfully rolled out

检查发布版本及其创建的 Kubernetes 对象:

helm list
kubectl get deployment,service -l app.kubernetes.io/instance=local-web

预期输出包括:

local-web
deployment.apps/local-web-web
service/local-web

创建一个客户端 Pod 并向 Service 发送请求。这证实了 chart 不仅创建了对象,而且安装的应用程序确实是可访问的。

kubectl run chart-client --image=busybox:1.36 --restart=Never --command -- sleep 3600
kubectl wait --for=condition=Ready pod/chart-client --timeout=120s
kubectl exec chart-client -- wget -qO- http://local-web

预期输出:

helm-v1

使用新配置值升级发布版本

在此步骤中,你将通过覆盖 chart 的配置值来升级现有的发布版本。

该 chart 已经包含了可重用的模板。你无需编辑模板文件即可更改消息或副本数量。helm upgrade 会使用新的配置值重新渲染同一个 chart,更新 Kubernetes 对象,并记录一个新的发布修订版本。

升级发布版本,使其通过 3 个副本提供 helm-v2 消息:

helm upgrade local-web ./local-web-chart --set message=helm-v2 --set replicaCount=3

预期输出包括:

Release "local-web" has been upgraded.
STATUS: deployed

等待升级后的 Deployment 就绪:

kubectl rollout status deployment/local-web-web --timeout=120s

预期输出:

deployment "local-web-web" successfully rolled out

检查发布历史记录以及当前随发布版本存储的配置值:

helm history local-web
helm get values local-web

预期输出包括两个修订版本以及被覆盖的配置值:

REVISION
1
2
message: helm-v2
replicaCount: 3

检查正在运行的 Deployment 和应用程序响应:

kubectl get deployment local-web-web
kubectl exec chart-client -- wget -qO- http://local-web

预期输出包括:

3/3
helm-v2

总结

你通过 chart 元数据、默认配置值和 Kubernetes 模板创建了一个本地 Helm chart。你在安装前渲染了 chart,将其安装为发布版本,测试了 Service,并通过覆盖配置值升级了发布版本。核心思想是:Helm 将可重复的应用程序部署工作打包,同时仍然生成你可以使用 kubectl 检查的普通 Kubernetes 对象。