Kubernetes Interview Questions

k8s是什么?请说出你的了解?

Kubenetes是一个针对容器应用,进行自动部署,弹性伸缩和管理的开源系统。主要功能是生产环境中的容器编排。

K8S是Google公司推出的,它来源于由Google公司内部使用了15年的Borg系统,集结了Borg的精华。

K8s架构

和大多数分布式系统一样,K8S集群至少需要一个主节点(Master)和多个计算节点(Node)。

  • 主节点主要用于暴露API,调度部署和节点的管理;
  •  计算节点运行一个容器运行环境,一般是docker环境(类似docker环境的还有rkt),同时运行一个K8s的代理(kubelet)用于和master通信。计算节点也会运行一些额外的组件,像记录日志,节点监控,服务发现等等。计算节点是k8s集群中真正工作的节点。

Master节点(默认不参加实际工作):

  • Kubectl:客户端命令行工具,作为整个K8s集群的操作入口;
  • Api Server:在K8s架构中承担的是“桥梁”的角色,作为资源操作的唯一入口,它提供了认证、授权、访问控制、API注册和发现等机制。客户端与k8s群集及K8s内部组件的通信,都要通过Api Server这个组件;
  • Controller-manager:负责维护群集的状态,比如故障检测、自动扩展、滚动更新等;
  • Scheduler:负责资源的调度,按照预定的调度策略将pod调度到相应的node节点上;
  • Etcd:担任数据中心的角色,保存了整个群集的状态;

Node节点:

  • Kubelet:负责维护容器的生命周期,同时也负责Volume和网络的管理,一般运行在所有的节点,是Node节点的代理,当Scheduler确定某个node上运行pod之后,会将pod的具体信息(image,volume)等发送给该节点的kubelet,kubelet根据这些信息创建和运行容器,并向master返回运行状态。(自动修复功能:如果某个节点中的容器宕机,它会尝试重启该容器,若重启无效,则会将该pod杀死,然后重新创建一个容器);
  • Kube-proxy:Service在逻辑上代表了后端的多个pod。负责为Service提供cluster内部的服务发现和负载均衡(外界通过Service访问pod提供的服务时,Service接收到的请求后就是通过kube-proxy来转发到pod上的);
  • container-runtime:是负责管理运行容器的软件,比如docker
  • Pod:是k8s集群里面最小的单位。每个pod里边可以运行一个或多个container(容器),如果一个pod中有两个container,那么container的USR(用户)、MNT(挂载点)、PID(进程号)是相互隔离的,UTS(主机名和域名)、IPC(消息队列)、NET(网络栈)是相互共享的。我比较喜欢把pod来当做豌豆夹,而豌豆就是pod中的container;

容器和主机部署应用的区别是什么

容器的中心思想就是秒级启动;一次封装、到处运行;这是主机部署应用无法达到的效果,但同时也更应该注重容器的数据持久化问题。

另外,容器部署可以将各个服务进行隔离,互不影响,这也是容器的另一个核心概念。

kubenetes针对pod资源对象的健康监测机制

K8s中对于pod资源对象的健康状态检测,提供了三类probe(探针)来执行对pod的健康监测:

  • livenessProbe探针

    可以根据用户自定义规则来判定pod是否健康,如果livenessProbe探针探测到容器不健康,则kubelet会根据其重启策略来决定是否重启,如果一个容器不包含livenessProbe探针,则kubelet会认为容器的livenessProbe探针的返回值永远成功。

  • ReadinessProbe探针

    同样是可以根据用户自定义规则来判断pod是否健康,如果探测失败,控制器会将此pod从对应service的endpoint列表中移除,从此不再将任何请求调度到此Pod上,直到下次探测成功。

  • startupProbe探针

    启动检查机制,应用一些启动缓慢的业务,避免业务长时间启动而被上面两类探针kill掉,这个问题也可以换另一种方式解决,就是定义上面两类探针机制时,初始化时间定义的长一些即可。

    每种探测方法能支持以下几个相同的检查参数,用于设置控制检查时间:

    • initialDelaySeconds:初始第一次探测间隔,用于应用启动的时间,防止应用还没启动而健康检查失败
    •  periodSeconds:检查间隔,多久执行probe检查,默认为10s;
    • timeoutSeconds:检查超时时长,探测应用timeout后为失败;
    • successThreshold:成功探测阈值,表示探测多少次为健康正常,默认探测1次。

​ https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/​

如何控制滚动更新过程?

可以通过下面的命令查看到更新时可以控制的参数:

1
[root@master yaml]# kubectl explain deploy.spec.strategy.rollingUpdate

maxSurge: 此参数控制滚动更新过程,副本总数超过预期pod数量的上限。可以是百分比,也可以是具体的值。默认为1。

(上述参数的作用就是在更新过程中,值若为3,那么不管三七二一,先运行三个pod,用于替换旧的pod,以此类推)

maxUnavailable: 此参数控制滚动更新过程中,不可用的Pod的数量。

(这个值和上面的值没有任何关系,举个例子:我有十个pod,但是在更新的过程中,我允许这十个pod中最多有三个不可用,那么就将这个参数的值设置为3,在更新的过程中,只要不可用的pod数量小于或等于3,那么更新过程就不会停止)。

image的状态有哪些?

  • Running:Pod所需的容器已经被成功调度到某个节点,且已经成功运行,
  •  Pending:APIserver创建了pod资源对象,并且已经存入etcd中,但它尚未被调度完成或者仍然处于仓库中下载镜像的过程
  • Unknown:APIserver无法正常获取到pod对象的状态,通常是其无法与所在工作节点的kubelet通信所致。

pod的重启策略

可以通过命令`kubectl explain pod.spec查看pod的重启策略。(restartPolicy字段)

  • Always:但凡pod对象终止就重启,此为默认策略。
  • OnFailure:仅在pod对象出现错误时才重启

Service这种资源对象的作用是什么?

用来给相同的多个pod对象提供一个固定的统一访问接口,常用于服务发现和服务访问。

标签与标签选择器的作用是什么?

标签:是当相同类型的资源对象越来越多的时候,为了更好的管理,可以按照标签将其分为一个组,为的是提升资源对象的管理效率。

标签选择器:就是标签的查询过滤条件。目前API支持两种标签选择器:

  • 基于等值关系的,如:“=”、“”“==”、“!=”(注:“==”也是等于的意思,yaml文件中的matchLabels字段);
  • 基于集合的,如:in、notin、exists(yaml文件中的matchExpressions字段);

注:in:在这个集合中;notin:不在这个集合中;exists:要么全在(exists)这个集合中,要么都不在(notexists);

使用标签选择器的操作逻辑:

  • 在使用基于集合的标签选择器同时指定多个选择器之间的逻辑关系为“与”操作(比如:- {key: name,operator: In,values: [zhangsan,lisi]} ,那么只要拥有这两个值的资源,都会被选中);
  • 使用空值的标签选择器,意味着每个资源对象都被选中(如:标签选择器的键是“A”,两个资源对象同时拥有A这个键,但是值不一样,这种情况下,如果使用空值的标签选择器,那么将同时选中这两个资源对象)
  • 空的标签选择器(注意不是上面说的空值,而是空的,都没有定义键的名称),将无法选择出任何资源;

在基于集合的选择器中,使用“In”或者“Notin”操作时,其values可以为空,但是如果为空,这个标签选择器,就没有任何意义了。

pod的生命周期有哪些状态?

  • Pending:表示pod已经被同意创建,正在等待kube-scheduler选择合适的节点创建,一般是在准备镜像;
  • Running:表示pod中所有的容器已经被创建,并且至少有一个容器正在运行或者是正在启动或者是正在重启;
  • Succeeded:表示所有容器已经成功终止,并且不会再启动;
  • Failed:表示pod中所有容器都是非0(不正常)状态退出;
  • Unknown:表示无法读取Pod状态,通常是kube-controller-manager无法与Pod通信。

创建一个pod的流程

  • 客户端提交Pod的配置信息(可以是yaml文件定义好的信息)到kube-apiserver;
  • Apiserver收到指令后,通知给controller-manager创建一个资源对象;
  • Controller-manager通过api-server将pod的配置信息存储到ETCD数据中心中;
  • Kube-scheduler检测到pod信息会开始调度预选,会先过滤掉不符合Pod资源配置要求的节点,然后开始调度调优,主要是挑选出更适合运行pod的节点,然后将pod的资源配置单发送到node节点上的kubelet组件上。
  • Kubelet根据scheduler发来的资源配置单运行pod,运行成功后,将pod的运行信息返回给scheduler,scheduler将返回的pod运行状况的信息存储到etcd数据中心。

删除一个Pod会发生什么事情?

Kube-apiserver会接受到用户的删除指令,默认有30秒时间等待优雅退出,超过30秒会被标记为死亡状态,此时Pod的状态Terminating,kubelet看到pod标记为Terminating就开始了关闭Pod的工作;

关闭流程如下:

  • pod从service的endpoint列表中被移除;
  • 如果该pod定义了一个停止前的钩子,其会在pod内部被调用,停止钩子一般定义了如何优雅的结束进程;
  • 进程被发送TERM信号(kill -14)
  • 当超过优雅退出的时间后,Pod中的所有进程都会被发送SIGKILL信号(kill -9)。

Kubernetes网络模型

kubernetes网络由于它集群的特性,面对不同的服务器,不同的pod,那么其网络流程就可以分出不同的场景。

同一个pod的不同容器之间的通信

在kubernetes中每一个pod都会有一个根容器,这个根容器里面就会包含ip、端口等网络信息,每个pod都会有一个单独的根容器,你在后面加的容器都只会添加,不会改变pod的网络内容。官方内容是指在同一个pod当中的不同容器是共享网络命名空间的。所以在同一个pod的不同容器是可以直接通过localhost的方式直接访问的。

同一台机器的不同pod之间的通信

同一机器的pod网络,以下图为例,pod当中含有container1,container2两个容器和一个pause容器(也就是根容器)。图中有三个网卡设备,eth0是kubernetes集群主机的网卡设备,这个作为服务器之间通信的基本条件一般都会有。docker0是一个虚拟网桥,可以简单理解为一个虚拟交换机,它是支持该节点上的Pod之间进行IP寻址和互通的设备。veth0则是Pod1的虚拟网卡,是支持该Pod内容器互通和对外访问的虚拟设备。docker0网桥和veth0网卡,都是linux支持和创建的虚拟网络设备。Pod的IP是由docker0网桥分配的,例如上图docker0网桥的IP是172.17.0.1,它给第一个Pod1分配IP为172.17.0.2。如果该节点上再启一个Pod2,那么相应的分配IP为172.17.0.3,如果再启动Pod可依次类推。因为这些Pods都连在同一个网桥上,在同一个网段内,它们可以进行IP寻址和互通。

不同机器之间不同pod的通信

在不同机器之间网络通信时,docker0网桥就不能跨机器了,这个时候我们需要一个桥梁将两者关联起来,也就是cni网络插件,现在比较流行的是flannel和calico。以flannel为例,flannel会在每一台集群主机之中创建一个flannel0,flannel0给创建的pod分配一个和它同网段的ip,flannel0和主机ip做关联,这时不同主机的pod就可以通过flannel0进行通信。