云原生的关键元素

发表时间: 2022-03-09 21:43

云的发展

之前的文章提到了云与基础设施的演进过程,也说了云原生带给团队和公司的益处;软件基础设施也随着软件开发方式和架构模式的改变而改变。他们说不清楚是谁促进了谁,而且这并不重要。云的发展从刚开始提出的以虚拟化为基础实现的云到现在常见的以容器为基础的云再到马上要来的无服务器化(serverless),不难看出基础设施也是一直不断发展的,我们不能无视时代的发展而闭门造车。所以我们需要了解现在的环境,反思自身的问题,有需要则要想法子用上,让自己搭上更快的车不是很好吗?

云原生的核心概念

顾名思义,云原生由两部分组成“云”和“原生”,“云”指的是把软件迁移到云上,“原生”指的是软件像“原生”运行在云端一样。这句话分为两部分:
“云”指的是基础设施换成云环境,具体就是从裸金属服务器或者虚拟化主机换成基于容器的云端平台。这个很好理解,不做过多解释,就是以前的软件运行在裸金属服务器上或者虚拟机上,现在都运行在通过编排管理的容器上。
“原生”比较难理解,我们的应用迁移到云原生平台后是要改造的,不能(不合适,其实是可以直接迁移上去的)直接把原来的庞大的大单体应用一股脑放到一个容器中运行。而是需要对已有的软件做一定的改造再放到云原生平台,当然改造需要成本,但肯定会有收益促进我们这么改造。

主要组成部分

这个章节主要介绍一下云原生的发展过程和重要组成部分,这个章节稍微涉及一些技术方向的东西,看不明白也没关系,知道个大概就行了。现在的云原生是一套基于容器的综合基础设施和开发模式的系统。它不再是单纯的提供一套基础设施,而是深入到软件的开发和设计的全流程的一套方案。除了软件本身需要改造以适应云原生环境,甚至你的团队也需要改变工作方式以适应云原生环境。它从基于运维团队的容器平台,发展到现在的复杂系统是经过了一个长期的过程的,所以我们从容器开始介绍云原生的重要组成部分:容器和基于容器的服务编排。

容器

容器是云原生基础设施的基础,说起容器不得不说Docker。一开始Docker是作为开发人员和运维人员在开发软件的过程中用来实现部署测试环境和其他开发工作环境(devops)使用的玩具,现在已经成熟到足够在生产环境中了。要说起Docker就不得不说起跟他对比的虚拟化技术,因为整个云端环境就是由虚拟化发展到容器化的,而且虚拟化也接近妇孺皆知了,所以从虚拟化开始讲容器比较容易,我尽量不提容器是基于多用户操作系统Linux,也不提Linux的NameSpace、CGroup、AUFS和Device Mapper等基础技术,有技术实力的你尽量去看看其他文章介绍这些技术的细节,不想了解也没关系,你只需知道容器是一个在Linux操作系统上运行的一个隔离技术就行了。以下通过图示展示容器和虚拟机的不同之处。


从上面的比较我们可以看出,VM 多了两层:GuestOS 和 Hypervisor,它们会占用更多的资源来部署服务。容器中的所有服务都是运行在宿主操作系统上,它没有自己的操作系统隔离,容器里的服务是直接运行在宿主操作系统上,它用一种更轻量级的方式来运行服务进程。简单说来相对虚拟机,容器有以下几个好处:

更高效地利用系统资源

容器不需要进行硬件虚拟以及运行完整操作系统等额外开销,Docker 对系统资源的利用率更高。无论是应用执行速度、内存损耗或者文件存储速度,都要比传统虚拟机技术更高效。因此,相比虚拟机技术,一个相同配置的物理主机,能运行的容器远大于虚拟机的数量。

更快速的启动时间

传统的虚拟机技术启动应用服务拉起时间往往需要数分钟,而 Docker 容器应用,由于直接运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间。

一致的运行环境

开发过程中一个常见的问题是环境一致性问题。由于开发环境、测试环境、生产环境不一致,导致有些 bug 并未在开发过程中被发现。而 Docker 的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现程序员对测试人员说“在我这里运行的好好的呀?” 这类问题。

持续交付和部署

对开发和运维(DevOps)人员来说,最希望的就是一次创建或配置,可以在任意地方正常运行。使用 Docker 可以通过定制应用镜像来实现持续集成、持续交付、部署。开发人员可以通过 Dockerfile 来进行镜像构建,并结合 持续集成(Continuous Integration) 系统进行集成测试,而运维人员则可以直接在生产环境中快速部署该镜像,甚至结合 持续部署(Continuous Delivery/Deployment) 系统进行自动部署。而且使用 Dockerfile 使镜像构建透明化,不仅仅开发团队可以理解应用运行环境,也方便运维团队理解应用运行所需条件,帮助更好的生产环境中部署该镜像。

更轻松的迁移

由于 Docker 确保了执行环境的一致性,使得应用的迁移更加容易。Docker 可以在很多平台上运行,无论是物理机、虚拟机、公有云、私有云,甚至是笔记本,其运行结果是一致的。因此用户可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。

更轻松的维护和扩展

Docker 使用的分层存储以及镜像的技术,使得应用重复部分的复用更为容易,也使得应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得非常简单。此外,Docker 团队同各个开源项目团队一起维护了一大批高质量的 官方镜像,既可以直接在生产环境使用,又可以作为基础进一步定制,大大降低了应用服务的镜像制作成本。

容器技术对比传统虚拟机总结

特性

容器

虚拟机

启动

秒级(甚至毫秒级)

分钟级

硬盘

单位是MB

单位是GB

性能

接近原生

弱于原生

系统

支持单机运行上千个容器

几十个

做了那么多对比,你只需要知道它和虚拟机不一样,没有宿主操作系统就比拥有操作系统动辄好几G几十G的虚拟机更小,更小就能更快的拉起,几十毫秒拉起一个服务比几分钟启动一个虚拟机那是本质的不同。有了快速拉起的容器就可以在容器的基础上实现容器的编排,对容器本身和它其中运行的服务管理起来,那就是服务编排了。

Kubernetes

Kubernetes 是在 Google 平台上开发的开源容器管理软件。它可以帮助您在各种类型的物理、虚拟和云环境中管理容器化应用程序。
它是一种高度灵活的容器工具,甚至可以交付复杂的应用程序。应用程序“在由成百上千台单独服务器组成的集群上运行。”它还允许您更有效地管理容器化应用程序。
作为最著名的服务编排工具,Kubernetes主要的作用当然就是服务编排了。它主要功能是:
服务发现和负载均衡
Kubernetes 可以使用 DNS 名称或自己的 IP 地址公开容器,如果进入容器的流量很大, Kubernetes 可以负载均衡并分配网络流量,从而使部署更稳定。
存储编排
Kubernetes 允许你自动挂载你选择的存储系统,例如本地存储、公共云提供商等。
自动部署和回滚
你可以使用 Kubernetes 描述已部署容器的所需状态,它可以以受控的速率将实际状态 更改为期望状态。例如,你可以自动化 Kubernetes 来为你的部署创建新容器, 删除现有容器并将它们的所有资源用于新容器。
自动完成装箱计算
Kubernetes 允许你指定每个容器所需 CPU 和内存(RAM)。 当容器指定了资源请求时,Kubernetes 可以做出更好的决策来管理容器的资源。
自我修复
Kubernetes 重新启动失败的容器、替换容器、杀死不响应用户定义的 运行状况检查的容器,并且在准备好服务之前不将其通告给客户端。
密钥与配置管理
Kubernetes 允许你存储和管理敏感信息,例如密码、OAuth 令牌和 ssh 密钥。 你可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥。

Kubernetes的结构说明


从上图可以看出来,整体的Kubernetes分为两大部分:主控节点和工作节点。其中主控节点和工作节点都是多个,我为了方便说明结构只画了一个主控节点和2个工作节点。

主控节点

Kubernetes里的主控节点指的是集群控制节点,每个Kubernetes集群里需要有一个主控节点来负责整个集群的管理和控制,基本上Kubernetes所有的控制命令都是发给它,它来负责具体的执行过程,我们后面所有执行的命令基本都是在Master节点上运行的。Master节点通常会占据一个独立的X86服务器(或者一个虚拟机),一个主要的原因是它太重要了,它是整个集群的“首脑”,如果它宕机或者不可用,那么我们所有的控制命令都将失效。以下简单介绍一下主控节点的几个重要组成部分:
主控节点中有好多个组件来编排管理容器:Etcd 用于存储集群中所有资源对象的数据;API Server用于组件之间的通信,Scheduler决定 pod 应该在哪些节点上运行,它就像公交公司的“调度室”;而Controller Manager则是所有资源对象的自动化控制中心,它是资源对象的“大总管”

工作节点

工作节点构成了 Kubernetes 集群的集体计算能力。这是容器实际部署运行的地方。节点是你的应用程序运行的物理基础设施。当它宕机或者因其他原因不可用的时候,主控节点会把它上面运行的工作负载自动迁移到别的工作节点上去。每个工作节点除了运行工作负载也同时运行着以下两个重要的组成部分:
kubelet:负责Pod对应的容器的创建、启停等任务,同时与Master节点密切协作,实现集群管理的基本功能。
kube-proxy:实现Kubernetes Service的通信与负载均衡机制的重要组件。 kube-proxy 维护节点上的网络规则。这些网络规则允许从集群内部或外部的网络会话与 Pod 进行网络通信。如果操作系统提供了数据包过滤层并可用的话,kube-proxy 会通过它来实现网络规则。否则, kube-proxy 仅转发流量本身。
当然同时工作节点中还运行着Pod,Pod是Kubernetes集群中最低级别的资源。一个Pod由一个或多个容器组成,但最常见的只是一个容器。在定义集群时,会为Pod设置限制,这些限制定义了它们需要运行的资源、CPU和内存,Scheduler通过这个定义来决定把Pod放到哪个工作节点上。

总结

你看以上的容器和基于容器的服务编排系统,就几乎解决了云原生中的绝大多数问题,你有了一个整体的服务运行平台,你能在上面运行你的服务,它会自动保证你的服务正确的运行,出错了它会想办法再让它运行起来,你可以通过资源定义保证你某个服务的算力要求等。你还能通过它管理除:CPU、内存、存储以外的资源,例如:配置和网络等。

云原生的其他组成部分

云原生除了提供服务运行的基础环境以外,同时云原生也是一个团队和基础设施共同协作的平台,你不能仅仅使用整个平台上的基础设施,而团队的工作方式还是老样子。整个其他组成部分就是除基础设施以外的其他部件。

微服务

前面两章说了一大堆微服务改造的必要性,这一章我就不详细说了,请自己参考前两章内容。

持续交付

为了满足业务需求频繁变动和快速迭代,软件产品要拥有能随时能发布的能力,这也是持续支付的开发实践方法。它可分为持续集成、持续部署、持续发布等阶段,用来保证从需求提出到设计开发和测试,再到代码快速、安全部署到产品环境中。持续集成是指每当开发人员提交一次变动,就立刻进行构建、自动化测试,确保业务应用和服务能符合预期,从而可以确定新代码和原有代码能否正确地集成在一起。持续交付是软件发布能力,是在持续集成完成之后,达到能够将系统发布到生产环境的条件。持续部署是指使用完全的自动化过程来把每个变更自动提交到测试环境,然后将应用安全部署到产品环境,打通开发、测试、生产的各个环节,自动持续、增量地交付产品,也是大量产品追求的最终目的。当然,在实际运行过程中,有些产品会增加灰度发布等环境。总之,它更多是代表一种软件交付的能力。

DevOps组件

DevOps如果从字面上来理解只是Dev(开发人员)+Ops(运维人员),实际上它是一组过程、方法与系统的统称,其概念从2009年首次提出发展到现在,内容非常丰富,有理论也有实践,包括组织文化、自动化、精益、反馈和分享等不同方面:①组织架构、企业文化与理念等,需要自上而下设计,用于促进开发部门、运维部门和质量保障部门之间的沟通、协作与整合,简单而言组织形式类似于系统分层设计;②自动是指所有的操作都不需要人工参与,全部依赖系统自动完成,比如上述的持续交付过程必须自动化才有可能完成快速迭代;③DevOps的起因是IT行业渐渐意识到,如果要准时交付软件产品或者服务,开发部、运维部必须紧密合作。总之,DevOps提倡的是高效组织团队之间的合作,通过自动化软件协作,完成软件的生命周期管理,目的是迅速频繁地交付应用软件。

监控和运维

这一部分内容会在后面详细说,你只需要知道除了以上的必要部件,监控和运维系统也是必须的,而且云原生的监控和运维还和传统的不太一样。它在内容上除了要对平台层运维和监控以外,也需要对运行在其上的服务进行运维和监控。