使用Kustomize管理K8S的yaml清单 - 图1

将应用部署到Kubernetes中的方式有很多,目前主流是就是使用kubectlHelm,不过其先决条件都需要YAML清单文件。

不同由于部署环境的多样化,比如有开发环境、测试环境、预生产环境、生产环境,我们就会针对不同的环境定制各种YAML文件,但是在很多情况下同一个应用在不同的环境可能只做了简单的更改,这样就会导致YAML泛滥。

Kustomize 就是用于帮助解决这些问题的开源配置管理工具。从 Kubernetes v1.14 开始,kubectl 就完全支持 Kustomize 和 kustomization 文件。

kustomize是什么?

kustomize lets you customize raw, template-free YAML files for multiple purposes, leaving the original YAML untouched and usable as is.

上面是官方对于kustomize的定义。大致是说:kustomize允许您自定义无模板的原始YAML文件来用于多种目的,而原始的YAML则保持不变并可以使用。

kustomize的作用

当我们在K8S中有多套环境的时候,就会面临如下问题:

  • 多环境多团队多个YAML资源清单
  • 不同环境差异微小,但是不得不copy and change
  • helm稍显复杂,需要额外的学习投入

而kustomize可以很好的解决这些问题:

  • kustomize 通过 Base & Overlays 方式方式维护不同环境的应用配置
  • kustomize 使用 patch 方式复用 Base 配置,并在 Overlay 描述与 Base 应用配置的差异部分来实现资源复用
  • kustomize 管理的都是 Kubernetes 原生 YAML 文件,不需要学习额外的 DSL 语法

安装

在kubernetes 1.14版本以上,已经集成到kubectl中了,你可以通过kubectl --help来进行查看命令。

如果需要额外安装,直接到https://github.com/kubernetes-sigs/kustomize/releases里进行下载对应的版本。

比如:

  1. wget https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv3.8.7/kustomize_v3.8.7_linux_amd64.tar.gz
  2. tar xf kustomize_v3.8.7_linux_amd64.tar.gz
  3. cp kustomize/kustomize /usr/local/bin

这样就完成了简单的安装了。

实践测试

背景

  • 版本信息
    • kubernetes:1.17.9
  • 集群信息,由于在一个环境中进行测试,所以采用不同的namespace进行分开
    • 开发环境:dev
    • 预发环境:stag
    • 生产环境:prod
  • 测试用例:一个简单的hello world示例

创建基础模板

首先创建一个helloworld目录,表示应用,然后在里面创建一个base目录,如下:

  1. mkdir helloworld/base -p

然后在base目录下创建以下配置清单:

  1. base/
  2. ├── configMap.yaml
  3. ├── deployment.yaml
  4. ├── ingress.yaml
  5. ├── kustomization.yaml
  6. └── service.yaml

他们的清单内容分别如下:
configMap.yaml

  1. apiVersion: v1
  2. kind: ConfigMap
  3. metadata:
  4. name: the-map
  5. namespace: default
  6. data:
  7. altGreeting: "Hello World!"
  8. enableRisky: "false"

deployment.yaml

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. name: the-deployment
  5. namespace: default
  6. spec:
  7. replicas: 3
  8. selector:
  9. matchLabels:
  10. deployment: hello
  11. template:
  12. metadata:
  13. labels:
  14. deployment: hello
  15. spec:
  16. containers:
  17. - name: the-container
  18. image: monopole/hello:1
  19. command: ["/hello",
  20. "--port=8080",
  21. "--enableRiskyFeature=$(ENABLE_RISKY)"]
  22. ports:
  23. - containerPort: 8080
  24. env:
  25. - name: ALT_GREETING
  26. valueFrom:
  27. configMapKeyRef:
  28. name: the-map
  29. key: altGreeting
  30. - name: ENABLE_RISKY
  31. valueFrom:
  32. configMapKeyRef:
  33. name: the-map
  34. key: enableRisky

service.yaml

  1. kind: Service
  2. apiVersion: v1
  3. metadata:
  4. name: the-service
  5. namespace: default
  6. spec:
  7. selector:
  8. deployment: hello
  9. type: NodePort
  10. ports:
  11. - protocol: TCP
  12. port: 8080
  13. targetPort: 8080

ingress.yaml

  1. apiVersion: extensions/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: the-ingress
  5. namespace: default
  6. spec:
  7. rules:
  8. - host: test.coolops.cn
  9. http:
  10. paths:
  11. - backend:
  12. serviceName: the-service
  13. servicePort: 8080
  14. path: /

kustomization.yaml

  1. # Example configuration for the webserver
  2. # at https://github.com/monopole/hello
  3. commonLabels:
  4. app: hello
  5. resources:
  6. - deployment.yaml
  7. - service.yaml
  8. - configMap.yaml
  9. - ingress.yaml

这样基础模板就创建好了,我们可以使用如下命令将所有文件连在一起。

  1. kustomize build ../base

然后如果想创建应用可以用以下方式。

  1. # 直接使用kubectl apply -k (集群版本要高于1.14)
  2. kubectl apply -k ../base/
  3. # 还可以通过kustomize命令
  4. kustomize build ../base | kubectl apply -f -

删除应用命令类似,可以自行尝试。

根据不同环境创建overlays

上面的是基础模板,所有的配置都是基于它,现在我们根据不同的环境进行定制。
首先创建如下目录结构

  1. .
  2. ├── base
  3. ├── configMap.yaml
  4. ├── deployment.yaml
  5. ├── ingress.yaml
  6. ├── kustomization.yaml
  7. └── service.yaml
  8. └── overlays
  9. ├── dev
  10. ├── prod
  11. └── stag

其中:

  • dev目录下存放开发环境定制清单
  • stag目录下存放预发环境定制清单
  • prod目录下存放生产环境定制清单

配置开发环境

在dev目录下创建以下文件:

  1. ../dev/
  2. ├── ingress.yaml
  3. ├── kustomization.yaml
  4. └── map.yaml

其中ingress.yaml如下:

  1. apiVersion: extensions/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: the-ingress
  5. namespace: default
  6. spec:
  7. rules:
  8. - host: hello-dev.coolops.cn
  9. http:
  10. paths:
  11. - backend:
  12. serviceName: the-service
  13. servicePort: 8080
  14. path: /

map.yaml

  1. apiVersion: v1
  2. kind: ConfigMap
  3. metadata:
  4. name: the-map
  5. data:
  6. altGreeting: "Hello,This is Dev!"
  7. enableRisky: "true"

kustomization.yaml

  1. namePrefix: dev-
  2. commonLabels:
  3. org: acmeCorporation
  4. variant: dev
  5. commonAnnotations:
  6. note: Hello, This is dev!
  7. patchesStrategicMerge:
  8. - map.yaml
  9. - ingress.yaml
  10. apiVersion: kustomize.config.k8s.io/v1beta1
  11. kind: Kustomization
  12. resources:
  13. - ../../base
  14. namespace: dev

开发环境更改了configmap的内容、ingress的host,还有namespace。

然后可以通过kustomize build .测试配置是否正确。

配置预发环境

在stag目录下创建以下文件:

  1. ../stag/
  2. ├── kustomization.yaml
  3. └── map.yaml

其中map.yaml内容如下:

  1. apiVersion: v1
  2. kind: ConfigMap
  3. metadata:
  4. name: the-map
  5. data:
  6. altGreeting: "Hello,This is Stag!"
  7. enableRisky: "true"

kustomization.yaml

  1. namePrefix: stag-
  2. commonLabels:
  3. org: acmeCorporation
  4. variant: stag
  5. commonAnnotations:
  6. note: Hello, This is stag!
  7. patchesStrategicMerge:
  8. - map.yaml
  9. apiVersion: kustomize.config.k8s.io/v1beta1
  10. kind: Kustomization
  11. resources:
  12. - ../../base
  13. namespace: stag

预发环境更改了configmap和namespace。

配置生产环境

在prod目录下创建以下文件:

  1. ../prod/
  2. ├── deployment.yaml
  3. ├── kustomization.yaml
  4. └── map.yaml

其中deployment.yaml配置如下:

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. name: the-deployment
  5. spec:
  6. replicas: 3

map.yaml

  1. apiVersion: v1
  2. kind: ConfigMap
  3. metadata:
  4. name: the-map
  5. data:
  6. altGreeting: "Hello,This is prod!"
  7. enableRisky: "true"

kustomization.yaml

  1. namePrefix: prod-
  2. commonLabels:
  3. org: acmeCorporation
  4. variant: prod
  5. commonAnnotations:
  6. note: Hello, This is prod!
  7. patchesStrategicMerge:
  8. - deployment.yaml
  9. - map.yaml
  10. apiVersion: kustomize.config.k8s.io/v1beta1
  11. kind: Kustomization
  12. resources:
  13. - ../../base
  14. namespace: prod

生产环境更改了configmap、deploy副本数、namspace。

发布使用

上面我们已经将整个需要的配置定制好了。现在就可以进行发布了。
如果要发布开发环境,则使用:

  1. cd helloworld/
  2. kustomize build overlays/dev/ | kubectl apply -f -

然后我们可以看到发布完成,如下:

  1. # kubectl get all -n dev
  2. NAME READY STATUS RESTARTS AGE
  3. pod/dev-the-deployment-6cdcbbc878-27n5g 1/1 Running 0 50s
  4. pod/dev-the-deployment-6cdcbbc878-fgx89 1/1 Running 0 50s
  5. pod/dev-the-deployment-6cdcbbc878-xz5q2 1/1 Running 0 50s
  6. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  7. service/dev-the-service NodePort 10.103.77.190 <none> 8080:32414/TCP 50s
  8. NAME READY UP-TO-DATE AVAILABLE AGE
  9. deployment.apps/dev-the-deployment 3/3 3 3 50s
  10. NAME DESIRED CURRENT READY AGE
  11. replicaset.apps/dev-the-deployment-6cdcbbc878 3 3 3 50s

然后通过域名访问如下:
image.png
其他环境是类似的操作,这里不再赘述。

结合CD使用

在进行持续部署的时候每次都需要修改镜像地址为最新的版本,使用kustomize也可以简单的实现。

加入我们要修改dev环境下的镜像地址为nginx,命令如下

  1. cd overlays/dev
  2. kustomize edit set image monopole/hello=nginx:latest

说明:

  • monopole/hello是原来的镜像名字
  • nginx:latest是新的镜像+标签

然后可以看到kustomization.yaml下的镜像地址已经变成了nginx,如下:

  1. namePrefix: dev-
  2. commonLabels:
  3. org: acmeCorporation
  4. variant: dev
  5. commonAnnotations:
  6. note: Hello, This is dev!
  7. patchesStrategicMerge:
  8. - map.yaml
  9. - ingress.yaml
  10. apiVersion: kustomize.config.k8s.io/v1beta1
  11. kind: Kustomization
  12. resources:
  13. - ../../base
  14. namespace: dev
  15. images:
  16. - name: monopole/hello
  17. newName: nginx
  18. newTag: latest

我们这时候再发布,就是nginx的镜像了。

  1. # kustomize build . | kubectl apply -f -
  2. configmap/dev-the-map unchanged
  3. service/dev-the-service unchanged
  4. deployment.apps/dev-the-deployment configured
  5. ingress.extensions/dev-the-ingress unchanged

同样,修改namespace可以使用如下命令。

  1. kustomize edit set namespace test

更多操作可以查看官方文档:https://kubernetes-sigs.github.io/kustomize/zh/guides/

写在最后

使用 Kustomize 简化了针对不同环境的应用程序配置的管理。我们将一组几乎重复的 YAML 文件重组为一个分层模型,这将减少错误,减少手动配置,并使代码更易于识别和维护。

参考文档