Skip to main content

Command Palette

Search for a command to run...

Kustomize 中的增删改查

Updated
4 min read

在之前的文章中,我曾经说过,相对于 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 命令,可以进行现场修改,进一步的提高了灵活(混乱)程度,有兴趣的读者可以自行摸索。

More from this blog

龙虾恐慌:AIOps 又要改名了?

ChatGPT 开始,把 AI 拉近到普罗大众的面前,让无数人感受到 AI 的亲民魅力。而龙虾,则把大模型驱动的自动化能力,突然间变得水灵灵、活泼泼地走进千家万户。它不只是“风口上的猪”,而是风口本身。热度高到让 Mac mini 一度断货,不知道这在不在库克的预料之内。 每代人都有每代人的鸡蛋,春节期间,我就领了我的鸡蛋。翻出古老的 MacBook Air M1,充值各种大模型。当然了,这个工具

Mar 9, 20261 min read

再见 2025

我猜不少人以为这个号废了吧?并没有,只是今年变化有点大,一直有种抄起键盘,无从说起的感觉,所以一直偷懒到今天,2025 的最后一天。 今年是我的第四个本命年,去年末一期播客里,大内说本命年不是灾年,是变化年,有危也有机。可是讲真啊,只看到危,没看到机。 各种因缘际会,从鹅厂跳槽到前东家,已经接近四年,第一个合同期已经进入尾声。除了前两年还在云原生领域嗷嗷叫,后两年基本都是些鸡零狗碎的东西了,用老东家的术语说是——偏离主航道,可谓是前景暗淡了。 一旦确定要滚蛋,反倒心思轻松起来,每天骑着我的小红车...

Jan 5, 20261 min read

辅助编程?dora 说:我知道你很急可是请你别急

从 OpenGPT 把大模型的火烧旺了之后,这三年来,相信很多组织或摩拳擦掌、或躬身入局,希望借助聪明能干的大模型,或想偿还技术宅,或想降本增效,或想弯道超车。一时间,沉寂许久的 AIxx 又活过来了,LLM Ops、Vibe Coding、中医大模型、GPT 算命等等,全都老树发新芽,焕发了勃勃生机。那么视角拉回从业者最关注的饭碗相关的领域之一——AI 辅助开发,产生了什么触动,应该如何拥抱呢? DORA 的年度报告中给出了很有意思的结论——强者恒强。 执行摘要部分总结了几个有趣的点: 问题...

Oct 6, 20251 min read

[译]dora:ai 辅助软件开发状态报告

执行摘要 在 2025 年,科技领导者面临的核心问题已不再是“是否要采用 AI”,而是“如何实现其价值”。 DORA 的研究基于超过 100 小时的定性访谈和来自全球近 5,000 名技术专业人士的问卷调查。研究揭示了一个关键事实:AI 在软件开发中的主要角色是“放大器”。它会放大高效能组织的优势,也会凸显组织的缺陷。 关键结论:AI 是放大器 AI 投资的最大回报并非来自工具本身,而是来自组织底层系统的战略性建设: 高质量的内部平台 清晰的工作流 团队的协同能力 缺少这些基础,AI ...

Oct 2, 202514 min read

僭越了,有人在用 Rust 写 Kubernetes

一个新语言问世,最爱做的事情之一,就是重写存量软件了。 云原生喝酒 SIG 重点扶持项目——rk8s(https://github.com/rk8s-dev/rk8s) 也可以归在这个范畴里,只不过这个项目重写的东西比较大,是 Kubernetes。 从 2025 年 1 月第一个 Commit 开始,到现在有了 200 多次 Commit,十几万行代码。当然距离 Kubernetes 的几百万行代码还差得远——老马就是喜欢整这种大无畏项目。 另外该项目也是国内第一个脱离 Cargo 转向使用 ...

Sep 27, 20253 min read

【伪】架构师

342 posts

Kustomize 中的增删改查