写点什么

《Kubernetes 与云原生应用》系列之云原生应用的设计理念与挑战

  • 2016-09-12
  • 本文字数:4322 字

    阅读完需:约 14 分钟

《Kubernetes 与云原生应用》专栏是 InfoQ 向轻元科技首席架构师王昕约稿的系列文章。本专栏包含 8 篇内容,将会从介绍和分析 Kubernetes 系统以及云原生应用入手,逐步推出基于 Kubernetes 的容器设计模式实践案例,希望对计划应用 Kubernetes 的朋友有所帮助。本文是该专栏的第二篇。

  1. Kubernetes 系统架构与设计理念
  2. 云原生应用的设计理念与挑战
  3. Kubernetes 与云原生应用的容器设计模式
  4. Kubernetes 容器设计模式实践案例 - 单节点多容器模式
  5. Kubernetes 容器设计模式实践案例 - 多节点选举模式
  6. Kubernetes 容器设计模式实践案例 - 工作队列模式
  7. Kubernetes 容器设计模式实践案例 - 分散收集模式
  8. 云原生应用的容器设计模式综述与展望

云原生应用的基本概念

云原生应用,是指原生为在云平台上部署运行而设计开发的应用。公平的说,大多数传统的应用,不做任何改动,都是可以在云平台运行起来的,只要云平台支持这个传统应用所运行的计算机架构和操作系统。只不过这种运行模式,仅仅是把虚拟机当物理机一样使用,不能够真正利用起来云平台的能力。

云原生应用与相关技术理念的关系

云原生应用与云平台的关系

云平台是用来部署、管理和运行 SaaS 云应用的。SaaS 是云计算的三种服务模型之一,即跟业务相关的应用即服务。云计算最根本的特性是提供按需分配资源和弹性计算的能力,而云原生应用的设计理念就是让部署到云平台的应用能够利用到云平台的能力,实现按需使用计算资源和弹性伸缩,成为一个合格的 SaaS 应用。

云原生应用与 12 要素的关系

12 要素是 PaaS 平台 Haroku 团队提出的应用设计理念,是有关 SaaS 应用设计理念的红宝书;可以说,12 要素应用就是云原生应用的同义词。

云原生应用与 Stateless 和 Share Nothing 架构的关系

为了实现水平伸缩的能力,云原生应用应该是 Stateless 和 Share Nothing 的。

云原生应用与微服务架构的关系

微服务架构是实现企业分布式系统的一种架构模式,即将一个复杂的单体应用按照业务的限定上下文,分解成多个独立部署的组件。这些独立部署的组件,就称为微服务。而在谈论云原生应用与微服务架构关系的时候,根据上下文不同可能是有两种不同的含义。一种含义是宏观的云原生应用,即将整个分布式系统看作一个应用,这种语境下,微服务架构是实现云原生应用的一种架构模式;另一种含义是微观的云原生应用,即每个微服务是一个应用,这种语境下,每个微服务要按照云原生应用的设计理念去设计,才能真正实现微服务架构所要达到的目的,即让分布式系统具备按需使用计算资源和弹性伸缩的能力,这里“应用”和“服务”变成了同义词。

云原生应用与宠物和牲畜的关系

云原生应用的设计理念是希望把应用当作牲畜来养,而不是当作宠物来养。部署一个云原生应用的集群,就好像圈养了一大群奶牛,目的主要是为了产奶,对待每头牛就像对待机器一样没有什么感情,死了一头就再养一头,而不会像对待宠物那样细心呵护。而传统应用,因为往往因为对运行环境依赖严重,运维人员需要细心照顾、维护,万一出现宕机,一般要在原来的服务器上修复问题再恢复运行;如果恢复不了,整个应用系统就瘫痪了,因此会令运维人员像“宠物死了”一样伤心。

云原生应用的设计理念——12 要素

一个应用对应一套代码多次部署

这一理念主要是强调应用应该清晰明确地区分什么是应用,什么是部署。一个应用对应的就是一个代码仓库,一个软件产品;一次部署对应的是一个运行起来的应用;因此应用与部署的关系是一对多。这种一对多的关系也体现了应用代码的可重用性,一套代码可以重用到多次的部署中去;不同部署之间的区分是配置,而代码是共享的。对应用架构来说,最基本的是要区分运行时行为和非运行时行为,一个应用的非运行时的代表就是一个代码仓库,它可能有多个运行时实例,每个实例就是一次部署。

明确地声明并隔离依赖的程序库

不管用什么语言开发应用,编程语言一定都有管理程序库的机制。这一理念强调所有依赖库一定要明确的声明出来,因为只有这样,在运行应用的时候,才能保证所有运行所需要的程序库都正确部署到了云环境中。

将配置存储到部署环境中

正像前面所说,一个应用的不同部署之间是共享一套代码的,不同之处是配置。代码是存储到代码仓库中的,那自然配置不应该是存到代码仓库中。每次部署都有自己独立的部署环境,每次部署所对应的配置要存到这次部署所对应的部署环境中去,因此配置的另一个同义词就是环境变量。这里的部署,不包括应用内部的配置,例如 Java 的 Properties 文件或者是 Servlet 的映射配置文件 web.xml 等,这些算作是代码而不是配置。这是一个容易令人混淆的地方,那到底什么算代码,什么算配置?判断的标准很简单,就是变化的频率。变动导致产品版本更新的,就是代码;每次部署都可能变更,而每次变动不导致产品版本更新的,就是配置,就是环境变量。

将后端支撑服务作为挂载资源来使用

这一理念强调应用使用后台支撑服务的方式。不同的服务之间的区别就只是资源的 URL 不同,也就是设定这个资源的相关环境变量不同。不管是本地资源还是远程资源,应用程序都可以正常使用,区别只是环境变量的值不同,而应用本身并不会因为环境变量不同而有所区别。最常用的后台支撑服务就是数据库、缓存、消息队列等服务。这一理念可以保证应用在任何环境都可以正常运行,不会因为后台支撑服务的变化而导致应用无法运行。

严格区分构建阶段和运行阶段

这一理念跟区分应用和部署类似,本质上也是要严格区分应用的非运行时行为和运行时行为。构建是将应用的代码仓库编译打包成可运行的软件的过程,是非运行时行为。因此说,这一理念另一方面也说明要防止在运行阶段改代码的行为,这样才能够保证运行中应用的稳定性。

将应用作为无状态的进程来运行

这一理念要求所有的用户数据都要通过后端支撑服务来存储,而应用本身是无状态的,因为只有这样,应用才能做到水平伸缩,从而利用云平台弹性伸缩的能力。

仅需要绑定一个端口就可以对外发布一个服务

这一理念强调应用本身对于发布服务的环境不应该有过多的要求,而应该是完全自包含的,也就是说不需要依赖云平台提供应用运行容器,而只需要云平台分配某个端口对外发布服务。这一理念保证应用可以使用云平台中任意分配的端口发布服务。

可以像 UNIX 进程一样水平扩展

在 UNIX 操作系统上,不同的进程彼此独立地运行着,共享这整个操作系统管理的计算机资源。云原生应用在云平台上的运行模式也是类似的,云平台就是分布式操作系统,不同的云原生应用彼此独立互补干扰的运行在一个云平台上,可以充分利用云平台的整体计算能力。

可以快速启动和优雅地关闭

快速启动是为了能充分利用云平台根据需要调度资源的能力,能够在需要的时候,以最小的延时扩展计算能力提供服务。优雅地关闭,一方面是为了释放资源,将不再使用的计算资源归还云平台;另一方面也是为了保证应用逻辑的完整性,将该完成的任务正确完成,未能完成的任务重新交回到系统由其它应用的运行实例来继续完成。要假设云原生应用的目标工作环境中随时有大量同样的应用实例在运行、启动和关闭,因此快速启动和优雅关闭对高性能和稳定的系统非常重要。

保持开发环境、预发布环境和生产环境尽量一致

保持环境一致,是为了提高开发单元测试、功能测试和集成测试的有效性,避免出现开发测试中正常而在生产环境中出现问题的情况。

将日志作为事件流来处理

云原生应用运行在复杂的分布式基础设施之上,如果日志不通过简单统一的模式来管理,将给系统排错或通过日志挖掘信息带来很大困难。同时,如果应用将日志输出到系统的文件中,也会给系统的存储空间造成压力,增加系统运维的复杂性。因此这一理念推荐应用将日志输出到标准输出,然后由云平台统一收集处理。

将应用管理任务当作一次性进程来运行

将应用的管理任务与应用的业务请求以相似的方式运行,以同样的方式进行调度、日志和监控,将有利于系统的稳定性和分析系统的整体行为。

云原生应用的挑战

处理分布式系统的网络通信问题

云原生应用必须要针对分布式系统中网络通信的复杂性进行设计。对于分布式系统,如果还像单一进程应用那样考虑问题,就会进入所谓的“分布式系统的认识误区”,包括武断地认为:网络是可靠的;网络的延时为零;网络带宽是无限大的;网络是安全的;网络拓扑是不变的;系统中只有一个管理员和网络环境都是统一一致的。也许现在很少会有人幼稚到真的认为分布式环境中的交互处理和运行在单一进程中的函数调用是一样的;但开发的复杂度、功能上线的压力,经常会使开发人员把这些复杂问题暂时放在一边,不断积累起越来越多的“技术负债”。

处理分布式系统的状态一致性问题

分布式系统的 CAP 理论认为,在分布式系统中,系统的一致性、可用性和分区容忍性,三者不可能同时兼顾。当然,实际在分布式系统中,由于网络通信固有的不稳定,分区容忍性是必须要存在的,因此在设计应用的时候,就要在一致性和可用性之间权衡选择。

最终一致性

很多情况下,在一致性和可用性之间,云原生应用比传统应用更加偏向可用性,而采用最终一致性代替传统用事务交易保证的 ACID 一致性。传统的 ACID 一致性编程模型与业务无关,开发人员对它经验丰富,而最终一致性的交互模式与业务相关,必须通过业务的合理性来校验阶段不一致的合理性,这使得最终一致性比 ACID 一致性复杂得多。

服务发现和负载均衡

云原生应用的运行实例随时可能关闭和启动,因此需要机制使得访问应用服务的客户端随时都能找到健康运行的实例,放弃对宕机实例的访问,这就是服务发现的问题。与服务发现同时存在的,是在多个健康实例中选择一个实例真正为某个客户请求提供服务的过程,这就是负载均衡。

任务分解和数据分片

大的任务要分解成很多小任务,分配到各个运行实例上去执行,然后再将执行结果汇总,这就是任务分解。数据分布到各个实例上做处理和存储,这个就是数据分片。这些都需要适应云计算环境的机制去支持。

主控角色选举

不管是任务分解还是数据分片,每个应用实例上负责的子任务和数据分片虽然是不同的,但如何分解、谁负责谁这种分配映射表一定是完全相同的;因此在这种情况下,需要负责计算分配映射表的主控角色;而因为云计算环境下没有实例是永远保证健康运行的,主控角色不可能是永远固定的;这就需要主控角色选举的机制,能够在主控角色空白或出现故障宕机的情况下,自选举出新的主控角色。

像设计模式解决面向对象设计中的复杂问题一样,面对云原生应用的复杂应用场景,我们也需要一些典型的设计模式能够可重用地解决一些特定场景的问题。这些我们将在本系列文章的后面结合应用案例予以介绍。


感谢魏星对本文的策划和审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

2016-09-12 17:203531

评论 1 条评论

发布
用户头像
Mark
2019-12-04 21:21
回复
没有更多了
发现更多内容

直播带货系统源码(开源系统版)——如何搭建测试呢?

开源直播系统源码

软件开发 直播源码 语音直播源码 连麦直播

助力人工智能迈向新阶段,YLearn因果学习开源项目重磅发布!

九章云极DataCanvas

人工智能 开源项目 因果学习 YLearn

这一次带你透彻解析RocketMQ消息中间件

Java永远的神

Java 程序员 面试 RocketMQ 消息中间件

uWebSockets.js 遇见 Http3

devpoint

JavaScript websocket HTTP3.0 7月月更

Android 自动化测试

沃德

android 程序员 7月月更

Python爬虫挺刑的,去VX公众某位置,平台登录加密参数扣取

梦想橡皮擦

Python 爬虫 python 爬虫 7月月更

博云入选Gartner中国云管理工具市场指南代表厂商

BoCloud博云

云原生 Gartner 云管理平台 云管理

LeetCode-112. 路径总和(java)

bug菌

Leet Code 7月月更

java零基础入门-String

喵手

Java 7月月更

简述Serverless原理及运用

南城FE

Serverless 前端 7月月更

首届京东科技合作伙伴大会召开,博云携手京东科技共创产业数字化新增长

BoCloud博云

容器 云原生 PaaS

YLearn因果学习开源项目「贡献者计划」精彩来袭!

九章云极DataCanvas

AI 开发者 因果学习 YLearn

电商订单支付时防止重复支付的原理

程序员小毕

Java 程序员 面试 程序人生 后端

2022最新面试八股文,共计12w字,200多页,16个Java技术栈

Java全栈架构师

Java spring 程序员 面试 程序人生

XGRIDS三维重建服务,构建云上数字孪生世界

阿里云弹性计算

容器 3D渲染 弹性计算 GPU算力

两数之和 II - 输入有序数组

面试官问

LeetCode 两数之和

团队管理之git提交规范:commit记录那点事儿

南极一块修炼千年的大冰块

7月月更

用什么承受全部的数据-RDD、DataFrame还是Dataset

怀瑾握瑜的嘉与嘉

spark 7月月更

【古月21讲】ROS入门系列(1)——ROS命令工具的使用及创建工作空间和功能包

秃头小苏

ROS 7月月更

面试官:小伙子你来说下缓存穿透、缓存雪崩、缓存击穿

Java永远的神

Java redis 程序员 面试 程序人生

数据治理实战篇!选择什么样的工具让数据治理落地更简单

雨果

数据治理

Wallys/WiFi6 MiniPCIe Module 2T2R 2×2.4GHz 2x5GHz MT7915 MT7975

wallys-wifi6

IPQ4019 IPQ6010 ipq6018 QCN9074 MT7975

【愚公系列】2022年7月 Go教学课程 011-字符串类型

愚公搬代码

7月月更

【C语言】进阶指针seven

謓泽

7月月更

从预测到决策,九章云极DataCanvas推出YLearn因果学习开源项目

九章云极DataCanvas

人工智能 YLearn 开源工具包 因果推断

好家伙!阿里人用5个案例就彻底讲清了SpringSecurity安全框架

程序员小毕

Java spring 程序员 面试 springsecurity

你玩过轻量系统软总线应用吗?

OpenHarmony开发者

OpenHarmony

不知道这4种缓存模式,你可能并不是真的懂缓存

Java永远的神

Java 缓存 程序员 面试 后端

mysql进阶(二)你真的了解索引吗?

No Silver Bullet

索引 MySQL 数据库 7月月更

语音驱动嘴型与面部动画生成的现状和趋势

行者AI

算法 人工智能’

什么是微软 Edge 浏览器 Tracking Prevention 的 Org Relationship Mitigation 策略

汪子熙

JavaScript html 前端开发 web开发 7月月更

《Kubernetes与云原生应用》系列之云原生应用的设计理念与挑战_语言 & 开发_王昕_InfoQ精选文章