docker及k8s容器面试精华汇总,希望可以加深大家对容器的理解,祝大家顺利通过企业面试。
一、如何在 Kubernetes 中实现负载均衡?
node中有kube-proxy,他可以提供负载均衡。每个 Node 都会运行 kube-proxy 服务,它负责将访问 service 的 TCP/UPD 数据流转发到后端的容器。如果有多个副本,kube-proxy 会实现负载均衡。
二.在生产中,你如何实现 Kubernetes 自动化?
1.日志:严重依赖日志,与任何分布式系统一样,日志的精准定位会提供非常重要的依据,可识别出根本原因。
2.弹性伸缩:弹性伸缩式k8s中的一大亮点功能,当负载大的时候,你可以对应用进行扩容,提升pod的副本数来应对大量的流量,当负载小的时候可以对应用进行缩容,以避免资源浪费
3. 自动缩放:缩放pod和缩放节点。
缩放pods是最常见的扩展形式之一。这将增加更多的服务实例,并让它们准备开始接受流量。典型的pod层级扩展是用Heapster度量来决定是否需要创建新的实例
扩展节点是比较少见的情况,但是对于高弹性的应用来说是非常有用的扩展机制
4.资源分配:资源分配可以让你在Kubernetes平台里限制namespace,确保一个应用不会消耗掉所有资源和影响其他应用。
5.容器资源限额:搞清楚单个容器或pod需要多少资源已经变成一项艺术
三、你如何扩展 Kubernetes 集群?
kubeadm join +IP +token
四、你能解释 Deployment、ReplicaSets、StatefulSets、Pod、CronJob 的不同用途吗?
他们都是控制器。
1、deployment是最常用的controller。deployment可以管理pod的多个副本,并确保pod按照期望的状态运行。
2、replicaset 实现了pod的多副本管理。使用deployment时会自动创建replicaset,也就是说deployment是通过replicaset来管理pod的多个副本的,我们通常不需要直接使用replicaset。
3、能够保证pod的每个副本在整个生命周期中名称是不变的,而其他controller不提供这个功能。当某个pod发生故障需要删除并重新启动时,pod的名称会发生变化,同时statefulset会保证副本按照固定的顺序启动、更新或者删除。
4、job用于运行结束就删除的应用,而其他controller中的pod通常是长期持续运行的,可以理解为一次性任务。
5、CronJob即定时任务,就类似于Linux系统的crontab,在指定的时间周期运行指定的任务
五、Kubernetes 如何处理持久性?
挂载pv/pvc 卷,nfs存储
六、 ingress 的作用是什么
就是它定义规则来允许进入集群的请求被转发到集群中对应服务上,从来实现服务暴漏。Ingress 使用开源的反向代理负载均衡器来实现对外暴漏服务,比如 Nginx、Apache、Haproxy等。
七、Pod 亲和性作用是什么
三种调度粘性,主要根据官方文档说明:
NodeSelector(定向调度)、NodeAffinity(Node亲和性)、PodAffinity(Pod亲和性)。
1、 nodeSelector
提供简单的pod部署限制,pod选择一个或多个node的label部署。
① 给node添加label
kubectl label nodes =
② 为pod添加nodeSelector机制
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd
2、Pod Affinity
通过《K8S调度之节点亲和性》,我们知道怎么在调度的时候让pod灵活的选择node,但有些时候我们希望调度能够考虑pod之间的关系,而不只是pod与node的关系。于是在kubernetes 1.4的时候引入了pod affinity。
为什么有这样的需求呢?举个例子,我们系统服务 A 和服务 B 尽量部署在同个主机、机房、城市,因为它们网络沟通比较多;再比如,我们系统数据服务 C 和数据服务 D 尽量分开,因为如果它们分配到一起,然后主机或者机房出了问题,会导致应用完全不可用,如果它们是分开的,应用虽然有影响,但还是可用的。
pod affinity 可以这样理解:调度的时候选择(或者不选择)这样的节点 N ,这些节点上已经运行了满足条件 X。条件 X 是一组 label 选择器,它必须指明作用的 namespace(也可以作用于所有的 namespace),因为 pod 是运行在某个 namespace 中的。
八、你能举例说明何时使用 Init Container 么?
当我们在运用一个服务之前,通常会做一些初始化的工作,而这些工作一般只需要运行一次,成功后就不再运行。为此kubernetes 引入了Init Container,用于在启动应用容器之前启动一个或多个“初始化”容器,完成应用容器的所需的预制条件
Init Containers与常规的容器非常类似,但是它一些独有的特征:
他们仅运行一次,成功后就会退出。
每个容器必须在成功执行完成后,系统才能继续执行下一个容器。
如果Init Container运行失败,kubernetes 将会重复重启Pod,直到Init Container 成功运行,但是如果 Pod的重启策略(restartPolicy)设置为Never,则Pod不会重启。
初始化容器,顾名思义容器启动的时候,会先启动可一个或多个容器,如果有多个,那么这几个Init Container按照定义的顺序依次执行,只有所有的Init Container执行完后,主容器才会启动。由于一个Pod里的存储卷是共享的,所以Init Container里产生的数据可以被主容器使用到。
Init Container可以在多种K8S资源里被使用到如Deployment、Daemon Set, Pet Set, Job等,但归根结底都是在Pod启动时,在主容器启动前执行,做初始化工作。
九、什么是 sidecar 容器?你能给出一个用例,说明你为什么要使用它么?
Sidecar模式——一种单节点、多容器的应用设计形式。Sidecar主张以额外的容器来扩展或增强主容器,而这个额外的容器被称为Sidecar容器
十、在构建和管理生产集群时遇到的主要问题是什么?
突然大部分pod状态为Unkown,此时一首“凉凉”正在耳边回荡。
于是在次界面开始展开了地毯式的排查,首先是使用describe 命令去看这些pod的运行情况(虽然已经知道是unkown状态,但通过这个命令可以看到一些详情)。未果,并没有得到我想要的为什么会unkown,但这些unkown的服务有一个共同特点都是运行在一台node上,于是通过get node发现果然这个节点状态为Notready.
所以在大量pod出现问题时,如果参数记得不是特别清楚的朋友,一定要养成习惯,多敲个get node 这类的常规命令,不会吃亏。当然如果我在一开始就加上了-o wide的话,可以清楚看到pod落在哪个节点上的话,第一时间应该就没清晰的定位到是节点出了问题。
那么节点为什么突然出问题了呢?(oh,更可怕的是这个节点正巧是kubenetes控制管理节点- -)。继续通过日志开始定位问题
发现并没有这个节点(172.16.4.65)状态的上报。紧接着查这台服务器上的k8s node相关服务。发现kubelet、kubeproxy等各类应用都处于运行状态。但在kubelet日志里看到“timeout”字眼,于是通过date查看服务器的运行时间较其他节点快了2个小时。so,最终根源找到了,也就是由于系统时间不同步造成的节点不正常。
改完系统时间后,迅速重启了kubelet、kubeproxy等相关服务。get node 看了看,很满意的点了点头(ready了),紧接着get pod 看了看服务,哟吼~服务也起来了,验证下服务就可以收工了;但乍一眼看去好像少了点什么。发现DNS服务没有起来,那好起呗。
可最终给我的回显示“ErrImagePull”,老套路describe pod 。一眼就能看出来错误,提示镜像拉不下来。没道理啊,我的dns镜像是本地私有库的,怎么可能拉不下来。特意用docker images确认了下镜像的存在与否及yaml内image的定义。完全ok.但咋报这个不讲道理的错呢?只好登陆到harbor再去确认下,结果harbor有问题登不上去了,再一看果然服务有部分异常。
但为什么其他的pod都是正常running的呢,那是因为我这些yaml里唯独dns里没有设置镜像的拉取机制(本地没有时才拉),在不定义imagePullPolicy: IfNotPresent #或者使用Nevers 时,默认是每次都会拽一次私有库里的镜像。于是乎,增加参数后apply这些yaml文件,先恢复线上服务。
最后解决一下harbor私有库的问题。这块儿,根据个人理解应该就是在重启node相关服务时,导致原本harbor使用的资源释放引起的,重启即恢复。
十一、什么是 Istio 和 Linkerd
流量管理
需要强调的是,Istio和Linkerd的区别在于数据平面使用了两种不同的代理技术。
Istio使用Envoy作为其代理。Envoy是C++编写的,最初是由Lyft构建,以便以非Kubernetes方式促进微服务的流量管理。许多公司已经将Envoy扩展为Kubernetes的ingress技术。
Linkerd(v2)使用的是一种名为Linkerd-proxy的专用服务网格代理。这个代理是使用Rust编写的,与该代理一起,许多低级代理(网络客户机与服务器)功能在另一个也是由rust编写名为Tower的项目中实现。Tower依赖于Tokio,Tokio是一个由Rust编写的事件驱动非阻塞I/O库。如果你和我一样欣赏统计学,那么Rust已经连续四年(2016、2017、2018、2019)一直是Stack-overflow最受欢迎的语言。
十二、什么是 Kubernetes Operator
Operator的概念很酷,它可以扩展Kubernetes功能,以更好的管理有状态应用。
十三、kubernetes 组件有哪些?
由master组件和node组成
master和node 上跑的核心组件为:apiserver、controller manager、scheduler、kubelet、kube-proxy。
十四、k8s的pause容器有什么用?
Pod是Kubernetes最基本的操作单元,包含一个或多个紧密相关的容器,一个Pod可以被一个容器化的环境看作应用层的“逻辑宿主机”;一个Pod中的多个容器应用通常是紧密耦合的,Pod在Node上被创建、启动或者销毁;每个Pod里运行着一个特殊的被称之为Pause的容器,其他容器则为业务容器,这些业务容器共享Pause容器的网络栈和Volume挂载卷,因此他们之间通信和数据交换更为高效,在设计时我们可以充分利用这一特性将一组密切相关的服务进程放入同一个Pod中。
同一个Pod里的容器之间仅需通过localhost就能互相通信。
kubernetes中的pause容器主要为每个业务容器提供以下功能:
PID命名空间:Pod中的不同应用程序可以看到其他应用程序的进程ID。
网络命名空间:Pod中的多个容器能够访问同一个IP和端口范围。
IPC命名空间:Pod中的多个容器能够使用SystemV IPC或POSIX消息队列进行通信。
UTS命名空间:Pod中的多个容器共享一个主机名;Volumes(共享存储卷):
Pod中的各个容器可以访问在Pod级别定义的Volumes。
十五、k8s中的pod内几个容器之间的关系是什么?
Pod中之所以能够包含多个容器,其主要原因是为了支持辅助主程序的辅助程序。辅助程序的经典例子是数据拉取器、数据推送器和代理。辅助程序与主程序间经常需要通信,通常情况下是通过一个共享文件系统来实现的,正如本文中展示的那样;或者,通过环回网络接口localhost。这种方式的一个例子是Web服务器,以及与之配套的拉取Git仓库更新的辅助程序。
祝大家工作顺利!