最近几年,随着Kubernetes在企业级部署场景下愈发流行和成熟,如果你从来没有在自己的项目上尝试过,说实话,都不好意思给别人打招呼。Kubernetes的流行和微服务,容器化技术的发展说不上谁先谁后,历史总是这么巧合。从更高的维度看,这可能也是技术发展的必然,但是不可否认的是,微服务架构被市场广泛接受加速了Kubernetes的发展和成熟。微服务架构下,由于应用程序被设计成由大量独立服务组成的高度分布式应用,因此对基础设施团队,运维团队和开发团队提出了更高的要求。
工程化能力和运维能力强的团队,可能会选择自己编写运维脚本,而大部分业务型企业,把目标转向了Kubernetes。和Linux这样的开源项目比起来,Kubernetes可以说非常年轻(2015年才发布第一个版本),因此围绕Kubernetes还有很多迷雾尚未消散,笔者接触过很多企业,大部分都有明确的技术愿景:容器化部署,但是Kubernetes在企业内部大多都是用来验证,测试,给老板汇报用的,你要是问负责人为啥不用来跑生产的系统,大多数人回答,资源不够,没有人手运维啊,这个真的能用来生产用?
由于笔者在过去几年成功主导过几个巨型数字化项目的开发,部署工作,因此亲眼见证,亲手实践过基于Kubernetes的容器化部署方案,也对很多企业对Kubernetes生产化这个事情持怀疑态度非常理解。Kubernetes非常复杂,的确不是安装到自己的机器上随便点点就能工作。幸运的是,但是得益于谷歌多年来容器化部署的实践经验,Kubernetes已经将这么复杂的系统进行了完美的抽象,因此Kubernetes对开发和运维来说是有章可循的,只要持续的关注和投入资源,基于笔者的经验,企业是能够逐步建立起胜任Kubernetes平台运维团队,让企业可以从云原生架构下的应用充分享用云计算带来的红利,这个红利能够促进业务发展的核心,就是Kubernetes平台。
正是由于以上的原因,笔者在逐步建立Kubernetes知识体系的过程中,发现这个问题很普遍:道理都懂,但是一到具体落地就怂。市面上这样的书籍也不多,为了拉齐理论和现实之间的GAP,就有了这个系列的文章。笔者希望围绕Kubernetes生产之路这个系列的文章,让大家对Kubernetes提供的功能清单有个全面的掌握,特别是从开发和运维的角度,同时笔者也会介绍不同类型企业的Kubernetes生产化路线图,以期通过理论加实践,让读者能够轻松的逾越Kubernetes这套复杂系统给大家带来的困惑和恐惧,从而开始在企业中“真正”的实践基于Kuberntes平台的大规模分布式应用的部署和运维管理。
有了明确的目标之后,第一篇文章我们从Kubernetes的一些基础内容开始,先来了解一下什么是Kubernetes,应用程序部署平台,以及我们为什么要使用Kubernetes来部署应用程序?
【什么是Kubernetes?】
虽然我们经常在不同的场合和上下文中听到Kubernetes这个词,不知道读者是否考虑过Kubernetes具体是什么? 你可能会说,是个平台,基础设施,应用程序,容器编排,应用程序管理等等。坦白讲随着Kubernetes版本的演进,我们已经很难用一个术语来定义这个平台,或许Kubernetes这个词本身就是最好的选择。因此咱就不费那么多精力重新发明Kubernetes的定义了,而把力气留下来详细聊聊Kuberntes具体解决了哪些问题上,这也是为了我们能够顺利的将业务系统切换到Kubeneretes做好铺垫。其实生产化之路这个词描述的是过程,而这条路的目标就是我们的核心业务运行在Kubernetes平台上,并且能够稳定的服务于灵活多变的真实业务流量。
Kubernetes这个单词来自于希腊语,意思是领航,领航员,舵手。而舵手其实就是站在轮船的方向盘(舵)前边的人,这个人的主要职责就是依靠舵来让轮船朝着正确的方向前进。穿上除了舵手,一般还有船长,船长的角色就是基于自己的经验以及获取到的信息,来给舵手下达轮船航行的命令,舵手的核心职责就是执行船长的命令,通过舵来让轮船改变方向和角度,是让轮船按照预期的方向行驶最基本的一套运行机制。而如果读者看Kubernetes的源码的话,会发现Kubernetes这个项目下大概有70+的repositories,因此Kubernetes更像是一把伞,一组软件包的统称。如果你再退后一步,会发现还有一个叫kubernetes-sigs的项目,下边大概有107+的项目,最后你应该听说CNCF(云原生基金会)的大名,下边有除了Kubernetes之外的很多云原生相关的项目,由于这些概念严格来讲会有部分重叠,因此在笔者的生产化之路的系列文章中,我们的讨论范围聚焦在Kuberntes的核心项目上。
你可能会问,核心的具体意思啥?笔者认为的核心是包含在项目Kubernetes/kubernetes代码库下的功能,这也是我们在大部分不同类型Kubernetes集群中都能发现的组件,模块的源代码的位置,具体来说我们讨论的模块,功能清单如下:
- 在多个工作节点上调度任务(Scheduler)
- 暴露给外部的一套声明式,可扩展的API服务,用来提供给用户访问集群功能(API Server)
- 客户端命令行工具CLI,也叫kubectl,封装了便于用户使用的调用API Server服务的命令(kubectl)
- 对象的目标状态和真实状态之间的调谐(Controller)
- 一套服务代理机制来将部署到集群中的服务暴露给外部系统和用户访问(kube-proxy,Service)
- 可扩展的网络,存储机制(CNI,CSI)
如果对上边的这些特性,功能进行稍微的抽象,一个准确描述Kuberntes的此就是:企业级的容器调度和编排平台。这也是Kubernetes最为人所熟知的功能,是Kubertes在markting的时候,用的最多的功能描述术语。笔者用大白话来翻译一下(说人话),Kubernetes为我们提供了一种在多台计算机上运行容器化应用的技术方案,希望大家能记住这句话,因为我们后续的文章都是围绕这句话来展开,来证明Kubernetes是否提供了这样的能力,让我们的应用能够以容器化的方式部署到生产环境的能力。
我们在Kubernetes架构体系介绍的文章中,曾经详细介绍过Kubernetes的架构体系,不过为了内容完整性,咱这个系列还是要简单的提一下组成Kubernetes的各个组件以及在整个架构中扮演的角色。从源代码的角度,我们可以从github上下载指定的发布版本,在本地解压后,我们可以运行cluste目录中的get-kube-binaries.sh脚本,来基于目标机器来检查和下载对应的组件和版本,如下图所示:
如上图所示,Kubernetes包含的核心组件有API Server,kubelet,Controller,Scheduler等,详细介绍如下:
- API Server,API Server是我们和Kubernetes集群进行交互的唯一入口,从原理上讲,无论是通过kubectl客户端命令行工具,还是其他的三方包,本质上都是通过API Server提供的Restful风格的接口来进行对象的增删改查。API Server是无状态的,客户端提交的对象YAML信息会被持久化保存到etcd数据库中。
- Kubelet,部署在工作节点上的插件,主要负责给API Server报告节点的状态信息,以及从API Server上接收任务。收到任务后,Kubelets进一步驱动容器运行时(比如Docker,Podman)将任务运行起来,并确保任务的健康运行(当任务运行出错,Kubelets需要通过容器运行时来重启应用)
- Controller Manager,控制管理器由一组控制器组成,每个控制负责某类对象的期望状态和当前状态的调谐。比如当我们在Deployment中声明replicas等于3,那么控制器(Controller)会负责创建对应数量的容器实例
- Scheduler,调度器组件人如其名啊,主要负责将用户提交的负载(workload,任务)调度到最合适的工作节点,从原理上看,调度分为过滤和打分两个环节,过滤阶段通过一组过滤器筛选出备选的节点,而打分阶段基于规则确定“最合适”的节点
- Kube Proxy,Kube代理实现了服务的虚拟机地址功能,访问流量会被路由到一组POD(应用程序实例)实例上来进行处理,从原理上看,proxy使用基于iptables和ipvs的数据包过滤机制
虽然如上的清单并不是完整,但是这些是组成Kubernetes的最核心的组件,提供了日常使用Kubernetes进行应用部署的所有功能,如下图是整个Kubernetes的体系架构。
注:Kubernetes的具体部署架构有很多不同的变种,比如有些集群将kube-apiserver,kube-scheduler,kube-control-manager运行为容器实例,这也意味着管理节点上也有容器运行时,kubelet和kube-proxy(大家需要注意的这三个组件一般情况下是工作节点上标配,用来处理我们作为用户提交的任务)。
注:Dashboard组件由于不是Kubernetes的核心组件,因此并没有出现在上图中。
好了,作为整个Kubernetes生产化之路的第一篇文章,我们的核心任务就是先给大家一个关于Kubernetes和Kubernetes整体架构的介绍,下篇文章我们会继续围绕Kubernetes提供的功能展开,看看除了调用功能之外,Kubernetes还有哪些属性,敬请期待!