1. Borg

在K8S之前,集群管理系统的典型案例是Google使用十年之久的容器化基础架构Borg系统,后出于商业目的,Google使用Go语言翻写了Borg,成为了如今的Kubernetes。Kubernetes具有轻量级、开源以及弹性伸缩的特点,可以在保证服务运行效率的情况下节省更多的资源,为各大互联网公司所青睐。

2. Borg架构

  1. BorgMaster* n:作为主要控制节点,为防止单节点故障,高可用副本数目尽量保持在3个以上的奇数个;
  2. Borglet* n:Borg所使用的工作节点;
  3. 访问BorgMaster可以通过如下方式:borgcfg、command-line tools、web browsers,即Borg配置文件、命令行工具以及浏览器;
  4. Borglet工作的方式为:调度器Scheduler将数据写入BorgMaster中的键值数据库Paxos中,Borglet对该数据库进行实时监听,遇到需要的资源就将其拉取下来进行消费。

3. Kubernetes组件与架构

3.1 Master架构

  1. Scheduler:用于接受并分配任务;
  2. API Server:Scheduler将任务发送给API Server,是所有服务的统一访问入口;
  3. Replication Controller:用于维护副本数量,将其保持在期望值。

3.2 ETCD架构

ETCD是一种键值数据库,用于存储配置数据与集群状态信息,与API Server交互。ETCD使用Go语言编写,是Kubernetes的持久化方案,具有可信赖、分布式的特点。

包含两种存储方案:将数据加载入内存中(v2)或提供一个本地卷服务(v3),在高版本的ETCD中,通常使用的是v3方案。

  1. ETCD采用Http进行C/S开发,并以此形式与Raft进行交互;
  2. Raft:用于存放读写信息的组件;
  3. WAL:日志组件,包含完整日志与临时日志,与Raft共同进行存储。

3.3 node架构

  1. Kubelet:用于与C(Container)、R(Runtime)、I(Interface)交互,负责服务生命周期的管理;
  2. Kube Proxy:用于操作firewall实现Pod映射,将规则写入至IPtables、IPvs;
  3. Docker或其他容器服务。

3.4 第三方组件

  1. CoreDNS:为集群中SVC创建一个IP的对应解析,访问时通过此部件生成的IP访问服务;
  2. Dashboard:B/S访问体系的提供者;
  3. Ingress Controller:相比官方提供的四层代理,其七层代理可以实现更好的负载均衡;
  4. Federation:跨集群中心多K8S集群统一管理;
  5. Prometheus:用于K8S监控;
  6. ELK:K8S日志分析的统一介入平台。

4. Pod概念

Pod总体分为两种类型:自主式Pod与控制器管理的Pod,自主式Pod是不能自主修复的,当这种Pod去世之后,是不可以恢复的,而与自主式Pod相反,被控制器管理的Pod去世之后,还可以被重新创建。在有控制器管理的情况下,创建Pod变得十分容易,只需要向控制器描述需要多少什么样的Pod即可。

什么是Pod?Pod是一种高级结构,一个Pod中包含有多个容器,并且有一个常驻容器Pause,该容器在Pod创建时就被启动,Pod内的其他容器共用该Pause容器的网络栈与存储卷。换一种说法,同一Pod中的多个容器不能出现冲突的端口,否则会造成一个或多个容器启动失败或无限重启。

Pod中的容器类型有多种:

  1. Replication Controller:较早的控制器类型,用于保证副本的期望值;
  2. ReplicaSet:RS与RC没有本质上的区别,但RS支持集合式的selector,所以目前RS正在取代RC;
  3. Deployment:虽然RS可以独立出来使用,但Deployment可以自动管理RS,这很好地避免了不同机制的兼容性问题。例如:RS不支持rolling update即滚动更新,但Deployment支持,通过Deployment管理RS,可以实现滚动更新的功能。Deployment创建RS,RS创建Pod,在滚动更新时,旧的RS不会被删除,而是会被停用,以便于进行回滚操作;
  4. HPA:即Horizontal Pod Autoscaling,HPA仅适用于Deployment & RS,可以实现一定条件下的Pod扩容;
  5. StatefullSet:相比Deployment & RS用于无状态服务,StatefullSet用于解决有状态服务的问题,使用StatefullSet的场景有如下几种:
    • 稳定的持久化存储:Pod被重新调度后还能正常访问相同的持久化数据,基于PVC实现;
    • 稳定的网络状态:在Pod被重新调度后的PodName & HostName都不会发生变化,基于Headless Service实现;
    • 有序部署、有序扩展:Pod是有顺序的,部署与扩展时,需要严格按照顺序进行,在运行下一个Pod时,必须保证上一个Pod已经处于Running或Ready状态下,基于init container实现;
    • 有序回收、有序删除。
  6. DaemonSet:用于确保所有Node上都运行一个Pod Replication,在新的Node加入集群时,DaemonSet也为其添加一个Pod,在Node被移除时,Pod也被删除。删除DaemonSet时,通过DaemonSet创建的Pod都会被删除,使用DaemonSet的场景如:在每个Node上运行如Prometheus Node Exporter的监控Daemon;
  7. Job:负责批处理任务,在脚本执行失败时,将脚本重复执行直到成功为止,保障批处理任务的一个或多个Pod成功结束;
  8. Cron Job:管理基于时间的Job。

5. 服务发现

与一个服务相关的Pod都会被打上标签,当Client想要访问某种服务时,与该服务相关的一组Pod都会被一个Service根据标签收集,Client可以通过访问Service来对这组Pod进行访问。这样做的目的在于:由于有些Pod被重新调度后,其IP地址可能发生变化,这无疑增加了Client的访问难度,而Service具有固定的IP & 端口,被Service收集到的Pod会被Service绑定,Client在访问时,只需访问Service即可。

6. 网络通讯模式

K8S网络模型假定所有的Pod都处于一个可以直接联通的扁平网络空间中,这个网络模型在GCE(Google Compute Engine)中是现成的,所以我们要在自己的云服务器中实现此模型,先将各节点上的Docker容器的相互访问打通,再运行K8S,如今我们借助如下几种方式来实现网络通讯的部署与规划:

6.1 K8S + Flannel

Flannel是CoreOS团队针对K8S设计的一个网络规划服务,目的是使集群中的不同node创建的Docker container都具有全集群唯一的虚拟IP地址。并为这些IP建立覆盖网络(Overlay Network),使数据包可以通过此网络传递至目标容器内。举例如下。

现有两台主机node01、node02,其上共有四个Pod,node01运行Pod01与Pod02,node02运行Pod03与Pod04,其中Pod01与Pod02分别运行webapp01与webapp02,Pod03运行webapp03,Pod04运行backend。几个Pod的工作模式为:外部的所有流量访问backend,backend将请求进行处理,给对应的服务分配对应的请求。此时,与backend处于同一node的webapp03需要与backend进行同主机不同Pod之间的通讯,而与backend处于不同node的webapp01与webapp02想要与其通信,就涉及到不同主机Pod之间的通信。

在一般情况下,我们会在运行Pod的主机上运行一个守护进程Flanneld,该进程会监听一个用于后期接收转发数据包的端口,且一旦Flanneld启动后,会开启一个Flannel0网桥,该网桥专门用于收集Docker0网桥发送出来的数据包,而Docker0会分配IP给对应的Pod。所以在同主机的不同Pod进行通信时,是通过Docker0网桥完成的。

在不同主机的不同Pod进行通信时,从Pod发送出来的数据包发送给Docker0,并由Flannel0抓取,Flanneld会对其进行封装,转发到目标Pod所在的主机。数据包由目标主机运行的Flanneld进行解包后,经Flannel0网桥与Docker0网桥一层层传递到目标主机的目标Pod中。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐