已复制
全屏展示
复制代码

部署 Airflow Scheduler 高可用HA


· 6 min read

一. 简要概述

在Airflow的高可用集群中,Scheduler是不允许在多个节点同时运行的,因为这样可能会导致任务被重复执行,所以同一时间它只允许在一个节点上运行。从官网的架构图中可以看出Scheduler也只能有一个。

所以为了高可用,我们需要两个节点运行Scheduler,一个Master一个Backup,在Master节点故障后,需要Backup能自动拉起Scheduler接替任务,也就是故障自动恢复功能。

官方文档中针对此场景没有提供相应的解决方法,网上搜索了一番后,在 github 上发现了一个用于此场景的仓库 airflow-scheduler-failover-controller,但是已经年久失修,在试用的过程中发现了一些明显的bug,而其他技术大佬推荐的方法比较复杂,上手也比较困难,最后我把目光投向了简单 稳定 而又可靠的 keepalived 。

二. VRRP协议

keepalived 是 Linux下一个轻量级别的高可用解决方案,通过虚拟路由冗余协议(VRRP)来实现服务或者网络的高可用,核心功能包括健康检查(通过 TCP ICMP HTTP 等协议)、故障自动切换,官网地址 https://www.keepalived.org/

在实际的网络环境中,主机之间的通信通过配置静态路由(默认网关),然后通过 MAC 地址寻找到通信目标。VRRP 可以将两台或多台设备虚拟成一个路由器,这个虚拟的路由器通过虚拟IP对外提供服务,同时多个主机之间会进行健康检查,Master 故障会进行重新选举、虚拟 IP 漂移等等。

但是本文讲述的 Airflow Scheduler 高可用不使用虚拟 IP 功能,而是使用它提供 Master、Backup 选举功能,即保证同时只能有一个 Master 运行服务。

三. 安装配置

节点说明:现在有两个节点,准备配置 Airflow Scheduler,假设 AIRFLOW_HOME=/opt/airflow/,高可用的 Scheduler 配置目录/opt/airflow/airflow_ha/,注意:airflow_ha 目录名不要包含 scheduler 关键字,因为后面要通过 ps 命令判断 scheduler 是否存活。

Airflow的其他组件的启动不在本文讨论范围之内。

节点 IP 故障切换服务
node01 1.1.1.1 airflow scheduler(只允许一个节点运行)
node02 2.2.2.2 airflow scheduler(只允许一个节点运行)

3.1 scheduler 服务脚本

在 node01 node02 上分别配置 scheduler 的启动脚本。

/opt/airflow/airflow_ha/schdler_start.sh

#!/bin/bash

export AIRFLOW_HOME=/opt/airflow/
nohup airflow scheduler 1>>/var/logs/airflow/schduler.log 2>>/var/log/airflow/scheduler_error.log &

3.2 安装keepalived

在 node01 node02 上分别安装 keepalived,安装后配置文件在 /etc/keepalived/keepalived.conf ,它非常简单,只有这一个配置文件,编辑好配置文件直接启停即可。

# Ubuntu 则使用 apt 安装
sudo yum install keepalived -y

# 常用操作
sudo systemctl restart keepalived
sudo systemctl status keepalived
sudo systemctl stop keepalived
sudo systemctl enable keepalived

3.3 管理服务脚本

在 node01 node02 分别添加管理脚本,用于 启动、停止 scheduler 服务,keepalived 需要调用此脚本,并传入启动、停止等参数。

/opt/airflow/airflow_ha/schdler_manager.sh,注意:脚本名不要包含 scheduler 关键字,因为后面要通过 ps 命令判断 scheduler 是否存活。

#!/bin/bash

echo "$(date) current state is $1" >> /opt/airflow/airflow_ha/check.log

# $1 表示当前节点被选举的角色:MASTER BACKUP STOP
# 在启动服务时,确保没有已经在运行着的服务
if [[ "$1" == "MASTER" ]];then
    num=$(ps aux | grep airflow | grep scheduler | grep -v grep | wc -l)
    if [[ "$num" == "0" ]];then
        bash /opt/airflow/airflow_ha/schdler_start.sh
    fi
elif [[ "$1" == "BACKUP" || "$1" == "STOP" ]];then
    ps aux | grep airflow | grep scheduler | awk '{print $2}' | xargs kill -9 2>/dev/null || true
else
    echo "arg \$1 must be one of these: MASTER BACKUP STOP"
fi

3.4 高可用配置

  • node1节点配置 /etc/keepalived/keepalived.conf ,两个节点大部分配置相同,详情见注释
global_defs {
    script_user root # 运行检查脚本的linux用户
}

vrrp_script chk_script_health {
    # 执行检查脚本: 查看日状态判断当前节点状态(MASTER、BACKUP)
    script "/bin/bash /opt/airflow/airflow_ha/schdler_manager.sh $(journalctl -u keepalived | grep Entering | grep -v 'Unsafe permissions' | tail -1 | awk '{print $8}')"
    interval 30 # 每隔多少秒进行检查一次
}

vrrp_instance VI_1 {
    virtual_router_id 53 # 一个标识, MASTER 和 BACKUP 必须一致
    advert_int 5 # 多久进行一次master选举,即健康检查时间间隔
    interface eth0 # 必须是一个真实存储的网络接口

    # 调用检查脚本
    track_script {
      chk_script_health
    }

    # 认证权限密码,防止非法节点进入
    authentication {
        auth_type PASS
        auth_pass 1111
    }

    # 停止keeplived进程,则应用程序也要停止,避免两个节点同时运行你的程序
    notify_stop "/bin/bash /opt/airflow/airflow_ha/schdler_manager.sh STOP"

    # -----------分割线以上可以完全相同,分割线一下必须不同-----------

    state MASTER # 表明当前节点类型: BACKUP 或者 MASTER
    priority 101 # BACKUP 的值必须小于 MASTER 的值

    # 用 vrrp 单播方式通告
    unicast_src_ip 1.1.1.1
    unicast_peer {
        2.2.2.2
    }
}
  • node2节点配置 /etc/keepalived/keepalived.conf
global_defs {
    script_user root # 运行检查脚本的linux用户
}

vrrp_script chk_script_health {
    # 执行检查脚本: 查看日状态判断当前节点状态(MASTER、BACKUP)
    script "/bin/bash /opt/airflow/airflow_ha/schdler_manager.sh $(journalctl -u keepalived | grep Entering | grep -v 'Unsafe permissions' | tail -1 | awk '{print $8}')"
    interval 30 # 每隔多少秒进行检查一次
}

vrrp_instance VI_1 {
    virtual_router_id 53 # 一个标识, MASTER 和 BACKUP 必须一致
    advert_int 5 # 多久进行一次master选举,即健康检查时间间隔
    interface eth0 # 必须是一个真实存储的网络接口

    # 调用检查脚本
    track_script {
      chk_script_health
    }

    # 认证权限密码,防止非法节点进入
    authentication {
        auth_type PASS
        auth_pass 1111
    }

    # 停止keeplived进程,则应用程序也要停止,避免两个节点同时运行你的程序
    notify_stop "/bin/bash /opt/airflow/airflow_ha/schdler_manager.sh STOP"

    # -----------分割线以上可以完全相同,分割线一下必须不同-----------

    state BACKUP # 表明当前节点类型: BACKUP 或者 MASTER
    priority 100 # BACKUP 的值必须小于 MASTER 的值

    # 用 vrrp 单播方式通告
    unicast_src_ip 2.2.2.2
    unicast_peer {
        1.1.1.1
    }
}
  • 两个节点分别重启 keepalived
sudo systemctl restart keepalived

四. 高可用验证

查看日志 /opt/airflow/airflow_ha/check.log ,正常情况下 node01 应该是 MASTER 状态,node2 是BACKUP,因为 node01 的权重更高。

4.1 服务挂掉自动拉起

在 node01 上杀掉 scheduler 服务,观察服务是否可自动拉起,并观察日志情况。其实这里运用的是 keepalived 的每隔一段时间进行健康检测功能,判断自己是Master的话就拉起服务。


ps aux | grep airflow | grep scheduler | awk '{print $2}' | xargs kill -9

4.2 Master失联自动选举

在 node01 停掉 keepalived 服务,或者通过 kill keepalived_pid 的方式模拟节点失联,观察 node02 是否可自动选举成 MASTER ,并拉起服务,并观察日志。

sudo systemctl stop keepalived

4.3 Master正常自动恢复

在 node01 启动 keepalived 服务,观察 node01 是否被选举为 MASTER,并拉起服务,并观察日志,观察 node02 的 scheduler 是否被杀掉


文章推荐