0、前言 K8s 是一个开源容器编排平台,可自动执行容器化应用程序的部署、扩展和管理。近年来,K8s 已成为采用云原生架构和容器化技术的组织的标准。
但是由于K8s的复杂性,所以很多公司以及开源组织都在开发相关的工具来简化k8s的使用门槛,这其中就包括两个很优秀的开源工具,Kustomize (K8s 的配置管理器)和Helm (K8s 的包管理器)。
本文将针对二者来进行对比。
Kustomize
Helm
操作方法
overlays
templating
使用成本
简单
复杂
是否支持封装
简单
是
kubectl集成
是
否
kubectl集成
声明式
命令式
1、Kustomize Kustomize 是 k8s集群的配置定制工具。它允许管理员使用非模板文件进行声明性更改,而不影响原始清单文件。
来看一下kubebuilder生成项目的Kustomize配置,以/config/crd目录为例:
1 2 3 4 5 6 7 8 ├── crd │ ├── bases │ │ └── apps.kubenode.alibaba-inc.com_myapps.yaml │ ├── kustomization.yaml │ ├── kustomizeconfig.yaml │ └── patches │ ├── cainjection_in_myapps.yaml │ └── webhook_in_myapps.yaml
其中config/crd目录是执行kubebuilder create api
后生成的,最原始的目录结构是:
1 2 3 ├── crd │ ├── kustomization.yaml │ └── kustomizeconfig.yaml
所以bases子目录和patches子目录都是执行make manifests
后生成的。
执行kubebuilder create api
可以参考:https://blog.csdn.net/qq_41004932/article/details/142702284
执行make manifests
可以参考:https://blog.csdn.net/qq_41004932/article/details/142703870
在 Kubebuilder 生成的项目中,config/crd 目录下的文件主要用于管理和配置自定义资源定义(Custom Resource Definitions, CRDs)。这些文件通过 Kustomize 工具进行管理,以便于在不同的环境中部署和管理 CRDs。下面是每个文件的作用解释:
bases 目录 bases/apps.kubenode.alibaba-inc.com_myapps.yaml: 这个文件包含了自定义资源定义(CRD)的 YAML 描述。它定义了你的自定义资源(Custom Resource, CR)的结构和元数据。 例如,如果我们创建了一个名为 MyApp 的自定义资源,这个文件将描述 MyApp 的 API 版本、资源名称、字段等。
kustomization.yaml: 这个文件是 Kustomize 的配置文件,用于定义如何组合和修改 Kubernetes 资源文件。 它指定了哪些资源文件(如 CRD 文件)需要被应用,并且可以包含补丁文件和其他配置选项。 例如,它可以指定 bases 目录中的 CRD 文件,以及 patches 目录中的补丁文件。
kustomizeconfig.yaml: 这个文件通常用于配置 Kustomize 的一些高级选项,但在这个上下文中可能不是必需的。它可能会包含一些特定的配置项,用于定制 Kustomize 的行为。 在大多数情况下,这个文件可能不需要手动编辑。
patches/cainjection_in_myapps.yaml: 这个文件是一个补丁文件,用于在 CRD 上应用 Webhook 注入(例如,证书注入)。 例如,如果你的 CRD 需要与 mutating 或 validating webhooks 一起工作,这个补丁文件会确保 Webhook 配置正确地注入到 CRD 中。
patches/webhook_in_myapps.yaml: 这个文件也是一个补丁文件,用于在 CRD 上应用 Webhook 配置。 例如,它可能会添加或修改 Webhook 的配置,以便在创建或更新自定义资源时触发特定的行为。
总结
bases 目录:包含 CRD 的基本定义文件。
kustomization.yaml:Kustomize 的配置文件,用于定义如何组合和修改资源文件。
kustomizeconfig.yaml:Kustomize 的高级配置文件(可选)。
patches 目录:包含用于修改 CRD 的补丁文件,通常用于注入 Webhook 配置。
如果我们像让这个crd根据不同的环境做针对性部署的,例如下面的目录结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ├── crd │ ├── bases │ │ └── apps.kubenode.alibaba-inc.com_myapps.yaml │ ├── development │ │ ├── kustomization.yaml │ │ └── patches │ │ └── webhook_in_myapps.yaml │ ├── testing │ │ ├── kustomization.yaml │ │ └── patches │ │ └── webhook_in_myapps.yaml │ ├── production │ │ ├── kustomization.yaml │ │ └── patches │ │ └── webhook_in_myapps.yaml │ ├── kustomization.yaml │ ├── kustomizeconfig.yaml │ └── patches │ ├── cainjection_in_myapps.yaml │ └── webhook_in_myapps.yaml
所有自定义规范都包含在 kustomization.yaml 文件中,该文件将规范叠加在现有清单之上以生成资源的自定义版本。
所以我们可以根据这一特性,针对不同的环境,对crd进行定制。
2、Helm Helm 是一个能够在 K8s 上打包、部署和管理应用程序的工具,即使是最复杂的 K8s 应用程序它都可以帮助定义,安装和升级,同时Helm 也是 CNCF 的毕业项目。 这里涉及到了以及关于helm的重要概念:
Helm Charts:预先配置yaml的模板,在这里叫Chart,用于描述 K8s 应用程序的yaml和配置
Helm Client:用于与 Helm 交互并管理这些Chart版本的命令行界面
Chart 仓库:管理Chart的仓库,跟Maven的Nexus一个意思,比如在公司环境构建上传,在客户的机房连接到这Chart 仓库下载Chart,并部署到k8s中。
2.1 helm示例 helm的示例需要用到kubectl、helm以及k8s集群,相应的安装参考:
Helm Charts 是预先配置的 K8s 资源包。Helm Chart 包含部署特定应用程序或服务所需的所有信息,包括 K8s 清单、环境变量和其他配置
目录名称是Chart的名称,如Helm 文档 所示,我们通过helm create demo命令创建一个Chart,执行完以后,默认会生成一个 nginx 的Chart。
结果:
1 2 $ helm create demo [10:33:35] Creating demo
查看目录结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 . ├── Chart.yaml ├── charts ├── templates │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── deployment.yaml │ ├── hpa.yaml │ ├── ingress.yaml │ ├── service.yaml │ ├── serviceaccount.yaml │ └── tests │ └── test-connection.yaml └── values.yaml 3 directories, 10 files
2.2 Chart.yaml 定义了当前 chart版本,以及描述当前chart用途,其中 name 参数表示 chart 名称,后期上传下载都会用此名称
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 apiVersion: v2 name: demo description: A Helm chart for Kubernetes # A chart can be either an 'application' or a 'library' chart. # # to be deployed. # # a dependency of application charts to inject those utilities and functions into the rendering # pipeline. Library charts do not define any templates and therefore cannot be deployed. type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. appVersion: "1.16.0"
2.3 values.yaml 可变参数,都是在此文件中定义,在yaml模板中引用,比如:image.repository,而引用则通过.Values+变量的名进行引用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 # Default values for demo. # 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: "" 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: {}
2.4 _helpers.tpl 定义通用代码块,然后yaml 文件会通过 include 引用
定义:
1 2 3 {{- define "demo.name" -}} {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} {{- end }}
引用:
1 {{ include "demo.fullname" . }}
2.5 templates 此目录主要存放的是要部署的 yaml文件模板,同时也包含_helpers.tpl文件,模板会引用values.yaml、Chart.yaml定义的参数,以及_helpers.tpl定义的通用代码块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "demo.fullname" . }} labels: {{- include "demo.labels" . | nindent 4 }} spec: {{- if not .Values.autoscaling.enabled }} replicas: {{ .Values.replicaCount }} {{- end }} selector: matchLabels: {{- include "demo.selectorLabels" . | nindent 6 }} template: metadata: {{- with .Values.podAnnotations }} annotations: {{- toYaml . | nindent 8 }} {{- end }} labels: {{- include "demo.selectorLabels" . | nindent 8 }} spec: {{- with .Values.imagePullSecrets }} imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} serviceAccountName: {{ include "demo.serviceAccountName" . }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} containers: - name: {{ .Chart.Name }} securityContext: {{- toYaml .Values.securityContext | nindent 12 }} image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} ports: - name: http containerPort: {{ .Values.service.port }} protocol: TCP livenessProbe: httpGet: path: / port: http readinessProbe: httpGet: path: / port: http resources: {{- toYaml .Values.resources | nindent 12 }} {{- with .Values.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.affinity }} affinity: {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.tolerations }} tolerations: {{- toYaml . | nindent 8 }} {{- end }}
1 image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
2.5 部署 如果想部署的话,可以使用下面命令进行
可以发现,这里helm是将要部署的资源当作一个整体来进行操作的,也就是讲一个资源的所有yaml配置作为一个整体的形式来进行操作。
3、主要差异 3.1 操作方法 Kustomize 依赖特定于目录的kustomization.yaml文件来构建各个资源并对其进行更改。这些文件将补丁和覆盖应用到共享基文件夹中声明的资源,以提供自动化的多环境配置。
Helm 通过引用value.yaml文件作为变量源,使用模板生成有效的 K8s 配置。模板目录托管 Helm Chart在部署期间用于创建资源的文件。
3.2 便捷性 从K8s 版本 1.14 开始,Kustomize 与 kubectl CLI 捆绑在一起,因此不需要掌握任何其他工具。Kustomize 支持声明式部署,并对每个文件使用纯 YAML,从而更容易使用。
Helm 为K8s包管理任务添加了额外的抽象层,从而加快了希望简化集群配置和发布自动化的团队的学习曲线。Helm Chart 相对Kustomize复杂,不过功能更加强大。
3.3 打包 Kustomize 缺乏的打包功能,并且每个资源都必须在基本文件夹中声明,并在覆盖kustomization.yaml文件中单独声明变体。
而Helm将所有必需的K8s资源都打包到一个文件夹中,该文件夹可以根据需要重复使用。Helm 还允许设置应用程序默认值,并且使用values.yaml文件修改参数,从而注入引用的 yaml 文件中。
3.4 原生 kubectl 集成 从 K8s 1.14 版开始,Kustomize 就预装了 kubectl,Helm 并未与 K8s 预先集成,因此必须手动安装 Helm。
3.5 Kustomize 与 Helm - 何时使用 3.5.1 何时使用 Kustomize Kustomize允许在不改变原始文件的情况下进行精确更改。 因此可以有以下场景
应用配置的变体管理:当你需要管理多个环境(例如开发、测试、生产)中应用的变体时,Kustomize 是一个很好的选择。它允许你为不同的环境创建不同的配置,并使用一套基础配置来定义通用部分。
持续集成和持续部署(CI/CD)流水线:Kustomize 可以与 CI/CD 工具集成,帮助你实现自动化部署。通过在流水线中使用 Kustomize,你可以根据需要生成特定环境的配置,并将其应用到集群中。
3.5.2 何时使用 Helm Helm 将所有 K8s 对象封装到一个包中,减少了与各个yaml 文件的交互。除此之外,大多数第三方供应商还提供预构建的 Helm 图表,以简化将其产品部署到 K8s 中的过程。因此,Helm 通常是安装现成解决方案(例如监控、数据库和消息中间件等)的首选