1. 基础概念
K8s中的命令执行中有很多协议相关的处理, 我们先一起看下这些协议处理相关的基础概念
1.1 Http协议中的Connection与Upgrade
HTTP/1.1中允许在同一个链接上通过Header头中的Connection配合Upgrade来实现协议的转换,简单来说就是允许在通过HTTP建立的链接之上使用其他的协议来进行通信,这也是k8s中命令中实现协议升级的关键
1.2 Http协议中的101状态码
在HTTP协议中除了我们常见的HTTP1.1,还支持websocket/spdy等协议,那服务端和客户端如何在http之上完成不同协议的切换呢,首先第一个要素就是这里的101(Switching Protocal)状态码, 即服务端告知客户端我们切换到Uprage定义的协议上来进行通信(复用当前链接)
1.3 SPDY协议中的stream
SPDY协议是google开发的TCP会话层协议, SPDY协议中将Http的Request/Response称为Stream,并支持TCP的链接复用,同时多个stream之间通过Stream-id来进行标记,简单来说就是支持在单个链接同时进行多个请求响应的处理,并且互不影响,k8s中的命令执行主要也就是通过stream来进行消息传递的
1.4 文件描述符重定向
在Linux中进程执行通常都会包含三个FD:标准输入、标准输出、标准错误, k8s中的命令执行会将对应的FD进行重定向,从而获取容器的命令的输出,重定向到哪呢?当然是我们上面提到过的stream了(因为对docker并不熟悉,所以这个地方并不保证Docker部分的准确性)
1.5 http中的Hijacker
在client与server之间通过101状态码、connection、upragde等完成基于当前链接的转换之后, 当前链接上传输的数据就不在是之前的http1.1协议了,此时就要将对应的http链接转成对应的协议进行转换,在k8s命令执行的过程中,会获取将对应的request和response,都通过http的Hijacker接口获取底层的tcp链接,从而继续完成请求的转发
1.6 基于tcp的流对拷的转发
在通过Hijacker获取到两个底层的tcp的readerwriter之后,就可以直接通过io.copy在两个流上完成对应数据的拷贝,这样就不需要在apiserver这个地方进行协议的转换,而是直接通过tcp的流对拷就可以实现请求和结果的转发
基础大概就介绍这些,接下来我们一起去看看其底层的具体实现,我们从kubectl部分开始来逐层分析