1.背景
在集群网络使用cilium之后,最明显的情况就是:服务暴露vip+port,在集群内怎么测试都正常,但集群外访问可能是有问题的。而这就在于cilium所使用的ebpf科技。
2.引子:curl请求的路程
相对底层一点的语言,比如c语言,在创建一个tcp连接时,主要分两步(其它语言可能会更简单):
int socket_desc;
struct sockaddr_in server;
//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
server.sin_addr.s_addr = inet_addr("1.1.1.1");
server.sin_family = AF_INET;
server.sin_port = htons( 80 );
//Connect to remote server
if (connect(socket_desc , (struct sockaddr *)&server , sizeof(server)) < 0)
一个连接的创建,主要分两个步骤:
-
创建socket对象
-
发起connect连接
而实际上,在内核层,它经历的步骤会非常多。可以通过perf工具来查看:
perf trace -e 'net:*' -e 'sock:*' -e 'syscalls:*' curl 1.1.1.1 -s >& /dev/stdout
上面的输出很多,而syscalls:sys_enter_socket前面的很长一段,是curl程序打开本身加载动态链接库需要的系统调用。
而本次需要关心的是以下这部分(截取的部分内容):
108.294 curl/15819 syscalls:sys_enter_socket(family: INET, type: STREAM)
108.351 curl/15819 syscalls:sys_exit_socket(__syscall_nr: 41, ret: AX25)
108.939 curl/15819 syscalls:sys_enter_connect(fd: 3, uservaddr: { .family: UNSPEC }, addrlen: 16)
108.991 curl/15819 sock:inet_sock_set_state(skaddr: 0xffff902527424c80, oldstate: 7, newstate: 2, dport: 80, family: 2, protocol: 6, saddr: 0x7f176658943b, daddr: 0x7f176658943f, saddr_v6: 0x7f1766589443, daddr_v6: 0x7f1766589453)
109.090 curl/15819 net:net_dev_queue(skbaddr: 0xffff9024f0a2d4e8, len: 74, name: "enp1s0")
109.140 curl/15819 net:net_dev_start_xmit(name: "enp1s0", skbaddr: 0xffff9024f0a2d4e8, protocol: 2048, ip_summed: 3, len: 74, network_offset: 14, transport_offset_vali
d: 1, transport_offset: 34, gso_segs: 1, gso_type: 1)
从上面可以看出,在定义socket后,接着就是connect连接,而在sock:inet_sock_set_state这一步,有输出地址相关信息,但输出的是内存地址,无法直接查看。能通过bcc工具集中的tcplife