阿里雲基於彈性網卡實現高可用ip


一、環境介紹

阿里雲服務器CentOS 7.9

[root@keep1 ~]# cat /etc/hosts
::1    localhost    localhost.localdomain    localhost6    localhost6.localdomain6
127.0.0.1    localhost    localhost.localdomain    localhost4    localhost4.localdomain4

172.16.208.195 keep1
172.16.208.196 keep2

 

 

二、創建阿里雲彈性網卡

 

 

 

 

 

 

三、安裝keepalived

yum install keepalived -y

 

四、安裝安裝自動配置eni網卡(2台都需安裝)

阿里雲的eni只對CentOS 7.3和CentOS 6.8能自動識別到網卡,其他版本需要配置網卡參數

官方文檔
https://www.alibabacloud.com/help/zh/doc-detail/56955.htm?spm=a2c63.p38356.b99.398.5367779fyWo75G

 

1、安裝自動配置eni網卡(系統需高於CentOS 7.3版本)

wget https://image-offline.oss-cn-hangzhou.aliyuncs.com/multi-nic-util/multi-nic-util-0.6.tgz
tar -zxvf multi-nic-util-0.6.tgz
cd multi-nic-util-0.6
bash install.sh

 

五、創建阿里雲的accessKeyId和accessSecret,授權ECS管理權限(AliyunECSFullAccess)

 

 

 

六、go環境安裝

go sdk安裝文檔:https://help.aliyun.com/document_detail/63640.htm?spm=5176.12573546.1318498.5.433c97a5QYvwVA
api文檔:https://www.alibabacloud.com/help/zh/doc-detail/25485.htm?spm=a2c63.p38356.b99.657.25a92647ynVJk3

1、golang安裝與代理配置

#golang安裝
yum install -y golang 
#添加代理
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct

 

 

七、創建eni項目

1、創建目錄

mkdir  /go/eni/ -p

 

2、創建main腳本文件

 

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
	"github.com/buger/jsonparser"
	"time"
)

type aliyunAuth struct {
	regionId string
	accessKeyId string
	accessSecret string
}


func (self aliyunAuth) ecsBindingEni(NetworkInterfaceId,InstanceId string) {
	client, err := ecs.NewClientWithAccessKey(self.regionId,self.accessKeyId,self.accessSecret)
	request := ecs.CreateAttachNetworkInterfaceRequest()
	request.Scheme = "https"
	request.NetworkInterfaceId = NetworkInterfaceId
	request.InstanceId = InstanceId
	response, err := client.AttachNetworkInterface(request)
	if err != nil {
		fmt.Print(err.Error())
	}
	fmt.Printf("response is %#v\n", response)
}

func (self aliyunAuth) ecsRemoveEni(NetworkInterfaceId,InstanceId string) {
	client, err := ecs.NewClientWithAccessKey(self.regionId,self.accessKeyId,self.accessSecret)
	request := ecs.CreateDetachNetworkInterfaceRequest()
	request.Scheme = "https"
	request.NetworkInterfaceId = NetworkInterfaceId
	request.InstanceId = InstanceId

	response, err := client.DetachNetworkInterface(request)
	if err != nil {
		fmt.Print(err.Error())
	}
	fmt.Printf("response is %#v\n", response)
}

func (self aliyunAuth) getEcsId( eni_ip string) string {
	client, err := ecs.NewClientWithAccessKey(self.regionId,self.accessKeyId,self.accessSecret)
	request := ecs.CreateDescribeNetworkInterfacesRequest()
	request.Scheme = "https"
	request.PrimaryIpAddress = eni_ip
	response, err := client.DescribeNetworkInterfaces(request)
	result, _ := json.Marshal(response)
	ecs_id, _ := jsonparser.GetString(result,"NetworkInterfaceSets","NetworkInterfaceSet","[0]","InstanceId")
	if err != nil {
		fmt.Print(err.Error())
	}
	fmt.Printf("response is %#v\n", response)

	return ecs_id
}

func main() {
	var (
		behavior         = flag.String("b","attach","執行操作")
		eniInterfaceId   = flag.String("n", "", "彈性網卡Id")
		ecsId            = flag.String("e", "", "ECSId")
		eniIp            = flag.String("i", "", "彈性網卡Ip")

	)
	flag.Parse()

	var eni = new(aliyunAuth)
	eni.regionId = "cn-hangzhou"
	eni.accessKeyId = "xxxxxxxxxxxx"
	eni.accessSecret = "xxxxxxxxxxxxxx"

	switch *behavior {
	case "attach" :
		ecs_id := eni.getEcsId(*eniIp)
		if ecs_id == "" {
			eni.ecsBindingEni(*eniInterfaceId,*ecsId)
		}else {
			if *ecsId == ecs_id {
				break
			}
			eni.ecsRemoveEni(*eniInterfaceId,ecs_id)
			for i := 0;i < 10; i++ {
				time.Sleep(time.Millisecond*500)
				if eni.getEcsId(*eniIp) == ""{
					eni.ecsBindingEni(*eniInterfaceId,*ecsId)
					break
				}
			}

		}

	case "remove":
		eni.ecsRemoveEni(*eniInterfaceId,*ecsId)
	default:
		fmt.Println("Usage: { attach|remove }")

	}
}

 

3、go mod與go vendor

 

[root@keep1 ~]# cd /go/eni/
[root@keep1 eni]# ls
main.go
[root@keep1 eni]# go mod init  eni
go: creating new go.mod: module eni
[root@keep1 eni]# go mod vendor
go: finding module for package github.com/buger/jsonparser
go: finding module for package github.com/aliyun/alibaba-cloud-sdk-go/services/ecs
go: downloading github.com/aliyun/alibaba-cloud-sdk-go v1.61.865
go: downloading github.com/buger/jsonparser v1.1.1
go: found github.com/aliyun/alibaba-cloud-sdk-go/services/ecs in github.com/aliyun/alibaba-cloud-sdk-go v1.61.865
go: found github.com/buger/jsonparser in github.com/buger/jsonparser v1.1.1
go: downloading github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af
go: downloading github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742
go: downloading gopkg.in/ini.v1 v1.42.0
go: downloading github.com/json-iterator/go v1.1.5
go: downloading github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd

 

4、編譯

go build  -o eni   main.go 

 

八、keepalived檢查腳本

[root@keep2 ~]# cat /etc/keepalived/check_eni.sh 
#!/bin/bash

KEEPALIVED_VIP=192.168.1.100
ENI_VIP=172.31.0.240

if [ `ip a s eth0|grep ${KEEPALIVED_VIP}|wc -l` -eq 1 ]; then
    if [ `ip a s eth1|grep $ENI_VIP|wc -l` -eq 1 ]; then
        ping -c 1 -w 1 $ENI_VIP >/dev/null
        [ $? -ne 0 ]&& exit 1
    fi    

fi

 

九、keepalived配置文件

1、主配置文件

! Configuration File for keepalived

global_defs {
   notification_email {
     acassen@firewall.loc  #發送郵箱
   }
   notification_email_from Alexandre.Cassen@firewall.loc #郵箱地址
   smtp_server 127.0.0.1   #郵件服務器地址
   smtp_connect_timeout 30  
   router_id LVS_DEVEL-01   #主機名,每個節點不同即可
}

vrrp_script check_LVS {
    script "/etc/keepalived/check_eni.sh" #腳本路徑
    interval 2 #2秒執行一次
    timeout 2  #超時時長
    weight -2  #腳本執行失敗優先級降低2
    rise 3     #連續3次執行腳本成功表示ok
    fall 3     #連續3次腳本執行失敗表示失敗
}


vrrp_instance VI_1 {
    state MASTER   #節點主從,在另一個節點上為BACKUP
    interface eth0  #IP地址漂移到的網卡
    virtual_router_id 51  #多個節點必須相同
    priority 100   #優先級,備用節點的值必須低於主節點的值
    advert_int 1   #通告間隔1秒
    authentication { 
        auth_type PASS   #預共享密鑰認證
        auth_pass 1111   #密鑰
    }

unicast_src_ip 172.16.208.195  #本機地址
    unicast_peer {
        172.16.208.196    #目標地址
    }
    notify_master "/go/eni/eni -b attach -n 彈性網卡Id  -e ECSId -i 172.16.208.200"
    track_script {
        check_LVS
    }

    virtual_ipaddress {
        192.168.1.100/24  dev eth0  #VIP地址
    }
}
主配置

 

2、備配置

! Configuration File for keepalived

global_defs {
   notification_email {
     acassen@firewall.loc
   }
   notification_email_from Alexandre.Cassen@firewall.loc
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id LVS_DEVEL-02
}
vrrp_script check_LVS {
    script "/etc/keepalived/check_eni.sh"
    interval 2 
    timeout 2  
    weight -2  
    rise 3    
    fall 3     
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 99
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }

unicast_src_ip 172.16.208.196
    unicast_peer {
        172.16.208.195
    }
    notify_master "/go/eni/eni -b attach -n 彈性網卡Id  -e ECSId -i 彈性網卡Ip"

    track_script {
        check_LVS
    }

    virtual_ipaddress {
        192.168.1.100/24 dev eth0 
    }
}
備配置

 

3、啟動keepalived

systemctl  start keepalived.service 

 

 

十、測試

keep1服務器停止keepalived后查看eni的ip是否會綁定到keep2服務器上

1、keep1服務器操作

[root@keep1 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> 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: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:16:3e:12:e6:15 brd ff:ff:ff:ff:ff:ff
    inet 172.16.208.195/20 brd 172.16.223.255 scope global dynamic eth0
       valid_lft 315354146sec preferred_lft 315354146sec
    inet 192.168.1.100/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::216:3eff:fe12:e615/64 scope link 
       valid_lft forever preferred_lft forever
8: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:16:3e:16:d2:e5 brd ff:ff:ff:ff:ff:ff
    inet 172.16.208.200/20 brd 172.16.223.255 scope global dynamic eth1
       valid_lft 315359996sec preferred_lft 315359996sec
    inet6 fe80::216:3eff:fe16:d2e5/64 scope link 
       valid_lft forever preferred_lft forever
[root@keep1 ~]# systemctl  stop keepalived.service 

 

2、keep2服務器查看(彈性網卡已綁定到keep2服務器)

[root@keep2 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> 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: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:16:3e:16:c4:39 brd ff:ff:ff:ff:ff:ff
    inet 172.16.208.196/20 brd 172.16.223.255 scope global dynamic eth0
       valid_lft 315353960sec preferred_lft 315353960sec
    inet 192.168.1.100/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::216:3eff:fe16:c439/64 scope link 
       valid_lft forever preferred_lft forever
9: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:16:3e:16:d2:e5 brd ff:ff:ff:ff:ff:ff
    inet 172.16.208.200/20 brd 172.16.223.255 scope global dynamic eth1
       valid_lft 315359985sec preferred_lft 315359985sec
    inet6 fe80::216:3eff:fe16:d2e5/64 scope link 
       valid_lft forever preferred_lft forever

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM