如今,Kubernetes 已成为 DevOps 从业者编排容器的必备工具。获得应用程序的 Docker 映像后,您必须编写 YAML 清单来定义 Kubernetes 工作负载。接下来,使用kubectl命令部署它们。
这种部署方式适用于只有一个应用程序的情况。当您开始拥有许多应用程序和多个环境时,它就会变得不堪重负。通常,90% 的时间您都会定义相同的 YAML 文件。
在这里,我们将重点讨论如何使用 Helm 智能管理应用程序。
通过本教程中的实践来学习 Helm。了解 Helm 是什么以及如何使用 Helm 图表打包应用程序。管理 Kubernetes 中的升级和回滚
什么是Helm?
Helm是 Kubernetes 的包管理器。Helm 是一个开源项目,最初由DeisLabs创建,并捐赠给云原生基金会( CNCF )。CNCF 现在维护该项目并已毕业。这意味着它已经成熟,而不仅仅是一种时尚。
包管理在软件行业并不是一个新概念。在 Linux 发行版上,您可以使用YUM/RPM或APT等包管理器来管理软件安装和删除。在 Windows 上,您可以在 Mac 上使用Chocolatey或Homebrew。
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 图表的树结构
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