论坛
潜水/灌水快乐,沉淀知识,认识更多同行。
ToB圈子
加入IT圈,遇到更多同好之人。
朋友圈
看朋友圈动态,了解ToB世界。
ToB门户
了解全球最新的ToB事件
博客
Blog
排行榜
Ranklist
文库
业界最专业的IT文库,上传资料也可以赚钱
下载
分享
Share
导读
Guide
相册
Album
记录
Doing
搜索
本版
文章
帖子
ToB圈子
用户
免费入驻
产品入驻
解决方案入驻
公司入驻
案例入驻
登录
·
注册
只需一步,快速开始
账号登录
立即注册
找回密码
用户名
Email
自动登录
找回密码
密码
登录
立即注册
首页
找靠谱产品
找解决方案
找靠谱公司
找案例
找对的人
专家智库
悬赏任务
圈子
SAAS
ToB企服应用市场:ToB评测及商务社交产业平台
»
论坛
›
容器及微服务
›
容器及微服务
›
Pod概述
Pod概述
冬雨财经
金牌会员
|
2023-3-15 06:09:35
|
显示全部楼层
|
阅读模式
楼主
主题
841
|
帖子
841
|
积分
2523
Pod的类型
Pod的类型有如下两个:
自主式Pod:
自主式Pod的含义简白来说就是不是被控制器管理的Pod,另一种就是被控制管理的Pod,不被控制器管理的Pod你会发现,它一旦死亡的话,就没有人把它拉起来,也不会进行重启,比如Pod死亡了,也不会去创建Pod副本,去满足它的期望值,这都是自主式Pod的缺点。
控制器管理的Pod:
只要创建Pod就会创建Pause容器,如果已经创建了容器,会共用Pause的网络栈,共用Pause的存储卷,也就意味着创建的容器没有自己独立的IP地址,容器有的只是Pause的地址或者Pod的地址,容器之间互相隔离,但是容器之间的进程不隔离,比如一个容器里是php-fpm服务,一个容器里是nginx服务,nginx容器想要反向代理到php-fpm容器上只需要写localhost:9000即可,不需要写IP地址、映射等等。原因是因为两个容器都共享的Pause的网络栈,既然是共享容器之间都是可以见面的,也就意味着在同一个Pod里面,端口不能冲突,如果一个容器是80,另一个容器也是80,那这个端口是起不来的或者是起来以后无限重启。假如Pod挂载了一个存储,容器1和容器2都想去访问到这个存储,同理,容器1和容器2也会共享Pause的存储,也就意味着在同一个Pod里即共享网络又共享存储卷。
Pod的控制器类型
以下是Pod的控制器类型:
ReplicationController:
ReplicationController用来确保容器应用的副本数始终保持在用户定义的副本数,即如果有容器异常退出,会自动创建新的Pod来替代;而如果异常多出来的容器也会被自动回收。在新版本的Kubernetes中建议使用ReplicationControlle;
ReplicaSet:
跟ReplicationController没有本质的不同,只是名字不一样,并且ReplicaSet支持集合式的Selector,我们在创建Pod的时候会给它打标签例如:app=apache,version=v1,我们会为它打一堆的标签,当我们有一天想删除我们的容器或一些设施的时候。我可以这样去说。当app=apache,version=v1的时候,我要干嘛干嘛。
Deployment:
虽然ReplicaSet可以独立使用,但一般还是建议使用Deployment来自动管理ReplicaSet,这样就无需担心跟其他机制的不兼容问题(比如ReplicaSet不支持rolling-update(滚动更新)但Deployment支持)。比如我们创建了两个Pod,两个Pod都是v1版,我们现在想要进行滚动更新,它先删除一个Pod或者是它先多一个Pod(多一个Pod是v2版,新版本),然后再把这个老旧Pod v1版删除,然后再创建一个Pod是v2版的,然后再删除一个旧的v1版的Pod,最终就会出现最新的版本状态了。为什么要把两个放在一起说呢?原因是Deployment并不支持Pod的创建。
HAP(Horizo ntal Pod AutoScale):
Horizontal Pod Autoscaling仅适用于Deployment和ReplicaSet,在v1版本中仅支持根据Pod的CPU利用率扩缩容,在vlalpha版本中,支持根据内存和用户自定义的metric扩缩容。
StatefullSet:
StatefulSet是为了解决有状态服务的问题(对应Deployments和ReplicaSets是为无状态服务而设计),其应用场景包括:
稳定的持久化存储:
即Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现。
稳定的网络标志:
即Pod重新调度后其PodName和HostName不变,基于Headless Service(即没有Cluster IP的Service)来实现。
有序部署,有序扩展:
即Pod是有顺序的,在部署或者扩展的时候要依次定义的顺序依次进行(即从0到N-1,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态),基于init containers来实现。为什么之前的Pod都必须是Running状态和Ready状态呢?是因为在大型集群中是有一定的启动顺序的,比如说一个nginx、一个apache,一个mysql,如果先起nginx,它会去解析apache,发现apache不在,所以要设置先后顺序。
有序收缩,有序删除:
(即从N-1到0)
DaemonSet:
DaemonSet确保全部(或者一些)Node上运行一个Pod的副本。当有Node加入集群时,也会为它们新增一个Pod。当有Node从集群移除时,这些Pod也会被回收。删除DaemonSet将会删除它创建的所有的Pod,这里面有一些说法,为什么说是全部(或者一些呢),因为我们在创建Pod的时候,会为Pod打一些污点,那这些污点可以是不被调度的,所以在DaemonSet创建的时候,这些打了污点的Node就不会创建Pod,但是正常情况下默认是,所有的Node都会被运行Pod,运行一个且只有一个需要注意。又假如我在一个Node上运行了好几个不同的Pod,你可以把这个好几个Pod里的主要进程给它提取出来,放到同一个Pod里面,不同容器上,那么这样的话也可以通过一个DaemonSet也可以去设置,当然也可以设置三个不同的DaemonSet。使用DaemonSet的一些典型用法:
运行集群存储daemon:
例如在每个Node上运行glusterd、ceph。
在每个Node上运行日志收集daemon:
例如fluentd、logstash。
在每个Node上运行监控daemon:
例如Prometheus Node Exporter。
Job,Cronjob:
Job负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个Pod成功结束。Cron Job管理基于时间的Job,举个例子,我想备份数据库,备份数据库完全可以把代码放到Pod里去运行,那我再放到Job里去执行一下,那我们的Job就可以正常运行,把我们的数据库备份出来,在Linux运行脚本不是也是一样的嘛?但是,我们这个Pod是可以重复利用的,这是之一,之二如果脚本执行意外退出是没办法重新执行的,但是Job如果判断这个脚本不是正常退出,那它就会重新执行一遍,直到正常退出为止,并且你还可以设置它的正常退出的次数,比如你正常退出2次,我才允许你这个脚本执行成功。即:
在给定时间点只运行一次
周期性地在给定时间点运行
Deployment和ReplicaSet滚动更新原理
假设我们创建了一个Deployment,它会去创建一个ReplicaSet,也就意味着这个ReplicaSet并不是我们自己定义的,它是由Deployment定义的,那ReplicaSet再去创建我们对应的Pod,先创建3个Pod,如果有一天跟Deployment说,把镜像给我更新成v2版,它会怎么做呢?
它会创建一个ReplicaSet,它会先启动第一个容器,镜像为v2版,然后退出一个v1版的容器,启动第二个容器v2版,会退出一个v1版的容器,启动第三个容器v2版,退出一个v1版的容器,达到滚动更新。
并且还可以回滚,比如v2版本有一些bug,它会去新建老旧版的v1版,然后删除新版的v2,依次类推,当回滚的时候,它并不会把老旧版本删掉,而是禁用,回滚的时候会启用老旧版本,达到回滚的目的。
HPA根据Pod的CPU利用率扩缩容原理
例如,我现在运行了一个ReplicaSet,ReplicaSet下面管理了两个Pod,然后我再定义一个HPA(HPA也是一个对象,需要被定义),HPA定义的是基于ReplicaSet去定义的,当我们的CPU大于80的时候,那就进行扩展,最大值是10个,最小值是2个,这是一种描述方式,cpu > 80;Max 10;Min 2。也就意味着HPA会去监控当前Pod的资源利用率,当CPU利用率达到80的时候,它会去新建Pod,直到达到它的最大值,当然,它创建了3个Pod的CPU利用率已经达不到80%了,它就不会创建了,当每创建一个时,它如果还是大于80%,它才会去创建,一旦Pod的CPU利用率变低了以后,Pod就会被回收,保持到最小值,所以这就达到了一个水平扩展的效果。
服务发现
客户端想要去访问一组Pod,记住是一组Pod,如果这些Pod不相干的话,是不能通过我们的service去代理的,那Pod必须要有相关性,比如说是我们的ReplicaSet、ReplicationController、Deployment创建的或者说有同一组标签,那都可以被我们的service所收集到,这些又衍生出来一个含义,service去收集这些Pod是通过我们的标签去选择到的。选择到以后,service会有自己的一个IP+端口,那我们访问service的IP+端口就会间接的访问到我们的Pod服务,并且这里是有一个RR(轮询)算法存在的,访问Pod1、Pod2、Pod3依次类推。
理解案例
假如我有一套上面架构图的集群,也就意味着,首先我要构建一个apache的集群,再构建一个mysql的集群,再构建一个squid的集群,然后再构建一个LVS,如果我想把这个架构放在K8S里运行的话,我们来看一下需要几步:第一步:mysql要先运行成一个Pod,当然我们mysql现在放在我们K8S中,放在我们的StatefullSet控制器里是可以做到的,但是集群化的话,不是那么方便,mysql封装完以后。
我们还有apache+fpm,既然有这么多节点,我们之前学过控制器,我们是不是可以在Deployment上去创建,也就是说我创建一个Deployment,Deployment会指定它的副本数目,指定3个副本,那这样的话就有三个不同的apache+fpm的Pod的存在了。
再往上会有三个squid,那么squid是不是也可以把它封装成Pod,通过控制器把它给控制,那LVS就可以靠我们集群本身的一个功能把它负载调度,那这样的话,会出现一种结构,你会发现不太好写,squid要写反向代理的话需要写三台机器,并且我们之前说过一个概念,Pod在退出以后,在重新建立以后,这个IP地址会变换对吧,除非你采用的是StatefullSet,但是在php-fpm里面是不是没有意义啊,所以怎么办呢?我们就可以在前端,在前面加一个service,这个service就是php-fpm的service,它会绑定php-fpm的标签,选择进行绑定,那squid想要进行反向代理的话就不需要去写php-fpm这3台php-fpm的地址了,因为我们一直在强调这个概念,php-fpm一旦死亡以后,我们控制器也会把它维持在3个副本,它会创建一个新的副本来取代死亡的副本,那取代它的副本跟现在的副本,它的IP是不一样的,那squid在里面填写的是它的目标IP的话,那就会出现问题,副本一换的话,我们squid里面的配置是不是得重新写,要重新修改,重启服务,这样不太友好,所以我们的squid里面写的是service php-fpm的地址,那这样的话,squid只需要指定到我们的service即可,并且php-fpm是一个Pod,mysql也是一个Pod,它们之间肯定会出现一定的关联,比如我们把我们的mysql部署在StatefullSet里面,那它的名称是不是就不会变啊,那我可以通过它的名称,去固定到我们对应的Pod上面,因为我之前提到过,K8S内部是一个扁平化的网络,那容器之间是能够互相访问的,所以这样我php-fpm里面写它的地址信息是没有问题的,那对于这三台squid来说,外网用户要访问对吧,我可以创建个service,已知绑定squid,通过去判断我们的squid的一些标签进行确定,那这样的话我们只需要把service暴露到外部即可,service其中有一种暴露模式叫NodePort,比如还可以通过我们的Ingrees等一些方案都可以做到,那这样的话我们就可以把这个架构完整的部署在我们的K8S集群中了,这也是我们的Pod与Pod的通讯方案,可以这么去做。
网络通讯模式
网络通讯模式简介
Kubernetes的网络模型假定了所有Pod都在一个可以直接连通的扁平的网络空间中,这在GCE(Google Compute Engine)里面是现成的网络模型,Kubernetes假定这个网络已经存在。而在私有云里搭建Kubernetes集群,就不能假定这个网络已经存在。我们需要自己实现这个网络假设,将不同节点的Docker容器之间的互相访问先打通,然后运行Kubernetes。
网络通讯模式
同一个Pod内的多个容器之间:localhost
各Pod之间的通讯:Overlay Network
Pod与Service之间的通讯:各节点的IP tables格则
网络解决方案Kubernetes + Flannel
Flannel是CoreOS团队针对Kubernetes设计的一个网络规划服务,简单来说,它的功能是让集群中的不同节点主机创建的Docker容器都具有全集群唯一的虚拟IP地址。而且它还能再这些IP地址之间建立一个覆盖网络(Overlay Network),通过这个覆盖网络,将数据包原封不动地传递到目标容器内。
上述的图中,分别是以IP为192.168.66.11/24和192.168.66.12/24的两台主机,两台主机各运行了两个Pod,首先在我们真实的主机上会去安装一个Flanneld的守护进程,这个进程会去监听一个端口,这个端口就是用于后期转发数据包以及接收数据包的服务端口,一旦Flanneld这个进程启动以后,它会开启一个监听端口,Flannel0,这个Flannel0专门去收集Docker0转发出来的数据报文,Docker0会分配自己的IP到对应的Pod上。
如果是同一台主机不同的Pod访问的话,它走的是Docker0的网桥,因为Pod在同一个网桥下,不同的子IP,也就是在真实的服务器中已经完成了一次数据包转换。
如何通过跨主机还可以通过对方的IP到达呢?首先假设Web app2想把数据包发送到Backend,它的数据包要写自己源地址10.1.15.2/24,目标要写10.1.20.3/24,因为目标网段跟我不是同一个网段,所以10.1.15.2.24发送到自己的网段Docker0,Docker0会有自己对应的钩子函数,会把数据包抓到Flannel0里面,Flannel0里面会有一堆的路由表记录,是从ETCD数据库里面获取到的,写入到我们当前的路由表里,判断到底路由到哪台机器,因为Flannel0是Flanneld的一个进程,所以数据包会转发到Flanneld,到Flanneld它会对数据报文进行封装,下面解释如何封装:
Mac部分到我们的三层,三层写的是源是192.168.66.11,目标写的是192.168.66.12,下一层封装的是udp的数据报文,也就意味着Flanneld它使用的是udp的数据报文,去转发这些数据包的,因为更快,毕竟在同一个局域网内部,在下一层又封装了一层新的三层信息,源是10.1.15.2,目标是10.1.20.3,封装到这一层以后,外面封装了一个数据包实体Payload,然后转发到192.168.66.12/24。
所以数据包是肯定能够到192.168.66.12/24的,并且它的目标端口是Flanneld的端口,所以这个数据包会被Flanneld所截获,截获以后它会拆封,它知道这个是干嘛的,会进行拆封,拆封完以后会被转发到Flannel0,Flannel0会转发到docker0,docker0自然而然会转发到Backend,并且数据包是经过二次解封的,第一层的信息,docker0是看不见的,docker0看的是第二层信息,所以docker0一看源是10.1.15.2/24的机器发过来的,目标找的是我自己下面的机器地址,这样的话就可以实现跨主机的扁平化网络。
Etcd在这里的作用,为Flannel提供说明:
存储管理Flannel可分配的IP地址段资源。
监控Etcd中每个Pod的实际地址,并在内存中建立维护Pod节点路由表。
网络通讯方式总结
同一个Pod内部通讯
同一个Pod共享同一个网络命名空间,共享同一个Linux协议栈。
Pod1和Pod2通讯,在同一台机器
Pod1与Pod2不在同一台主机,Pod的地址是与docker0在同一个网段的,但docker0网段与宿主机网卡是两个完全不同的IP网段,并且不同的node之间的通信只能通过宿主机的物理网卡进行。将Pod的IP和所在的node的IP关联起来,通过这个关联让Pod可以互相访问。
Pod1和Pod2通讯,不再同一台机器
Pod1与Pod2在同一台机器,由docker0网桥直接转发请求至Pod2,不需要经过Flannel。
Pod至Service的网络
目前基于性能考虑,全部为IP tables(现在版本都是通过LVS)维护和转发
Pod到外网
Pod向外网发送请求,查找路由表,转发数据包到宿主机的网卡,宿主网卡完成路由选择后,IP tables执行Masquerade,把源IP更改为宿主网卡的IP,然后向外网服务器发送请求。
外网访问Pod
外网访问Pod通过Service。
组件通讯示意图
在我们K8S里面,它有三层网络:
节点网络
Pod网络
Service网络
需要注意的是
真实的物理的网络只有一个就是节点网络
,也就意味着我们在构建服务器的时候,只需要一张网卡就可以去实现,并不是说多张网卡不行,一张网卡就可以实现,Pod网络是一个虚拟网络,Service网络也是一个虚拟网络,这里可以理解为是一个内部网络,所有的Pod都会在这个扁平化的网络中进行通讯,如果想访问Service的话,那就需要在Service的网络中去访问,Service在去跟后端的Pod通过对应的IP tables或者说通过LVS的转换去达到,最新版会用到LVS转换,这样效率会更高。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
本帖子中包含更多资源
您需要
登录
才可以下载或查看,没有账号?
立即注册
x
回复
使用道具
举报
0 个回复
倒序浏览
返回列表
快速回复
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
or
立即注册
本版积分规则
发表回复
回帖并转播
回帖后跳转到最后一页
发新帖
回复
冬雨财经
金牌会员
这个人很懒什么都没写!
楼主热帖
信息与网络安全期末复习(完整版) ...
ts保姆级教程,别再说你不会ts了 ...
Elasticsearch学习系列五(零停机索引 ...
如何通过JDBC访问MySQL数据库?手把手 ...
iOS全埋点解决方案-手势采集 ...
Linux安装PHP8 新版笔记
有趣的特性:CHECK约束
React技术栈 --》 JSX语法书写JS和Reac ...
BLE蓝牙模块NRF518/NRF281/NRF528/NRF2 ...
《ABP Framework 极速开发》教程首发 ...
标签云
挺好的
服务器
快速回复
返回顶部
返回列表