kubectl Patch Deployment的volume和volumeMounts

K8s运维中,为Deployment添加/追加volumes及volumeMounts(如挂载配置、license文件)时,手动操作效率低、风险高。本文精简介绍patch-exist.sh脚本,聚焦其用法、适用场景及核心原理,帮助运维人员高效安全完成配置更新。

一、脚本核心定位

patch-exist.sh专为K8s Deployment设计,核心是「先备份、再操作」,兼容"无原有卷/挂载""有原有卷/挂载"两种场景,不覆盖原有配置,降低运维门槛,避免误操作故障。

二、脚本详细用法

(一)前置准备

  1. 依赖:安装kubectl(K8s客户端)和jq(JSON解析工具),命令:yum install jq -y,kubectl需配置集群连接。

  2. 配置:修改脚本中NAMESPACE参数(默认your_namespace),匹配实际集群命名空间。

  3. 权限:执行用户需拥有目标命名空间Deployment的get、patch权限。

(二)脚本执行

仅需传入Deployment名称,命令格式:bash patch-exist.sh <deployment-name>

示例:bash patch-exist.sh bus-server,执行后自动完成备份、配置处理、结果验证,失败则终止。

(三)结果验证与备份恢复

  1. 验证:手动执行命令确认配置生效(筛选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")'

  1. 恢复:脚本自动在./backup目录生成备份文件,恢复命令:kubectl apply -f ./backup/<backup-file-name> -n <namespace>

三、脚本适用场景

  1. 批量挂载:多Deployment统一挂载配置(如tongweb-lic),示例:for deploy in admin-server portal-server; do bash patch-exist.sh $deploy; done。

  2. 新增配置:新建Deployment无卷/挂载时,自动创建字段并添加配置。

  3. 追加配置:已存在卷/挂载的Deployment,在原有数组末尾追加,不覆盖原有配置。

  4. 高安全场景:备份失败终止操作,可通过备份快速恢复,适配生产环境。

四、脚本核心原理

脚本依托K8s JSON Patch机制和Shell逻辑,核心分4个模块:

  1. 前置校验:检查Deployment名称参数、kubectl和jq是否安装,缺失则退出。

  2. 备份逻辑:自动创建备份目录,导出Deployment配置至YAML文件,备份失败终止操作。

  3. 配置Patch:用jq判断volumes/volumeMounts是否存在------不存在则创建字段并添加配置;存在则在数组末尾追加(路径末尾加-)。

  4. 结果验证:提取目标配置并筛选,确认Patch生效。

五、脚本完整源码(含精简注释)

bash 复制代码
#!/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、卷名称、挂载路径适配需求,注释聚焦核心逻辑,便于快速使用。

相关推荐
猿究院_夏燊6 小时前
Spring Bean 生命周期
java·后端·spring
CCblandy8 小时前
雪花 ID 四个边界实测:时钟回拨重号 500 个,前端 JSON.parse 直接丢精度
后端·python·算法·性能优化·架构
我是人✓8 小时前
SpringBoot项目的五种创建方式
java·spring boot·后端
念念清晰9 小时前
000-OpenJDK17 源码构建:MacOS环境(M芯片)
java·后端
来福猿10 小时前
SpringCloud Config 源码分析:配置拉取、刷新与多环境管理
后端·spring·spring cloud
IT_陈寒12 小时前
React组件莫名重渲染?你可能忘了这个小细节
前端·人工智能·后端
用户98883218717412 小时前
给 .NET 网络调用设定“预算”:用 CancellationTokenSource.CancelAfter 处理超时取消
后端
清风儿32912 小时前
一块不会说话的电表,把我们折腾了半个月
后端
预知同行12 小时前
深入解析 MoE 混合专家模型:从 Router 到 All-to-All 的架构全景与生产实践
后端·架构
upala12 小时前
【仓颉语言入门 · 第二篇 第 8 课】
后端