Go语言用户态协议栈gVisor/Netstack介绍及使用
虚拟机中流量有时需要访问元数据服务,为了避免此控制面流量与VPC业务流量互相干扰,需要使用用户态协议栈承接此部分流量,与VPC流量使用的内核态协议栈隔离。Go语言主流的用户态协议栈为Netstack,后续作为gVisor的网络模块进行维护。本文将对gVisor中该模块的实现及使用进行介绍。
先看代码,gVisor/tcpip目录结构如下:
tree -L 1 ./gvisor/pkg/tcpip
./gvisor/pkg/tcpip
├── adapters
├── checksum
├── errors.go
├── faketime
├── hash
├── header
├── internal
├── link
├── network
├── ports
├── seqnum
├── sock_err_list.go
├── socketops.go
├── stack
├── stdclock.go
├── stdclock_state.go
├── tcpip.go
├── tcpip_state.go
├── tcpip_state_autogen.go
├── timer.go
└── transport
其中adapters
包封装了传输层连接相关的属性,比如tcp listener/conn, udp conn等。network
包封装了网络层的属性,比如arp、ipv4、ipv6等协议的实现。transport
对传输层协议(icmp/tcp/udp)实现了endpoint
接口,供初始化协议栈时使用。
gVisor/Netstack中模型抽象如上图所示。其中连接层提供go chan
,pipe
,fd
等多种方式,作为网卡设备抽象的具象化实现。网络层协议栈通过读取连接层设备对应的endpoint,实现网络层报文的传输。
正如gVisor官方仓库所描述的,go
分支提供了与标准go程序兼容的工具,虽然官方不推荐,但使用该分支可更快速进行开发。
go get gvisor.dev/gvisor@go
个人仓库gVisor-usage提供了基于fd
和go chan
两种设备使用gVisor/Netstack协议栈的方法。可参考,在此不作赘述。