#!/bin/bash set -euo pipefail # ========================== 全局配置 ========================== # a颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # 打印工具函数 info() { echo -e "${YELLOW}[INFO]${NC} $1"; } success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; } error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; } step() { echo -e "\n${BLUE}>> $1${NC}"; } # 配置参数 ACTION="" VIP="" PRIORITY=150 INTERFACE="" KEEPALIVED_CONF="/etc/keepalived/keepalived.conf" CHECK_SCRIPT="/usr/local/bin/check_haproxy.sh" # ========================== 帮助信息 ========================== usage() { cat << EOF Keepalived 高可用配置脚本(适配K8s VIP管理) 功能:安装/卸载Keepalived,配置虚拟IP(VIP)及HAProxy健康检查 用法: $0 [操作] [选项] 操作: --install 安装并配置Keepalived --uninstall 卸载Keepalived及清理配置 安装选项: --vip 必选,虚拟IP(格式:192.168.1.100/24) --priority <数值> 可选,节点优先级(默认150,主节点建议150+,备节点140-) 示例: 主节点安装: $0 --install --vip 192.168.61.200/24 --priority 150 备节点安装: $0 --install --vip 192.168.61.200/24 --priority 140 卸载: $0 --uninstall EOF exit 1 } # ========================== 工具函数 ========================== # 获取默认网卡(非回环,第一个激活的网卡) get_default_interface() { INTERFACE=$(ip -br link show up | grep -v LOOPBACK | awk '{print $1}' | head -n1) [[ -z "$INTERFACE" ]] && error "无法获取有效网卡,请检查网络接口状态" info "自动获取网卡:$INTERFACE" } # ========================== 安装逻辑 ========================== install_keepalived() { # 参数校验 [[ -z "$VIP" ]] && error "必须通过--vip指定虚拟IP(格式:IP/子网掩码,如192.168.61.200/24)" [[ ! "$VIP" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+$ ]] && error "VIP格式无效,正确格式:192.168.61.200/24" [[ ! "$PRIORITY" =~ ^[0-9]+$ ]] && error "优先级必须是整数(如150)" step "开始安装Keepalived" # 获取网卡 get_default_interface # 安装软件(静默模式,去除apt警告) info "安装Keepalived软件包..." apt update -qq >/dev/null 2>&1 apt install -y -qq keepalived >/dev/null 2>&1 || error "Keepalived安装失败" success "Keepalived软件包安装完成" # 备份原有配置 if [[ -f "$KEEPALIVED_CONF" ]]; then local backup="${KEEPALIVED_CONF}.bak.$(date +%F_%H%M%S)" mv "$KEEPALIVED_CONF" "$backup" info "原有配置已备份至:$backup" fi # 创建健康检查脚本(监控HAProxy状态) info "创建HAProxy健康检查脚本..." cat > "$CHECK_SCRIPT" << 'EOF' #!/bin/bash pgrep -x "haproxy" >/dev/null 2>&1 || { systemctl stop keepalived; exit 1; } exit 0 EOF chmod +x "$CHECK_SCRIPT" || error "健康检查脚本权限设置失败" success "健康检查脚本已创建:$CHECK_SCRIPT" # 生成配置文件 info "生成Keepalived配置..." local state="BACKUP" [[ "$PRIORITY" -ge 150 ]] && state="MASTER" # 优先级≥150默认为主节点 cat > "$KEEPALIVED_CONF" << EOF global_defs { router_id LVS_K8S_$(hostname) script_security 2 enable_script_security } vrrp_script check_haproxy { script "$CHECK_SCRIPT" interval 2 weight -5 } vrrp_instance VI_1 { state $state interface $INTERFACE virtual_router_id 51 priority $PRIORITY advert_int 1 authentication { auth_type PASS auth_pass k8s_ha_auth_2024 } virtual_ipaddress { $VIP } track_script { check_haproxy } } EOF [[ -f "$KEEPALIVED_CONF" ]] || error "配置文件生成失败" success "配置文件已生成:$KEEPALIVED_CONF" # 启动服务 info "启动并设置开机自启..." systemctl enable --now keepalived >/dev/null 2>&1 || error "Keepalived启动失败(日志:journalctl -u keepalived)" [[ "$(systemctl is-active keepalived)" == "active" ]] || error "Keepalived启动后状态异常" # 安装完成汇总 echo -e "\n${GREEN}===== 安装完成 =====${NC}" echo " VIP: $VIP" echo " 节点角色: $state(优先级: $PRIORITY)" echo " 绑定网卡: $INTERFACE" echo " 健康检查: $CHECK_SCRIPT" echo " 服务状态: 运行中" } # ========================== 卸载逻辑 ========================== uninstall_keepalived() { step "开始卸载Keepalived" # 停止服务 if systemctl is-active --quiet keepalived; then info "停止Keepalived服务..." systemctl stop keepalived >/dev/null 2>&1 || info "服务停止失败,继续卸载" success "服务已停止" else info "Keepalived未运行,跳过停止步骤" fi # 卸载软件 if dpkg -l keepalived &>/dev/null; then info "卸载软件包..." apt purge -y -qq keepalived >/dev/null 2>&1 || error "软件包卸载失败" apt autoremove -y -qq >/dev/null 2>&1 success "软件包已卸载" else info "Keepalived未安装,跳过卸载" fi # 清理配置 if [[ -d /etc/keepalived/ ]]; then local backup="/etc/keepalived.bak.$(date +%F_%H%M%S)" mv /etc/keepalived/ "$backup" success "配置目录已备份至:$backup" fi # 清理健康检查脚本 if [[ -f "$CHECK_SCRIPT" ]]; then rm -f "$CHECK_SCRIPT" success "健康检查脚本已删除:$CHECK_SCRIPT" fi # 卸载完成 echo -e "\n${GREEN}===== 卸载完成 =====${NC}" } # ========================== 主逻辑 ========================== main() { # 解析参数 while [[ $# -gt 0 ]]; do case "$1" in --install|--uninstall) ACTION="$1"; shift ;; --vip) [[ $# -lt 2 ]] && error "--vip需指定IP/子网掩码"; VIP="$2"; shift 2 ;; --priority) [[ $# -lt 2 ]] && error "--priority需指定数值"; PRIORITY="$2"; shift 2 ;; *) error "未知参数:$1" ;; esac done # 校验操作 [[ -z "$ACTION" ]] && error "必须指定--install(安装)或--uninstall(卸载)" # 检查root权限 [[ $EUID -ne 0 ]] && error "请使用root权限运行(sudo $0 ...)" # 执行操作 case "$ACTION" in --install) install_keepalived ;; --uninstall) uninstall_keepalived ;; esac } main "$@"