什么是Helm? Kubernetes 初学者快速入门教程
在本教程中通过实践学习 Helm。了解 Helm 是什么以及如何使用 Helm 图表打包应用程序。管理 Kubernetes 中的升级和回滚
如今,Kubernetes 已成为 DevOps 从业者编排容器的必备工具。有了应用程序的 Docker 映像后,您必须编写 YAML 清单来定义 Kubernetes 工作负载。接下来,使用kubectl命令部署它们。
这种部署方式适用于只有一个应用程序的情况。当您开始拥有许多应用程序和多个环境时,它就会变得不堪重负。通常您会在 90% 的时间内定义相同的 YAML 文件。
在这里,我们将重点介绍如何使用 Helm 智能地管理应用程序。
什么是Helm?
[图片上传失败...(image-8fa3af-1684742728274)]
Helm是 Kubernetes 的包管理器。Helm 是一个开源项目,最初由DeisLabs创建并捐赠给Cloud Native Foundation ( CNCF )。CNCF 现在维护并毕业了该项目。这意味着它已经成熟,而不仅仅是一种时尚。
包管理在软件行业中并不是一个新概念。在 Linux 发行版上,您可以使用YUM/RPM或APT等包管理器来管理软件安装和删除。在 Windows 上,您可以在 Mac 上使用Chocolatey或Homebrew。
Helm 让您可以在 Kubernetes 中打包和部署完整的应用程序。包称为“图表”。Helm 使用基于Go 模板的模板系统从图表中呈现 Kubernetes 清单。图表是分隔模板和值的一致结构。
作为一个包,图表还可以管理与其他图表的依赖关系。例如,如果您的应用程序需要 MySQL 数据库才能工作,您可以将图表作为依赖项包含在内。当 Helm 在 chart 目录的顶层运行时,它会安装整个依赖项。您只需一个命令即可将您的应用程序呈现并发布到 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
该服务将 NGINX 暴露给外部。与 pod 的链接是通过选择器完成的:
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 8080
现在我们必须使用 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 80/TCP 4m58s
- YAML 清单中的特定值是硬编码的,不可重复使用。
- 要指定的冗余信息(例如标签和选择器)会导致潜在的错误。
- Kubectl 不会在执行后处理潜在的错误。您必须一个接一个地部署每个文件。
- 没有变化的可追溯性。
从头开始创建 Helm Chart
Helm 可以在单个命令行中创建图表结构:
$ helm create nginx
了解 Helm 图表结构
[图片上传失败...(image-26dcb4-1684742728274)]
-
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: {}
您可以指定一个特定的values.yaml
文件来为特定于环境的设置自定义部署
安装 Helm Chart
部署 Helm chart 之前的好建议是,如果您进行了更新,请运行 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