golang vrrp 包

vrrp 是一个比较有用的功能,可以实现业务访问的的高可用,keepalived 就使用了此协议(当然还集成了lvs )
此包是基于了社区提供的VRRP-go 包调整的,解决了一些问题:比如不是go mod 的,部分依赖三方包不兼容

参考使用

  • go mod
 
go mod init github.com/rongfengliang/demoappvrrp
  • main.go
    集成了netlink 进行vip 的bind
 
package main
 
import (
    "flag"
    "fmt"
    "net"
    "os"
    "os/signal"
    "syscall"
    "time"
 
    "github.com/rongfengliang/vrrp/vrrp"
    "github.com/vishvananda/netlink"
)
 
var (
    VRID     int
    Priority int
)
 
func init() {
    flag.IntVar(&VRID, "vrid", 233, "virtual router ID")
    flag.IntVar(&Priority, "pri", 100, "router priority")
}
 
func main() {
    flag.Parse()
    sigs := make(chan os.Signal, 1)
    done := make(chan bool, 1)
 
    signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
    var vr = vrrp.NewVirtualRouter(byte(VRID), "enp0s1", false, vrrp.IPv4)
    vr.SetPriorityAndMasterAdvInterval(byte(Priority), time.Millisecond*800)
    vr.AddIPvXAddr(net.IPv4(10, 10, 17, 29))
    vr.Enroll(vrrp.Backup2Master, func() {
        // vip bind
        eth, _ := netlink.LinkByName("enp0s1")
        addr, _ := netlink.ParseAddr("10.10.17.29/32")
        netlink.AddrAdd(eth, addr)
        fmt.Println("backup to master")
    })
    vr.Enroll(vrrp.Init2Master, func() {
        // vip bind
        eth, _ := netlink.LinkByName("enp0s1")
        addr, _ := netlink.ParseAddr("10.10.17.29/32")
        netlink.AddrAdd(eth, addr)
        fmt.Println("init to master")
    })
    vr.Enroll(vrrp.Master2Init, func() {
        // remove vip bind
        eth, _ := netlink.LinkByName("enp0s1")
        addr, _ := netlink.ParseAddr("10.10.17.29/32")
        netlink.AddrDel(eth, addr)
        fmt.Println("master to init")
    })
    vr.Enroll(vrrp.Master2Backup, func() {
        // remove vip bind
        eth, _ := netlink.LinkByName("enp0s1")
        addr, _ := netlink.ParseAddr("10.10.17.29/32")
        netlink.AddrDel(eth, addr)
        fmt.Println("master to backup")
    })
    vr.Enroll(vrrp.Init2Backup, func() {
        // remove vip bind
        eth, _ := netlink.LinkByName("enp0s1")
        addr, _ := netlink.ParseAddr("10.10.17.29/32")
        netlink.AddrDel(eth, addr)
        fmt.Println("init  to backup")
    })
    vr.Enroll(vrrp.Backup2Init, func() {
        // remove vip bind
        eth, _ := netlink.LinkByName("enp0s1")
        addr, _ := netlink.ParseAddr("10.10.17.29/32")
        netlink.AddrDel(eth, addr)
        fmt.Println("backup to init")
    })
    go func() {
        // starting vrrp server
        vr.StartWithEventLoop()
    }()
    go func() {
        sig := <-sigs
        fmt.Println()
        fmt.Println(sig)
        done <- true
        vr.Stop()
        // remove vip bind
        eth, _ := netlink.LinkByName("enp0s1")
        addr, _ := netlink.ParseAddr("10.10.17.29/32")
        netlink.AddrDel(eth, addr)
    }()
    fmt.Println("awaiting signal")
    <-done
    fmt.Println("exiting")
}
  • 效果

启动的时候

 


进行切换(可以看到backup 切换到了master 了)

 

说明

以上是一个简单的包装集成,ip bind 部分使用了netlink,对于开发使用可以直接使用go 包了,内置实现具体可以参考github,同时VRRP-go 也是值得看看的
当然单纯直接依赖vrrp 的一些机制并不是特别可靠,比如keepalived 同时也利用了bfd 协议进行状态检测,确保vip 的快速切换以及状态处理

参考资料

https://github.com/rongfengliang/vrrp
https://github.com/napw/VRRP-go
https://datatracker.ietf.org/doc/html/rfc5798
https://github.com/vishvananda/netlink
https://www.keepalived.org/
https://github.com/acassen/keepalived

posted on 2023-05-14 09:34  荣锋亮  阅读(139)  评论(1编辑  收藏  举报

导航