Kustomize实战:从0到1实现K8s多环境配置管理与资源部署
在Kubernetes日常运维与开发中,多环境配置复用、差异化管理一直是核心痛点------重复编写资源配置易导致冗余,手动修改配置易引发环境不一致,而Kustomize作为K8s原生内置的配置管理工具,无需模板引擎,通过纯YAML实现「基础配置+环境覆盖」的分层管理,完美解决这一问题。
一、Kustomize核心概念铺垫
-
Base(基础层):存储所有环境(开发、测试、生产)共用的通用资源配置(如Deployment、Service、通用Secret),一次定义,多环境复用,是配置的「底座」;
-
Overlay(覆盖层):基于Base层,通过「补丁机制」实现特定环境的差异化配置(如调整副本数、添加环境标签、生成专属配置/密钥),不修改Base原始配置,实现「按需定制」;
-
核心优势 :原生集成于
kubectl,无需额外安装;纯YAML操作,无学习成本;多环境配置解耦,维护成本大幅降低。
二、环境说明
-
K8s集群版本:1.14+(兼容Kustomize v1beta1)
-
操作节点:K8s Master节点(或已配置kubectl权限的节点)
-
目标:搭建Base基础配置,基于Overlay实现开发环境(ml-devops)差异化部署,包含MySQL部署、Service暴露、配置/密钥管理等能力。
三、Step 1:搭建Base基础层,定义通用资源
Base层的核心是定义所有环境共用的基础资源 ,本次实验包含Secret(存储MySQL根密码)、Deployment(MySQL部署)、Service(NodePort暴露服务),并通过kustomization.yaml编排所有资源。
3.1 创建Base目录并编写通用资源
bash
# 创建base目录并进入(路径优化,便于后续管理)
mkdir -p /k8s/kustomize-demo/base
cd /k8s/kustomize-demo/base
1. 编写Secret配置(存储MySQL根密码,已base64加密)
新建mysql-secret.yaml,注意:data字段值需为base64加密字符串(本文中MTIzNDU2Nzg5对应明文123456789),添加类型声明增强规范性:
yaml
apiVersion: v1
data:
root-password: MTIzNDU2Nzg5 # base64加密,明文:123456789
kind: Secret
metadata:
name: mysql-root-secret
type: Opaque # 通用密钥类型,适用于存储任意敏感信息
2. 编写Deployment配置(MySQL核心部署,3副本通用配置)
新建mysql-deployment.yaml,引用上述Secret中的密码,添加资源限制、端口声明,优化配置健壮性:
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-deployment
labels:
app: mysql
component: database # 新增组件标签,便于资源分类
spec:
replicas: 3 # 通用副本数,多环境可通过补丁修改
selector:
matchLabels:
app: mysql # 匹配Pod标签,确保Deployment管理正确Pod
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0 # 固定镜像版本,避免版本漂移
imagePullPolicy: IfNotPresent # 本地有镜像则不重新拉取,提升部署效率
ports:
- containerPort: 3306
name: mysql-port # 命名端口,增强可读性
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-root-secret # 引用Base层定义的Secret
key: root-password
resources:
# 资源限制,避免单个Pod占用过多集群资源
limits:
cpu: 1000m # 最大CPU占用:1核
memory: 1Gi # 最大内存占用:1GB
requests:
cpu: 500m # 请求CPU:500毫核
memory: 512Mi # 请求内存:512MB
3. 编写Service配置(NodePort暴露,通用端口配置)
新建mysql-service.yaml,通过NodePort类型暴露MySQL服务,端口选择30000-32767范围内的可用端口:
yaml
apiVersion: v1
kind: Service
metadata:
name: mysql-nodeport-service
labels:
app: mysql
spec:
type: NodePort # 节点端口类型,便于集群外部访问
selector:
app: mysql # 匹配MySQL Pod标签,实现流量转发
ports:
- protocol: TCP
port: 3306 # Service内部端口,集群内可通过该端口访问
targetPort: 3306 # 容器端口,与MySQL容器暴露端口一致
nodePort: 30306 # 集群节点端口(固定,便于外部访问,需确保未被占用)
3.2 编写Base层kustomization.yaml,编排所有通用资源
新建kustomization.yaml(Kustomize核心配置文件,必选),声明API版本并引用上述所有资源,作为基础配置的入口:
yaml
apiVersion: kustomize.config.k8s.io/v1beta1 # 稳定版API,兼容性最广
kind: Kustomization
metadata:
name: mysql-base-config # Base层配置名称,便于识别
# 引用Base层所有通用资源,Kustomize会自动解析这些YAML文件
resources:
- mysql-secret.yaml
- mysql-deployment.yaml
- mysql-service.yaml
3.3 验证Base层目录结构
安装tree工具并查看目录结构,确保所有配置文件正确放置,避免路径错误:
bash
# 安装tree(Debian/Ubuntu系列,CentOS可使用yum install tree)
apt update && apt install tree -y
# 查看当前目录(Base层)结构
tree .
预期输出(确保目录结构与以下一致):
text
.
├── kustomization.yaml
├── mysql-deployment.yaml
├── mysql-secret.yaml
└── mysql-service.yaml
0 directories, 4 files
至此,Base层通用配置搭建完成,所有环境均可直接引用该层配置,无需重复编写通用资源。
四、Step 2:搭建Overlay覆盖层,实现开发环境差异化配置
基于Base层,我们在overlays/development目录下搭建开发环境的专属配置,核心实现:
-
指定开发环境专属命名空间
ml-devops,实现环境隔离; -
通过策略合并补丁将MySQL副本数从3改为4(开发环境需更多测试实例);
-
通过JSON 6902补丁为Pod添加开发环境专属标签;
-
生成开发环境专属ConfigMap(存储配置参数)和Secret(存储专属密钥);
-
为所有资源添加通用环境标签
env: dev; -
引用Base层配置,实现配置复用。
4.1 创建Overlay开发环境目录
回到上级目录,递归创建Overlay开发环境目录,路径与Base层对应,便于管理:
bash
# 回到kustomize-demo根目录
cd /k8s/kustomize-demo
# 递归创建overlay开发环境目录(overlays/development)
mkdir -p overlays/development
# 进入开发环境Overlay目录
cd overlays/development
4.2 编写开发环境核心配置:kustomization.yaml
新建kustomization.yaml,这是Overlay层的核心,集成「资源引用、补丁修改、配置/密钥生成、环境隔离」等所有能力,代码优化后注释清晰,便于后续维护:
yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
# 开发环境专属命名空间,实现与测试/生产环境的资源隔离,避免冲突
namespace: ml-devops
# 引用Base层基础配置(相对路径,../../base指向上级目录的base文件夹)
resources:
- ../../base
# 为所有资源添加通用标签,方便按环境、版本筛选资源,便于运维管理
commonLabels:
env: dev # 环境标签:开发环境
version: v1.0 # 版本标签,便于版本追溯
project: ml-devops # 项目标签,关联项目归属
# 生成器配置:关闭ConfigMap/Secret名称的哈希后缀(默认开启,关闭后便于记忆和引用)
generatorOptions:
disableNameSuffixHash: true
# 补丁列表:修改Base层的Deployment配置,实现开发环境差异化
patches:
# 补丁1:策略合并补丁(Strategic Merge)
# 适用场景:简单字段修改(如副本数、镜像版本、标签等),无需完整资源结构
- path: deploy-strategic-merge-patch.yaml
target:
# 指定补丁作用的目标资源:Base层的mysql-deployment(Deployment类型)
kind: Deployment
name: mysql-deployment
options:
allowNameChange: false # 不允许修改资源名称,保证Base与Overlay资源名称一致
# 补丁2:JSON 6902补丁
# 适用场景:复杂嵌套字段操作(如添加/删除标签、修改嵌套配置等)
- path: deploy-json6902-patch.yaml
target:
kind: Deployment
name: mysql-deployment
options:
allowNameChange: false
# 生成开发环境专属ConfigMap(两种方式:文件式、字面量式,按需选择)
configMapGenerator:
- name: dev-mysql-config
files:
- config/mysql-config.properties # 从文件加载MySQL配置,便于批量修改
- name: dev-env-config
literals: # 直接写字面量配置,适用于简单键值对
- MYSQL_DATABASE=ml_dev_db # 开发环境专属数据库名称
- MYSQL_CHARSET=utf8mb4 # 数据库字符集
- MYSQL_COLLATION=utf8mb4_unicode_ci # 数据库排序规则
# 生成开发环境专属Secret(两种方式:文件式、字面量式,存储敏感信息)
secretGenerator:
- name: dev-mysql-account
files:
- secret/account-info.yaml # 从文件加载业务账号密码,便于维护
type: Opaque
- name: dev-api-secret
literals: # 直接写字面量密钥,适用于简单敏感信息
- api_key=dev_8s9f7d6a5b4c3e2f1
- token=dev_mlops_2025_token
type: Opaque
4.3 编写补丁文件,实现Deployment差异化修改
根据上述kustomization.yaml的配置,编写两个补丁文件,分别实现副本数调整和标签添加。
1. 策略合并补丁(deploy-strategic-merge-patch.yaml)
适合简单字段修改,只需编写要修改的字段,无需完整资源结构,本次将副本数从3改为4:
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-deployment # 必须与Base层Deployment名称一致,否则无法匹配
spec:
replicas: 4 # 开发环境副本数调整为4,满足测试需求
2. JSON 6902补丁(deploy-json6902-patch.yaml)
适合复杂嵌套字段操作,通过op指定操作类型(add/delete/replace),path指定字段路径,value指定值:
json
[
{
"op": "add", # 操作类型:添加字段
"path": "/spec/template/metadata/labels/dev", # 字段路径:Pod标签下添加dev键
"value": "release-v1.0" # 标签值:开发环境版本标识
},
{
"op": "add",
"path": "/spec/template/metadata/labels/team",
"value": "ml-dev-team" # 新增团队标签,便于团队归属管理
}
]
4.4 编写ConfigMap和Secret的配套文件
根据kustomization.yaml中的配置,创建对应的配置文件和密钥文件目录及内容,确保路径一致:
bash
# 创建config(存储ConfigMap配套文件)和secret(存储Secret配套文件)目录
mkdir -p config secret
1. ConfigMap配套文件:config/mysql-config.properties
存储开发环境MySQL专属配置参数,便于集中管理和修改:
properties
# 开发环境MySQL专属配置(优化数据库性能,适配开发场景)
mysql_max_connections=100 # 最大连接数,开发环境无需过高
mysql_wait_timeout=86400 # 连接超时时间(24小时)
mysql_interactive_timeout=86400 # 交互式连接超时时间
mysql_query_cache_size=0 # 关闭查询缓存,适配MySQL 8.0+版本
character_set_server=utf8mb4 # 服务器字符集
collation_server=utf8mb4_unicode_ci # 服务器排序规则
2. Secret配套文件:secret/account-info.yaml
存储开发环境MySQL业务账号密码,敏感信息单独存放,便于维护:
yaml
# 开发环境MySQL业务账号(非root账号,降低权限风险)
app_user=ml_dev_user # 业务账号名称
app_password=dev_ml@2025 # 业务账号密码,复杂度适中,适配开发环境
4.5 验证Overlay开发环境目录结构
执行tree命令,查看Overlay开发环境目录结构,确保所有文件正确放置:
bash
tree .
预期输出:
text
.
├── config
│ └── mysql-config.properties
├── deploy-json6902-patch.yaml
├── deploy-strategic-merge-patch.yaml
├── kustomization.yaml
└── secret
└── account-info.yaml
2 directories, 6 files
4.6 预览Overlay配置效果(关键步骤)
在部署到集群前,通过kubectl kustomize预览最终生成的K8s资源清单,验证配置是否正确,避免部署出错(核心校验:副本数、标签、命名空间等):
bash
kubectl kustomize ./
预览说明:命令会自动合并Base层配置与Overlay层的补丁、配置/密钥生成规则,输出最终的YAML资源清单。可重点检查以下内容:
-
Deployment副本数是否为4;
-
Pod标签是否包含
env: dev、dev: release-v1.0等; -
命名空间是否为
ml-devops; -
ConfigMap/Secret是否包含开发环境专属配置。
五、Step 3:部署到K8s集群并验证所有资源
完成配置预览且确认无误后,开始将配置部署到K8s集群,并通过kubectl命令逐步验证所有资源的创建状态,确保部署成功。
5.1 创建开发环境专属命名空间
先创建开发环境专属命名空间ml-devops,实现环境隔离,避免与其他环境资源冲突:
bash
kubectl create namespace ml-devops
预期输出 :namespace/ml-devops created
5.2 基于Kustomize部署所有资源
使用kubectl apply -k .命令,Kustomize会自动合并Base和Overlay层配置,一次性部署所有资源到指定命名空间(ml-devops),无需手动逐个部署YAML文件:
bash
kubectl apply -k .
预期输出(所有资源创建成功):
text
configmap/dev-env-config created
configmap/dev-mysql-config created
secret/dev-api-secret created
secret/dev-mysql-account created
secret/mysql-root-secret created
service/mysql-nodeport-service created
deployment.apps/mysql-deployment created
5.3 验证所有资源部署状态
部署完成后,通过以下kubectl命令,逐步验证所有资源的状态,确保符合预期。所有命令均指定命名空间ml-devops,避免查询到其他环境资源。
1. 验证ConfigMap(开发环境专属)
查看开发环境下所有ConfigMap,确认两个专属ConfigMap均已创建:
bash
kubectl get configmaps -n ml-devops
预期输出(包含dev-env-config、dev-mysql-config):
text
NAME DATA AGE
dev-env-config 3 1m
dev-mysql-config 5 1m
2. 验证Secret(通用+开发环境专属)
查看开发环境下所有Secret,确认Base层的通用Secret和Overlay层的专属Secret均已创建:
bash
kubectl get secrets -n ml-devops
预期输出(包含mysql-root-secret、dev-mysql-account、dev-api-secret):
text
NAME TYPE DATA AGE
dev-api-secret Opaque 2 1m
dev-mysql-account Opaque 2 1m
mysql-root-secret Opaque 1 1m
3. 验证Service(NodePort暴露)
查看开发环境下的Service,确认NodePort服务已创建,端口与配置一致(nodePort: 30306):
bash
kubectl get service -n ml-devops
预期输出:
text
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mysql-nodeport-service NodePort 10.96.xxx.xxx <none> 3306:30306/TCP 1m
4. 验证Deployment(副本数是否为4)
查看开发环境下的Deployment,确认副本数已通过补丁修改为4,且就绪副本数与总副本数一致:
bash
kubectl get deployments.apps -n ml-devops
预期输出(replicas: 4,READY: 4/4):
text
NAME READY UP-TO-DATE AVAILABLE AGE
mysql-deployment 4/4 4 4 1m
5. 验证Pod(是否正常运行、标签是否正确)
查看开发环境下的Pod,确认所有Pod均为Running状态,且包含开发环境专属标签:
bash
kubectl get pods --show-labels -n ml-devops
关键验证点:
-
Pod状态均为
Running,数量为4个(与Deployment副本数一致); -
Labels列包含
env=dev、dev=release-v1.0、team=ml-dev-team、app=mysql等标签; -
Pod名称以
mysql-deployment-xxx开头,与Deployment名称一致。
6. 验证MySQL服务可访问性(可选,确保服务正常可用)
通过kubectl exec进入Pod,验证MySQL服务是否正常启动,可正常登录:
bash
# 替换<pod-name>为上述命令查询到的任意Pod名称(如mysql-deployment-7f89dxxx)
# 替换<node-ip>为你的K8s节点IP(Master或Worker节点均可)
kubectl exec -it <pod-name> -n ml-devops -- mysql -h <node-ip> -P 30306 -u root -p
执行命令后,输入Base层配置的MySQL根密码123456789,若能成功进入MySQL命令行(如下所示),说明服务部署正常:
text
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.xx MySQL Community Server - GPL
Copyright (c) 2000, 2025, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>