以前在找工作的时候面试了一些大厂,其中在面试字节跳动和阿里巴巴的时候,对于K8S这块,他们问了一个相同的问题:请详细说说,用户执行了一个deployment.yaml文件时,新创建了一个Pod,这个Pod的创建流程是怎样的, Pod的更新流程又是怎样的。简短的一个问题,要是想答的详细,其实还是涉及了K8S中的很多东西,我觉的这是一道比较有质量的题,我在现场答出来了,在这里,我想再总结一下,查漏补缺,算是对面试的总结,更是对K8S自身的学习和沉淀。
我在回答这个问题的时候,其实头脑里大概是有一个流程图的,然后再按着从头到尾,逐步展开的的原则来详细说明,下面就参照这幅图,再来还原一个Pod被创建时的流程。
文章图片
第一步:假如我们的deployment.yaml中使用了Nginx镜像,且replicas的值设置为1,然后用户执行了kubectl create -f deployment.yaml命令。
第二步:kubectl执行yaml文件后,对api-server发起了请求,这时api-server会对此次操作进行身份认证,在客户端的~/.kube文
件夹下,已经设置好了相关的用户认证信息,这样api-server会知道我是哪个用户,并对此用户进行鉴权,当api-server确定我们的请求合法后,就会接受本次操作,并把相关的信息保存到etcd中。
第三步:下面controller-manager组件就会介入,controller-manager是有多个类型的,比如Deployment Controller, 它的作用就是负责监听Deployment,此时Deployment Controller发现我们的deployment.yaml文件诉求是需要一个复本集且数量为1,那么它就会去创建一个ReplicaSet,一个ReplicaSet的产生,又被另一个叫做ReplicaSet的Controller监听到了,紧接着它就会去分析ReplicaSet的语义,它了解到是要依照ReplicaSet的template去创建Pod, 它一看这个Pod并不存在,那么就新建此Pod,当Pod刚被创建时,它的nodeName属性值为空,代表着此Pod未被调度。
第四步:调度工作自然是由Scheduler组件来完成的,Scheduler一直关注Pod及Node的信息,所以它就要把未被调度的Pod,调度到合适的Node上去。但是它所做的也只是把它的调度方案,返回给api-server。
第五步:kubelet组件布署于Node之上,它从api-server处知道有一个Pod应该要被调度到自身所在Node上来,它会先判断本地是否在此Pod,如果不存在,则会进入创建Pod流程,创建Pod有分为几种情况,第一种是容器不需要挂载外部存储,则相当于直接docker run把容器启动,但不会直接挂载docker网络,而是通过CNI调用网络插件配置容器网络,如果需要挂载外部存储,则还要调用CSI来挂载存储。
第六步:Pod建立成功后,ReplicaSet Controller会对其持续进行关注,如果Nginx Pod因意外或被我们手动退出,ReplicaSet Controller会知道,并创建新的Pod,以保持replicas数量期望值。
第七步:更新Pod,什么时候会更新Pod? 当deployment.yaml文件中template的部分被更新,就会触发Pod更新,因为Deployment Controller 会把template部分文本计算一个hash值,根据这个hash值判断文本变化。
第八步:既然触发了更新,那么ReplicaSet Controller就会新建一个ReplicaSet并在其中启动新的Pod,在老的ReplicaSet里关闭Pod,直到新的ReplicaSet接替老的ReplicaSet。
总结:
可以看到,对于一个简单的问题,可以回答的内容还是很多,我相信上述内容,如果面试官不是要求你对源码上熟悉与开发,已经回答的比较详尽了。我建议在面试的时候,如果面试官问了一个你比较熟或精通的问题,那么你应该抓住机会尽可能的把这个问题讲深,讲广,如果面试官不叫停,甚至可以把与此相关的东西说出来。你知道这样做的目的吗?可以在评论处与一讨论 : )
【面试了字节跳动和阿里,他们都问了这个K8S问题】本文参与了 SegmentFault 思否征文「如何“反杀”面试官?」,欢迎正在阅读的你也加入。