Go语言用户态协议栈gVisor/Netstack介绍及使用

虚拟机中流量有时需要访问元数据服务,为了避免此控制面流量与VPC业务流量互相干扰,需要使用用户态协议栈承接此部分流量,与VPC流量使用的内核态协议栈隔离。Go语言主流的用户态协议栈为Netstack,后续作为gVisor的网络模块进行维护。本文将对gVisor中该模块的实现及使用进行介绍。

gVisor/Netstack框架

代码接口

先看代码,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接口,供初始化协议栈时使用。

模型抽象

36-gvisormodel.png

gVisor/Netstack中模型抽象如上图所示。其中连接层提供go chanpipefd等多种方式,作为网卡设备抽象的具象化实现。网络层协议栈通过读取连接层设备对应的endpoint,实现网络层报文的传输。

gVisor/Netstack使用

正如gVisor官方仓库所描述的go分支提供了与标准go程序兼容的工具,虽然官方不推荐,但使用该分支可更快速进行开发。

go get gvisor.dev/gvisor@go

使用方法

个人仓库gVisor-usage提供了基于fdgo chan两种设备使用gVisor/Netstack协议栈的方法。可参考,在此不作赘述。

参考

  1. Netstack

  2. gVisor

  3. gVisor-usage