Helm初学者快速入门教程

1,639 阅读7分钟

如今,Kubernetes 已成为 DevOps 从业者编排容器的必备工具。获得应用程序的 Docker 映像后,您必须编写 YAML 清单来定义 Kubernetes 工作负载。接下来,使用kubectl命令部署它们。

这种部署方式适用于只有一个应用程序的情况。当您开始拥有许多应用程序和多个环境时,它就会变得不堪重负。通常,90% 的时间您都会定义相同的 YAML 文件。

在这里,我们将重点讨论如何使用 Helm 智能管理应用程序。

通过本教程中的实践来学习 Helm。了解 Helm 是什么以及如何使用 Helm 图表打包应用程序。管理 Kubernetes 中的升级和回滚


什么是Helm?

头盔标志

Helm是 Kubernetes 的包管理器。Helm 是一个开源项目,最初由DeisLabs创建,并捐赠给云原生基金会( CNCF )。CNCF 现在维护该项目并已毕业。这意味着它已经成熟,而不仅仅是一种时尚。

包管理在软件行业并不是一个新概念。在 Linux 发行版上,您可以使用YUM/RPMAPT等包管理器来管理软件安装和删除。在 Windows 上,您可以在 Mac 上使用ChocolateyHomebrew

Helm 允许您在 Kubernetes 中打包和部署完整的应用程序。包称为“Chart”。Helm 使用基于Go 模板的模板系统从图表中呈现 Kubernetes 清单。图表是分隔模板和值的一致结构。

作为一个包,图表还可以管理与其他图表的依赖关系。例如,如果您的应用程序需要 MySQL 数据库才能工作,您可以将图表作为依赖项包含在内。当 Helm 在图表目录的顶层运行时,它会安装整个依赖项。您只需一个命令即可渲染应用程序并将其发布到 Kubernetes。

Helm 图表使用版本来跟踪清单中的更改 - 因此您可以为特定基础设施配置安装特定图表版本。Helm 在专用工作区中保存所有已部署图表的发布历史记录。如果发生错误,这使得应用程序更新和回滚变得更加容易。

Helm 允许您压缩图表。其结果是一个与 Docker 镜像相当的工件。然后,您可以将其发送到远程存储库以供重用和共享。


使用 Helm 有什么好处?

  • Helm 使您能够使用单个命令安装应用程序。图表可以包含其他图表作为依赖项。因此,您可以使用 Helm 部署整个堆栈。您可以像docker-compose一样使用 Helm ,但适用于 Kubernetes。
  • 图表包含各种 Kubernetes 资源的模板,以形成完整的应用程序。这降低了微服务的复杂性并简化了它们在 Kubernetes 中的管理。
  • 图表可以被压缩并发送到远程存储库。这会为 Kubernetes 创建一个应用程序工件。您还可以从存储库获取并部署现有的 Helm 图表。这是可重用性和共享性的一个优点。
  • Helm 在 Helm 工作区中维护已部署发行版本的历史记录。当出现问题时,回滚到以前的版本很简单——Helm 可以促进金丝雀发布,实现零停机部署。
  • Helm 使部署具有高度可配置性。应用程序可以在部署过程中即时定制。通过更改参数,您可以在开发、登台和生产等多种环境中使用相同的图表。
  • 简化 CI/CD 管道 – 转发 GitOps 最佳实践。

快速查看 Helm 解决的问题

基本的 Kubernetes 实践是手动编写 YAML 清单。我们将创建最少的 YAML 文件以在 Kubernetes 中部署 NGINX。

这是将创建 Pod 的 Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.21.6
        ports:
        - containerPort: 80

deploy.yaml

该服务将 NGINX 暴露给外部。与 pod 的链接是通过选择器完成的:

apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080

NGINX 的 Kubernetes 服务:service.yaml

现在我们必须使用 kubectl 命令创建之前的资源:

$ kubectl create -f deployment.yaml
$ kubectl create -f service.yaml

我们检查所有资源是否已启动并正在运行:

$ kubectl get deployment -l app=nginx
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
nginx   1/1     1            1           8m29s
$ kubectl get pods -l app=nginx                                                                                      
NAME                     READY   STATUS    RESTARTS   AGE
nginx-65b89996ff-dcfs9   1/1     Running   0          2m26s
$ kubectl get svc -l app=nginx 
NAME    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
nginx   ClusterIP   10.106.79.171   <none>        80/TCP    4m58s
  • YAML 清单中的特定值是硬编码的且不可重用。
  • 指定的冗余信息(例如标签和选择器)会导致潜在的错误。
  • Kubectl 不处理执行后潜在的错误。您必须一个接一个地部署每个文件。
  • 没有变更可追溯性。

从头开始创建 Helm 图表

Helm 可以在单个命令行中创建图表结构:

$ helm create nginx

了解 Helm 图表结构

Helm 图表的树结构

Helm 图表的树结构

  • Chart.yaml:包含图表信息的 YAML 文件。
  • charts:包含此图表所依赖的任何图表的目录。
  • templates:Helm 可以在此处查找服务、部署和其他 Kubernetes 对象的 YAML 定义。您可以添加或替换您自己的生成的 YAML 文件。
  • templates/NOTES.txt:这是一个模板化的纯文本文件,在图表成功部署后打印出来。这是一个有用的地方,可以简要描述使用图表的后续步骤。
  • templates/_helpers.tpl: 该文件是模板部分的默认位置。名称以下划线开头的文件被假定为内部_没有_清单。这些文件不会呈现给 Kubernetes 对象定义,但可以在其他图表模板中随处使用。
  • templates/tests:测试验证您的图表在安装后是否按预期工作
  • values.yaml:该图表的默认配置值

自定义模板

values.yaml默认情况下,部署图表时会自动加载。这里我们将图像标签设置为1.21.5

# Default values for nginx.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

replicaCount: 1

image:
  repository: nginx
  pullPolicy: IfNotPresent
  # Overrides the image tag whose default is the chart appVersion.
  tag: "1.21.5"

imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""

serviceAccount:
  # Specifies whether a service account should be created
  create: true
  # Annotations to add to the service account
  annotations: {}
  # The name of the service account to use.
  # If not set and create is true, a name is generated using the fullname template
  name: ""

podAnnotations: {}

podSecurityContext: {}
  # fsGroup: 2000

securityContext: {}
  # capabilities:
  #   drop:
  #   - ALL
  # readOnlyRootFilesystem: true
  # runAsNonRoot: true
  # runAsUser: 1000

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: false
  className: ""
  annotations: {}
    # kubernetes.io/ingress.class: nginx
    # kubernetes.io/tls-acme: "true"
  hosts:
    - host: chart-example.local
      paths:
        - path: /
          pathType: ImplementationSpecific
  tls: []
  #  - secretName: chart-example-tls
  #    hosts:
  #      - chart-example.local

resources: {}
  # We usually recommend not to specify default resources and to leave this as a conscious
  # choice for the user. This also increases chances charts run on environments with little
  # resources, such as Minikube. If you do want to specify resources, uncomment the following
  # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
  # limits:
  #   cpu: 100m
  #   memory: 128Mi
  # requests:
  #   cpu: 100m
  #   memory: 128Mi

autoscaling:
  enabled: false
  minReplicas: 1
  maxReplicas: 100
  targetCPUUtilizationPercentage: 80
  # targetMemoryUtilizationPercentage: 80

nodeSelector: {}

tolerations: []

affinity: {}

值.yaml

您可以指定特定values.yaml文件来自定义特定于环境的设置的部署


安装 Helm Chart

在部署 Helm 图表之前,如果您进行了更新,最好的建议是运行 linter:

$ helm lint nginx
==> Linting nginx
[INFO] Chart.yaml: icon is recommended

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

运行 Helm 以试运行和调试模式安装图表,以确保一切正常:

$ helm install --debug --dry-run nginx nginx 

使用 helm linter 和带有调试模式的试运行安装将为您节省宝贵的开发时间。

要安装图表,请删除该--dry-run标志:

$ helm install nginx nginx          
NAME: nginx
LAST DEPLOYED: Mon Mar 14 12:01:46 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
  export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=nginx,app.kubernetes.io/instance=nginx" -o jsonpath="{.items[0].metadata.name}")
  export CONTAINER_PORT=$(kubectl get pod --namespace default $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
  echo "Visit http://127.0.0.1:8080 to use your application"
  kubectl --namespace default port-forward $POD_NAME 8080:$CONTAINER_PORT

NOTES.txt您可以看到解释如何连接到应用程序的模板化内容。

现在,您可以在 Helm 工作区中检索版本:

$ helm list               
NAME    NAMESPACE       REVISION        UPDATED                                 STATUS          CHART           APP VERSION
nginx   default         1               2022-03-14 12:01:46.926038 +0100 CET    deployed        nginx-0.1.0     1.0.0 

升级 Helm 版本

想象一下您想要升级容器映像以1.21.6用于测试目的。

values.yaml我们将从命令行更改设置,而不是创建新的。

$ helm upgrade nginx nginx --set image.tag=1.21.6
Release "nginx" has been upgraded. Happy Helming!
NAME: nginx
LAST DEPLOYED: Mon Mar 14 12:04:40 2022
NAMESPACE: default
STATUS: deployed
REVISION: 2
NOTES:
1. Get the application URL by running these commands:
  export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=nginx,app.kubernetes.io/instance=nginx" -o jsonpath="{.items[0].metadata.name}")
  export CONTAINER_PORT=$(kubectl get pod --namespace default $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
  echo "Visit http://127.0.0.1:8080 to use your application"
  kubectl --namespace default port-forward $POD_NAME 8080:$CONTAINER_PORT

该 Pod 也使用新的容器镜像:

$ kubectl get pod -l app.kubernetes.io/name=nginx -o jsonpath='{.items[0].spec.containers[0].image}'
nginx:1.21.6

升级在图表历史记录中可见:

$ helm history nginx                                                   
REVISION        UPDATED                         STATUS          CHART           APP VERSION     DESCRIPTION     
1               Mon Mar 14 12:07:33 2022        superseded      nginx-0.1.0     1.0.0           Install complete
2               Mon Mar 14 12:08:25 2022        deployed        nginx-0.1.0     1.0.0           Upgrade complete

可以通过以下方式检查更改helm diff

$ helm diff revision nginx 1 2
default, nginx, Deployment (apps) has changed:
  # Source: nginx/templates/deployment.yaml
  apiVersion: apps/v1
  kind: Deployment
  metadata:
    name: nginx
    labels:
      helm.sh/chart: nginx-0.1.0
      app.kubernetes.io/name: nginx
      app.kubernetes.io/instance: nginx
      app.kubernetes.io/version: "1.0.0"
      app.kubernetes.io/managed-by: Helm
  spec:
    replicas: 1
    selector:
      matchLabels:
        app.kubernetes.io/name: nginx
        app.kubernetes.io/instance: nginx
    template:
      metadata:
        labels:
          app.kubernetes.io/name: nginx
          app.kubernetes.io/instance: nginx
      spec:
        serviceAccountName: nginx
        securityContext:
          {}
        containers:
          - name: nginx
            securityContext:
              {}
-           image: "nginx:1.21.5"
+           image: "nginx:1.21.6"
            imagePullPolicy: IfNotPresent
            ports:
              - name: http
                containerPort: 80
                protocol: TCP
            livenessProbe:
              httpGet:
                path: /
                port: http
            readinessProbe:
              httpGet:
                path: /
                port: http
            resources:
              {}

回滚 Helm 版本

升级尚未结束,您想返回。由于 Helm 保留了所有更改,因此回滚非常简单:

$ helm rollback nginx 1
Rollback was a success! Happy Helming!

Pod 现在回到1.21.5容器镜像:

$ kubectl get pod -l app.kubernetes.io/name=nginx -o jsonpath='{.items[0].spec.containers[0].image}'
nginx:1.21.5

卸载 Helm Chart

卸载 Helm Chart 与安装一样简单:

$ helm uninstall nginx

重用现有 Helm 图表

很多著名的项目都提供了 Helm 图表,使集成更加人性化。他们通过存储库提供图表。您只需将其添加到您这边:

$ helm repo add bitnami https://charts.bitnami.com/bitnami

添加后,更新本地缓存以与远程存储库同步信息:

$ helm repo update

您现在可以在 Kubernetes 集群上安装图表:

$ helm install nginx bitnami/nginx

图表使用默认值进行部署。您可以激发并指定定制values.yaml以满足您的需求!

$ helm install my-release bitnami/nginx -f values.yaml