K8s运维中,为Deployment添加/追加volumes及volumeMounts(如挂载配置、license文件)时,手动操作效率低、风险高。本文精简介绍patch-exist.sh脚本,聚焦其用法、适用场景及核心原理,帮助运维人员高效安全完成配置更新。
一、脚本核心定位
patch-exist.sh专为K8s Deployment设计,核心是「先备份、再操作」,兼容“无原有卷/挂载”“有原有卷/挂载”两种场景,不覆盖原有配置,降低运维门槛,避免误操作故障。
二、脚本详细用法
(一)前置准备
-
依赖:安装kubectl(K8s客户端)和jq(JSON解析工具),命令:
yum install jq -y,kubectl需配置集群连接。 -
配置:修改脚本中
NAMESPACE参数(默认your_namespace),匹配实际集群命名空间。 -
权限:执行用户需拥有目标命名空间Deployment的get、patch权限。
(二)脚本执行
仅需传入Deployment名称,命令格式:bash patch-exist.sh <deployment-name>
示例:bash patch-exist.sh bus-server,执行后自动完成备份、配置处理、结果验证,失败则终止。
(三)结果验证与备份恢复
- 验证:手动执行命令确认配置生效(筛选tongweb-lic相关配置):
kubectl get deployment <deployment-name> -n <namespace> -o jsonpath='{.spec.template.spec.volumes}' | jq '.[] | select(.name=="tongweb-lic")'
kubectl get deployment <deployment-name> -n <namespace> -o jsonpath='{.spec.template.spec.containers[0].volumeMounts}' | jq '.[] | select(.name=="tongweb-lic")'
- 恢复:脚本自动在
./backup目录生成备份文件,恢复命令:kubectl apply -f ./backup/<backup-file-name> -n <namespace>
三、脚本适用场景
-
批量挂载:多Deployment统一挂载配置(如tongweb-lic),示例:
for deploy in admin-server portal-server; do bash patch-exist.sh $deploy; done。 -
新增配置:新建Deployment无卷/挂载时,自动创建字段并添加配置。
-
追加配置:已存在卷/挂载的Deployment,在原有数组末尾追加,不覆盖原有配置。
-
高安全场景:备份失败终止操作,可通过备份快速恢复,适配生产环境。
四、脚本核心原理
脚本依托K8s JSON Patch机制和Shell逻辑,核心分4个模块:
-
前置校验:检查Deployment名称参数、kubectl和jq是否安装,缺失则退出。
-
备份逻辑:自动创建备份目录,导出Deployment配置至YAML文件,备份失败终止操作。
-
配置Patch:用jq判断volumes/volumeMounts是否存在——不存在则创建字段并添加配置;存在则在数组末尾追加(路径末尾加
-)。 -
结果验证:提取目标配置并筛选,确认Patch生效。
五、脚本完整源码(含精简注释)
#!/bin/bash
# patch-exist.sh - 先备份再兼容添加/追加volumes和volumeMounts,不覆盖原有配置
# 用法:bash patch-exist.sh <deployment-name>
# 检查参数
if [ -z "$1" ]; then
echo "错误:请传入Deployment名称,例如:bash patch-exist.sh bus-server"
exit 1
fi
DEPLOY_NAME=$1
NAMESPACE="your_namespace"
# 定义备份目录和备份文件名(含时间戳,避免覆盖)
BACKUP_DIR="./backup"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="${BACKUP_DIR}/${DEPLOY_NAME}_backup_${TIMESTAMP}.yaml"
# 依赖检查
if ! command -v jq &> /dev/null; then
echo "错误:未安装jq,请执行 yum install jq -y 安装"
exit 1
fi
if ! command -v kubectl &> /dev/null; then
echo "错误:未安装kubectl,请先配置K8s客户端"
exit 1
fi
# -------------------------- 核心备份逻辑 --------------------------
echo "==== 开始备份Deployment配置 ===="
# 创建备份目录(不存在则创建)
mkdir -p "${BACKUP_DIR}"
# 备份Deployment完整配置到YAML文件
if kubectl get deployment "${DEPLOY_NAME}" -n "${NAMESPACE}" -o yaml > "${BACKUP_FILE}"; then
echo "备份成功!配置文件已保存至:${BACKUP_FILE}"
else
echo "备份失败!请检查Deployment名称或K8s连接状态"
exit 1 # 备份失败则终止脚本,避免误操作
fi
# -------------------------- 处理volumes --------------------------
echo -e "\n==== 处理volumes配置 ===="
# 判断volumes字段是否存在
VOLUMES_EXIST=$(kubectl get deployment "${DEPLOY_NAME}" -n "${NAMESPACE}" -o json | jq -r '.spec.template.spec | has("volumes")')
if [ "${VOLUMES_EXIST}" = "false" ]; then
# 字段不存在:直接创建volumes字段并添加目标卷(一步到位,无空数组)
kubectl patch deployment "${DEPLOY_NAME}" -n "${NAMESPACE}" \
--type json \
--patch '[
{"op":"add","path":"/spec/template/spec/volumes","value":[
{"name":"tongweb-lic","configMap":{"name":"tongweb-lic","items":[{"key":"license.dat","path":"license.dat"}],"defaultMode":420}}
]}
]'
echo "volumes字段不存在,已直接创建并添加tongweb-lic卷"
else
# 字段存在:追加卷到现有数组(保留原有配置)
kubectl patch deployment "${DEPLOY_NAME}" -n "${NAMESPACE}" \
--type json \
--patch '[
{"op":"add","path":"/spec/template/spec/volumes/-","value":
{"name":"tongweb-lic","configMap":{"name":"tongweb-lic","items":[{"key":"license.dat","path":"license.dat"}],"defaultMode":420}}
}
]'
echo "volumes字段已存在,已追加tongweb-lic卷(原有配置保留)"
fi
# -------------------------- 处理volumeMounts --------------------------
echo -e "\n==== 处理volumeMounts配置 ===="
# 判断volumeMounts字段是否存在
VOLUME_MOUNTS_EXIST=$(kubectl get deployment "${DEPLOY_NAME}" -n "${NAMESPACE}" -o json | jq -r '.spec.template.spec.containers[0] | has("volumeMounts")')
if [ "${VOLUME_MOUNTS_EXIST}" = "false" ]; then
# 字段不存在:直接创建volumeMounts字段并添加目标挂载(一步到位,无空数组)
kubectl patch deployment "${DEPLOY_NAME}" -n "${NAMESPACE}" \
--type json \
--patch '[
{"op":"add","path":"/spec/template/spec/containers/0/volumeMounts","value":[
{"name":"tongweb-lic","readOnly":true,"mountPath":"/app/config/lic/license.dat"}
]}
]'
echo "volumeMounts字段不存在,已直接创建并添加tongweb-lic挂载"
else
# 字段存在:追加挂载到现有数组(保留原有配置)
kubectl patch deployment "${DEPLOY_NAME}" -n "${NAMESPACE}" \
--type json \
--patch '[
{"op":"add","path":"/spec/template/spec/containers/0/volumeMounts/-","value":
{"name":"tongweb-lic","readOnly":true,"mountPath":"/app/config/lic/license.dat"}
}
]'
echo "volumeMounts字段已存在,已追加tongweb-lic挂载(原有配置保留)"
fi
# -------------------------- 验证结果 --------------------------
echo -e "\n==== 验证配置 ===="
echo "volumes配置:"
kubectl get deployment "${DEPLOY_NAME}" -n "${NAMESPACE}" -o jsonpath='{.spec.template.spec.volumes}' | jq '.[] | select(.name=="tongweb-lic")'
echo -e "\nvolumeMounts配置:"
kubectl get deployment "${DEPLOY_NAME}" -n "${NAMESPACE}" -o jsonpath='{.spec.template.spec.containers[0].volumeMounts}' | jq '.[] | select(.name=="tongweb-lic")'
echo -e "\n所有操作完成!备份文件路径:${BACKUP_FILE}"
源码说明:可修改NAMESPACE、卷名称、挂载路径适配需求,注释聚焦核心逻辑,便于快速使用。