k8s诞生背景及核心概念
docker解决了应用打包的问题后,应用大规模部署与管理的问题愈发突出。容器本身没有价值,有价值的是容器编排
容器编排(Orchestration):对Docker及容器进行更高级更灵活的管理,按照用户的意愿和整个系统的规则,完全自动化的处理好容器之间的各种关系
容器技术做为底层基础技术,只能用来创建和启动容器的工具。k8s是docker技术的上层架构
Kubernetes,舵手,k8s,基于Google borg系统(前身),目前容器编排的事实标准
整个系统由控制面(Master)与数据面(Worker Node)组成。
Master包含:
Kubernetes架构具备高可用:一方面Master节点高可用;另一方面所部署的业务也是高可用的。系统高可用的核心在于冗余部署,当某一个节点或程序出现异常时,其他节点或程序能分担或替换工作。Master节点高可用,主要由以下几个方面的设计实现:
Work Node包含:
Container:普通的业务应用容器
Pause: 连接多个Container,健康性检查
Pod: 包含多个容器,相关联的容器可以放到一个pod
RelicaSet(RS): 管理pod的生命周期
Deployment: 滚动部署时,Deploy先创建一个rs,rs起一个pod,健康性检查通过把原来的pod停掉,再起一个pod,再停原来的,rs的两个pod都停掉后,再销毁rs,完成滚动部署
Label:标签,depoyment/pod等都可以打标签
Service:通过标签找到一组服务
ClusterIp:service有clusterIp,client通过该ClusterIp访问服务
Kubernetes中API Server的核心功能是提供Kubernetes各类资源对象(如Pod、RC、Service等)的增、删、改、查及Watch等HTTP REST接口,成为集群内各个功能模块之间数据交互和通信的中心枢纽,是整个系统的数据总线和数据中心。除此之外,它还是集群管理的API入口,提供了完备的集群安全机制。API Server是由多实例同时工作,各个组件通过负载均衡连到具体的API Server实例上。
各组件与API Server通信时,采用List-Watch机制,通过API server获取etcd配置与状态信息,进而触发行为。以下图为例是kubectl创建一个deployment时,各个组件与API Server的流程交互。
Api Server的作用:
三大核心设计:
Kubernetes在对象抽象方面,核心创新在于Pod对象的设计。**容器设计本身是一种“单进程”模型。**该表述不是指容器里只能启动一个进程,而是指容器无法管理多个进程。只有容器内PID=1的进程生命周期才受到容器管理(该进程退出后,容器也会退出),其他进程都是PID=1的进程的子进程。根据容器设计模式,传统架构中多个紧密配合的业务进程(例如业务进程与日志收集进程,业务进程与业务网络代理进程)应该部署成多个容器。但这些容器之间存在亲密的关系,需要一起调度和直接共享某些资源(网络和存储)。
Kubernetes抽象出一个Pod对象,是一组(一个或多个)容器, 这些容器共享存储、网络等, 这些容器是相对紧密的耦合在一起的。Pod是Kubernetes内创建和管理的最小可调度单元,调度过程是按Pod整体所需资源一起进行调度的。Pod本身只是逻辑上的概念,在容器管理这层并不认识Pod对象。
Pod的实现需要使用一个中间容器(Infra容器),在这个Pod中,Infra容器永远是第一个被创建的容器,用户定义的其他容器通过Join Network Namespace的方式与Infra容器关联在一起。抽象一个中间容器的原因在于各个业务容器是对等的,其启动没有严格的先后顺序,需借助中间容器实现共享网络和存储的目的。
通过Kubernetes中各个对象的关联关系来更为深刻的理解Pod的意义。下图可以看出,Pod其实是整个编排过程中操作的核心,很多对象直接或间接的同Pod相关联。
Kubernetes编排抽象的另一个核心对象是Service对象,它统一的 解决了集群内服务发现与负载均衡。 Service是对一组提供相同功能的Pod的抽象,为其提供了一个统一的入口。Service通过标签选择服务后端,匹配标签的Pod IP和端口列表组成endpoints,由kube-proxy负责将请求负载到相关的endpoints。
上图是kube-proxy通过iptables模式来实现Service的过程,Service对象有一个虚拟clusterIP,集群内请求访问clusterIP时,会由iptables规则负载均衡到后端endpoints。
Declarative(声明式设计)指的是一种软件设计理念和编程方式,描述了目标状态,由工具自行判断当前状态并执行相关操作至目标状态。声明式强调What,目标是什么。而Imperative(命令式)需要用户描述一系列详细指令来达到期望的目标状态。命令式强调How,具体如何做。
下图描绘了一个场景:目标副本数为3。对于声明式而言,用户设定目标为3,系统获取当前副本数为2,系统判定当前值与目标值的差为1,便自行加1,最终实现副本数为3的目标状态。而对于命令式,需用户判断当前副本数为2,用户给出指令副本+1,系统接收用户指令,执行副本数+1操作,最终系统副本数为3。
kubernetes的一大核心设计就是采用了声明式API,利用该设计思想有效的实现了系统的自动化运行。Kubernetes声明式API指定了集群期望的运行状态,集群控制器会通过List&Watch机制来获取当前状态,并根据当前状态自动执行相应的操作至目标状态。
Kubernetes推荐使用:声明式对象配置(YAML)。kubectl replace执行过程是通过新的YAML文件中的API对象来替换原有的API对象,而Kubectl apply执行了一个对原有API对象的PATCH操作。除此之外,YAML配置文件用于Kubernetes对象的定义,还会有以下收益:
Kubernetes的设计初衷就是支持可插拔的架构,解决PaaS平台使用不方便、不易扩展等问题。为了便于系统的扩展,Kubernetes中开放了以下接口可对系统资源(计算、网络、存储)插件进行扩展,可分别对接不同的后端来实现自己的业务逻辑。
私有镜像库