1.Deployment,StatefulSet和DeamonSet以及job/cronjob有什么区别?

这也是面试的经典问题了。

首先我们要清楚它们之间的联系,这四个都是管理和运行Pod的控制器,他们的目标和适用场景完全不同

Deployment:是部署和更新无状态的应用的最常用的控制器,它确保指定数量的Pod副本始终运行,并支持轻松回滚和更新

在这里简单讲一下什么是无状态的应用,打个比方,无状态应用就像是收银员,他不知道你之前点了什么,因为他的记忆全部都在小票上,所以说换个收银员只要看着小票也能工作,而有状态的应用就像是客户经理,他要时刻记得每一位客户的需求,他将所有信息都存在他个人的笔记本,如果说换一个人为你服务,客户就要为这个新人重新介绍情况。

总而言之就是无状态应用本身不保存任何客户端的状态,每个请求都包含处理该请求所需要的全部信息,而应用处理完后不记住任何东西。

而有状态应用在多次请求之间保存客户端的状态数据,记住用户是谁之前做过什么从才能执行下一步操作。

前者作为k8s推崇的应用,原因就在于他没有像有状态应用那么多数据,可以轻松扩展。而且如果故障损坏有状态应用可能会导致数据丢失,无状态应用则快速无感知。无状态本身不存在数据,由专门的外部服务或组件来保存。

特性:有可以自动维持指定数量的Pod副本,还可以滚动更新,实现零停机部署,轻松回滚到之前的任一版本,并且他的Pod可以自动切换。

网络:所有Pod共享一个service,通过clusterIP进行负载均衡。

工作流程:

StatefulSet: 用于部署需要稳定身份,稳定存储和有序部署有状态应用

而他所创建的Pod都有自己专用的存储卷,有点像我之前说得客户经理的笔记本。注意他在创建Pod时必须是顺序创建,而且扩展和终止也是顺序的。它不同于管理无状态应用,由于有状态应用每个实例都有其独特的身份,状态和角色,他们之间往往存在依赖关系严格的启动/关闭顺序,所以有顺序的管理其实不是限制而是保障机制。

特性:其Pod都是唯一的,有身份的,每一个Pod都有自己固定且有序的标识符,并且独立存储空间和唯一且稳定的DNS域名。由于有状态应用的特性在管理或创建Pod中也必须按顺序。

网络:每一个Pod都有自己的DNS域名,要想实现发现机制,就要为其创建一个对应的Headless Service,他和普通的Service的区别在于他的clusterIP的值为None,也就是说可以直接通过其DNS名访问的Pod。由于Pod IP本身是不固定,但是DNS会记录会自动更新,从而维持网络身份的稳定性。他不同于Department通过ClusterIP均衡负载,让请求落在任何Pod上,而statefulSet管理的不同Pod在集群中扮演者不同的角色。

工作流程:

DeamonSet: 确保每个节点上都运行一个且仅有一个Pod副本,当有新节点加入集群时,会自动在新节点上创建Pod;当节点被删除时,Pod则会被当作垃圾回收。

为什么每个节点有且仅需要一个呢?

对于某些服务来说,如果一个节点中拥有多个功能一样的Pod就会产生冲突,好比在一个很小的行政区我只需要一个消防站,如果过多不仅没有提高效率还会导致冲突或者浪费。

而在k8s中有很多服务类似这样,首先是节点监控,这时候如果再来一个节点监控,二者绑定端口l类似则会冲突,然后还有节点日志以及网络插件等。

同时DaemonSet还有两个核心配置——节点选择和污点容忍。

节点选择:告诉DaemonSet应该在哪个节点运行Pod

污点容忍:告诉DaemonSet可以在哪些节点运行Pod

两者协同工作,共同决定 DaemonSet Pod 的最终部署位置。

节点选择最常用的就是nodeselector来判断哪些pod拥有特定标签

在这里讲一下污点容忍,首先污点是在节点上的标签,告诉调度器不符合条件的Pod不允许调度他。而容忍就是Pod声明的能力,告诉调度器我有特殊能力,可以适应那些有特殊情况的节点。

虽然目的也是为了节点和Pod相匹配,但是不同于标签匹配,标签匹配是Pod是主动方,而容忍污点是节点是主动方,就好比公司招人,前者类似公司正在找会k8s的人,求职者(Pod)看到后主动过去,而后者是公司率先提出要求,要能接受出差的人,求职者(Pod)表示我能适应。这么做的目的就是为了保护了专用节点以及优雅节点维护。

Job/Cronjob: Job一次性创建一个或多个Pod,并确保指定数量Pod成功完成。而CronJob基于时间调度Job。

这两个没有什么要讲的,主要是Cron的格式为分时日月周,类似linux的crontab。

2.简述 Kubernetes 的网络模型。Pod 之间是如何通信的?

回答此问题之前一定要明白一个核心的概念——NAT

打个比方,NAT就像是公司的前台总机,当外部电话(外部IP)打进来时,需要通过总机来进行转接到内部分机;而员工向外部打时,对方看到的时前台总机的电话号码。

Kubernetes 对网络设定了两个强制性要求,任何网络解决方案(CNI插件)都必须满足:

1.所有 Pod 之间必须可以不经过 NAT 直接通信,无论它们运行在哪个节点上。

2.所有节点必须可以不经过 NAT 直接与所有 Pod 通信。

通过NAT的作用不难理解,k8s的强制性要求是为了抹平节点网络的差异,构建了一个扁平的,IP可达的“Pod网络”

在k8s内部主要有三种通信场景:

1.同一个 Pod 内的容器间通信

他们之间通过localhost和端口号通信,是因为Pod内所有容器共享同一个网络命名方式。

2.同一个节点上不同Pod间的通信

他们可以直接通过访问Pod的IP来直接访问(不包含Service内的Pod),因为节点上会创建一个虚拟网络设备,每个pod的虚拟网卡一端插到这个网桥上,另一端插到Pod上。通信就像连接在同一个交换机上的设备,通过网桥来进行二次转发。

3.不同节点上的Pod的通信

通过Pod的IP直接访问,不同于同一个节点上的网桥建立连接,而是CNI网络插件通过创建Overlay网络或路由规则,确保跨节点流量能够准确送达。

Overlay网络,他的工作原理是在物理网络上构建一个虚拟的叠加网络,当PodA要往PodB发送一个,节点A的内核会将该数据包封装在一个新的UDP包内,这个过程叫做VXLAN。而这个UDP的目的地就是节点B和VXLAN端口,当节点B接收到这个UDP包解封装,取出原始的数据包,发现目标是PodB的IP,然后交给PodB。

路由规则,让动态路由协议让每个节点都知道其他节点上Pod子网上的路由信息。

每个节点被分配一个 Pod IP 的 CIDR 块(如 node-1: 10.244.1.0/24, node-2: 10.244.2.0/24)

节点通过 BGP 协议向网络中的其他节点宣告:“发往 10.244.1.0/24 的流量,请发给我(node-1)”。这样,节点 A 的路由表中就会有一条规则。

后者相较于前者少了封装的开销。

ok这篇文章到这也差不多了,实际上都比3问多了不少hhh,感谢你的阅读!如有错误欢迎指出!

更多推荐