批量删除OpenStack实例

在Linux终端实现批量删除OpenStack实例,支持并发删除、安全确认、重试机制、优先清理运行中实例

#!/bin/bash
# ======================================================================
# 增强版 OpenStack 删除实例脚本
# 功能:支持并发删除、安全确认、重试机制、优先清理运行中实例
# 更新:2025年4月30日
# ======================================================================

#######################################
# 配置区(用户可自定义参数)
#######################################
delete_InstanceMAX_RETRY=20     # 最大尝试次数(删除失败时尝试再次删除实例)
CHECK_INTERVAL=5                # 实例状态检测间隔(单位:秒)
no_InstanceMAX_RETRY_TIME=20    # 实例列表为空,连续监测实例列表都是空的次数
CONCURRENCY=2                   # 并发删除线程数(建议不超过 API 限制)
MAX_WAIT_TIME=3600              # 最大等待超时时间(单位:秒,60 分钟)

LOG_FILE="./log_instance_delete_$(date +%Y%m%d).log" # 日志文件路径(自动按日期生成)

# 统计变量
TOTAL_DELETED_INSTANCES=0        # 已删除实例总数统计
DELETED_INSTANCES_FILE="/tmp/deleted_instances.txt" # 已删除实例ID临时记录文件

# 颜色定义(终端输出美化)
RED='\033[0;31m'    # 红色 - 错误/危险操作
GREEN='\033[0;32m'  # 绿色 - 成功/正常状态
YELLOW='\033[0;33m' # 黄色 - 警告/等待状态
BLUE='\033[0;34m'   # 蓝色 - 执行中/进度信息
NC='\033[0m'        # 无颜色 - 重置终端颜色

#######################################
# 函数:带重试机制的实例删除
# 参数:
#   $1 : 实例ID(必填)
# 返回值:
#   0 - 删除成功 | 1 - 删除失败
# 描述:
#   使用指数退避策略重试删除,最多尝试 delete_InstanceMAX_RETRY 次删除实例
#######################################
retry_delete() {
    local instance_id=$1
    for ((i=1; i<=delete_InstanceMAX_RETRY; i++)); do
        log "${BLUE}尝试删除实例 [ID: $instance_id] (第 $i 次尝试)...${NC}"
        if nova force-delete "$instance_id"; then
            log "${GREEN}删除实例成功: $instance_id${NC}"
            echo "$instance_id" >> "$DELETED_INSTANCES_FILE"
            return 0
        fi
        sleep $((i*2)) # 指数退避等待
    done
    log "${RED}错误:删除实例 $instance_id 失败,已达最大重试次数(${delete_InstanceMAX_RETRY} 次)${NC}"
    return 1
}

#######################################
# 函数:安全获取实例列表
# 参数:
#   $1 : 实例状态(默认 ACTIVE)
# 返回值:
#   实例ID列表(格式:每行一个ID)
# 描述:
#   过滤无效字符并格式化输出,避免脏数据干扰
#######################################
safe_get_instances() {
    local status=${1:-"ACTIVE"}
    nova list --status $status | awk -F '|' '
        /[0-9a-f]{8}-/ {
            gsub(/ /, "", $2);
            if ($4 ~ status) print $2
        }' status="$status"
}

#######################################
# 函数:日志记录
# 参数:
#   $1 : 日志信息(支持颜色代码)
# 描述:
#   自动添加时间戳,并同时输出到终端和日志文件
#######################################
log() {
    local msg="$1"
    echo -e "$(date '+%Y-%m-%d %T') - $msg" | tee -a "$LOG_FILE"
}

# 导出函数到子 Shell(确保并发调用时可用)
export -f log retry_delete

#######################################
# 主流程
#######################################

# 解析命令行参数
while getopts "s:i:c:l:" opt; do
    case $opt in
        s) STATUS=$OPTARG;;    # 指定目标实例状态(如 ACTIVE/BUILD)
        i) CHECK_INTERVAL=$OPTARG;;  # 自定义检测间隔时间
        c) CONCURRENCY=$OPTARG;;     # 调整并发线程数
        l) LOG_FILE=$OPTARG;;        # 指定日志文件路径
        *) echo -e "${RED}用法: $0 [-s 状态] [-i 间隔] [-c 并发数] [-l 日志路径]${NC}"
           exit 1;;
    esac
done

# 初始化 OpenStack 环境
source /openstack/admin-openrc.sh || { 
    log "${RED}错误:环境变量加载失败,请检查 admin-openrc.sh 文件权限或路径${NC}"
    exit 1
}

# 检查日志目录可写性
if [ ! -w "$(dirname "$LOG_FILE")" ]; then
    echo -e "${RED}错误:日志目录不可写 [路径: $(dirname "$LOG_FILE")]${NC}" >&2
    exit 1
fi

# 初始化临时文件(记录已删除实例)
> "$DELETED_INSTANCES_FILE"

# 进程锁检查(防止重复运行)
LOCK_FILE="/tmp/os_clean.lock"
if [ -e "$LOCK_FILE" ]; then
    log "${YELLOW}警告:检测到已有清理进程运行中 [PID: $(cat $LOCK_FILE)]${NC}"
    exit 1
fi
echo $$ > "$LOCK_FILE"
trap 'rm -f "$LOCK_FILE"; 
      TOTAL_DELETED_INSTANCES=$(wc -l < "$DELETED_INSTANCES_FILE"); 
      log "${GREEN}===== 脚本进程中断退出,已删除实例数: $TOTAL_DELETED_INSTANCES ====="; 
      rm -f "$DELETED_INSTANCES_FILE"' EXIT

# 安全确认(确保转义符被解析)
if [[ -t 0 ]]; then
    read -p "$(printf "${YELLOW}危险操作:是否确认执行删除实例?(y/N): ${NC}")" -n 1 confirm
    [[ $confirm != "y" ]] && { log "操作已取消"; exit; }
    echo
fi

# 主循环(状态检测与删除)
log "\n${GREEN}===== 开始删除实例 [时间: $(date +%T)] ====="
start_time=$(date +%s)
empty_count=0  # 连续空检测计数器

while :; do
    # 超时检查(防止无限等待)
    if (( $(date +%s) - start_time > MAX_WAIT_TIME )); then
        log "${RED}错误:操作超时,已超过最大等待时间(${MAX_WAIT_TIME} 秒)${NC}"
        exit 1
    fi

    # 获取目标实例列表
    instances=$(safe_get_instances "${STATUS:-ACTIVE}")
    creating_instances=$(safe_get_instances "BUILD")

    # 优先删除运行中的实例
    if [ -n "$instances" ]; then
        log "检测到 ${#instances[@]} 个运行中实例,启动并发删除..."
        printf "%s\n" "${instances[@]}" | xargs -P $CONCURRENCY -I {} bash -c "
            delete_InstanceMAX_RETRY='$delete_InstanceMAX_RETRY'
            LOG_FILE='$LOG_FILE'
            DELETED_INSTANCES_FILE='$DELETED_INSTANCES_FILE'
            $(declare -f log retry_delete)
            retry_delete \"{}\"
        "
        sleep $((CHECK_INTERVAL/2))  # 降低 API 请求频率
        continue
    fi

    # 处理创建中的实例(等待后重试)
    if [ -n "$creating_instances" ]; then
        log "${YELLOW}提示:检测到 ${#creating_instances[@]} 个创建中实例,等待 ${CHECK_INTERVAL}...${NC}"
        sleep $CHECK_INTERVAL
        continue
    fi

    # 空状态处理(连续检测退出机制)
    if [ -z "$instances" ]; then
        log "${YELLOW}提示:未发现可操作实例,等待 ${CHECK_INTERVAL} 秒后重试,至多重试${no_InstanceMAX_RETRY_TIME}...${NC}"
        sleep $CHECK_INTERVAL
        # 连续${no_InstanceMAX_RETRY_TIME} 次空检测则退出
        if (( empty_count++ >= ${no_InstanceMAX_RETRY_TIME} )); then
            TOTAL_DELETED_INSTANCES=$(wc -l < "$DELETED_INSTANCES_FILE")
            log "${GREEN}===== 脚本运行清理完成,已删除实例总数: ${TOTAL_DELETED_INSTANCES} ====="
            exit 0
        fi
        continue
    fi

    empty_count=0  # 重置空检测计数器
done

### 如何进行OpenStack清理 #### 清理前准备 为了确保清理过程顺利,在开始之前应备份重要数据并确认当前环境状态。由于直接检查实际运行在容器中的 OpenStack 服务进程的状态对于更详细的监控至关重要[^1],建议先记录下现有服务的健康状况。 #### 停止所有相关服务 停止所有与OpenStack有关的服务是必要的一步。可以通过Ansible脚本批量处理多个节点上的服务停用工作。具体来说,进入`playbooks/inventory`目录,并利用`./dynamic_inventory.py`来获取最新的主机列表信息以便后续操作。 ```bash ansible all -m service -a "name=openstack-* state=stopped" ``` 这条命令会遍历整个集群内的机器并将所有的OpenStack关联服务暂停掉。 #### 删除实例和资源 接下来要删除所有正在使用的计算实例和其他占用存储空间的对象。登录到Horizon界面或者使用CLI工具完成这项任务: ```bash openstack server list | awk '/|/{print $2}' | grep -v ID | xargs -I {} openstack server delete {} ``` 上述指令将列出所有活动服务器ID并通过管道传递给删除函数逐一移除它们。 #### 卸载软件包 当不再需要特定版本的OpenStack组件时,可以选择卸载这些RPM或DEB包以释放磁盘空间。请注意不同Linux发行版之间的差异可能会影响具体的命令语法;这里给出基于RedHat/CentOS系统的例子: ```bash yum remove 'openstack-*' ``` #### 数据库清除 如果计划完全重置OpenStack,则还需要清空数据库内保存的数据。访问MySQL/MariaDB控制台后执行如下SQL语句即可达到目的: ```sql DROP DATABASE keystone; DROP DATABASE nova_api; DROP DATABASE nova_cell0; DROP DATABASE neutron; -- 继续针对其他模块对应的schema... FLUSH PRIVILEGES; ``` > **警告**: 执行以上动作会造成不可逆的影响,请谨慎行事! #### 文件系统整理 最后一步是对文件系统做一次全面扫描,找出残留的日志、配置模板以及其他临时文件予以彻底消除。考虑到安全性和效率问题,推荐采用自动化脚本来辅助完成该环节的工作。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北观止

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值