Intro
k8s是一个开源的,用于管理云平台中多个主机的容器化的应用。
目标是让部署容器化的应用简单而且高效,k8s提供了应用部署,规划,更新以及维护的一种机制。
核心特点:自主管理容器,以此来保证云平台中的容器按照用户的期望状态运行。
k8s中,所有容器都运行在pod上。一个pod可以承载一个或者多个相关的容器。同一个pod上的容器会部署在同一个物理机器上,以此实现资源共享
用户可以自己创建并且管理pod,k8s简化为两个操作:
-
基于相同的Pod配置文件部署多个pod复制品。
-
当一个pod或者机器挂了的时候,创建可以替代的pod
k8s的API中负责来重新启动,迁移的部分叫做"replication controller",具体工作原理是针对一个pod生成许多备份。这些冗余的pod就会组成一个应用或者服务,或者服务的一层。
然后系统就会不停地监控Pod的健康情况以及pod所在主机的健康情况,如果这个Pod因为软件原因挂掉了或者所在的机器挂掉了,replication controller会自动在一个健康的机器上创建一个一模一样的Pod来维持原来的pod冗余状态不变,一个应用的多个pod可以共享一个机器。
那k8s是如何对pod进行基本操作呢?
如果需要选中一组pod,用户可以给k8s的api中的任何对象贴上一组key:value的标签,然后可以通过标签来选择一组相关的k8s API对象,然后执行一些特定的操作。每个资源额外拥有一组keys和values,然后外部工具可以使用这些keys和values进行对象的检索。这些map叫做annotations.
k8s可以允许用户选择任何想使用的端口。它会为每个pod分配ip地址。
所有k8s中的资源,比如pod,都通过URI来区分,URI的组成部分是对象类型,对象名字,明明空间等。
Kubernetes提供了服务的抽象,并提供了固定的IP地址和DNS名称,而这些与一系
列Pod进行动态关联,这些都通过之前提到的标签进行关联,所以我们可以关联任
何我们想关联的Pod,当一个Pod中的容器访问这个地址的时候,这个请求会被转发
到本地代理(kube proxy),每台机器上均有一个本地代理,然后被转发到相应的后
端容器。Kubernetes通过一种轮训机制选择相应的后端容器,这些动态的Pod被替
换的时候,Kube proxy时刻追踪着,所以,服务的 IP地址(dns名称),从来不变。
k8s对计算资源进行了更高层次的抽象,具体来说是通过容器的组合,最终把应用服务交给用户。
要考虑的地方是容器跨机链接,以及支持多种网络解决方案,同时在service层次构建集群范围的SDN网络。目的是将服务发现和负载均衡放到容器可达的范围。
k8s设计架构
Kubernetes集群包含有节点代理kubelet和Master组件(APIs, scheduler, etc),一切都基于分布式的存储系统。
-
kubelet 每个节点运行的主要节点代理
每个节点上都要运行一个worker,对容器进行生命周期的管理 -
Master
1.etcd 保存整个集群的状态
2.api server 提供了资源操作的唯一入口
3.scheduler 负责资源调度,按照预订的调度策略把pod调度到相应机器上
4.controller manager 负责维护集群状态
* 核心层 k8s最核心功能,对外提供API构建高层的应用,对内提供插件式应用执行环境。
-
应用层 部署应用以及路由
-
管理层 系统度量(如基础设施,容器和网络的度量),自动化(自动扩展)与策略管理
-
接口层
-
生态系统
- Kubernetes外部:日志、监控、配置管理、CI、CD、Workflow、FaaS、OTS应用、ChatOps等
- Kubernetes内部:CRI、CNI、CVI、镜像仓库、Cloud Provider、集群自身的配置和管理等
k8s核心技术概念和API对象
API对象是k8s集群中的管理操作单元。
每个API对象都有三大类属性:
-
元数据metadata
用于标识API对象,每个对象至少有3个元数据
namespace,name和uid -
规范spec
所有的配置都是通过API对象的spec去设置,所有的操作都是声明式的。
声明式操作在分布式系统中好处是稳定,不怕丢操作或者运行多次。 -
状态 status
例如用户可以通过复制控制器Replication Controller设置期望的Pod副本数为3;status描述了系统实际当前达到的状态(Status),例如系统当前实际的Pod副本数为2;那么复制控制器当前的程序逻辑就是自动启动新的Pod,争取达到副本数为3
pod
k8s中部署应用或者服务最小单元,可以理解为一种微服务。
可以支持多容器,其设计理念是支持多个容器在一个Pod中共享网络地址和文件系统,然后通过进程间通信和文件共享来实现组合服务。
Pod对多容器的支持是K8s最基础的设计理念。比如你运行一个操作系统发行版的软
件仓库,一个Nginx容器用来发布软件,另一个容器专门用来从源仓库做同步,这两
个容器的镜像不太可能是一个团队开发的,但是他们一块儿工作才能提供一个微服
务;这种情况下,不同的团队各自开发构建自己的容器镜像,在部署的时候组合成
一个微服务对外提供服务。
RC(复制控制器)
通过监控运行中的Pod来保证集群中运行指定数目的Pod副本。指定的数目可以是多个也可以是1个;少于指定数目,RC就会启动运行新的Pod副本;多于指定数目,RC就会杀死多余的Pod副本。
即使只运行一个pod,用RC也是明智的选择,因为其可以保证永远有一个pod在运行。
副本集(Replica Set,RS)
提供同样的高可用能力。副本集对象一般不单独使用,而是作为Deployment的理想状态参数使用。
部署(Deployment)
部署表示用户对k8s集群的一次更新操作。
可以是创建一个新的服务,更新一个新的服务,也可以是滚动升级一个服务。滚动升级一个服务,实际是创建一个新的RS,然后逐渐将新RS中副本数增加到理想状态,将旧RS中的副本数减小到0的复合操作;这样一个复合操作用一个RS是不太好描述的,所以用一个更通用的Deployment来描述。
服务
一个Pod只是一个运行服务的实例,随时可能在一个节点上停止,在另一个节点以一个新的IP启动一个新的Pod,因此不能以确定的IP和端口号提供服务。要稳定提供服务需要服务发现和负载均衡能力。服务发现完成的工作,是针对客户端访问的服务,找到对应的后端服务实例。
在k8s集群中客户端需要访问的服务是service对象
每个service会对应一个集群内部的一个虚拟ip,集群内部通过虚拟ip访问一个服务。
在k8s集群中微服务的负载均衡是由kube-proxy实现的。kube-proxy是k8s集群内部的负载均衡器,是一个分布式代理服务器,在每个k8s节点上都有一个。
有状态服务集(petset)
RC和RS主要是控制提供无状态服务的,其所控制的Pod的名字是随机设置的,一个Pod出故障了就被丢弃掉,在另一个地方重启一个新的Pod,名字变了、名字和启动在哪儿都不重要,重要的只是Pod总数。
对于RC和RS中的Pod,一般不挂载存储或者挂载共享存储,保存的是所有Pod共享的状态,Pod像牲畜一样没有分别(这似乎也确实意味着失去了人性特征);
petSet是用来控制有状态服务,PetSet中的每个Pod的名字都是事先确定的,不能更改。
对于PetSet中的Pod,每个Pod挂载自己独立的存储,如果一个Pod出现故障,从其他节点启动一个同样名字的Pod,要挂载上原来Pod的存储继续以它的状态提供服务。
适合于PetSet的业务包括数据库服务MySQL和PostgreSQL,集群化管理服务Zookeeper、etcd等有状态服务。PetSet的另一种典型应用场景是作为一种比普通容器更稳定可靠的模拟虚拟机的机制。传统的虚拟机正是一种有状态的宠物,运维人员需要不断地维护它,容器刚开始流行时,我们用容器来模拟虚拟机使用,所有状态都保存在容器里,而这已被证明是非常不安全、不可靠的。使用PetSet,Pod仍然可以通过漂移到不同节点提供高可用,而存储也可以通过外挂的存储来提供高可靠性,PetSet做的只是将确定的Pod与确定的存储关联起来保证状态的连续性。
存储卷(Volume)
k8s集群的存储卷与docker的存储卷有些类似。
不过Docker的存储卷作用范围为一个容器,而K8s的存储卷的生命周期和作用范围是一个Pod。每个Pod中声明的存储卷由Pod中的所有容器共享。
为了保证数据的持久性,必须保证数据在外部存储在docker容器中,为了实现数据的持久性存储,在宿主机和容器内做映射,可以保证在容器的生命周期结束,数据依旧可以实现持久性存储。但是在k8s中,由于pod分布在各个不同的节点之上,并不能实现不同节点之间持久性数据的共享,并且,在节点故障时,可能会导致数据的永久性丢失。为此,k8s就引入了外部存储卷的功能。
PV 和 PVC
PV和PVC使得k8s具备了存储的逻辑抽象能力,使得在配置pod的逻辑里可以忽略对实际后台存储技术的配置。
PV和Node是资源的提供者
PVC和Pod是资源的使用者
Node
计算能力由Node提供,是所有pod运行的工作主机。
上面要运行kubelet管理节点上运行的容器
summary
K8s系统最核心的两个设计理念:一个是容错性,一个是易扩展性。容错性实际是保证K8s系统稳定性和安全性的基础,易扩展性是保证K8s对变更友好,可以快速迭代增加新功能的基础。