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
命令,可以进行现场修改,进一步的提高了灵活(混乱)程度,有兴趣的读者可以自行摸索。