【Kubernetes 002】Pod的概念和网络通讯方式

上一节我们了解了k8s的整体架构,这一节我们来深入了解下最基本的工作单元Pod,以及多台机器上的Pod之间的通信方式。

我是T型人小付,一位坚持终身学习的互联网从业者。喜欢我的博客欢迎在csdn上关注我,如果有问题欢迎在底下的评论区交流,谢谢。

Pod是什么

Pod就是一个或多个容器的集合。

因为一个Pod里面的所有容器共享该Pod的网络栈(pause)和存储卷积,所以这些容器使用的端口不能冲突,不然会导致Pod起不来或者不停重启。而一个Pod内的容器相互访问直接用localhost即可。

Pod的分类

上一节我们讲到了master中的一个组件:Controller。按照是否被控制器控制,Pod可以被分为如下两类

  • 被控制器控制的Pod

也就是说如果Pod有故障,控制器会自动剔除并起一个新的Pod

  • 不被控制器控制的Pod

这种Pod如果出现故障不会自动被替换

既然说到了控制器,下面我们来看一下到底有多少种控制器。

控制器

Replication Controller/ReplicaSet/Deployment

这里将RC,RS和Deployment放到一起讲,是因为这三个基本是一个东西。

前面说了RC是用来确保容器副本始终保持用户的设定值,如果副本出故障会被新副本替代,有多的副本会被剔除。

RS本质上是和RC一样的,不同的就是RS在选择目标Pod的时候支持集合式的选择。每个Pod会被加上一些标签,例如App=NginxVersion=v1,RS在选择目标Pod的时候可以将多个条件进行复合考虑,RC只能对单一条件进行考虑。所以新版本的k8s中建议使用RS而不是RC。

RS独立使用是没有任何问题的,不过一般情况下使用Deployment来自动管理RS。也就是说不要自己创建RS,而是通过控制Deployment,让Deployment自动去创建删除RS。这样做的好处就是可以实现滚动更新。

所谓滚动更新就是对多个Pod依次进行更新,例如有3个V1版本的Pod,现在要将3个V1版本都更新到V2。Deployment会创建一个新的RS,然后在底下创建V2版本的Pod,每创建一个V2版本的新Pod,就在原先的RS下面删除一个V1版本的Pod,一直到最后3个V1版本的Pod都被更新为V2版本为止。而因为之前的3个V1版本的Pod并没有被删除,而只是在旧的RS下被停用,所以可以很方便的直接回滚

说了这个多,结论就是,在生产环境中建议使用Deployment配合RS的方式

HPA(Horizontal Pod Autoscaling)

HPA是基于Deployment或者RS的。可以根据Pod的CPU利用率自动增加和删除Pod,直到CPU符合要求。HPA中可以设定增删Pod的CPU域值,以及最大和最小的Pod数量。

StatefulSet

前面说的RS和Deployment是针对无状态服务而设计的,SS是为了解决有状态服务问题而产生的。

无状态服务是指该服务运行的实例不会在本地存储需要持久化的数据,并且多个实例对于同一个请求响应的结果是完全一致的。有状态服务是指该服务的实例可以将一部分数据随时进行备份,并且在创建一个新的有状态服务时,可以通过备份恢复这些数据,以达到数据持久化的目的。

无状态服务可以有一个或多个实例,因此支持两种服务容量调节模式;有状态服务只能有一个实例,不允许创建多个实例,因此也不支持服务容量调节模式。

无状态服务可以有存储卷,也可以没有,即使有也无法备份存储卷里面的数据;有状态服务必须要有存储卷,并且在创建服务时,必须指定给该存储卷分配的磁盘空间大小。

无状态服务运行过程中的所有数据(除日志和监控数据)都存在容器实例里的文件系统中,如果实例停止或者删除,则这些数据都将丢失,无法找回;而对于有状态服务,凡是已经挂载了存储卷的目录下的文件内容都可以随时进行备份,备份的数据可以下载,也可以用于恢复新的服务。但对于没有挂载卷的目录下的数据,仍然是无法备份和保存的,如果实例停止或者删除,这些非挂载卷里的文件内容同样会丢失。

StatefulSet具有如下特性

  • 稳定的持久化存储,即使旧Pod被新Pod替代还是能访问到完全相同的持久化数据
  • 稳定的网络标识,新Pod的hostname和Podname不变
  • 有序部署和有序收缩,Pod可以按照指定顺序来启动和停止

DaemonSet

相当于在所有Node(或者部分Node,因为Node可能有污点)上面运行一个(有且只有一个)Pod的副本,当有Node加入集群时,也会自动为其创建一个Pod副本

Job/Cron Job

和Linux中类似,用来执行单次和周期性的任务而创建的Pod

服务发现

服务(Service)的本质就是一组相关Pod的集合,要么是一个RS或者Deployment创建的Pod,或者是具有同一个标签的Pod。

之所以要有服务,因为无状态服务新的Pod代替旧的Pod以后,IP会变化,所以通过服务给这些Pod提供一个统一的访问入口,后面再对各个Pod做负载均衡,就不用担心这些Pod被访问的时候单个Pod的IP变化的问题。

网络通讯方式

K8s的网络基础是所有Pod都在一个可以直接连通的扁平网络空间中,也就是说任何Pod都可以直接访问到任何别的Pod。如果是在GCE上搭建k8s集群的话,这个网络是直接存在的。但是如果是自己搭建的k8s集群,这个网络基础是没有的,需要自己去实现。

有了这个网络基础之后就可以看看不同层次的通讯方式了。

单Pod内的容器之间

因为单Pod内的容器共用网络栈,所以直接用localhost即可

各Pod之间的通讯

Flannel是CoreOS开发的专门用来解决各个Pod间通讯的网络规划服务。通过Flannel创建的Ovrelay Network来实现每个Pod的IP是全局唯一的。

下图是Flannel的网络通讯的示意图
1-flannel.png

  • 如果是单台Node内的Pod间访问,直接通过Docker0这个网桥即可
  • 如果是多台Node的Pod之间访问,例如上图中的app2访问backend,首先走到Flannel0这个网桥,然后通过Flanneld这个服务里面存储的信息(Node物理网卡IP和Node内部Docker0的对应关系)就知道了目标Pod在哪台Node。之后在真正的三层包外面封装上包含Node物理网卡IP的包头用于在Node之间的通讯,注意Flanneld之间的通讯是基于UDP的,因为都是内网所以不用担心包丢失。到了目的Node包被对方的Flanneld捕获再走一遍逆向流程即可。

从上面的流程当中可以看到,ETCD给Flanneld提供的信息至关重要。ETCD内存储的主要是下面两个信息:

  • 已被各个Node中Flannel0使用的IP资源和剩余可用的IP资源
  • 每个Pod的IP和实际Node物理网卡IP的对应关系

Pod和Service的通讯

因为Service的目的就是用来给外网访问的,所以Pod访问别的Node上的service就跟访问外网IP一个道理,通过iptables的SNAT规则来解决。如果是外网要访问Pod就需要用到service的nodeport方式

总结

总结起来,k8s里面一共有3层网络:

  • 节点网络 - 也就是真实的物理网卡
  • Pod网络
  • Service网络

虽然每个物理机器中可以有很多的Pod,但是因为有Flannel这种服务帮我们完成Overlay网络,所以每个物理Node只需要有一个物理网卡就可以完成k8s集群的搭建。

好了,光说不练假把式。理论知识已经够多了,下一节我们就先来实际搭一个环境出来,再继续向下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值