k8s本质上是以应用为中心的应用基础设施,POD就是其运行应用以及应用调度的最小逻辑单元。

本质上就是共享network、IPC、UTS

POD是什么?
POD我们可以想象成一台物理机或者虚拟机,各个容器就是该主机的进程。
各个容器 共享网络协议栈,网络设备、路由、IP地址、端口mount和PID 以及USER是隔离的
每个POD上可以附加一个存储卷,作为该POD的外部存储,独立于POD的生命周期,可以由POD内各个容器共享

不可变基础设施?

POD 具有动态性,可容忍误删除或者主机故障
存储卷可确保数据能超越POD的生命周期

同一个POD也只能是具有超亲密关系的容器才能存在于同一个POD

为什么需要service 资源?

POD具有动态性,其IP地址会基于配置清单的重新构建,可能会分配到不同的node节点,因此当我们客户端再次请求的时必须借助服务发现service。

service 功能:
1 能够为一组提供相同服务的POD提供负载均衡的机制,其IP地址(Service ip 或者叫 cluster ip)为客户端流量的入口
2 一个service对象存在于集群的各个节点之上,不会因为个别的节点故障而丢失可以为POD提供固定的前端入口
3 service使用标签选择器,(label selector)筛选并且配置POD对象上的标签(label),从而发现POD由service对作为后端端点的使用。

在这里插入图片描述

POD与工作负载型控制器之间的关系?

pod是运行应用的原子单元,其生命周期和健康检查是由kubelet负责完成,但是比如更新,扩缩容,和重新构建等等应用编排的功能是由专门的控制器完成。
replicaset 副本控制器,为规定pod的副本数
deployment创建无状态应用类型的pod控制器
statefuset有状态应用pod控制器
job
cronjb

所有的控制器都需要通过Label selector筛选pod标签从而完成关联
工作负载型控制器的工作核心

1 确保pod符合期望的数量
2 按照配置定义进行扩缩容
3 依照策略和配进行应用的更新

什么是有状态什么又是无状态?

无状态:
比如我们现在有3个Nignx pod 我们kubectl delete 其中任意一个pod对于该集群没有影响。

有状态:
比如我们现在存在3节点的redis cluster的实例,那其中每个redis 它的槽位存储的key都具有一定差异,当我们删除其中任意一个pod那么对于集群有影响。我们恢复该pod时,也只能根据当前的pod的持久化存在节点的数据库进行恢复。

总结:无状态就是相同的app 的POD,不存在差异性;有状态就是同一个app的pod,每个Pod都有单独存在的意思,数据本身具有差异,不能够随意删除,然后调度到其他的node上。

虽然k8s具有管理有状态应用POD的控制器,statefuset 但是它也只能解决有状态应用的部分问题,不具有通用性,所以现在很多的生产环境也只是使用deployment去管理无状态的应用,有状态的应用更多使用operator

通过deployment创建pod时怎么实现自动扩缩pod
通过pod template 控制pod的数量
超出pod template定义的pod数,deployment会随机的删除任意一个pod
当少于定义的pod数量,deployment会从pod template获取还差几个pod 然后再创建相同的pod补全。

部署并访问应用

1 依照编排需求,选定合适的工作负载型控制器
2 创建工作负载型控制器对象,由其确保运行合适数量的POD对象
3 创建service对象,为POD提供固定的访问入口

客户端是如何访问service上的服务

1 如果访问的客户端是集群内部的

client ------ kubeapiserver—service----pod

2 外网的客户端怎么访问service上的服务。

我们基于service入口就能访问pod,但是客户端可以是来自于内部或者外部的用户。但是service只能暴露在内网,外网是无法直接访问,所以我们需要借助DNAT来实现, 比如现在有N个节点上面有若干个service 端口都是80,但是每个service 都存在于所有的节点,那么客户端去请求不同service下服务端口都相同, 那么nodeport 的80端口也只能DNAT 到某个service,所以不可行

问题1: 就是nodeport上开启N多个port映射到分别映射到不同的SIP:SPORT 但是这显然不合理,虽然解决了相同端口不能够重复的DNAT到同样PORT的不同SIP的service,但是外网的客户端,就无法知道我该去访问哪一个端口。

问题2:在客户端在访问nodeip:nodeport的之间我们建立一个外置的负载均衡器,将调度阶段Nodport:nodeport 上的N多的PORT映射到不同的SIP:SPORT 以此来区分不同的service下的服务,但是问题是service只是一对的iptables规则或者ipvs规则,具有无状态性,那么当用户删除某个service的时候,那么我们就需要去更改外置负载均衡器上的DNAT规则,这是非常的不合理也是非常难以维护。

目前常见的解决方案:
1 将k8s 部署在iass云上例如华为云、阿里云、青云
原因: 因为这些iass云上上具有LBaas服务 ,因为k8s 有控制器能够直接对接到iaas云上的负载均衡器的API,
总结:
当我们创建一个service时关联到nodeip:nodeport,LBaas 会自动调用service 的API 然后创建一个软负载均衡器,负载到该service 上,完成请求的负载调度。

1 k8s+openstack
所以我们可以考虑将k8s 部署在openstack上,openstack上具有LBaas能够对接到负载到k8s的service,但是为了解决此问题而在底层部署openstack不太合理。

2 openELB+k8s

k8s 网络类型

service 网络
service网络,是为service分配网络。service网络的网段与POD网络不在一个网段,所有客户端的访问请求必须经过service网络然后再DNAT到某个POD网络,再到达POD中。
pod网络
所有的Pod网段都相同 ,而这些pod 网络之间通信可以是under lay 或者 overlay
Node网络
节点自身我网络,一般在集群外部是可见的。

总结:
1 节点网络
集群节点间的通信网络,负责打通与集群外部端点间的通信
网络及各个节点地址需k8s部署完成配置,非k8s自身管理,因此,需要由管理员手动进行或者借助主机虚拟化管理程序进行

2 Pod网络
为集群上的pod对象提供的网络
虚拟网络,需要CNI网络插件实现,例如flanel、calico、cilium等

3 service网络
由k8s集群管理
service对象的IP地址存在于其相关的iptables或者ipvs规则中
在部署k8s集群时指定,各service对象使用的地址将从网络中配置

k8s 集群中的通信流量类型

1 同一个POD中的容器间通信
2 POD之间的通信 under lay/over lay
3 POD 与service 通信
4 集群外部的流量与service之间的通信

Pod网络需要借助遵循CNI网络接口规范的第三方网络插件进行通信,该插件需要满足如下的条件

1 所有POD间的通信可以不经过NAT 机制直接通信
2 所有节点可以不经过NAT机制直接与POD通信
3 所有POD 对象都位于同一个网络层面中(都在同一个2层网络只中)

补充:
NAT原理:
NAT(Network Address Translation)网络地址转换/网络地址翻译。
工作原理:NAT主要的通过对数据包头的地址替换来完成内网计算机访问外网服务的。当内部机器要访问外部网络时,NAT设备把内部的IP1与端口号1(网络层地址与传输层地址),转换成NAT的外部IP2与新的端口号2,再送给外部网络,数据返回时,再把目的为IP2:端口2的数据包替换为IP1:端口1,送给内网机器。
若通讯协议的内容中有IP地址的传递,如FTP协议,NAT在翻译时还要注意数据包内涉及协议地址交互的地方也要替换,否则协议就会出现地址混乱。在NAT设备中维护了这个要替换地址的映射表,并根据内部计算机的通讯需求维护该表。外部网络来数据包能否进入NAT,主要是看是否已经有可映射的表项,若没有就会丢弃。

NAT的外部公网地址可以是一个IP,也可以是一个网段,形成地址池。NAT还可以把某个外网地址直接影射给内网的某个服务器,让外网的用户可以直接访问到这台服务器。NAT的工作的隐藏内网的机器,但允许内网主动打开到外网的通讯“通道”,也就是建立映射表项。

2层网络3层网络的用途
二层网络仅仅通过MAC寻址即可实现通讯,但仅仅是同一个冲突域内;三层网络需要通过IP路由实现跨网段的通讯,可以跨多个冲突域;

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐