Kustomize 中的增删改查

在之前的文章中,我曾经说过,相对于 Helm Chart,Kustomize 具有更平缓的学习曲线,更灵活的派生方式,当然这也不是没有代价的,Kustomize 的分享方式和规范性都弱于 Helm Chart,而且上游对下游也是相当缺乏控制能力的。

本文会从实际出发,列出一系列的场景,看看拿到一个上游应用的标准 YAML 之后,如何使用 Kustomize 对其进行增删改查,形成新的 Kubernetes 资源组,完成对派生应用的定义。

准备工作

首先我们创建实验目录 lab/base,在其中生成一组 YAML 文件,作为后续实验的基础(base),这是一个很简单的应用,只有一个 Deployment:

deploy.yaml:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: flaskapp
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: flaskapp
        version: v1
    spec:
      containers:
        - name: flaskapp
          image: dustise/flaskapp
          imagePullPolicy: IfNotPresent
          env:
            - name: version
              value: v1
          ports:
            - containerPort: 80

如果使用 Kubectl 提交,会在当前命名空间中新建一个 Deployment 和一个 Pod,当然我们暂时不会这么做。

接下来是创建一个 Kustomize 的定义,作为后续实验的基础,基础定义很简单,它甚至可能不会由上游应用的开发者编写,而是下游的定制者用它来做一个基础。

kustomization.yaml

resources:
- deploy.yaml

对它进行渲染,会毫无意外的出现一个和 deploy.yaml 一样的输出内容:

kubectl kustomize base
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: flaskapp
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: flaskapp
...

创建一个新的工作目录,lab/overlays/c,本节的内容都会使用这个目录来完成。

在继承上游应用的 YAML 时,经常需要向其中加入定制元素,比如加入新的 Ingress、Service、Configmap 等,还有可能新增一些对象内的定义。下面的两个例子分别展示了 Kustomize 完成这类任务的方法。

加入新对象

上面的 Base 中,有了一个孤零零的 Deployment,多数的业务应用还是需要有个 Service 提供服务的,我们就给它加入一个新对象。

c 目录中,新建一个 service.yaml

apiVersion: v1
kind: Service
metadata:
  name: flaskapp
  labels:
    app: flaskapp
spec:
  selector:
    app: flaskapp
    version: v1
  ports:
    - name: http
      port: 80
      targetPort: 80

然后新建一个 kustomization.yaml

bases:
- ../../base
resources:
- service.yaml

执行命令 kustomize build overlays/c,可以看到,在原有 Deployment 的基础上,新增了一个服务。

新增字段

很多应用都会声明运行时的资源需求,但是我们的 base 中并没有这个字段,Kustomize 可以用补丁的方式加入这个字段。

首先创建一个补丁文件 overlays/c/resource-patch.yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: flaskapp
spec:
  replicas: 1
  template:
    spec:
      containers:
      - name: flaskapp
        resources:
          requests:
            memory: "64Mi"
            cpu: "250m"
          limits:
            memory: "64Mi"
            cpu: "250m"

上面的补丁文件用最简单的字段赋值标识出了要打补丁的位置,并加入了资源限制。

修改 overlays/c/kustomization.yaml,加入补丁:

bases:
- ../../base
resources:
- service.yaml
patchesStrategicMerge:
- resource-patch.yaml

再次使用 kustomize build overlays/c,或者直接使用 kubectl apply -k overlays/c,都能看到,资源限制已经应用。

创建 Configmap 并加载

overlays/c 下面新建一个配置文件 config.ini

key=value

新增的 configMapGenerator 要求使用 config.ini 生成一个 ConfigMap。

然后再做一个补丁文件 env-patch.yaml,用来加载 Config:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: flaskapp
spec:
  replicas: 1
  template:
    spec:
      containers:
      - name: flaskapp
        env:
        - name: CONFIG
          valueFrom:
            configMapKeyRef:
              name: config-ini
              key: config.ini

修改 kustomization.yaml,加入我们的 Configmap 和补丁,结果为如下内容:

bases:
- ../../base
resources:
- service.yaml
configMapGenerator:
- name: config-ini
  files:
    - config.ini
patchesStrategicMerge:
- resource-patch.yaml
- env-patch.yaml
generatorOptions:
  disableNameSuffixHash: true

kubectl apply -k overlays/c 之后,会看到 Pod 中加入了对 Configmap 的引用,进入 Pod 也能看到新增的环境变量,例如:

$ kubectl exec -it flaskapp-5b886b8dfc-qq68w env | grep CONFIG
CONFIG=key=value

创建一个新的工作目录,lab/overlays/d,本节的内容都会使用这个目录来完成。

使用 patchesStrategicMerge 的特定语法,可以删除指定内容。

删除一个对象

c 案例中新建的 Service 对象,我并不想要,如何通过 Kustomize 删掉?同样也使用打补丁的方式来解决。首先创建一个继承自 overlays/c 的 Kustomization,在 overlays/d 中创建 kustomization.yaml

bases:
- ../c
patchesStrategicMerge:
- remove-svc.yaml

以及 remove-svc.yaml

kind: Service
apiVersion: v1
metadata:
  name: flaskapp
$patch: delete

运行 kustomize build overlays/d,可以看到,输出内容中的 Service 不见了。

删除一个字段

接下来我们用类似的方法,删除前面设置的环境变量:

新建一个 remove-field.yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: flaskapp
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: flaskapp
        version: v1
    spec:
      containers:
        - name: flaskapp
          image: dustise/flaskapp
          env:
          - name: CONFIG
            $patch: delete

再把补丁加入 kustomization.yaml

bases:
- ../c
patchesStrategicMerge:
- remove-svc.yamlƒ
- remove-field.yaml

再次 kustomize build overlays/d,可以看到新的环境变量已经被删除。

创建一个新的工作目录,lab/overlays/u,本节的内容都会使用这个目录来完成。

除了 patchesStrategicMerge 之外,kustomize 还提供了一些方便快捷的方式能够对特定内容进行修改。

修改名字

可以用 namePrefix 和 nameSuffix 修改对象的名字,例如我们要给所有名字加上 overlay-u

kustomization.yaml

bases:
- ../c
namePrefix: overlay-u

接下来可以看看结果:

$ kubectl apply -k overlays/u --dry-run -o yaml | grep -E "^\s+name:"
    name: overlay-u-config-ini
    name: overlay-u-flaskapp
    name: overlay-u-flaskapp
                name: overlay-u-config-ini
          name: flaskapp

输出内容中,前三个分别是 ConfigMap、Service 以及 Deployment,第四行中对 Configmap 的引用也修改成了新的名字。

除了修改名字之外,还有以下几个暴力的修改功能:

  • 命名空间:namespaces
  • 注解:commonAnnotations
  • 标签:commonLabels

说这几个东西比较野蛮的原因是:他们的应用范围是整个 Kustomization,例如下面的定制:

bases:
- ../c
namePrefix: overlay-u
commonLabels:
    auto: label

生成之后会发现,从 Service、Deployment、Configmap 一直到 Pod,都会打上新标签。

修改镜像

修改镜像也是个常见任务,相对上面的几个暴力修改,镜像的修改相对精确一点——从一种镜像修改为另一种,例如我们把 flaskapp 的镜像更换为 nginx:alpine

kustomization.yaml

bases:
- ../c
namePrefix: overlay-u
commonLabels:
    auto: label
images:
- name: dustise/flaskapp
  newName: nginx
  newTag: alpine

修改副本数量

修改副本数量,指定资源名称以及副本数量即可:

例如如下的 kustomization.yaml

bases:
- ../c
replicas:
- name: flaskapp
  count: 2

使用 kustomize build overlays/u,会看到 Deployment 的该字段已经改为 2。

创建一个新的工作目录,lab/overlays/r,本节的内容都会使用这个目录来完成。

前面提到,namePrefix 修改了 ConfigMap 的名称之后,加载这个 CM 的 Deployment 也会修改引用的名称,然而如果在其它位置,例如命令行参数或者环境变量中引用的服务名称之类,就无法完成修改了。假设我们给 Deployment 中加入一个新的环境变量,叫 deploy,用如下的 kustomization.yaml 实现:

bases:
- ../../base
namePrefix: overlay-r-
patchesStrategicMerge:
- env-patch.yaml

其中引用的 env-patch.yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: flaskapp
spec:
  replicas: 1
  template:
    spec:
      containers:
      - name: flaskapp
        env:
        - name: deploy
          value: flaskapp

kustomize build overlays/r 渲染出来之后,很明显的 value 已经无法对应:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: overlay-r-flaskapp
...
      - env:
        - name: svc
          value: flaskapp
        - name: version

kustomization.yaml 中加入 vars,用一系列条件选择一个对象来进行引用,为变量赋值:

...
vars:
- name: DEPLOY_NAME
  objref:
    kind: Deployment
    name: flaskapp
    apiVersion: extensions/v1beta1

env-patch.yaml 中的环境变量定义修改为引用新变量:

...
        - name: deploy
          value: $(DEPLOY_NAME)

再次 kustomize build overlays/r,会看到符合预期的输出内容:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: overlay-r-flaskapp
...
        - name: deploy
          value: overlay-r-flaskapp

命令行

除了上面说的这些声明式的用法之外,kustomize 还提供了更为即兴的 edit 命令,可以进行现场修改,进一步的提高了灵活(混乱)程度,有兴趣的读者可以自行摸索。

Avatar
崔秀龙

简单,是大师的责任;我们凡夫俗子,能做到清楚就很不容易了。

comments powered by Disqus
下一页
上一页

相关