部署 Airflow Scheduler 高可用HA
一. 简要概述
在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 是否被杀掉