kubectl exec 背后原理介绍

2020-08-18

我们知道,kubectl是封装curl操作的命令行工具,kubernetes通过Api-Server向外暴露Restful接口,当我们执行命令kubectl exec命令时,实际在执行什么,和docker exec有什么关联?
下面我们来一探究竟。

我们的default命令空间下有Pod:

MacBook-Pro-WRJ:~ wrj$ kubectl get po 
NAME                                   READY   STATUS    RESTARTS   AGE
prometheus-operator-6f6b75f46f-h4gl4   1/1     Running   0          20d
MacBook-Pro-WRJ:~ wrj$ kubectl exec prometheus-operator-6f6b75f46f-h4gl4 ping baidu.com

执行exec命令,打印详细日志:

MacBook-Pro-WRJ:~ wrj$ kubectl -v=7 exec prometheus-operator-6f6b75f46f-h4gl4 ls
I0818 20:15:57.037226   11518 loader.go:375] Config loaded from file:  /Users/wrj/.kube/config
I0818 20:15:57.054763   11518 round_trippers.go:420] GET https://10.172.58.142:6443/api/v1/namespaces/default/pods/prometheus-operator-6f6b75f46f-h4gl4
I0818 20:15:57.054799   11518 round_trippers.go:427] Request Headers:
I0818 20:15:57.054805   11518 round_trippers.go:431]     Accept: application/json, */*
I0818 20:15:57.054810   11518 round_trippers.go:431]     User-Agent: kubectl/v1.16.3 (darwin/amd64) kubernetes/b3cbbae
I0818 20:15:57.093926   11518 round_trippers.go:446] Response Status: 200 OK in 39 milliseconds
I0818 20:15:57.106419   11518 round_trippers.go:420] POST https://10.172.58.142:6443/api/v1/namespaces/default/pods/prometheus-operator-6f6b75f46f-h4gl4/exec?command=ls&container=prometheus-operator&stderr=true&stdout=true
I0818 20:15:57.106459   11518 round_trippers.go:427] Request Headers:
I0818 20:15:57.106466   11518 round_trippers.go:431]     X-Stream-Protocol-Version: v4.channel.k8s.io
I0818 20:15:57.106473   11518 round_trippers.go:431]     X-Stream-Protocol-Version: v3.channel.k8s.io
I0818 20:15:57.106480   11518 round_trippers.go:431]     X-Stream-Protocol-Version: v2.channel.k8s.io
I0818 20:15:57.106484   11518 round_trippers.go:431]     X-Stream-Protocol-Version: channel.k8s.io
I0818 20:15:57.106488   11518 round_trippers.go:431]     User-Agent: kubectl/v1.16.3 (darwin/amd64) kubernetes/b3cbbae
I0818 20:15:57.187518   11518 round_trippers.go:446] Response Status: 101 Switching Protocols in 81 milliseconds
bin
dev
etc
home
lib
proc
root
sys
tmp
usr
var

重点1:exec请求相当于向Api-server发起路径为/api/v1/namespaces/default/pods/prometheus-operator-6f6b75f46f-h4gl4/exec?command=ls&container=prometheus-operator&stderr=true&stdout=true的请求

重点2:日志里这一行:Response Status: 101 Switching Protocols in 81 milliseconds。表示最后 API Server 返回了 101 Ugrade 响应,向客户端表示已切换到 SPDY 协议

SPDY 允许在单个 TCP 连接上复用独立的 stdin/stdout/stderr/spdy-error 流

我们知道,Pod对应的是某个Node节点运行的docker容器,所以大致流程是:

kubectl exec -> Api-server -> kubelet(pod所在的宿主机) -> docker container

涉及到kubelet注册exec处理器、kubelet与docker运行时接口之间的交互以及请求的转发,用下面一张图可以更好的说明:
upload successful

具体原理还需要弄清楚以下问题:

  • Kubelet 是如何注册 exec 处理器的?
  • Kubelet 与 Docker API 如何交互?

这块涉及代码层的理解,笔者目前理解不够深入,还需要加强源码阅读

本文参考自:https://fuckcloudnative.io/posts/how-it-works-kubectl-exec/ 。 源码级的分析在此文中有介绍,可以点击进入阅读。