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