前面简单的介绍了一下keepalived track script | interface weight & instance priority & election的关系, 
http://blog.163.com/digoal@126/blog/static/163877040201471992259474/
本文将重点介绍一下keepalived跟踪脚本的配置用法以及参数的解释 : 
keepalived VRRP配置中有一个配置项, vrrp_script : 
截取自 : keepalived.conf.SYNOPSIS

        2.1. VRRP scriptsThe configuration block looks like :vrrp_script <STRING> {          # VRRP script declarationscript <QUOTED_STRING>      # script to run periodicallyinterval <INTEGER>          # run the script this every secondsweight <INTEGER:-254..254>  # adjust priority by this weight  , 用于动态变更vrrp_instance优先级(by vrrp_update_priority). 或者路由器状态(当weight=0)fall <INTEGER>              # required number of failures for KO switch , rise <INTEGER>              # required number of successes for OK switch
}The script will be executed periodically, every <interval> seconds. Its exit
code will be recorded for all VRRP instances which will want to monitor it.
Note that the script will only be executed if at least one VRRP instance
monitors it with a non-zero weight. Thus, any number of scripts may be
declared without taking the system down.If unspecified, the weight equals 2, which means that a success will add +2
to the priority of all VRRP instances which monitor it. On the opposite, a
negative weight will be subtracted from the initial priority in case of
failure.

以上是对脚本的配置, 是否在实例中使用(监控), 需要在相应的vrrp_instance 配置 : 
这里的weight配置将覆盖vrrp_script中weight的配置.

vrrp_instance <STRING> {                # VRRP instance declarationtrack_script {                     # Scripts state we monitor<STRING><STRING> weight <INTEGER:-254..254>...}
}

脚本对应的数据结构 :

/* external script we call to track local processes */
typedef struct _vrrp_script {char           *sname;     /* instance name */char         *script;    /* the command to be called */long          interval;   /* interval between script calls */long         timeout;    /* seconds before script timeout */int          weight;     /* weight associated to this script */int           result;     /* result of last call to this script: 0..R-1 = KO, R..R+F-1 = OK */int          inuse;      /* how many users have weight>0 ? */   int           rise;       /* R: how many successes before OK */  int          fall;       /* F: how many failures before KO */
} vrrp_script_t;
注意当配置的weight不等于0时, 用于动态调整vrrp instance的优先级. 并不会直接的改变vrrp的状态.
当weight=0时, 用于变更vrrp_instance的状态例如脚本检测失败, 则vrrp的状态直接变为FAULT. (不管有没有其他节点存在来接管MASTER)
只有脚本的weight配置不等于0时才需要被跟踪(用于跟踪result, 判断ko和ok状态).  跟踪脚本对应的数据结构 :

/* Tracked script structure definition */
typedef struct _tracked_sc {int         weight;     /* tracking weight when non-zero */vrrp_script_t        *scr;       /* script pointer, cannot be NULL */
} tracked_sc_t;
脚本一旦配置在vrrp instance中启用, 
在调用过程中, 就会动态的改变对应的instance的优先级. (when weight<>0)
或者变更vrrp instance的状态 (when weight=0)

vrrp_script <STRING> {          # VRRP script declarationscript <QUOTED_STRING>      # script to run periodicallyinterval <INTEGER>          # run the script this every secondsweight <INTEGER:-254..254>  # adjust priority by this weight  , 不等于0时用于动态变更vrrp_instance优先级(by vrrp_update_priority).fall <INTEGER>              # required number of failures for KO switch , rise <INTEGER>              # required number of successes for OK switch
}
当脚本为OK状态时, 并且最终weight(以track_script中的weight覆盖值为准)>0, 则优先级可以加上weight.
当脚本为KO状态时, 并且终止的weight(以track_script中的weight覆盖值为准)<0, 则优先级可以减去weight.
优先级最终的范围是(1到254)
OK和KO和fall, rise的配置有关. 不要关注状态, 就关注这两个值, 因为没有地方标记状态.
通过标记与变更脚本的result值, 通过result值和fall, rise来比较, 判断OK还是KO.
脚本状态的转换过程详细参考 :

vrrp_script_child_thread 函数if (WIFEXITED(wait_status)) {int status;status = WEXITSTATUS(wait_status);  // 脚本返回值为0, 表示执行成功, 非0表示失败.if (status == 0) {/* success */if (vscript->result < vscript->rise - 1) {  // result < rise-1, 表示当前还是KO状态vscript->result++;   // KO状态下, 调用成功则result+1.} else { if (vscript->result < vscript->rise)  // result = rise 表示当前是KO状态转变成OK状态log_message(LOG_INFO, "VRRP_Script(%s) succeeded", vscript->sname);vscript->result = vscript->rise + vscript->fall - 1;  // 脚本从failed状态转变到success状态后, 直接把result改成最大. 要变回KO的话, 还需要fall-1次failure.}} else {/* failure */if (vscript->result > vscript->rise) {  // result > rise, 表示当前是OK状态vscript->result--;  //OK状态下, 脚本调用失败的话, result-1.} else {if (vscript->result >= vscript->rise)  // result=rise, 表示当前是OK状态转变成KO状态log_message(LOG_INFO, "VRRP_Script(%s) failed", vscript->sname);vscript->result = 0;  // 脚本从success状态转变到failed状态后, 直接把result改到最小. 要变回OK的话还需要rise次success}}}
优先级的变动和脚本状态的关系参考 : 
注意一个脚本对全局weigh的影响只有一次, 例如多次OK状态也最大加一次正的weight.
或者多次KO状态下, 最多也只加一次负的weight.

vrrp_script_weight 函数for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {tsc = ELEMENT_DATA(e);if (tsc->scr->result == VRRP_SCRIPT_STATUS_DISABLED)continue;if (tsc->scr->result >= tsc->scr->rise) {     // 当脚本的result>=配置的rise时(即OK态), 如果脚本配置的weight>0 , 那么全局weight累加脚本weight.if (tsc->weight > 0)weight += tsc->weight;} else if (tsc->scr->result < tsc->scr->rise) {  // 当脚本的result<配置的rise时(即KO态), 如果脚本配置的weight<0, 那么全局weight减去脚本的weight.  脚本的result在vrrp_script_child_thread中跟踪.if (tsc->weight < 0)weight += tsc->weight;}}
动态调整优先级的范围 : 
如果配置的instance的初始优先级是255的话, 则不受track weight的影响. 见vrrp_update_priority函数的内容.

 if (vrrp->base_priority == VRRP_PRIO_OWNER) {/* we will not run a PRIO_OWNER into a non-PRIO_OWNER */vrrp->effective_priority = VRRP_PRIO_OWNER;} else {/* WARNING! we must compute new_prio on a signed int in orderto detect overflows and avoid wrapping. */new_prio = vrrp->base_priority + prio_offset;if (new_prio < 1)new_prio = 1;else if (new_prio > 254)new_prio = 254;vrrp->effective_priority = new_prio;}keepalived / include / vrrp.h
#define VRRP_PRIO_OWNER     255     /* priority of the ip owner -- rfc2338.5.3.4 */

换句话说, 只有初始优先级配置<255的instance, 才可以动态调整优先级. 并且动态调整后的优先级范围是1到254.

    priority <INTEGER-0..255>        # VRRP PRIO
[参考]
1. keepalived/vrrp/vrrp_scheduler.c

/* if run after vrrp_init_state(), it will be able to detect scripts that* have been disabled because of a sync group and will avoid to start them.*/
static void
vrrp_init_script(list l)
{vrrp_script_t *vscript;element e;for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {vscript = ELEMENT_DATA(e);if (vscript->inuse == 0)vscript->result = VRRP_SCRIPT_STATUS_DISABLED;if (vscript->result == VRRP_SCRIPT_STATUS_INIT) {vscript->result = vscript->rise - 1; /* one success is enough */  // 初始化过程中设置result=rise-1 thread_add_event(master, vrrp_script_thread, vscript, vscript->interval);} else if (vscript->result == VRRP_SCRIPT_STATUS_INIT_GOOD) {vscript->result = vscript->rise; /* one failure is enough */   // 初始化成功, 设置result=risethread_add_event(master, vrrp_script_thread, vscript, vscript->interval);}}
}static int
vrrp_script_child_thread(thread_t * thread)
{int wait_status;vrrp_script_t *vscript = THREAD_ARG(thread);if (thread->type == THREAD_CHILD_TIMEOUT) {pid_t pid;pid = THREAD_CHILD_PID(thread);/* The child hasn't responded. Kill it off. */if (vscript->result > vscript->rise) {vscript->result--;} else {if (vscript->result == vscript->rise)log_message(LOG_INFO, "VRRP_Script(%s) timed out", vscript->sname);vscript->result = 0;    // 初始化时, 脚本调用超时, 将result改成0(最小)}kill(pid, SIGTERM);thread_add_child(thread->master, vrrp_script_child_timeout_thread,vscript, pid, 2);return 0;}wait_status = THREAD_CHILD_STATUS(thread);if (WIFEXITED(wait_status)) {int status;status = WEXITSTATUS(wait_status);  // 脚本返回值为0, 表示执行成功, 非0表示失败.if (status == 0) {/* success */if (vscript->result < vscript->rise - 1) {  // result < rise-1, 表示当前还是KO状态vscript->result++;   // KO状态下, 调用成功则result+1.} else { if (vscript->result < vscript->rise)  // result = rise 表示当前是KO状态转变成OK状态log_message(LOG_INFO, "VRRP_Script(%s) succeeded", vscript->sname);vscript->result = vscript->rise + vscript->fall - 1;  // 脚本从failed状态转变到success状态后, 直接把result改成最大.}} else {/* failure */if (vscript->result > vscript->rise) {  // result > rise, 表示当前是OK状态vscript->result--;  //OK状态下, 脚本调用失败的话, result-1.} else {if (vscript->result >= vscript->rise)  // result=rise, 表示当前是OK状态转变成KO状态log_message(LOG_INFO, "VRRP_Script(%s) failed", vscript->sname);vscript->result = 0;  // 脚本从success状态转变到failed状态后, 直接把result改到最小. }}}return 0;
}/* Update VRRP effective priority based on multiple checkers.* This is a thread which is executed every adver_int.*/
static int
vrrp_update_priority(thread_t * thread)
{vrrp_t *vrrp = THREAD_ARG(thread);int prio_offset, new_prio;/* compute prio_offset right here */prio_offset = 0;/* Now we will sum the weights of all interfaces which are tracked. */if ((!vrrp->sync || vrrp->sync->global_tracking) && !LIST_ISEMPTY(vrrp->track_ifp))prio_offset += vrrp_tracked_weight(vrrp->track_ifp);/* Now we will sum the weights of all scripts which are tracked. */if ((!vrrp->sync || vrrp->sync->global_tracking) && !LIST_ISEMPTY(vrrp->track_script))prio_offset += vrrp_script_weight(vrrp->track_script);if (vrrp->base_priority == VRRP_PRIO_OWNER) {/* we will not run a PRIO_OWNER into a non-PRIO_OWNER */vrrp->effective_priority = VRRP_PRIO_OWNER;} else {/* WARNING! we must compute new_prio on a signed int in orderto detect overflows and avoid wrapping. */new_prio = vrrp->base_priority + prio_offset;if (new_prio < 1)new_prio = 1;else if (new_prio > 254)new_prio = 254;vrrp->effective_priority = new_prio;}/* Register next priority update thread */thread_add_timer(master, vrrp_update_priority, vrrp, vrrp->adver_int);return 0;
}

2. keepalived/include/vrrp_track.h

/* VRRP script tracking results.* The result is an integer between 0 and rise-1 to indicate a DOWN state,* or between rise-1 and rise+fall-1 to indicate an UP state. Upon failure,* we decrease result and set it to zero when we pass below rise. Upon* success, we increase result and set it to rise+fall-1 when we pass above* rise-1.*/
#define VRRP_SCRIPT_STATUS_DISABLED  -3
#define VRRP_SCRIPT_STATUS_INIT_GOOD -2
#define VRRP_SCRIPT_STATUS_INIT      -1/* external script we call to track local processes */
typedef struct _vrrp_script {char           *sname;     /* instance name */char         *script;    /* the command to be called */long          interval;   /* interval between script calls */long         timeout;    /* seconds before script timeout */int          weight;     /* weight associated to this script */int           result;     /* result of last call to this script: 0..R-1 = KO, R..R+F-1 = OK */int          inuse;      /* how many users have weight>0 ? */int          rise;       /* R: how many successes before OK */int            fall;       /* F: how many failures before KO */
} vrrp_script_t;/* Tracked script structure definition */
typedef struct _tracked_sc {int         weight;     /* tracking weight when non-zero */vrrp_script_t        *scr;       /* script pointer, cannot be NULL */
} tracked_sc_t;

[参考]
1. http://blog.163.com/digoal@126/blog/static/163877040201471992259474/

keepalived track script introduce相关推荐

  1. keepalived vrrp script|interface weight when positive,nagtive,zero vrrp's status transition

    本文以实例的形式来展示一下脚本的weight对vrrp的影响(状态或优先级). 注意优先级的变化可能导致vrrp master重新选举, 从而导致状态的变化. 而直接导致状态的变化则是当script ...

  2. keepalived 多个应用_Keepalived高可用软件概述

    Keepalived高可用软件概述: 1)互联网主要的高可用软件:Keepalived.Hearttbeat.其中Keepalived是轻量级的,Keepalived是一款开源.免费的实现网站.数据库 ...

  3. kubernetes1.15.0高可用(keepalived+haproxy)

    一.Master高可用 解决Master单节点,以及etcd单节点的问题,需要针对Master高可用,etcd数据要保持一致. [root@localhost ~]# hostnamectl set- ...

  4. linux下配置nginx+keepalived高可用的各种问题以及解决办法

    本人的环境Centos 7 + nginx 1.12.2 + keepalived 1.3.5 nginx 主机 192.168.26.26 备机 192.168.26.126 安装: 在俩台服务器上 ...

  5. 那些年我们一起追过的Shell Script

    原本这是自己在几个月前为公司的一个分享活动写的一个投影片,今天趁大脑负荷比较小,把这个话题拿到blog上面来分享一下.从知道shell算起至今也就几个年头而已,如今勉强算是入门了.对某一个新事物的掌握 ...

  6. 基于keepalived+nginx部署强健的高可用7层负载均衡方案20151214

    高可用是个老生常谈的问题了,开源的高可用软件已经做的相当成熟了,之前也在debian下做过lvs+heartbeat的4层LB,一直很稳定(可惜流量不大啊),现在由于业务的需要,做一个基于keepal ...

  7. 《SaltStack技术入门与实践》—— 实践案例 中小型Web架构2 Keepalived

    实践案例 <中小型Web架构>2 本章节参考<SaltStack技术入门与实践>,感谢该书作者: 刘继伟.沈灿.赵舜东(本章节中有好几处错误) Keepalived配置管理 首 ...

  8. LVSKeepalived—集群、负载均衡、企业高可用详解

    LVS负载均衡集群及配置 负载均衡概述 1.集群 通过集群(cluster)技术,可以在付出较低成本的情况下获得在性能.可靠性.灵活性方面的相对高的收益,其任务调度则是集群系统中的核心技术. 集群搭建 ...

  9. HAproxy+Nginx7层负载均衡

    一.关于4/7层负载平衡 1.1 4层负载均衡 将网络流量负载,平衡到多个服务器的最简单方法,是使用第4层(传输层)负载平衡.以这种方式进行负载均衡将根据IP范围和端口转发用户流量(即,如果请求进入h ...

最新文章

  1. 安川g7接线端子图_西门子SIWAREX称重模块安装接线注意事项!
  2. python枪战项目计划书_燕山大学操作系统课程设计计划书
  3. Android自带的图标集合
  4. Python Django Q查询和F查询API
  5. 【操作系统】对操作系统的了解
  6. 小爱同学100个奇葩回复_小米小爱音箱Pro开箱评测,看到的不仅是全面升级更是小米loT的高速发展...
  7. springboot controller 分页查询_Spring Boot实战分页查询附近的人: Redis+GeoHash+Lua
  8. iOS逆向之自动化重签名
  9. Unity性能优化专题---腾讯牛人分享经验
  10. fireworks CS6安装教程
  11. goland 注释模板_Java程序员简历模板,怎样才是一份好的技术简历
  12. dac生成信号频率取决于_关于高速AD/DAC测量及设计中82个疑难问题的解答
  13. linux下普通文件和目录文件区别详解
  14. Linux阅码场原创精华文章汇总
  15. P6 EPPM 安装与配置指南 16 R1 2016.4
  16. 抓包工具-Charles
  17. 极光推送集成厂商通道(java)
  18. 人肉反编译使用yield关键字的方法
  19. 锂电池OCV曲线拟合python实现
  20. mediasoup transport dtls

热门文章

  1. 分布式时序数据库InfluxDB
  2. Jboss jar包冲突及jar加载顺序
  3. Understanding Linux CPU Load - when should you be worried?
  4. [译] JavaScript 的函数式编程是一种反模式
  5. 创业公司如何切入巨头垄断的芯片市场?
  6. js准确获取当前页面url网址信息
  7. 日期工具类---DateUtil
  8. 使用qsort()和bsearch()函数对值和字符串进行排序和查找
  9. 天气查询接口演示示例
  10. win03组策略-入门篇