Kustomize详解与实例 - 如何在k8s中管理多版本y
K8S Kustomize详解与实例
常见的场景
假设您使用一个特定供应商的Helm图表,它对您的需求来说很好,但不完美,需要进行一些定制。您对这个图表进行了fork,并进行了一些配置更改,然后将其应用到您的集群中。几个月后,您的供应商发布了这个图表的新版本,其中包括您需要的一些重要功能。为了使用这些新功能,您必须再次fork新的图表并进行定制。重新fork和定制这些Helm图表将会非常耗时,并增加配置错误的风险,可能会影响产品和服务的稳定性。
上图显示了以 git 事件开始的持续交付管道的常见用例。该事件可能是推送、合并或创建新分支。在这种情况下,Helm 用于生成 yaml 文件,Kustomize 将根据事件使用环境特定值对其进行修补。
Kustomize是什么?
Kustomize 是一种配置管理解决方案,在不改变原始yaml文件的情况下,通过patch有选择地覆盖来生成新的配置,很方便维护多版本的yaml文件,特别是项目较大或者需要处理很多case情况下,非常方便并且易于维护。
Kustomize 是一种强大的配置管理方法,适用于大多数组织构建产品时依赖自己创建的应用程序和常见的现成应用程序的组合。过度定制配置文件不仅降低可重用性,还会导致升级变得困难和痛苦。
利用 kustomize,您的团队可以轻松获取底层组件的基本文件更新,并保持自定义覆盖的完整性。补丁覆盖还可以为您的配置添加维度,可以隔离和排除配置错误,并创建从最广泛到最具体的配置规范的框架。
回顾一下,Kustomize 依赖以下配置管理层系统来实现可重用性:
- 基层 - 指定最常见的资源
- 补丁层 - 指定用例特定资源
Kustomize 功能
如上所述,Kustomize 通常与 Helm 结合使用,并且自2019 年 3 月发布版本 1.14(通过命令调用apply -k)以来,它已嵌入到 Kubernetes 中。
Kustomize 提供以下有价值的功能:
- Kubectl 原生 -无需作为单独的依赖项安装或管理
- 普通 Yaml - 没有复杂的模板语言
- 声明式 - 纯粹声明式(就像 Kubectl 一样)
- 多种配置 - 管理任意数量的不同配置
在深入了解 Kustomize 的功能之前,让我们将 Kustomize 与原生 Helm 和原生 Kubectl 进行比较,以更好地突出它提供的差异化功能。
模板化 | 无模板 | 复杂的模板 | 无模板 |
设置 | 无需单独设置 | 需要设置 | 无需单独设置 |
配置 | 使用一个base文件管理多种配置 | 使用一个base文件管理多种配置 | 每个不同的配置应该有单独的文件 |
易用性 | 简单 | 难 | 简单 |
使用 Kustomize 的好处
1. 可重复使用
Kustomize 允许您在所有环境(开发、暂存、生产)中重复使用一个基本文件,然后为每个环境覆盖唯一的规范。
2. 快速生成
由于 Kustomize 没有模板语言,因此您可以使用标准 YAML 快速声明您的配置。
3.更容易调试
当出现问题时,YAML 本身很容易理解和调试。再加上您的配置在补丁中被隔离,您将能够立即找出性能问题的根本原因。只需将性能与您的基本配置和正在运行的任何其他变体进行比较即可。
示例
让我们使用涉及 3 个不同环境的部署场景逐步了解 Kustomize 的工作原理:dev、staging和production。在此示例中,我们将使用服务、部署和水平 Pod 自动缩放器资源。所有环境都将使用不同类型的服务:
- Dev - Cluster IP
- Staging - Node Port
- Production - LadBalance
它们每个都有不同的 HPA 设置。这是目录结构的样子:
├── base
│ ├── deployment.yaml
│ ├── hpa.yaml
│ ├── kustomization.yaml
│ └── service.yaml
└── overlays
├── dev
│ ├── hpa.yaml
│ └── kustomization.yaml
├── production
│ ├── hpa.yaml
│ ├── kustomization.yaml
│ ├── rollout-replica.yaml
│ └── service-loadbalancer.yaml
└── staging
├── hpa.yaml
├── kustomization.yaml
└── service-nodeport.yaml
1. 检查base文件
base文件夹包含公共资源,例如标准的deployment.yaml、service.yaml和hpa.yaml资源配置文件。我们将在以下部分中探讨它们的每个内容。
base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend-deployment
spec:
selector:
matchLabels:
app: frontend-deployment
template:
metadata:
labels:
app: frontend-deployment
spec:
containers:
- name: app
image: foo/bar:latest
ports:
- name: http
containerPort: 8080
protocol: TCP
base/service.yaml
apiVersion: v1
kind: Service
metadata:
name: frontend-service
spec:
ports:
- name: http
port: 8080
selector:
app: frontend-deployment
base/hpa.yaml
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: frontend-deployment-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: frontend-deployment
minReplicas: 1
maxReplicas: 5
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
base/kustomization.yaml kustmization.yaml 文件是基本文件夹中最重要的文件,它描述了您使用的资源。
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- service.yaml
- deployment.yaml
- hpa.yaml
2. 定义开发补丁文件
补丁文件夹包含特定于环境的覆盖。它有 3 个子文件夹(每个环境一个)。
dev/kustomization.yaml 此文件定义要引用的基础配置并使用 patchStrategicMerge 进行修补,这允许定义部分 YAML 文件并将其覆盖在基础之上。
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../../base
patchesStrategicMerge:
- hpa.yaml
dev/hpa.yaml 该文件与基础文件中的资源名称相同。这有助于匹配要修补的文件。
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: frontend-deployment-hpa
spec:
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 90
如果将之前的 hpa.yaml 文件与 base/hpa.yaml 文件进行比较,您会注意到 minReplicas、maxReplicas 和 AverageUtilization 值之间的差异。
3. 检查补丁
要在应用于集群之前确认补丁配置文件更改正确,您可以运行kustomize build overlays/dev
apiVersion: v1
kind: Service
metadata:
name: frontend-service
spec:
ports:
- name: http
port: 8080
selector:
app: frontend-deployment
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend-deployment
spec:
selector:
matchLabels:
app: frontend-deployment
template:
metadata:
labels:
app: frontend-deployment
spec:
containers:
- image: foo/bar:latest
name: app
ports:
- containerPort: 8080
name: http
protocol: TCP
---
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: frontend-deployment-hpa
spec:
maxReplicas: 2
metrics:
- resource:
name: cpu
target:
averageUtilization: 90
type: Utilization
type: Resource
minReplicas: 1
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
4. 应用补丁
确认补丁正确后,请使用以下kubectl apply -k overlays/dev
命令将设置应用到集群:
kubectl apply -k overlays/dev
service/frontend-service created
deployment.apps/frontend-deployment created
horizontalpodautoscaler.autoscaling/frontend-deployment-hpa created
处理完开发环境后,我们将演示生产环境,因为在我们的例子中它是 staging 的超集(就 k8s 资源而言)。
5. 定义产品补丁文件
production/hpa.yaml 在我们的生产hpa.yaml 中,假设我们希望允许最多 10 个副本,新副本由平均 CPU 使用率 70% 的资源利用率阈值触发。看起来是这样的:
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: frontend-deployment-hpa
spec:
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
production/rollout-replicas.yaml 我们的生产目录中还有一个rollout-replicas.yaml文件指定了我们的滚动策略:
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend-deployment
spec:
replicas: 10
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
type: RollingUpdate
prod/service-loadbalancer.yaml 我们使用此文件将服务类型更改为 LoadBalancer(而在 中staging/service-nodeport.yaml,它被修补为 NodePort)。
apiVersion: v1
kind: Service
metadata:
name: frontend-service
spec:
type: LoadBalancer
prod/kustomization.yaml
此文件在生产文件夹中的操作方式与在基本文件夹中的操作方式相同:它定义要引用的基本文件以及要应用于生产环境的补丁。在本例中,它还包括两个文件:rollout-replica.yaml 和 service-loadbalancer.yaml。
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../../base
patchesStrategicMerge:
- rollout-replica.yaml
- hpa.yaml
- service-loadbalancer.yaml
6. 查看产品补丁
检查一下 kustomize build overlays/production
检查完毕后,将patch应用到集群 kubectl apply -k overlays/production
kubectl apply -k overlays/production service/frontend-service created deployment.apps/frontend-deployment created horizontalpodautoscaler.autoscaling/frontend-deployment-hpa created
Kustomize最佳实践
- 将您的自定义资源及其实例保存在单独的包中,否则可能会遇到冲突,并导致创建过程中出现问题。例如,许多人将证书管理器(CertManager)的CRD和资源保存在同一个包中,这可能会引起问题。大多数情况下,重新应用 YAML 文件可以解决此问题。但是最好将它们分开管理。
- 尽量将namespace、公共元数据等常见值保存在基本文件中。
- 按种类对资源进行组织,使用以下命名约定:小写连字符.yaml(例如,horizontal-pod-autoscaler.yaml)。将服务放置在service.yaml 文件中。
- 遵循标准的目录结构,使用bases/保存基础文件,使用patches/或overlays/保存特定于环境的文件。
- 在开发过程中或在将文件推送到git之前,运行kubectl kustomize cfg fmt file_name命令来格式化文件并设置正确的缩进。