《零入门kubernetes网络实战》视频专栏地址
https://www.ixigua.com/7193641905282875942
本篇文章视频地址(稍后上传)
本篇文章主要是使用golang自带的syscall包来创建tun类型的虚拟网络设备。
注意:
目前只能使用syscall包来创建tun类型的虚拟设备。
tun虚拟网卡设备的启动,IP配置,路由配置可能需要其他方式实现。
比方说通过netlink包方式来实现。
1、golang代码 |
package main
import (
"bytes"
"fmt"
"github.com/vishvananda/netlink"
"net"
"os"
"syscall"
"unsafe"
)
const (
tunDevice = "/dev/net/tun"
ifnameSize = 16
)
type ifreqFlags struct {
IfrnName [ifnameSize]byte
IfruFlags uint16
}
func ioctl(fd int, request, argp uintptr) error {
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), request, argp)
if errno != 0 {
return fmt.Errorf("ioctl failed with '%s'", errno)
}
return nil
}
func fromZeroTerm(s []byte) string {
return string(bytes.TrimRight(s, "\000"))
}
func OpenTun(name string) (*os.File, string, error) {
tun, err := os.OpenFile(tunDevice, os.O_RDWR, 0)
if err != nil {
fmt.Printf("----OpenTun----err:%v\n", err.Error())
return nil, "", err
}
var ifr ifreqFlags
copy(ifr.IfrnName[:len(ifr.IfrnName)-1], []byte(name+"\000"))
ifr.IfruFlags = syscall.IFF_TUN | syscall.IFF_NO_PI
err = ioctl(int(tun.Fd()), syscall.TUNSETIFF, uintptr(unsafe.Pointer(&ifr)))
if err != nil {
fmt.Printf("----OpenTun---ioctl----err:%v\n", err.Error())
return nil, "", err
}
// 1,表示,程序结束后,创建的tun设备依旧在。
// 默认为0,程序结束后,创建的tun设备就自动删除了
err = ioctl(int(tun.Fd()), syscall.TUNSETPERSIST, 1)
if err != nil {
fmt.Printf("----OpenTun---ioctl---persist---err:%v\n", err.Error())
return nil, "", err
}
ifname := fromZeroTerm(ifr.IfrnName[:ifnameSize])
return tun, ifname, nil
}
func configureIface(ifname string, ipn *net.IPNet, mtu int) error {
iface, err := netlink.LinkByName(ifname)
if err != nil {
return fmt.Errorf("failed to lookup interface %v", ifname)
}
err = netlink.AddrAdd(iface, &netlink.Addr{IPNet: ipn, Label: ""})
if err != nil {
return fmt.Errorf("failed to add IP address %v to %v: %v", ipn.String(), ifname, err)
}
err = netlink.LinkSetMTU(iface, mtu)
if err != nil {
return fmt.Errorf("failed to set MTU for %v: %v", ifname, err)
}
err = netlink.LinkSetUp(iface)
if err != nil {
return fmt.Errorf("failed to set interface %v to UP state: %v", ifname, err)
}
err = netlink.RouteAdd(&netlink.Route{
LinkIndex: iface.Attrs().Index,
Scope: netlink.SCOPE_UNIVERSE,
Dst: ipn,
})
if err != nil && err != syscall.EEXIST {
return fmt.Errorf("failed to add route (%v -> %v): %v", ipn.String(), ifname, err)
}
return nil
}
func main() {
tun, fname, err := OpenTun("flannel-test")
if err != nil {
fmt.Printf("----Create--Tun------err:%v\n", err.Error())
return
}
fmt.Printf("-----create---tun---name:%v\tfname:%v\n", tun.Name(), fname)
_, ipn, _ := net.ParseCIDR("10.244.1.0/24")
configureIface(fname, ipn, 1500)
//time.Sleep(time.Hour)
}
2、本地编译 |
Makefile
build:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go
scp:
scp main root@10.211.55.122:/root
all:
make build && make scp
3、远程服务器测试 |
route -n
å
ip a s | grep 10.211
ip link sh flannel-test
./main
ip link sh flannel-test
ip a sh flannel-test
route -n
ip tuntap list
ethtool -i flannel-test
ethtool -i eth0
4、测试虚拟网卡flannel-test的连通性 |
5、/dev/net/tun: not pollable |
read /dev/net/tun: not pollable
其实,曾经还出现过,此代码存在的情况下,也会报上面的错误。
可惜,已经不知道如何恢复异常场景了。
点击 下面 返回 专栏目录 |
<<零入门kubernetes网络实战>>技术专栏之文章目录