keepalived 使用子网卡的ip创建HA失败

Keepalived是个一个基于VRRP 协议来实现的 LVS 服务高可用方案的开源组件,可以利用其来解决单点故障问题。一个LVS服务器(Linux Virtual Server Linux虚拟服务器)会有2台服务器运行Keepalived,一台为主服务器(MASTER),一台为备份服务器(BACKUP),但是对外表现为一个虚拟IP,主服务器会发送特定的消息给备份服务器,当备份服务器收不到这个消息的时候,即主服务器宕机的时候, 备份服务器就会接管虚拟IP,继续提供服务,从而保证了高可用性。


当利用keepalived配置主备ip地址进行组建HA时,发现当使用的ip为子网卡上的ip时,组建HA失败。


[ root@localhost ~]# ifconfig 
eth0:  flags=4163 mtu 1500 
            inet 101.13.17.174 netmask 255.255.255.0 broadcast 10.14.15.255 
            inet6 2001:123::121 prefixlen 64 scopeid 0x0 
            inet6 fe80::eda:4lff:feld:b3f0 prefixlen 64 scopeid 0x20
            ether 0c:da:4l:ld:b3:f0 txqueuelen 1000 (Ethernet) 
            RX packets 4275596 bytes 902081284 (860.2 MiB) 
            RX errors 0 dropped 0 overruns 0 frame 0 
            TX packets 1526855 bytes 209418917 (199.7 MiB) 
            TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 


eth0:1:  flags=4l63 mtu 1500 
           inet 101.13.17.233 netmask 255.255.255.0 broadcast 10.14.15.255 
           ether 0c:da:4l:ld:b3:f0 txqueuelen 1000 (Ethernet) 


lo:  flags=73 mtu 65536 
           inet 127.0.0.1 netmask 255.0.0.0 
           inet6 ::1 prefixlen 128 scopeid 0xl0 
           loop txqueuelen 1000 (L ocal Loopback ) 
           RX packets 1062532 bytes 164572192 (156.9 MiB) 
           RX errors 0 dropped 0 overruns 0 frame 0
           TX packets 1062532 bytes 164572192 (156.9 MiB) 
           TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 


[root@localhost ~]#

其中eth0:1 为eth0的子网卡。


先了解下eth0 和 eth0:1 的区别, eth0属于物理网卡,eth0:1属于子网卡。

物理网卡:物理网卡指的是服务器上实际的网络接口设备,比如上面的配置中只有一个eth0网络接口。

子网卡:子网卡在这里并不是实际上的网络接口设备,但是可以作为网络接口在系统中出现,如eth0:1、eth1:2这种网络接口。它们必须要依赖于物理网卡,虽然可以与物理网卡的网络接口同时在系统中存在并使用不同的IP地址,而且也拥有它们自己的网络接口配置文件。但是当所依赖的物理网卡不启用时(Down状态)这些子网卡也将一同不能工作。


因此从上面了解到,子网卡并不是实际的网络接口设备,依赖于对应的物理网卡。

接下来继续keepalived组HA时,主节点或者备节点配置子网卡上的ip时组HA失败问题。

当配置HA时,主或备节点使用子网卡上的ip时,启动keepalived时会出现如下错误


# cat keepalived.conf
! Configuration File for keepalived


global_defs{
  router_id 11.12.13.54
}


vrrp_instance VI_1_t{
  state BACKUP
  insterface eth0:1
  mcast_src_cp 11.12.13.54
  virtual_router_id 99
  priority 20
  advert_int 1
  nopreempt
  authentication{
    auth_type PASS
    auth_pass 1111
  }
  virtual_ipaddress{
    11.12.13.99
  }
}

通过查看日志发现,主节点使用的ip为eth0上的ip,而备节点使用的ip为eth0:1上的ip,搭建HA时失败,通过查看日志,显示如下

# cat /var/log/messages
Keepalived_vrrp[42201]: Opening file '/opt/keepalived.conf'
...
Keepalived_vrrp[42201]: Cant find interface eth0:1 for vrrp_instance VI_1_t !!!
Keepalived_vrrp[42201]: Configuration error: VRRP definition must belong to an interface
Keepalived_vrrp[42201]: VRRP_Instance(VI_1_t) Unknown interface !
Keepalived_vrrp[42201]: Thread task.
...

从上面的日志来看,是没有找到实例对应的eth0:1网络接口。


根据keepalived的源码进行分析了解到

static void start_vrrp(void)
{
    ...
    kernel_netlink_init();
    ...
    init_data(conf_file, vrrp_init_keywords);
    ... 
    if(!vrrp_complete_init())
    {
        stop_vrrp(KEEPALIVED_EXIT_CONFIG);
        return;
    }
    
}


kernel_netlink_init()
{
    ...
    init_interface_queue();
    ...
}


void init_interface_queue()
{
    init_if_queue();
    netlink_interface_lookup(NULL);
#ifdef _HAVE_VRRP_VMAC
    set_base_ifp();
#endif
}


static void init_if_queue()
{
    if_queue = alloc_list(free_if, dump_if);
}

1、keepalived启动时,在调用start_vrrp(void)时,会调用init_interface_queue(), 该函数的作用就是从内核中读取系统的网卡设备,然后把网卡信息放到if_queue的全局链表中。


if_queue链表中保存的都是实际的网卡设备信息,而eth0:1属于子网卡并不是实际的网络接口设备。因此链表中不存在eth0:1的信息。

void init_data(const char *conf_file, vector_t *(*init_keywords)(void))
{
    ...
    (*init_keywords)();
    ...
}


vector_t * vrrp_init_keywords(void)
{
    init_global_keywords(reload);
    init_vrrp_keywords(true);
#ifdef _WITH_LVS_
    init_check_keywords(false);
#endif
#ifdef _WITH_BFD_
    init_bfd_keywords(true);
#endif
    return keywords;        
}

2、接下来start_vrrp(void)调用init_data(conf_file, vrrp_init_keywords)进行初始化。

init_data的作用就是读取keepalived.conf配置文件中的实例来初始化全局vrrp_data链表,vrrp_data中有个vrrp的链表,vrrp链表节点中保存的是vrrp_instance, 该vrrp_instance就是keepalived.conf配置文件中的关键字,然后获取配置中的信息,挂到vrrp链表节点中。

在初始化节点过程中当读到interface eth0:1时,会根据获取的名字eth0:1 从if_queue的全局链表中获取网卡接口实例信息来初始化vrrp节点中的ifp字段。由于获取不到,所以日志会打印:

Cant find interface eth0:1 for vrrp_instance VI_1_t !!!


此时ifp字段是空的。

在从配置文件读取virtual_ipaddress 初始化虚拟ip的时候(对应函数vrrp_vip_handler),它会判断ifp字段是否为空,若为空,则打印日志

Configuration error: VRRP definition must belong to an interface


bool vrrp_complete_init(void)
{
    ...
    LIST_FOREACH(vrrp_data->vrrp, vrrp, e){
        if(!vrrp_complete_instance(vrrp))
            return false;
            
        if(vrrp->ifp->mtu > max_mtu_len)
            max_mtu_len = vrrp->ifp->mtu;
    }
    ...
}


static bool vrrp_complete_instance(vrrp_t *vrrp)
{
    ....
    if(!chk_min_cfg(vrrp))
        return false;
     ...
}


static bool chk_min_cfg(vrrp_t *vrrp)
{
    ...
    if(!vrrp->ifp){
        log_message(LOG_INFO, "(%s) Unknown interface!", vrrp->iname);
        return false;
    }
}

3、接下来start_vrrp(void)调用vrrp_complete_init()进一步完成vrrp的初始化工作,同时判断一些之前的初始化值是否成功,由于第二步初始化ifp字段时该值为空,也就是找不到eth0:1的接口实例,因此会打印日志:

VRRP_Instance(VI_1_t) Unknown interface !

并返回失败,结束keepalived。

所以使用keepalived组HA使用子网卡的ip时,由于子网卡不是网络设备,导致keepalived启动时根据配置文件获取不到网卡信息,导致keepalived启动失败。

因此使用keepalived组HA使用子网卡的ip时,keepalived.conf中的insterface 字段要设置为子网卡(eth0:1)对应的物理网卡(eth0)。

脚本中根据子网卡ip获取物理网卡脚本如下:

[ rootelocalhost ~]# ip addr 
l: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
     link/loopback 00:00: 00:00:00:00 brd 00: 00: 00:00:00:00 
     inet 127.0.0.1/8 scope host lo valid lft forever preferred lft forever inet6 : :1/128 scope host 
      valid lft forever preferred lft forever 
2: eth0:  mtu 1500 qdisc pfifo fast state UP group default qle1000 
     link/ether 0c:da:41:1d:b3:f0 brd ff:ff:ff:ff:ff:ff 10 
     inet 101.11.12.174/23 brd 10.14.15.255 scope global eth0
       valid lft forever preferred lft forever 
     inet 101.11.12.233/23 brd 10.14.15.255 scope global secondary eth0:1 
       valid lft forever preferred lft forever
   
#获取子网卡101.11.12.233 (eth0:1) 对应的物理网卡       
[ rootelocalhost ~]# ip addr | grep -w 101.11.12.233 | awk '{print $NF}' | head -n 1 | cut -d ":" -f 1  #去掉冒号取第一列
 eth0   
展开阅读全文

页面更新:2024-04-16

标签:子网   网卡   节点   字段   初始化   接口   物理   服务器   设备   网络

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top