#Kubernetes #Docker #golang

定期轮询删除或重建的job面临资源的冲突解决方案-锁文件

背景:terraform 项目中有些任务需要定期执行,但job 流水线作业资源与进程强绑定关系,进程间需要互斥,避免多个进程同时操作

  • 例如:1点执行脚本后 1点05分脚本还没有退出,如果是每2分钟启动的定时任务,那么就会有冲突。

解决方案常见有两种

  • 1.认为设置sleep ,根据业务规则自定义,坏处就是运行定时任务脚本时,假如不了解业务的的会无法确认是否执行成功。
  • 2.创建一个锁文件

案例

#!/bin/bash

# 配置环境变量
export TENCENTCLOUD_SECRET_ID="******"
export TENCENTCLOUD_SECRET_KEY="******"
export TF_LOG=ERROR                                  # 仅输出错误日志

# 定义关键路径
TF_DIR="/root/terraform_proj/spot_cvm_2c4g"         # Terraform配置目录
LOCK_FILE="/tmp/terraform_rotate.lock"              # 防止并发执行锁文件
LOG_FILE="/var/log/terraform_rotate.log"            # 统一日志文件

# 函数:记录带时间戳的日志
log() {
  echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> $LOG_FILE
}

# 函数:错误处理并退出
error_exit() {
  log "❌ 错误: $1"
  rm -f $LOCK_FILE
  exit 1
}

# 主程序开始
log "=== 开始执行资源轮转 ==="

# 检查锁文件防止并发
if [ -f $LOCK_FILE ]; then
  error_exit "上一个任务仍在运行中,跳过本次执行"
fi
touch $LOCK_FILE

# 进入Terraform目录
cd $TF_DIR || error_exit "无法进入目录 $TF_DIR"

# Step 1: 销毁旧资源
log "执行 terraform destroy..."
terraform destroy -auto-approve >> $LOG_FILE 2>&1 
if [ $? -ne 0 ]; then
  error_exit "terraform destroy 失败"
fi

# 等待资源清理完成(根据实际API等待时间调整)
sleep 300  # 等待5分钟确保资源释放

# Step 2: 重新创建资源
log "执行 terraform apply..."
terraform apply -auto-approve >> $LOG_FILE 2>&1
if [ $? -ne 0 ]; then
  error_exit "terraform apply 失败"
fi

# 清理锁文件
rm -f $LOCK_FILE
log "✅ 资源轮转完成"
exit 0

运行脚本后,会在日志中记录执行时间,并输出执行结果。如果执行过程中出现错误,则会记录错误信息并退出。

flock 命令

flock 是一个POSIX兼容的命令,用于实现文件锁。它允许多个进程同时访问一个文件,但只有一个进程可以同时拥有该文件的写入权限。

  1. 安装flock命令:
    sudo apt-get install -y procps
    
  2. 使用flock命令
    #!/bin/bash
    LOCK_FILE="/tmp/mylock.lock"
    # 1. 打开文件描述符 200 并关联锁文件
    exec 200>"$LOCK_FILE"
    # 2. 尝试获取文件锁(非阻塞模式)
    if flock -n 200; then
     echo "成功获取锁,执行关键操作..."
     # 在此处编写需要互斥执行的代码
     sleep 10
    else
     echo "无法获取锁,其他进程正在运行"
     exit 1
    fi
    # 3. 退出时自动释放锁(无需手动操作)
    trap 'flock -u 200' EXIT
    echo "执行完毕,释放锁"
    exit 0
    

这种写法是官方推荐写法,但是由于flock命令在某些情况下会阻塞进程,所以不建议使用。