• Post author:
  • Post category:Kubernetes
  • Post comments:0评论

一、基础概念

  Kustomize 是一个独立的工具,用来通过 kustomization 文件定制 Kubernetes 资源对象配置。它提供了一种无需模板和 DSL(领域特定语言) 即可自定义 Kubernetes 资源对象配置的解决方案。
  它提供以下功能特性来管理应用配置文件:

• 从其他来源生成资源,可以基于文件或字面值来生成 Secret 和 ConfigMap。
• 为资源设置贯穿性(Cross-Cutting)字段,如为所有资源对象设置相同的名字空间、前缀后缀、标签集合、注解集合。
• 组织和定制资源集合。一种常见的做法是在项目中构造资源集合并将其放到同一个文件或目录中管理,基于不同文件来组织资源并向其应用补丁或者其他定制的能力。

  官方文档:

https://kubernetes.io/zh-cn/docs/tasks/manage-kubernetes-objects/kustomization/ https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/
https://github.com/kubernetes-sigs/kustomize

二、结构

  Kustomize 中有基准(bases)和覆盖(overlays)的概念区分。
  基准是包含 kustomization.yaml 文件的一个目录,其中包含一组资源及其相关的定制。 基准可以是本地目录或者来自远程仓库的目录,只要其中存在 kustomization.yaml 文件即可。 覆盖也是一个目录,其中包含将其他 kustomization 目录当做 bases 来引用的 kustomization.yaml 文件。
  基准不了解覆盖的存在,且可被多个覆盖所使用。 覆盖则可以有多个基准,且可针对所有基准中的资源执行组织操作,还可以在其上执行定制。
  所以我们通常使用 base + overlays 的结构来管理 yaml 文件。base 中包含基准 yaml 文件,overlays 中则是继承 base 的 yaml 并向其中加入定制元素进行修改,已适应于不同的环境。
  结构如下:

nginx-kustomize
├── base                             # 基准文件
│   ├── kustomization.yaml
│   └── nginx-deploy.yaml
└── overlays
    ├── development                  # 开发环境
    │   ├── kustomization.yaml
    │   ├── ns.yaml
    │   ├── path_env.yaml
    │   └── path_nginx-ing.yaml
    └── production                   # 生产环境
        ├── kustomization.yaml
        ├── ns.yaml
        ├── path_env.yaml
        └── path_nginx-ing.yaml

三、示例

以上述结构做为示例,简单演示下。

1、base

定义 kustomization.yaml,指定要包含那些文件做为基准 yaml 文件。

[root@cp nginx-kustomize]# cat base/kustomization.yaml 
resources:
- nginx-deploy.yaml

注:
resources:要包括的资源,资源可以是文件、目录、URL。
资源将按深度优先顺序读取和处理。
文件应包含 YAML 形式的 k8s 资源,一个文件可能包含由文档标记分隔的多个资源---。
目录规范可以是相对的、绝对的或 URL 的一部分,目录必须包含一个 kustomization.yaml 文件。
URL 规范应遵循 hashcorp URL 格式。

nginx 部署文件,包含 svc、ing、deploy:

[root@cp nginx-kustomize]# cat base/nginx-deploy.yaml 
apiVersion: v1
kind: Service
metadata:
  labels:
    k8s-app: nginx
  name: nginx
spec:
  type: ClusterIP
  selector:
    k8s-app: nginx
  ports:
  - port: 80
    targetPort: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx
spec:
  rules:
  - host: dev.nginx.example
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx
            port:
              number: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.18
        ports:
        - containerPort: 80
        env:
          - name: ENV
            value: "dev"

2、overlays

以 production 为例,要在生产环境部署,我们要在基准文件上定制如下:

  • 所有资源对象全部处于 nginx-prod 命名空间下。
  • Ingess 的 host 字段改为 prod.nginx.example。
  • Deployment 的 replicas 从 1 增加至 2,镜像版本改为1.20,ENV 变量值改为 prod。

创建 kustomization.yml 文件以定义生产环境:

[root@cp nginx-kustomize]# cat overlays/production/kustomization.yaml
resources:      # 包含的资源
- ../../base
- ns.yaml

patchesStrategicMerge:      # 策略合并补丁
- patch_nginx-ing.yaml
- patch_env.yaml

namespace: nginx-prod       # 为所有资源设置命名空间
replicas:                   # 配置资源副本数
- name: nginx
  count: 2

images:                     # 设置镜像
- name: nginx
  newName: nginx
  newTag: 1.20

注:

1、patchesStrategicMerge
注意,只用于修改已知资源。
即此条目下的文件中的 name 必须和 resources 加载的 name 字段匹配,或者通过 bases 中的 name 字段匹配。

2、namespace
为所有资源设置相同的名字空间。
如果在资源上设置了现有 namespace,则将覆盖现有 namespace。
如果在资源上未设置现有 namespace,则使用现有 namespace。

3、replicas
修改资源的副本数。该字段内容为列表,所以可以同时修改许多资源。
只能作用于:Deployment、ReplicationController、ReplicaSet、StatefulSet

4、images
修改镜像的名称、tag 或 image digest。
如果一个资源对象下面定义了多个镜像,则所有镜像都会被改变。

其它文件:

[root@cp nginx-kustomize]# cat overlays/production/ns.yaml 
apiVersion: v1
kind: Namespace
metadata:
  name: nginx-prod
[root@cp nginx-kustomize]# cat overlays/production/path_env.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  template:
    spec:
      containers:
      - name: nginx
        env:
          - name: ENV
            value: "prod"
[root@cp nginx-kustomize]# cat overlays/production/path_nginx-ing.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx
spec:
  rules:
  - host: prod.nginx.example
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx
            port:
              number: 80

3、部署

下面我们来部署生产环境:

# 检查,会定制化生成 yaml 到标准输出
kubectl kustomize overlays/production/

# 部署
kubectl apply -k overlays/production/

验证:

[root@cp nginx-kustomize]# kubectl get deploy,svc,ing -n nginx-prod
NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx   2/2     2            2           41s

NAME            TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/nginx   ClusterIP   10.1.89.78   <none>        80/TCP    41s

NAME                              CLASS    HOSTS                ADDRESS   PORTS   AGE
ingress.networking.k8s.io/nginx   <none>   prod.nginx.example             80      41s

[root@cp nginx-kustomize]# kubectl describe deploy -n nginx-prod nginx  | grep Image
    Image:      nginx:1.20

[root@cp nginx-kustomize]# kubectl exec -n nginx-prod nginx-5cbc6c98f6-24r9h -- env | grep ENV
ENV=prod

四、扩展

官方给了不少示例:https://github.com/kubernetes-sigs/kustomize/tree/master/examples

1、patchesJson6902 语法

官方文档:https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesjson6902/
target 字段通过对象的组、版本、种类、名称和命名空间来筛选需要 patch 的资源对象。
path 字段是 JSON 补丁文件的相对文件路径。此补丁文件中的内容可以是 JSON 格式

patchesJson6902:
- target:
    group: <Group>
    version: <Version>
    kind: <Kind>
    name: <Name>
    namespace: <Namespace>
    labelSelector: <LabelSelector>
    annotationSelector: <AnnotationSelector>
  path: <PatchFile>
  patch: -|

示例:

patches:
- target:
    group: apps
    version: v1
    kind: Deployment
    name: deploy.*
    labelSelector: "env=dev"
    annotationSelector: "zone=west"
  path: patch.yaml
- target:
    kind: MyKind
    labelSelector: "env=dev"
  patch: |-
    - op: replace
      path: /some/existing/path
      value: new value    

2、多容器镜像

  如果单个资源对象下有多个容器,对于不同容器镜像怎么在 kustomization.yaml 文件中设置,使用 images 肯定是不行的,它会修改所有镜像。这种情况下,我们可能会想到用 patchesStrategicMerge,但是我们需要额外定义文件。
  这种情况使用 patchesJson6902 可以达成我们想要的效果,如下示例将 nginx1 容器镜像版本改成 1.20,将 nginx2 容器镜像版本改成 1.18。
  示例 Deployment:

[root@cp test-kustomize]# cat nginx-deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx1
        image: nginx:1.18
      - name: nginx2
        image: nginx:1.20

kustomization.yaml:

[root@cp test-kustomize]# cat kustomization.yaml 
resources:
- nginx-deploy.yaml

patchesJson6902:
- target:              # 匹配名为 nginx 的 Deployment
    kind: Deployment
    name: nginx
  patch: |-
    - op: replace
      path: /spec/template/spec/containers/0/image
      value: nginx:1.20   
    - op: replace
      path: /spec/template/spec/containers/1/image
      value: nginx:1.18

验证:

[root@cp test-kustomize]# kubectl kustomize .
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.20
        name: nginx1
      - image: nginx:1.18
        name: nginx2

3、批量修改变量

目前有两个微服务,现在要上生产,需要批量修改相关变量:

  • JVM_OPTS 变量,将堆栈大小调整到 1024m。
  • JAVA_OPTS 变量,将 profiles 修改为 prod。
  • 添加 ENV 变量,值为 prod。

示例 Deployment:

[root@cp test-kustomize]# cat auth-deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: auth
  labels:
    app: auth
spec:
  replicas: 1
  selector:
    matchLabels:
      app: auth
  template:
    metadata:
      labels:
        app: auth
    spec:
      containers:
      - name: auth
        image: auth
        env: 
        - name: JVM_OPTS
          value: -Xms512m -Xmx512m
        - name: JAVA_OPTS
          value: --spring.profiles.active=dev

[root@cp test-kustomize]# cat admin-deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: admin
  labels:
    app: admin
spec:
  replicas: 1
  selector:
    matchLabels:
      app: admin
  template:
    metadata:
      labels:
        app: admin
    spec:
      containers:
      - name: admin
        image: admin
        env: 
        - name: JVM_OPTS
          value: -Xms512m -Xmx512m
        - name: JAVA_OPTS
          value: --spring.profiles.active=dev

kustomization.yaml:

[root@cp test-kustomize]# cat kustomization.yaml 
resources:
- auth-deploy.yaml
- admin-deploy.yaml

patchesJson6902:
- target:              # 匹配所有类型为 Deployment 的资源
    kind: Deployment
    name: .*
  patch: |-
    - op: replace
      path: /spec/template/spec/containers/0/env/0/value
      value: -Xms1024m -Xmx1024m
    - op: replace
      path: /spec/template/spec/containers/0/env/1/value
      value: --spring.profiles.active=prod
    - op: add
      path: /spec/template/spec/containers/0/env/-
      value: {"name":"ENV","value":"prod"}

验证:

[root@cp test-kustomize]# kubectl kustomize .
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: admin
  name: admin
spec:
  replicas: 1
  selector:
    matchLabels:
      app: admin
  template:
    metadata:
      labels:
        app: admin
    spec:
      containers:
      - env:
        - name: JVM_OPTS
          value: -Xms1024m -Xmx1024m
        - name: JAVA_OPTS
          value: --spring.profiles.active=prod
        - name: ENV
          value: prod
        image: admin
        name: admin
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: auth
  name: auth
spec:
  replicas: 1
  selector:
    matchLabels:
      app: auth
  template:
    metadata:
      labels:
        app: auth
    spec:
      containers:
      - env:
        - name: JVM_OPTS
          value: -Xms1024m -Xmx1024m
        - name: JAVA_OPTS
          value: --spring.profiles.active=prod
        - name: ENV
          value: prod
        image: auth
        name: auth

4、添加容器

以上例的两个微服务为例,给它们添加一个 nginx 容器:
方式1:

[root@cp test-kustomize]# cat kustomization.yaml 
resources:
- auth-deploy.yaml
- admin-deploy.yaml

patchesJson6902:
- target:
    kind: Deployment
    name: .*
  patch: |-
    - op: add
      path: /spec/template/spec/containers/-
      value: {"name":"nginx","image":"nginx:1.20"}

[root@cp test-kustomize]# kubectl kustomize .
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: auth
  name: auth
spec:
  replicas: 1
  selector:
    matchLabels:
      app: auth
  template:
    metadata:
      labels:
        app: auth
    spec:
      containers:
      - env:
        - name: JVM_OPTS
          value: -Xms512m -Xmx512m
        - name: JAVA_OPTS
          value: --spring.profiles.active=dev
        image: auth
        name: auth
      - image: nginx:1.20
        name: nginx
......

方式2,注意使用此方式添加容器,会将添加的容器排列在第一位:

[root@cp test-kustomize]# cat kustomization.yaml 
resources:
- auth-deploy.yaml
- admin-deploy.yaml

patches:
- target:
    kind: Deployment
    name: .*
  path: add_nginx_container.yaml
[root@cp test-kustomize]# cat add_nginx_container.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: add-nginx-container     # 这个名称无所谓,会作用到所有 Deployment
spec:
  template:
    spec:
      containers:
      - name: nginx
        image: nginx:1.20
[root@cp test-kustomize]# kubectl kustomize .
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: admin
  name: admin
spec:
  replicas: 1
  selector:
    matchLabels:
      app: admin
  template:
    metadata:
      labels:
        app: admin
    spec:
      containers:
      - image: nginx:1.20
        name: nginx
      - env:
        - name: JVM_OPTS
          value: -Xms512m -Xmx512m
        - name: JAVA_OPTS
          value: --spring.profiles.active=dev
        image: admin
        name: admin

发表评论

验证码: 27 − 21 =