一、三个容器管理器平台

  • Apache MESOS 开源的分布式资源管理框架,被推特选为基础平台,2019年推特换位k8s,MESOS最新版可以在MESOS上管理k8s
  • DOCKER SWARM docker总部发行的,实现docker的集群方案,和docker捆版一起,比较轻量,功能少,但是大规划话实现非常好,对docker实现好
  • Kubernetes Goolge研发, 由borg采用go语言开发,资源消耗少,弹性伸缩,开源,负载均衡

二、kubernetes组件

1️⃣ 服务的分类

  • 有状态服务:数据库管理系统(DBMS)
  • 无状态服务:lvs APACHE

2️⃣ borg架构

image-20240427003124803

3️⃣ k8s架构

image-20240427003223530
  • replication controller :简称rc 控制器,维护副本数目,副本数量如果达不到数量值控制器就会去申请副本,以便于达到数量值,也就是删除对应的pod和删除对应的pod
  • kubectl : 命令行管理工具
  • web UI : web界面
  • Scheduler:调度器,负载介绍任务,选择合适的节点进行分配任务
  • api server : 所有服务访问统一入口
  • kubetet:负责维护容器的生命周期,同时也复制Volume和网络的管理
  • kube proxy:负责为Service提供集群内部的服务发现和负载均衡

⭐️ 看上图,就可以看见以上所有服务都要以 api server 交互,所以看起来会很繁忙,但是每个服务都会在服务本身产生一定的缓存,并不是每件事都要到 api server里面去请求


组件一: Etcd

⭐️ etcd的官方将它定位成一个可信赖的分布式键值存储服务,它能够为整个分布式集群存储一些关键数据,协助分布式集群的正常运转,天生支持集群不需要中间件,可以保存一些配置文件

⭐️ etcdCoreOS 团队于 2013 年 6月发起的开源项目,它的目标是构建一个高可用的分布式键值 (key-value)数据库。etcd 内部采用 raft协议作为一致性算法,etcd 基于 Go 语言实现。

⭐️ etcd 的特点

  • 简单:安装配置简单,而且提供了HTTP API进行交互,使用也很简单
  • 安全:支持SSL证书验证
  • 快速:根据官方提供的benchmark数据,单实例支持每秒2k+读操作
  • 可靠:采用raft算法,实现分布式系统数据的可用性和一致性

⭐️ 为了保证数据的强一致性,etcd 集群中所有的数据流向都是一个方向,从 Leader (主节点)流向 Follower,也就是所有 Follower 的数据必须与 Leader 保持一致,如果不一致会被覆盖。

⭐️ 用户对于 etcd 集群所有节点进行读写

  • 读取:由于集群所有节点数据是强一致性的,读取可以从集群中随便哪个节点进行读取数据
  • 写入:etcd 集群有 leader,如果写入往 leader 写入,可以直接写入,然后然后Leader节点会把写入分发给所有 Follower,如果往 follower 写入,然后Leader节点会把写入分发给所有 Follower

⭐️ etcd目前有两个版本一个是v3 一个是v2,v2版是将数据写入到内存中,v3是把数据写入到本地数据卷的库中,但是推荐使用v3,v2以及被弃用

⚠️ 需要注意的是在kubernetes1.11版本前的是不支持v3版本的

⭐️ETCD的内部架构图

1️⃣使用的模式是C/S的构建服务

k8也是用http协议支持C/S

image-20240427004503538

  • C/SClinet-Server,服务器负责数据库的管理,客户机负责完成与用户的交互。ETCD就是采用这种模式,kubernetes也是。
  • Raft:存储读写信息
  • WAL:预写日志

其他插件

CoreDNS:可以为集群中的SVC创建一个域名IP的对应关系解析。、

Dashboard:k8s集群提供B/S结构

ps: B/S 浏览器/服务器模式

Ingress controller: 官方只能实现四层代理,ingress实现7层代理

Federation:可以提供一个可以夸集群中心多K8s统一管理的功能

Prometheus:普罗米修斯,提供K8s集群的监控能力

ELK:提供k8s的集群日志统一分析接入平台


三、Pod

  • 自主式Pod:不是被控制器管理的Pod,死了以后不会被控制器“复活”,也不会创建一个和他期望值一样的Pod
  • 控制器管理的Pod: 被控制器管理的Pod,和自助式Pod是反着来的

⭐️ 在同一个容器里面他们的网络,存储都是共享的,因此不能发生端口冲突。

image-20240427004715134

1️⃣ReplicationController & ReplicaSet & Deployment

  • ReplicationController用来确保容器应用的副本数始终保持在用户定义的副本数,即如果有容器异常退出,会自动创建新的Pod来替代;而如果异常多出来的容器也会自动回收。在新版本的 Kubernetes 中建议使用 ReplicaSet 来取代 ReplicationControlle
  • ReplicaSetReplicationController没有本质的不同,只是名字不一样,并且 ReplicaSet支持集合式的 selector,通过 labels 来操作
  • 虽然 ReplicaSet可以独立使用,但-般还是建议使用 Deployment 来自动管理 ReplicaSet,这样就无需担心跟其他机制的不兼容问题(比如 ReplicaSet 不支持 rolling- updateDeployment 支持)

⭐️selector:搜索,标签搜索,rc不支持集合式搜索,rs支持,就是创建 Pod的时候会给 Pod打上标签,可以直接搜索标签,或者一组标签

⭐️rolling-update:滚动更新,也就是你需要把一个或者一组 Pod更新成最新版本,它就会给你先生成一个新版的 Pod,在给你删除你旧版的 Pod

⭐️ 回滚:和更新类似,只不过式反着来的

2️⃣ Deployment (ReplicaSet )

⭐️ DeploymentPodReplicaSet 提供了一个声明式定义(declarative) 方法,用来替代以前的 ReplicationController 来方便的管理应用。典型的应用场景包括:

  • 定义 Deployment 来创建Pod和ReplicaSet
  • 滚动升级和回滚应用
  • 扩容和缩容
  • 暂停和继续Deployment

命令式编程: 它侧重于如何实现程序,就像我们刚接触编程的时候那样,我们需要把程序的实现过程按照逻辑结果一步步写下来

声明式编程: 它侧重于定义想要什么,然后告诉计算机/引擎,让他帮你去实现

3️⃣ HPA (HorizontalPodAutoScale)

⭐️ Horizontal Pod Autoscaling 仅适用于 DeploymentReplicaSet ,在V1版本中仅支持根据 PodCPU利用率扩所容,在 v1alpha 版本中,支持根据内存和用户自定义的 metric 扩缩容.

image-20240427005119697

4️⃣ StatefulSet

⭐️ StatefulSet是为了解决有状态服务的问题(对应 DeploymentsReplicaSets 是为无状态服务而设计),其应用场景包括:

  • 稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于 PVC来实现
  • 稳定的网络标志,即Pod重新调度后其 PodNameHostName 不变,基于H eadless Service(即没有 Cluster IPService )来实现
  • 有序部署,有序扩展,即 Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次依次进行(即从0到N-1,在下-一个Pod运行之前所有之前的 Pod必须都是 RunningReady 状态) ,基于 init containers 来实现
  • 有序收缩,有序删除(即从N-1到0)

5️⃣ Service

⭐️ Kubernetes中一个应用服务会有一个或多个实例(Pod),每个实例(Pod)的IP地址由网络插件动态随机分配(Pod重启后IP地址会改变)。为屏蔽这些后端实例的动态变化和对多实例的负载均衡,引入了Service这个资源对象

  • ClusterIP: 默认方式。根据是否生成 ClusterIP又可分为普通 ServiceHeadless Service两类:
  • 普通 Service:通过为Kubernetes的Service分配一个集群内部可访问的固定虚拟IP(Cluster IP),实现集群内的访问。为最常见的方式。
  • Headless Service:该服务不会分配 Cluster IP,也不通过 kube-proxy做反向代理和负载均衡。而是通过DNS提供稳定的网络 ID来访问,DNS会将 headless service的后端直接解析为podIP列表。主要供StatefulSet使用。
  • NodePort:除了使用 Cluster IP之外,还通过将 serviceport映射到集群内每个节点的相同一个端口,实现通过 nodeIP:nodePort从集群外访问服务。
  • LoadBalancer:和 nodePort类似,不过除了使用一个 Cluster IPnodePort之外,还会向所使用的公有云申请一个负载均衡器(负载均衡器后端映射到各节点的nodePort),实现从集群外通过LB访问服务。
  • ExternalName:是 Service 的特例。此模式主要面向运行在集群外部的服务,通过它可以将外部服务映射进 k8s集群,且具备 k8s内服务的一些特征(如具备 namespace等属性),来为集群内部提供服务。此模式要求 kube-dns的版本为 1.7或以上。这种模式和前三种模式(除 headless service)最大的不同是重定向依赖的是dns层次,而不是通过 kube-proxy

6️⃣ DaemonSet

⭐️ DaemonSet确保全部(或者一些) Node上运行 一个 Pod的副本。当有 Node 加入集群时,也会为他们新增一个 Pod。当有Node从集群移除时,这些 Pod也会被回收。删除 DaemonSet将会删除它创建的所有 Pod

  • 使用 DaemonSet 的一些典型用法:
  • 运行集群存储 daemon, 例如在每个 Node . 上运行 glusterdceph
  • 在每个 Node.上运行 日志收集 daemon, 例如 fluentdlogstash
  • 在每个 Node . 上运行监控 daemon, 例如 Prometheus Node Exporter

为什么会有一些呢?因为我们可以在创建Pod的时候打上一个污点,这些被打上污点的就不会在被创建副本了

7️⃣ Job, Cron job

⭐️ Job负责批处理任务,即仅执行一次的任务,它保证批处理任务的-一个或多个 Pod 成功结束

打个比方,就比如你运行一个脚本,job就会判断你是不是正常退出,如果不是正常退出,他就会在去执行那个脚本,直到正常退出为止

⭐️ Cron Job 管理基于时间的Job, 在特定达到时间循环创建job 即:

  • 在给定时间点只运行一次
  • 周期性地在给定时间点运行

四、服务发现

image-20240427005533333

1️⃣clientservice发送请求,这个请求会带有标签,service就通过标签来寻找对应 Pod

2️⃣ 客户端向访问一组 pod,但是 podpod之间都不相干的时不可以通过 service统一代理的,但是如果时同一个rc创建的或者有同一个标签就就可以访问代理


五、网络通讯方式

⭐️ Kubernetes的网络模型假定了所有 Pod都在一一个可以直接连通的扁平的网络空间中,这在GCE (Google Compute Engine)里面是现成的网络模型,Kubernetes 假定这个网络已经存在。而在私有云里搭建Kubernetes 集群,就不能假定这个网络已经存在了。我们需要自己实现这个网络假设,将不同节点上的 Docker容器之间的互相访问先打通,然后运行 Kubernetes

1️⃣同一个 Pod内的多个容器之间通过lo回环通讯

2️⃣各个 Pod之间通过 Overlay Network来通讯

  • 同节点通过 cni网桥转发数据包
  • 不同节点的 pod需要通过网络插件来支持通讯

3️⃣ PodServicer之间的通讯就要通过各节点的Iptables

1️⃣Flannel

⭐️ FlannelCore0S 团队针对 Kubernetes设计的一一个网络规划服务,简单来说,它的功能是让集群中的不同节点主机创建的 Docker 容器都具有全集群唯一- 的虚拟 IP地址。而且它还能在这些 IP地址之间建立-一个覆盖网络(Overlay Network),通过这个覆盖网络,将数据包原封不动地传递到目标容器内

image-20240427005646273

⭐️Flannel首先创建了一个名为 flannel0的网桥,而且这个网桥的一端连接 docker0的网桥,另一端连接一个名为 flanneld的服务进程。

⭐️ Flanneld进程并不简单,它首先上连 etcd,利用 etcd来管理可分配的 IP地址段资源,同时监控 etcd中每个 Pod的实际地址,并在内存中建立了一个 Pod节点路由表;然后下连 docker0和物理网络,使用内存中的 Pod节点路由表,将 docker0发给它的数据包包装起来,利用物理网络的连接将数据包投递到目标 flanneld上,从而完成 podpod之间的直接的地址通信。

⭐️ Flannel之间的底层通信协议的可选余地有很多,比如 UDPVXlanAWS VPC等等。只要能通到对端的 Flannel就可以了。源 Flannel封包,目标 Flannel解包,最终 docker0看到的就是原始的数据,非常透明,根本感觉不到中间 Flannel的存在。

2️⃣ETCD和Flannel

⭐️ 存储管理 Flannel可分配的IP地址段资源,监控 ETCD中每个 Pod的实际地址,并在内存中建立委会 Pod节点路由表

⭐️ 同一 Pod内的网络通信。在同一个 Pod内的容器共享同一个网络命名空间,共享同一个 Linux协议栈。所以对于网络的各类操作,就和它们在同一台机器上一样,它们可以用 localhost地址直接访问彼此的端口。其实这和传统的一组普通程序运行的环境是完全一样的,传统的程序不需要针对网络做特别的修改就可以移植了。这样做的结果是简单、安全和高效,也能减少将已经存在的程序从物理机或者虚拟机移植到容器下运行的难度。

⭐️Pod1Pod2的网络,分两种情况。Pod1Pod2不在同一台主机与 Pod1Pod2在同一台主机。

  • 不在同一主机:Pod的地址是与 docker0在同一个网段的,但 docker0网段与宿主机网卡是两个完全不同的 IP网段,并且不同 Node之间的通信只能通过宿主机的物理网卡进行。将 PodIP和所在 NodeIP关联起来,通过这个关联让 Pod可以互相访问。
  • 在同一主机Pod1Pod2在同一台主机的话,由 Docker0网桥直接转发请求到 Pod2,不需要经过 Flannel

⭐️ PodService的网络。创建一个 Service时,相应会创建一个指向这个 Service的域名,域名规则为{服务名}.{namespace}.svc.{集群名称}。之前 Service IP的转发由 iptableskube-proxy负责,目前基于性能考虑,全部为 iptables维护和转发。iptables则由 kubelet维护。Service仅支持UDP和 TCP协议,所以像 pingICMP协议是用不了的,所以无法 pingService IP

⭐️ Pod到外网。Pod向外网发送请求,查找路由表, 转发数据包到宿主机的网卡,宿主网卡完成路由选择后,iptables执行 Masquerade,把源IP更改为宿主网卡的 IP,然后向外网服务器发送请求。

⭐️ 集群外部访问 PodService

image-20240427005955554