118-深入浅出云计算

开篇词 | 云计算，这是开发者最好的时代

你好，我是何恺铎，一个云计算的爱好者、践行者、布道者。欢迎你加入这个专栏，和我一起探索云计算的宏大与美妙。

先简单介绍一下我自己。在职业生涯的早期，我曾在摩根士丹利的应用程序基础架构部门工作，在那里从事高性能数据处理组件和类库的研发。

我们部门所构造的框架和“轮子”呢，会作为可复用的组件，用来构建摩根最为关键的各类金融市场实时交易程序。从这个角度看来，我当时的工作内容，与如今云计算的一些中间件服务颇为类似。

大约十年前，我加入了国双科技，历任技术经理、技术总监、技术总经理，工作内容上我从“造轮子”转而开始做应用，尤其是构建面向互联网的各类大数据应用，比如用户行为分析、舆情社交聆听产品等。在漫长的研发岁月中，我和你一样，看遍了编程语言、框架类库的兴衰更迭，在基础设施层面，也经历了从物理机到虚拟化，再到云计算的梦幻旅程。

正是在这一个时期，我开始接触到云计算，并在工作中不断地加以实践和应用。从陌生到熟悉，从喜欢到痴迷，云的强大和高效使我成为了不折不扣的云计算狂热者。在业余时间，我也会在电脑前一遍遍地反复研究各个公有云的新发布特性，并思考它能否为我所用，为正在构建的应用发挥价值。

我也曾发表过一些和云计算相关的文章，比如去年在 InfoQ 发表的万字长文《激荡十年：云计算的过去、现在和未来》曾入选虎嗅当月的全行业精选，也获得了业内媒体的广泛转载。我还有一个公众号“云间拾遗”，点滴记录着我在云计算之旅中的实操和感悟。

现在，终于有一个专栏课程的机会，能让我系统地把自己对于云计算的认知进行梳理，并以面向开发者的方式呈现。我很珍惜这个宝贵的机会，我会尽可能地分享与云有关的知识体系、最佳实践，甚至自己的经验教训。

所以，这会是一个注重实用的云计算专栏，它为我们开发者而生。希望你一起“上车”，共同开启云计算之旅。

开发者为什么要学习云计算？

云计算，不仅是一个妇孺皆知的技术热词，也早已成长为一个巨大的行业。根据 Gartner 的报告，全球公共云服务市场在 2019 年已经突破两千亿美元。毫无疑问，历经多年的发展和成熟，云计算已经成为一种潮流，也是现代企业数字化转型中的重要组成部分。

产业的发展必然影响个体。那么，问题来了，这一趋势对于我们开发者而言意味着什么？

这意味着，未来我们的代码，和我们构建的应用，将越来越多地运行在云上；它还意味着，我们的架构模式和思维方式，将更多地与云契合共生。因此，我们必须学习了解云，以适应在云上构建应用的新时代。

另一个你应当学习云计算的原因，在于效率。现代社会的节奏飞快，业务需求多如牛毛，而且瞬息万变。更快更稳定地构建和交付，成为开发者的核心竞争力。云就能够帮助你做到这一点，触手可及的庞大资源规模、高度自动化的各类服务、可重用的基础组件，都会是你提高效率的好帮手。

另外，在日常工作和社区交流中，我发现许多开发者对于语言、框架和类库都比较重视和了解，毕竟这是每天接触的工具。但大家往往对于云的特性却还不够熟悉，导致在资源配置、技术选型和架构设计等环节没有选择最佳的方案，造成稳定性或是成本上的损失。如果对云计算有足够的理解，这些损失是完全可以避免的。

还有一部分开发者，在过去尝试过云计算的产品或服务，但由于早期云产品不成熟或者使用方式的问题，无意识地形成了一些误解甚至偏见，比如出于思维惯性，会觉得云虚拟机的硬盘性能低下，但事实并非如此。要知道，云计算的发展并非一蹴而就，而是历经多年逐步发展成熟的。所以，在 2020 年，你也可能需要来刷新一下认知，了解云的最新能力与动态。

以上种种，共同构成了开发者应当认真对待和系统学习云计算的原因。这是云计算最好的时代。而在云的赋能下，这也应该是开发者最好的时代，是新时期优秀开发者的制胜之道。

开发者应该如何学习云计算？

那么，面对云计算这样一个宏大的课题，我们应该怎样入手学习呢？

市面上存在的云计算类书籍与课程，大致可分为这样几种：

一类是面向大众的科普书籍，侧重于云的历史发展和社会价值，技术上讲得不深；

一类是侧重于讲解虚拟化技术等云计算的内部实现，适合底层研发工程师而非应用开发者阅读；

还有一类常见的形式，则是云厂商自行制作的培训材料，其中不乏精品，但和某一个云绑定比较深，也总难免带上一些产品宣传痕迹。

我一直在想，能不能有更加适合开发者的云计算课程呢？毕竟，开发者才是云计算的最终用户啊。

所以，我希望这个专栏有所不同，有它的鲜明特点：

一方面，专栏会立足于开发者和架构师的视角来介绍云计算技术，尽可能多地结合应用场景来解析云的概念和能力，帮助你学习“用云”而非“做云”；

另一方面，专栏也会尽量不倾向于任何一个云，不进行“厂商绑定”，而是同时观察运用多个主流云厂商的服务，帮助你了解云的共性，也体会不同云的各自特点。

所以在我们的后续内容中，我们将同时以阿里云、AWS 和微软 Azure 为主要研究对象（因为这三家正是全球云计算三甲），再结合穿插腾讯云、华为云等优秀云服务作为案例进行讲解。如果你之前只是熟悉一个云，希望这样的方式也能够破除单个云的信息茧房，让你拥有更广阔的视野。

需要说明，这个专栏将以讲解公有云为主，私有云暂不涉及。不过不用担心，公有云和私有云的许多理念和实现都非常类似，颇有相通之处。所以这个课程对于你了解学习私有云也能有不小的帮助。

在每篇课程有限的篇幅中，我还会非常注意加入一些实操的内容，而非仅仅作概念解释和纸上谈兵。因为接地气的动手实验能帮助形成更直观的认识，和理性的解读一起参照，可以强化和加深对知识的理解。

另外，云和传统 IT 架构方面的一个显著差别在于成本：云的成本是非常动态的，会更多地由应用架构和技术选型所决定。换一句话说，云让我们开发者离钱更近了。因此我认为成本是云端的一个重要话题，所以成本意识和成本控制技巧也将贯穿这个课程的始终。毕竟，能为公司和项目省下真金白银，和赚取利润同样关键。

以上几点，是我觉得开发者在学习云计算时应有的要点，也正是我们这个专栏的定位和撰写思路了。

课程设置

我们知道，现代云计算是由大大小小、形态各异的云服务所组成。业界通行的做法，是将它们大致划分为 IaaS 和 PaaS 两个领域。

IaaS（Infrastructure as a Service），即“基础设施即服务”，一般指云计算所提供的计算、存储、网络等基本底层能力；

PaaS（Platform as a Service），即“平台即服务”，通常指基于云底层能力而构建的面向领域或场景的高层服务，如数据库、应用服务等。

广义上的云计算，还可包括 SaaS（Software as a Service，软件即服务）的内容，一般指基于云构建可开箱即用的各种业务应用。这是另一个宏大的领域，我们这个开发者课程就不予以关注和讨论了。

所以在专栏内容上面，我们的课程也会遵循这样的方式来划分，分为 IaaS 篇和 PaaS 篇，各自为你精心挑选了领域内最重要的若干话题。

IaaS 篇，我会从云上的数据中心入手，然后分别讲解在云上如何让计算、存储、网络等基础能力为你所用。小到一台虚拟机的选择，大到云上架构的最佳实践，和整个数据中心的规划，都会有相关的讲解。最后，我们还会探讨云端运维有哪些重要的工作不可忽略。

PaaS 篇，我们首先会探讨 PaaS 的本质，同时教你掌握 PaaS 最重要的几个观察视角，然后分别按篇章介绍那些最炙手可热的 PaaS 服务，像是云存储、云数据库、云容器服务、无服务器架构、云 AI 平台等等，这些你耳熟能详的云服务都会一一专门讨论，尤其会着重剖析它们与自建服务相比有何优势，以及适合的应用场景。

这个专栏并不会对你的先验知识有很高的要求，只要你有一定的计算机基础和研发经验，对体系结构、操作系统、数据库、编程语言等常见内容有一定了解就可以了。云计算本就是各领域技术的抽象和组合，所以全面系统地学习云计算对提升你的专业综合素养也是大有裨益的。

当然，作为一个力求“深入浅出”的课程，在覆盖了广度的前提下，篇幅所限，我无法去深度讲解每一个相关领域的基础知识。比如说，云数据库会是专栏的重要章节，但显然我不会去教授 MySQL 或者 PostgreSQL，你需要订阅其他专栏来学习这些数据库本身。不过，我会力求讲清每一个领域在云端的差异化特点和最佳实践。

写在最后

以上就是我对于自己以及这个专栏的介绍了。云计算其实并不困难，也没有那么神秘。只要你跟随专栏认真学习，我相信一定会有所收获。你会对于云计算的产品和能力形成一个清晰的宏观认知；也会了解到一些重要细节和实践经验；最后也是最重要的，回到你自己的生产场景，你将能够判断和决定如何正确运用云的力量。

所以，请坐稳扶好，我们马上就要启航了，方向：广阔云端。

在每篇课程的末尾，我都会给你留下思考题，或是动手操作的实验，欢迎你来参与和交流。这个开篇词也不例外：

如果你尚未拥有一个云账号的话，为便于后续的实验，请自己动手申请一个。现在的注册流程都很方便了，付款也都相当容易。不妨真的自己充值体验，这样你才会对成本和消耗有切身的感受。

各家云厂商经常会进行一些促销活动，尤其非常重视拉新。你所选择的云平台，现在有什么针对新用户的活动吗？哪个是你觉得最诱人的？

欢迎你在留言区和我互动，我会第一时间给你反馈。如果觉得有收获，也欢迎你把这篇文章分享给你的朋友。我是何恺铎，感谢你的阅读，我们第一讲再见。

01 | 区域和可用区：欢迎来到云端数据中心

你好，我是何恺铎，欢迎来到《深入浅出云计算》专栏。这是课程的第一讲，我们就从 IaaS 来入手，开始对云计算的讨论。

IaaS 的本质，是对云数据中心和各类 IT 基础设施的抽象，是基于软件技术对物理硬件进行的封装和虚拟。这为云计算用户屏蔽了大量底层细节，能让我们在较高的层面进行架构设计和资源使用，大大提高了工作效率。

说起我们大多数开发者最常用的 IaaS 服务，恐怕要数云上虚拟机了。没错，虚拟机肯定会是我们 IaaS 部分的讲解重点。不过在此之前，我想让你对整个云端数据中心，先建立起一个高屋建瓴的认识，帮助你理解宏观层面的重要概念。这会对我们后续的学习大有裨益。

所以第一讲，我们就先来谈谈云计算中的区域和可用区。

指点江山，云计算中的“区域”

云计算中最顶层的概念，就是区域（Region）了。在大家的日常认知中，它当然是一个地理概念。而在云计算行业中，区域对应的则是云计算厂商在某个地理位置提供的所有云服务的组合，是厂商对外提供云服务的基本单位和容器。

所以绝大多数的云服务，都会按区域进行部署和落地；用户使用的所有云资源，也都会隶属于一个区域，这通常是在创建资源时就确定了的。

常见的区域，我们一般以国家或地区命名，也经常辅以城市和序号予以区分。比如，阿里云的华北 1 区（青岛）、华北 2 区（北京），以及 AWS 的美国西部 1 区（加利福尼亚北部）、美国西部 2 区（俄勒冈州）等。

与此同时，每个区域还会有个字母数字构成的区域代号（Region ID 或 Region Code）。比方说，阿里云华北 1 区代号为 cn-qingdao，AWS 美国西部 1 区的代号为 us-west-1 等。这些代号方便我们在程序或脚本中对区域进行唯一指定，有时也会出现在门户控制台 URL 中。

阿里云的全球区域

当然，想要开设一个新区域，绝非一件容易的事情。它有点像网络游戏中的“开服”，包含了云计算服务商在某个地区建立数据中心，安置大量的计算、存储、网络等硬件资源，以及部署虚拟化、服务组件、资源调度等各种复杂软件，最后与外界互联网相连，获得批准对外提供云服务的全过程。

所以区域的设立和分布，相当程度地体现了云厂商的业务重点和地区倾向。小型云厂商一般会着重在个别国家或地区深耕；而大型云厂商实力雄厚，会在全球范围内拥有众多开放区域，以便用户能够在全球范围内管理和部署自己的应用。

考虑到经济效益和地理冗余，在典型情况下，云厂商设置的不同区域之间的距离，一般为数百公里或以上，这也对应了单个区域能够辐射和服务的范围。

云厂商在选址时一般会有两种思路：

一种是考虑放在人口稠密的中心城市，离用户和商业更近，以提供较快的接入体验；

另一种则是在相对偏远的地区，当地往往能够提供良好的气候条件、充足的建设空间，以及较低的电力、带宽等运营维护成本。

AWS 在中国开设的两个区域，就是典型的例子：由光环新网运营的北京区域，位处繁华都市；由宁夏西云运营的宁夏区域则地广人稀。有时这样的搭配被称为“前店后厂”模式。

如何选择云上“区域”？

区域是如此的重要，所以不仅是云厂商，我们的应用和架构，同样需要先挑选最合适的落脚点。那么，当我们作为用户时，应该如何选择合适的区域呢？

首要的考量因素，当然在于区域的地理位置本身。这很好理解，我们需要让它尽可能地靠近我们应用所面向的最终用户，来保证更快的接入速度。

比如，当我们主要面向中国大陆用户服务，那自然不需要考虑其他国家的区域。

而如果我们的应用是具有鲜明地域性特征的服务，像是搭建一个面向华东地区的本地生活服务，那就应该更细致地就近选择区域了，比如说，我可以选择阿里云的“华东 1（杭州）”或者“华东 2（上海）”等区域。

另外，如果你的场景中需要本地数据中心与云端进行互联，也就是混合云架构，那么同样也需要事先注意云区域的地理位置选择。混合云的专线接入，一般以同城或短距离接入为主，这样你也能够较好地控制费用，同时提高线路的稳定性。

第二个考量因素，非常重要而又容易被忽视，那就是区域之间云服务的差别。

前面我们提到，区域是云计算物理上存在的一个基本单位，所以从 IaaS 到 PaaS 各项云服务的落地，也是按照区域进行的。换句话说，同一个云在不同的区域，所能提供的服务和规模可能是不同的。

小提示：

厂商通常会大力宣传新机型或新服务的推出，但关于这个新服务在哪些区域可用的信息时常会淡化处理，放在不那么显眼的位置。我们需要特别注意这些信息。

因此，你就非常有必要在选择区域之前，先摸清楚相关区域的具体某项服务的可用性。

比如，生产环境需要一些 GPU 机型来运行深度学习工作，那你就一定要通过官方网站查询，最好是进行实操验证，来确认理想的 GPU 机型真的存在于你所准备选择的区域；或者，你看到云厂商发布了全新数据库服务，那么在技术选型时也千万不要忘记，验证一下该服务在你选择的区域是确实可用的。

另外，区域的“开服时间”，也往往会与区域内云服务的可用性有比较大的关联。

一般来说，新开服的区域通常会落地最新一代的硬件和云端服务，也有非常充沛的资源可供调用，但它未必能迅速覆盖该云的所有服务，相关支持团队可能也需要进行磨合。

而历经时间考验的老区域，则通常会拥有更为丰富的产品选择和成熟的技术支持，但有时对新特性的部署和落地，可能会因为原有条件的限制而进展得缓慢一些。如果早期规划过于保守，极端情况下还可能出现局部“满服”而无法扩展某类资源的尴尬局面。

小提示：

不同云不同区域的实际情况千差万别。我上面说的这些，只是给了你一定的判断思路，仅供参考。必要时，你应当咨询云销售或客服来获取更细致的信息。

总而言之，新旧区域哪个更好，并不能一概而论，需要根据你的服务需求和待选区域的实际情况来综合衡量。

第三个区域选择的考量因素，则是成本因素。即便是同一种服务的价格，在不同区域也往往是不相同的。

当你的应用需要大批量地采购同一种型号的虚拟机时，或者是你想利用云存储设立一个大规模的云端备份中心，我都建议你仔细比对一下不同区域相关服务的价格，也许你会有惊喜的发现。个别区域会具有明显的价格优势，比如阿里云的华北 5 区（呼和浩特），和 AWS 中国的宁夏区域，以此来吸引用户的入驻。

谈到成本，这里我还想补充说明一下区域的流量费用，是你需要注意的。如果把区域作为一个有边界范围的实体圈起来，这个流量可以分为三类：入站流量、出站流量和内部流量。在现代云计算的计费框架下，一般会倾向于让入站流量和内部流量免费或接近免费，而出站流量则单独收费。

多区域架构浅谈

接下来我们谈谈多区域架构，它指的是部分关键应用，为了追求最佳的用户体验和高可用性，需要把多个区域的资源和能力结合起来进行构建。

你首先需要了解，主流云厂商在跨区域方面也进行了大量建设和投资，主要体现为：

物理上，各区域之间建设有网络互联专线，一般称为骨干网（Backbone）。骨干网的存在使得同一个云在不同区域间的通信，能够有较高的带宽和较低的延时。

软件层面，允许位于不同区域的虚拟网络跨区域进行互联，使得多区域的私有内网能够借助自有骨干网无缝高速打通。

DNS 解析层面，通常会提供就近解析和智能路由能力，将分布广泛的 C 端流量引流到最近的数据中心，以获得最快的响应速度。

AWS 全球骨干网（来自AWS 官网）

由此可见，公有云的基础设施（尤其是骨干网的存在）能够极大地方便我们构建多区域的应用程序。为了让你对云的骨干网有一个感性的认识，我们来进行一个动手小实验，实际感受一下区域间互联的吞吐能力。

我们就以 AWS 中国的北京区域和宁夏区域作为例子。

首先，我在两边都各自创建了一台虚拟机，在获取 IP 并开放相应端口后，使用 iperf3 工具进行网络吞吐能力测试。先让一端作为服务器在某个端口监听：

[ec2-user@ip-172-31-xx-yy ~]$ iperf3 -s -p 3390
-----------------------------------------------------------
Server listening on 3390
-----------------------------------------------------------

然后让另一端作为客户端，发送数据进行测试：

[ec2-user@ip-10-0-1-101 ~]$ iperf3 -c aa.bb.cc.dd -p 3390
Connecting to host aa.bb.cc.dd, port 3390
[  4] local 10.0.1.101 port 43640 connected to aa.bb.cc.dd port 3389
[ ID] Interval           Transfer     Bandwidth       Retr  Cwnd
[  4]   0.00-1.00   sec  53.6 MBytes   450 Mbits/sec    0   3.11 MBytes
[  4]   1.00-2.00   sec  61.2 MBytes   514 Mbits/sec    0   3.11 MBytes
[  4]   2.00-3.00   sec  61.2 MBytes   514 Mbits/sec    0   3.11 MBytes
[  4]   3.00-4.00   sec  61.2 MBytes   514 Mbits/sec    0   3.11 MBytes
[  4]   4.00-5.00   sec  60.0 MBytes   503 Mbits/sec    0   3.11 MBytes
[  4]   5.00-6.00   sec  60.0 MBytes   503 Mbits/sec    0   3.11 MBytes
[  4]   6.00-7.00   sec  61.2 MBytes   514 Mbits/sec    0   3.11 MBytes
[  4]   7.00-8.00   sec  61.2 MBytes   514 Mbits/sec    0   3.11 MBytes
[  4]   8.00-9.00   sec  61.2 MBytes   514 Mbits/sec    0   3.11 MBytes
[  4]   9.00-10.00  sec  60.0 MBytes   503 Mbits/sec    0   3.11 MBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth       Retr
[  4]   0.00-10.00  sec   601 MBytes   504 Mbits/sec    0             sender
[  4]   0.00-10.00  sec   599 MBytes   502 Mbits/sec                  receiver

iperf Done.

可以看到，在并发度默认为 1 且未做任何调优的情况下，距离上千公里的双机点对点传输就达到了 500Mbps 以上，效果相当不错。

小提示：

网络传输速度受到许多因素的影响。此处的测试结果数字仅供参考，不代表所测专线的实际带宽能力。事实上，通过增加并发度（如 iperf3 的 -P 选项）并加强机器配置等，你还可以成倍地提升测试效果。建议你一定要结合自己的云环境和需求场景进行实际的测试。

所以，在骨干网的加持下，通过合理架构完全可以让多个区域的云服务融为一体。借助云的力量，小厂也能轻松拥有巨头的分布式部署能力。

在应用架构层面，多区域并不意味着，我们需要把某区域的资源依葫芦画瓢复制到其他区域，而是可以根据实际情况各司其职，让不同区域担任不同的角色，联动起来达到业务目的。

比如，我们可以将面向消费者服务的触点部署到多个区域，就近服务各地区的互联网流量，而偏后台的数据分析和 BI 服务，则可以安置在性价比较高的非一线城市区域，业务数据可通过骨干网不断回传。这是一种经典的分工模式。

当然，多区域架构固然诱人，我们也不应当走向另一个极端：轻率、随意地拓展区域。因为每一个区域的增加，都会相应增加应用架构的复杂性和流量费用，也给我们的维护工作带来负担，这些额外的成本可能会抵消多区域架构带来的好处。

什么是“可用区”？

除了“区域”之外，很可能你还听说过“可用区”（Availability Zone）这个术语，它同样是非常重要的概念。因为看上去和区域有点相似，有些同学会把它们等同看待。事实并非如此。

可用区是区域的下级概念，是指一个具备完整而独立的电力供应、冷却系统、网络设施的数据中心单元。一个区域通常由多个可用区高速互联组成。区域内的可用区一般位于同一个城市，之间相距往往在一百公里以内。

所以物理上的“数据中心”和“机房”概念，若要严谨地对应到云端，其实是在可用区这个层面。

你可能会问，一个区域看上去拥有一个数据中心就足够了，为什么还要建造多个可用区呢？

首要的原因，当然是为了解决区域内高可用性问题，这也正是“可用区”名字的由来。尽管数据中心内部有着非常精密的运作系统和冗余机制，但地震、火灾、雷击等极端情况下，仍有可能造成数据中心级别的故障。

为了避免单个数据中心故障让整个区域不可用，那自然就有必要建设多个相对独立的数据中心，也就是多个可用区了。它能让区域中的服务达到相当高的可用性。许多云上的 PaaS 服务，正是依赖多可用区，来建设架构并保证冗余的。

所以你在设计 IaaS 层面架构时，也可以利用可用区来实现自己的业务效果。比如在创建云虚拟机时，我们是可以指定可用区的：

阿里云华东 1 区可用区选择界面

多可用区架构的选择，与前面探讨的多区域架构类似，同样是一个在网络性能、成本、可用性之间权衡的问题。我们可以将资源安排在同一个可用区，以便获得较高的网络互访性能；也可以安排在不同的可用区，以实现故障隔离和服务冗余。

区域需要多个可用区的另一个原因，在于区域本身有扩展的需求。一些区域由于早期的容量规划和成本控制原因，很可能在若干年的运营后就会变得资源紧张、后劲不足。

这时得益于可用区的机制，区域可以通过新建可用区，不断扩展自身容量，补充新鲜血液；而老旧的可用区，则可不对新用户开放，逐步封存甚至淘汰，这让区域形成了良好的新陈代谢机制。

所以反过来讲，可用区的数量也可以成为一个衡量区域规模的重要指标。数量越多，意味着这个区域规模越大。在选择区域的时候，这个指标也可以作为重要参考。

课堂总结与思考

今天是我们《深入浅出云计算》的第一讲，主要讨论了区域和可用区这两个核心概念。我把这一讲的要点简单总结如下：

区域是云计算的顶层概念，云服务以区域为单位对外开放；

区域选择需要考虑多种因素，包括但不限于地理位置、服务丰富性、开服时间、资源成本、可用区数量等；

可用区是区域之下的重要层级，代表独立的数据中心，一个区域内往往有多个可用区；

妥善将资源分布到不同可用区，可实现故障隔离，提升架构的可用性。

在讲解这些内容的同时，今天我们也触碰到了网络和高可用架构等相当硬核的话题。如果你觉得还不过瘾，也没有关系，后续会有相关的专题章节作进一步的探讨。

最后，我想给你留下两个思考题，欢迎你在留言区和我互动：

你日常接触的云计算区域是哪些？你有察觉到区域之间的一些差别吗？

在 2019 年 AWS re:Invent 大会上，亚马逊还推出了全新的“本地区域”（Local Zone）概念。这又是为什么场景所设计的？层级上它更接近“区域”还是“可用区”呢？

如果你觉得有收获，也欢迎把这篇文章分享给你的朋友。感谢阅读，我们下期再见。

02 | 云虚拟机（一）：云端“攒机”，有哪些容易忽视的要点？

你好，我是何恺铎。

前一讲，我先从数据中心的角度入手，和你讲解了云计算中“区域”和“可用区”的概念，帮助你建立起了大局观。今天，我们就开始进入微观层面，来介绍和讨论 IaaS 中最重要的核心服务：云虚拟机。

我想，你可能对虚拟机并不陌生，现在虚拟机的应用已经很普遍了。传统的物理服务器上通过安装虚拟化软件，就可以虚拟出多个互相隔离的虚拟机，来帮助我们提高资源的使用效率。云计算中的虚拟机，本质上也是如此，也是底层计算存储能力的抽象和开放。

所以你也许会问，那么云虚拟机到底有什么值得讨论的呢？看上去也就是选取 CPU、内存、硬盘几大件，然后启动后登录使用，似乎没有什么新鲜的东西？

没错，云虚拟机粗看起来和传统服务器较为类似。但当你对它的应用逐渐深入、规模不断加大时，就非常有必要去深入了解云虚拟机的特点了，因为你开始需要针对不同的场景进行选型，也要在性能和成本间找到最佳的平衡，让你的应用效益最大化。

因此，我接下来就会用三讲课程，为你详细讲解下云端虚拟机的“门道”。

云虚拟机到底是什么？

云虚拟机，顾名思义，是在云端虚拟出的服务器。这个服务器你可以完全地控制它，从底层操作系统到安装上层应用。

站在技术实现的角度来讲，虚拟化技术是云虚拟机服务的核心，它本身是一个非常宏大的技术领域。比如你可能听说过 Xen、KVM、VMWare、HyperV 等等虚拟化产品和技术。云计算中所使用的虚拟化技术，也大都是从这些虚拟化实现方式演化而来的。

作为开发者，我们当然不需要成为虚拟化技术专家。我们只需要知道，云端的虚拟化技术在不断进步和发展，使得云端虚拟化的性能损耗在不断减少、资源利用率不断提升就可以了。但你很有必要去了解云计算中虚拟机的体系结构，这也是云虚拟机与传统虚拟机的最大不同。

云虚拟机的体系结构，用一句话来概括一下，就是全面解耦的计算存储分离的设计思想。

小提示：计算存储分离是云计算设计理念中最重要的思想之一，不仅仅体现在虚拟机上，也体现在其他的云服务架构中。我们今后还会不断涉及。

传统的虚拟化，往往是对单一物理机器资源的纵向切割，计算、存储、网络等各方面的能力都是一台物理机的子集。因此，从可伸缩性的角度来说，传统虚拟机存在较大的局限，当物理机的局部出现故障时，也很容易影响到里面的虚拟机。

得益于云端大规模的专属硬件以及高速的内部网络，云虚拟机的组成则有所不同。除了核心的 CPU 与内存部分仍属于一台宿主机外，它的网络、硬盘等其他部分，则可以超脱于宿主机之外，享受云端其他基础设施的能力。大致架构如下图所示：

你要注意的是，这里我所给出的仅仅是一个简化加工之后的示意图。实际的云计算内部实现，会远比这个要复杂和精妙。不同的云的内部，也会有许多不同的专用硬件各显神通。

所以，云虚拟机，与其说是由一台宿主机虚拟而成的，不如说是云数据中心中的不同部分一起协作，“拼凑”而成的一台机器。这样虚拟出来的机器，我们在使用感受上其实与传统服务器并无不同，但在可扩展性和故障隔离方面，它就具有很大的优势了。

举个例子来说，一台云虚拟机，它可以同时挂载很多硬盘，还能够插上很多“网卡”，拥有多个不同的外部 IP。这就是充分解耦带来的好处。

各家厂商的云虚拟机服务的名称会略有不同，阿里云称为云服务器 ECS（Elastic Compute Service），AWS 称为 EC2（Elastic Compute Cloud），Azure 就叫 Virtual Machine，腾讯云则叫做云服务器 CVM（Cloud Virtual Machine）等等。

这里，你需要注意将虚拟机服务和一些建站类服务区分开来，因为它们有时在名称上可能比较类似。比如“云主机”这个叫法，很多云上就是指云虚拟机，在个别云上对应的却是简单建站服务，请你注意不要混淆。

建站类服务主要是提供一些网站的托管运行环境，如 PHP。它是一个相对受限的环境，严格来说属于 PaaS 服务的范畴，比较注重易用性。而虚拟机呢，则提供了一台真正意义上的服务器，从操作系统到上层应用，都可以自己控制，比起建站类服务来说要开放、通用得多。

虽然各个云厂商对云虚拟机有不同的叫法，但它们的产品形态是比较一致的。当你来到虚拟机服务的门户，一般会有一个列表界面，能够列出当前你拥有的所有虚拟机，你可以按照不同字段过滤、删选、排序。你还可以点击某个 VM 查看详情，界面一般会展示出 VM 的常用运行指标。

AWS EC2 自带的指标监控

云端“攒机”实战

讲到这里，你已经基本了解云虚拟机的概念了。接下来，让我们进入云虚拟机的实际操作环节。

所有的云上，创建虚拟机时一般都会有相当贴心的向导，你可以在虚拟机门户上点击“创建”，然后按照步骤一步步进行即可。今天，我们就以在阿里云上创建 Linux 虚拟机为例，帮你把“攒机”时最主要的环节串一串，同时顺便给你介绍一下，那些在“攒机”时容易被忽视但又非常关键的要点。

小提示：在本次实验中，建议你选择“按量付费”的付费模式，这也是云计算的经典付费模式。这种模式是按虚拟机的使用时间付费，比较适合短期实验。当然，更多付费模式都各有特点，后面的第 4 讲中我们会进行比较和探讨。

第一步，当然是选择和确认虚拟机的所在区域。区域的概念，我在上一讲中已经提到过，它决定了虚拟机的地理位置。

小提示：在部分云中，区域是顶级概念，指定新建虚拟机的区域需要你事先在门户的右上角进行选择和切换，如 AWS。

这样，新建的虚拟机就会处于你当前选择的区域。你还可以指定区域内的特定可用区。

随后，就是虚拟机的配置确认环节，也就是我们通常所说的什么型号、几个核、几 G 内存的选择。配置的选择无疑非常重要，我会在下一讲着重介绍，这里我们先不妨选择默认的 2 核 8G 配置。

接着，就有你需要注意的一个要点：选择操作系统镜像。在这里，你可以选择虚拟机所要安装和使用的操作系统，比如常见的 CentOS 和 Ubuntu，同时你也需要选择这个系统具体的版本号。

在操作系统的列表中，你往往会看到厂商的自有操作系统，比如阿里云的 Aliyun Linux、AWS 的 Amazon Linux 等。这是一个很有意思的事情。既然已经有诸多流行的 Linux 发行版了，为什么云厂商还要推出自己的 Linux 版本呢？我们什么时候才应该考虑使用它们呢？

你可以这样理解：

首先，厂商的 Linux 版本，在理论上会和自己云上的硬件有更好的适配，这样能够更充分地发挥相关硬件的性能。一般来说，厂商也会在自己的云上进行充分的测试和验证。

其次，在内核和基础组件的选择上，厂商专有操作系统往往会根据自己的需求判断，来进行一些取舍和裁剪，所以一般会有一个相对苗条的身材，占用比较小的磁盘空间，同时启动速度更快。这是一种更适合云环境的选择，尤其是当你的虚拟机集群规模较大时，就能够显出规模经济效应了。

再次，厂商操作系统会预装和云的使用操作方面的一些软件包和 SDK，能够为你提供便利。比如说，厂商一般会预装该云的命令行工具（CLI，Command Line Interface），像是 AWS CLI 等。

另外，当然也有云厂商出于“自主可控”方面的考虑，想拥有自己能完全控制的操作系统，不但技术上可以自主演化，还能防范一些商务合作上的风险。厂商自家的 PaaS 服务，它的底层也一般是使用自己的操作系统。

所以，如果你希望操作系统有更好的软件“兼容性”，或是公司有统一的标准，就可以选择熟悉的老牌 Linux 系统；而如果你有一些大规模、注重性能的业务，不妨考虑尝试下厂商的 Linux 操作系统。

接下来，在系统盘方面，我们选择默认给出的 40G“高效云盘”即可。云硬盘的故事非常精彩，我们第 5 讲中会专项讨论，这里你只需要保持这个默认选项就可以了。

点击“下一步”，我们来到网络和安全组的配置页面。在这里，你可以配置私有网络、IP、带宽等重要的网络选项。虚拟私有网络（VPC）同样是一个很大的话题，我们会在第 6 讲展开学习。

这里我们简单起见，请勾选“分配公网 IP 地址”的选项。这样创建的虚拟机，会自动被分配一个公开 IP 地址，便于我们稍后从自己的电脑直接发起连接。

今天我想着重讨论的另一个重点，是接下来选项中的网络安全组（Network Security Group, 简称 NSG）。如果这里配置不当，就会直接影响虚拟机的使用。很多新同学由于不太了解这个概念，常常会造成无法远程连接登录的情况。

你可以把网络安全组理解为一层覆盖在虚拟机之外的网络防火墙。它能够控制虚拟机入站、出站的流量，并能根据协议、端口、流向等所设定的规则，来决定是否允许流量通过。

所以某种程度上，网络安全组和操作系统中我们熟知的防火墙（如 Linux 的 iptables 和 Windows 防火墙）一样，都起到网络安全防护的作用。

但你需要注意的是它们的区别：网络安全组并不工作在操作系统层面，而是在操作系统层之外，是额外的一层防护。非法流量在尚未到达 OS 的网络堆栈之前，就已经被它阻断了。所以 NSG 的一个优点在于，它不会影响 VM 的性能。

另外，网络安全组是一种可复用的配置。如果你有大量虚拟机适用于同样的网络控制规则，那么，你就能够很方便地让它们使用同一个网络安全组，这样你管理起来会非常方便。

网络安全组是绝大多数云都支持和实现了重要特性，它体现了云计算中软件定义网络的特点。网络安全组非常灵活，你可以随时更改，规则也会动态生效。

小提示：当你在排查虚拟机的连通性相关问题时，比如假设你的网站或 API 无法被访问，那你一定要记得检查网络安全组中的设置，查看它相关的端口和协议是否已经开放。

OK，回到我们虚拟机创建的流程，所以我们要创建或使用一个，至少开放了 22 端口的网络安全组，以便我们能够通过 SSH 连接上去。阿里云中，就提供了方便的“默认安全组”，我们只需要勾选需要开放的端口，就会帮助我们生成一个安全组实例，并对这台机器启用。你也可以事先手工创建一个安全组，并在此处选择。

再点击下一步，我们就进入了“系统配置”阶段，在这里，你可以为实例命名，指定用于登录的用户名密码或密钥对等，这里比较简单我就不再赘述了。

然后，暂时跳过一些可选的高级设置，确认订单后，按下“创建实例”，就可以等待虚拟机的生成了。一般数十秒至数分钟之内，一台崭新的云服务器就会就绪，进入运行状态。

此时，你可以通过 SSH 连接上虚拟机的公开 IP，使用 hostnamectl 命令查看一下虚拟机的信息，嗯，一切正常。

client@clientVM:~$ ssh -i ./geektime-ali-sh.pem root@101.133.209.214
Welcome to Alibaba Cloud Elastic Compute Service !

[root@my-ecs-vm1 ~]# hostnamectl
   Static hostname: my-ecs-vm1
         Icon name: computer-vm
           Chassis: vm
        Machine ID: 201908292149004344218446xxxxxxxx
           Boot ID: 2228122a7f3c4b4eb5756824xxxxxxxx
    Virtualization: kvm
  Operating System: Aliyun Linux 2.1903 (Hunting Beagle)
            Kernel: Linux 4.19.57-15.1.al7.x86_64
      Architecture: x86-6

成功地登录上去之后，你就可以正常使用这台机器了。比如，通常我们会使用 yum 或 apt 等包管理器进行一些应用软件的安装。

到这里，我就带你初步体验完了云虚拟机的创建过程。VM 类服务的本质就是租用，我们通过在门户上的简单操作，就能够完成一台定制服务器的“租用”过程。

从原理上说，这和租户从房东那租房子其实没有什么两样。而且云上的租用相当便捷，动动手指你就能轻松完成。唯一不同的是，云厂商一般不会把租客“扫地出门”，只要你按时付费，一般不会出现不允许续租的情况。

课堂总结与思考

在今天这一讲中，我先帮助你了解了云虚拟机的一些理论知识，尤其是一些体系结构方面的特点。然后，我们进入了创建云虚拟机的实操环节，了解了相关的流程和步骤，也讨论了其中所牵涉的一些注意事项。我强烈建议你自己也动手操作一下，完成从创建到连接的全过程，形成一个直观的感受。

我们把这一讲的要点总结如下：

云虚拟机是最重要的 IaaS 服务之一，它基于计算存储分离的架构进行构建；

云虚拟机的创建过程，由地域、机型、操作系统、存储、网络等多方面选项共同构成；

云虚拟机可使用云厂商自有操作系统，与云有较好的适配；

网络安全组是保护云虚拟机的网络防火墙，可以同时应用于多个虚拟机。

在今天我们实践的过程中，也引出了若干重要的概念和选项，如机型配置、云硬盘、云网络等等。后续我们会逐个地展开讨论，敬请期待。

最后，给你留下两个思考题：

在上面的实验当中，为了便于连接我们给机器自动分配了公网 IP。在生产环境中为了安全性考虑，应该尽可能避免给虚拟机分配公网 IP，那么这时你如何连接到这些机器呢？

暂时不再使用的云虚拟机，和传统服务器一样可以“关机”。关机状态的云虚拟机仍然会存在于虚拟机列表中，随时可以再启动。那么，关机之后它还会继续收费吗？

欢迎你在留言区和我互动，我会第一时间给你反馈。如果觉得有收获，也欢迎你把这篇文章分享给你的朋友。感谢阅读，我们下期再见。

03 | 云虚拟机（二）：眼花缭乱的虚拟机型号，我该如何选择？

你好，我是何恺铎。

在上一讲中，我带你了解了云虚拟机的大致构架和组成，实际体验了在云上建立第一台虚拟服务器的完整流程，还介绍了在创建过程中，你所需要注意的若干重要选项及其含义。

而在这些选项之中，最重要的恐怕就是虚拟机的规格了，因为它直接决定了虚拟机的计算能力和特点，同时，也会深刻地影响使用成本，是你在选型时需要考虑的重点问题。

很多同学在实际工作中，都会遇到这样的困惑：公司要上云，或者因为业务发展需要采购新的云服务器，但是在查看某云厂商的官网时，发现可选择的虚拟机型号列表很长，有点儿眼花缭乱。

那么，不同种类的虚拟机到底有什么区别呢？在选择时又应该从哪儿入手呢？

今天，我们就来详细聊聊这个话题。

建立对虚拟机配置的多维认知

完整形容一个虚拟机的核心配置和能力，需要从多个角度来入手和描述。弄懂了这些重要维度的含义，你才能够准确理解一个虚拟机的性能预期和使用场景，从而作出正确的型号选择。这里并非只有决定 CPU 核数和内存大小这么简单。那么，主要是哪几个维度呢？

第一个维度，就是虚拟机的“类型”，或者说“系列”。

这是一个非常重要的概念，它是指具有同一类设计目的或性能特点的虚拟机类别。

一般来讲，云厂商会提供通用均衡型、计算密集型、内存优化型、图形计算型等常见的虚拟机类型。这些类型对应着硬件资源的某种合理配比或针对性强化，方便你在面向不同场景时，选择最合适的那个型号。

而 vCPU 数和内存大小（按 GB 计算）的比例，是决定和区分虚拟机类型的重要指征之一。

通用均衡型的比例通常是 1:4，如 2 核 8G，这是一个经典的搭配，可用于建站、应用服务等各种常见负载，比如作为官网和企业应用程序的后端服务器等。如果你对未来工作负载的特征还没有经验和把握，那你也可以先使用通用型实例，等程序运行一段时间后再根据资源占用情况按需调整。

如果 vCPU 和内存比是 1:2 甚至 1:1，那就是计算密集型的范畴，它可以用于进行科学计算、视频编码、代码编译等计算密集型负载。

比例为 1:8 及以上，一般就会被归入内存优化型了，比如 8 核 64G 的搭配，它在数据库、缓存服务、大数据分析等应用场景较为常见。

图形计算型很好理解，就是带有 GPU 能力的虚拟机，一般用于机器学习和深度学习模型的训练和推理。随着 AI 的火热，这类机器也越来越多地出现在各种研发和生产环境中。

在主流云计算平台上，常常使用字母缩写来表达虚拟机系列。比如，AWS 的通用型是 M 系列，阿里云的内存优化型为 R 系列，Azure 的计算优化型为 F 系列等。

不同云平台之间使用的字母可能相同，也可能大相径庭，你在记忆时需要小心，不要混淆。在这里，我根据各家 2020 年的最新情况，简单整理了一个表格供你参考：

需要注意的是，上表中还提到了本地存储型，它是指带有高性能或大容量的本地存储的机型。我们在后续讨论云盘的课程中还会提到，这里你先了解一下就可以了。

第二个重要的维度，是虚拟机的“代”(Generation)，用来标识这是该系列下第几代的机型。

我们知道，数据中心硬件和虚拟化技术是在不断发展的，云厂商需要不断地将最新的技术和能力推向市场，让你享受到时代进步带来的技术提升。这和我们个人用的笔记本电脑是非常类似的，笔记本厂商也总是在不断地更新设计和配置，以赢得消费者的青睐。所以即便是同一系列的机型，不同的代别之间也会有不小的区别。

具体来讲呢，同类型虚拟机的更新换代，往往首先会带来相应硬件 CPU 的换代提升。随着一代新机型的推出，云厂商一般都会详细说明背后支撑的硬件详细信息。

比如说，AWS 在 2017 年末，在全球发布的新一代 EC2 实例 M5/C5/R5，它们的背后是升级到了 Skylake 架构的 Intel 至强铂金系列处理器，相比前一代采用的 Broadwell 或 Haswell 架构处理器，进步了不小，还支持了可大幅提升矢量和浮点运算能力的 AVX-512 指令集。

再比如，阿里云在 2019 年的云栖大会上，也盛大发布了第六代 ECS，它全线采用了更新一代的 Intel 至强 Cascade Lake 处理器，相较前一代的 Skylake 实例，又在性能、价格优势等各方面有了进一步提升。你可以参考下面给出的截图：

阿里云的第六代 ECS（内存型）型号选择界面

这里你需要特别注意，正是由于虚拟机所采用的物理 CPU 在不断更新，所以云上虚拟机的单核性能未必相同。有时，虽然两个虚拟机的核数一致，但由于底层芯片的架构和频率原因，性能上可能有较大的差别，我们需要注意在不同机型间做好比较和区分。

像微软 Azure，就引入了 Azure Compute Unit（ACU）的概念，来帮助量化不同 CPU 的单核性能。比如其历史较久的通用型 A 系列，它的单核性能基准为 100 单位，而计算型的 F 系列的单核算力则高达 210~250，是 A 系列的两倍还多。

另外，你还应当看到，云虚拟机的换代更新并不仅仅只在 CPU 等硬件配置层面，很多时候也伴随着底层软硬件架构的更新和提升，尤其是虚拟化技术的改进。

前面我提到的 AWS 第 5 代 EC2 实例，正是全面地构建在 AWS 引以为傲的 Nitro System 新一代虚拟化技术栈之上。

Nitro System 的本质，是将许多原来占用宿主机资源的虚拟化管理工作进行了剥离，并将这部分工作负载，通过 Nitro Card 这样的专用硬件进行了硬件化，达到了最大化计算资源利用率的效果。在这一点上，阿里云的神龙架构也采用了类似的做法，与 AWS Nitro 可谓一时瑜亮，有异曲同工之妙。

总的来说，我们消费电子产品时的“买新不买旧”，在云端同样适用。新一代的型号，往往对应着全新的特制底层物理服务器和虚拟化设施，能够给我们提供更高的性能价格比。

所以，有些云平台在选择虚拟机型号时，会贴心地默认隐藏相对过时的型号。当然在个别情况下，比如数据中心的新机型容量不足，或者老型号有促销活动时，你也可以酌情选用之前的型号。

第三个重要的维度，就到了我们所熟知的实例大小（Size），也就是硬件计算资源的规模。

在选定的机器类型和代别下，我们能够自由选择不同的实例大小，以应对不同的计算负载。

如果你只是个人用来实验，那么也许单核或者双核的机器就足够了；如果是要放在大规模的生产环境当中，则可以按需选取高得多的配置，现代云计算已经能够提供多达 128vCPU 的机型了。

在描述实例大小时，业界常常使用 medium、large、xlarge 等字眼来进行命名区分，这样的描述基本已经成为事实标准，包括 AWS、阿里云、腾讯云在内的多家主流厂商都在使用。

我们可以大致这样记忆：标准 large 对应的是 2vCPU 的配备，xlarge 则代表 4 个 vCPU，而更高的配置一般用 nxlarge 来表达，其中 n 与 xlarge 代表的 4vCPU 是乘法关系。比如，8xlarge 就说明这是一台 8*4=32vCPU 的机器。

注意：这里在进入更严谨的配置表达时，我们更多倾向于使用 vCPU 而非核数（Core）来描述虚拟机处理器的数量。因为超线程（HyperThreading）技术的普遍存在，常常一个核心能够虚拟出两个 vCPU 的算力，但也有些处理器不支持超线程，所以 vCPU 是更合适的表达方式，不容易引起混淆和误解。

在某些场景下，你可能还会看到“metal”或者“bare metal”这样的描述规格的字眼，中文称为“裸金属”。它们就是云服务商尽最大可能将物理裸机以云产品方式暴露出来的实例，主要用于一些追求极致性能，或是需要在非虚拟化环境下运行软件的场景。

理解虚拟机命名规则

经过前面的介绍，我们已经了解了决定虚拟机配置的最重要的三个要素，即类型、代别和实例大小。这样，一个完整的虚拟机型号命名就已经呼之欲出了。我们来看最具代表性的 AWS 命名规则（阿里云采用的也是非常类似的格式）：

这其实就是利用上述的各维度，按照某种顺序排列的一个组合。理解了这一点，当你今后看到某个具体型号的时候，就能够很快地明白该型号命名背后的含义了。

比如，对于 r5.4xlarge 这个型号，我们会很快想到，这首先是一个 R 类型的第 5 代的内存型机器，它应该有 4×4=16 个 vCPU，内存大小则是 16×8=128G（内存型机器的 CPU 内存比一般为 1:8）。这样分解下来，原来看上去比较陌生晦涩的一个字符串，是不是就立刻变得清晰起来了？

当然，并非所有的云都一定是采用类似 AWS 的命名规则，像是微软 Azure，就用了一个略有不同的命名体系，大致可以总结为：

比如“E4 v3”，就代表了微软 Azure 上 4 核 32G 的第三代内存型机器。掌握了 Azure 的格式特征后，你同样能够很快地解读标识的具体含义。

不知道你有没有注意到，在前面的命名公式中，还有一个我们称之为“后缀”的可选部分，在许多的型号命名中都能看到它。这个可选部分呢，它一般是作为型号硬件信息的一个重要补充，这种型号与不带此后缀的标准版本相比，会有一些显著的区别或特点，这也是你需要重点关注的地方。

这里我给你举一些型号后缀的例子吧。

比如，AMD 现在凭借 EPYC 霄龙芯片，也开始在服务器硬件市场攻城拔寨，许多云厂商就专门推出了使用 AMD CPU 的云虚拟机，这些虚拟机往往会使用字母 a 作为后缀。AWS 上的 m5a 型号，就是使用 AMD EPYC 7000 系列服务器 CPU 构建的通用型虚拟机。

再比如，AWS 的 C5n 计算型虚拟机，其中“n”这个后缀表达的是，该规格在网络层面进行了增强，会比同型号标准机型拥有更大的带宽和网络吞吐能力。在阿里云上，表达相同“网络增强”含义的后缀则是“ne”。

有时，为了验证机型配置是否与我们的期望相符，在 Linux 环境下，我们可以使用 lscpu 命令，来了解手中虚拟机的 CPU 信息，并与机器的具体型号名称进行对照。下面的信息，是我在一台 AWS 的 m5a.xlarge 机型上运行的结果，你可以看到芯片提供商 AMD 及双核四线程等关键信息，与机型命名的含义相符：

[ec2-user@ip-xx-yy-zz ~]$ lscpu
Architecture:        x86_64
CPU op-mode(s):      32-bit, 64-bit
Byte Order:          Little Endian
CPU(s):              4
On-line CPU(s) list: 0-3
Thread(s) per core:  2
Core(s) per socket:  2
Socket(s):           1
NUMA node(s):        1
Vendor ID:           AuthenticAMD
CPU family:          23
Model:               1
Model name:          AMD EPYC 7571
Stepping:            2
CPU MHz:             2379.224
BogoMIPS:            4399.39
Hypervisor vendor:   KVM
Virtualization type: full
...

课堂总结与思考

今天，我们主要探讨了云上虚拟机的类型与规格，相关要点可总结如下：

云虚拟机的配置规格主要取决于类型、代别、实例大小三个最重要的维度。

实例所属的类型，决定了虚拟机相应的硬件资源配比与专项能力，分别为不同的场景优化设计。你可以根据实际场景来酌情选用，这样既能满足需求又好控制成本。

云虚拟机的型号名称一般由类型、代别、实例大小这几项的缩写组合而成，有时还会带有补充后缀。了解了某个云的型号格式后，通过拆分对应，你很容易理解具体型号的含义。

最后，作为今天的交流讨论题，你可以回忆一下，在生产或测试环境中，使用过的最强劲的云端机型。你注意过它是什么系列、什么型号的吗？它主要被用于什么业务场景呢？

欢迎在留言区和我互动，我会第一时间给你反馈。如果觉得有收获，也欢迎你把这篇文章分享给你的朋友。我是何恺铎，感谢阅读，我们下期再见。

04 | 云虚拟机（三）：老板要求省省省，有哪些妙招？

你好，我是何恺铎。让我们继续云虚拟机的话题。今天这一讲，我想从一个不一样的视角，也是你会很感兴趣的一个角度来进行讨论，那就是成本。

的确，很多时候，我们上云的障碍是在于价格。

打个比方吧，假设我们要为公司的业务上云进行虚拟机采购，这时如果你只是简单地将物理服务器的报价，与按量付费模式下的“通用型”云虚拟机进行对比，那你很容易就会得出云上机器太贵的结论。

但其实呢，在云上，我们有很多实用的招数来控制虚拟机的成本，是可以“少花钱、多办事”的。

那么，都有哪些省钱的妙招呢？今天我就来“偷偷”告诉你。

省钱妙招之一：使用包年包月机型

包年包月，可能是我们最先会想到的降低成本的办法了。

顾名思义，包年包月就是我们要提前预估好自己虚拟机的使用时间，比如半年、一年甚至三年，并提前支付相关款项的一种购买方式。这样的购买方式，通常能够给你带来较大幅度的折扣，帮你显著地节约成本。

云厂商其实是鼓励和欢迎虚拟机包年的，因为这样降低了云端动态租用的不确定性，减少了服务器空置的情况，也为厂商做中长期的数据中心容量规划提供了便利。另外一方面，包年包月一般都是先付费的模式，所以从财务层面上看，也有利于厂商的现金流。这些都是采用包年包月方式能够获得让利的原因。

在许多国内云厂商的虚拟机创建界面上，包年包月甚至成为了默认的选项，你需要注意在界面下方选择购买的时长。时长越长，你能获得的折扣越大。

那么，包年包月具体能帮我们省多少呢？这没有一个唯一确定的答案。因为，不同的云、不同的区域以不同的时长购买，折扣力度都可能有所不同。通常来讲，一般常见的机型在 3~7 折不等。

不过，在包年包月的模式下，也有一些你需要注意的问题。

首先，这个模式意味着我们牺牲了一些资源安排上的灵活性。因为在它到期之前，你一般是无法取消的，或者在某些云上，即便是允许你取消，也需要扣除一部分费用，这就像我们买了保险后中途退保一样，就要承担一些损失。

另外，包年机给我们带来了一个后续维护工作：续费管理。尤其是当包年虚拟机的数量陆陆续续变多时，由于创建时间不同，到期时间也就比较分散，那么续费的工作就变得更加复杂和重要起来。如果忘记续费，过了缓冲期后，机器会被自动关闭甚至删除，那就会影响业务的连续性。这是你需要小心的一个地方，千万不要错过云上的续费提醒。

省钱妙招之二：使用竞价实例

相比包年包月的广为人知，竞价实例（Spot Instances）的知名度似乎小一些。但如果运用得当，竞价实例其实威力巨大，这也是我十分推荐你去尝试和使用的一种省钱的办法，因为它往往能够提供相当大幅度的折扣。

竞价实例，是 AWS 所首创的产品形式，其他的云厂商近几年也在纷纷跟进。它的基本原理是，把云数据中心上闲置的机器资源拿出来，进行公开的拍卖，价高者得。让“市场机制”，也就是各个用户，来主导这些闲置资源的定价。

因为是闲置资源，所以大家的出价都会比较低，颇有一点共同来“薅羊毛”的意思。所以在很多时候，你甚至能够拿到相对标准按时计费价格 1~2 折的折扣力度，这无疑是非常有诱惑力的。而对于厂商而言，这也不是什么坏事，因为这些资源本就闲置，还不如顺水推舟、对外开放，以获得一些回报。所以说，竞价实例，是一个伟大的发明，是一种双赢的机制。

但也因为是闲置资源，所以它主要的限制在于可能会被随时回收。

当数据中心的闲置资源不足时，比如说，有人要创建大批更高优先级的、“正牌”的非竞价实例，或者当竞价市场涌入大量土豪，推动市场价格高于你的最高出价时，你的虚拟机就会被停止运行，并自动回收（一般会有一个提前数分钟通知的机制）。

因此，竞价实例能够有较低折扣的本质，是在于牺牲了稳定性。所以，你在使用竞价实例时，还需要注意选择场合。生为竞价实例，就要时刻有“退位让贤”的觉悟和准备。

如果你要搭建一个对外服务的网站，或者是数据库的话，这些需要 24 小时不间断运行的生产负载，就并不适合跑在竞价实例上。竞价实例非常适合的应用场景，包括一些后台批量计算、爬虫、性能测试等等。这些无持久化状态、可打断的工作，今后你可以第一时间想到用竞价实例来支撑。

竞价实例也是按照运行时间来付费的，你可以随时主动关闭和终止。所以，这种方式的动态性还是不错的，你可以随时按需启停。

小提示：在实操时，你需要注意一下在创建界面上选择竞价的策略。常见的竞价方式有两种，一种是手动设定你所能接受的最高价格，一种则是选择跟随市场价格的变动，也即自动出价。这和我们买卖股票时的操作选择很类似。

省钱妙招之三：使用突发性能类型

对于一台固定配置的服务器来说，总是会或多或少地存在资源闲置的情况。比如说，我们为了潜在的工作负载，申请了比较强劲的 CPU 资源，但也就是在业务高峰到来的时候，服务器才能够发挥出全部实力。而在相对长得多的业务低谷期，机器的 CPU 资源利用率其实会比较低。

因此，我们常常可以见到一些服务器 CPU 平均使用率非常低下，这显然是一种巨大的成本浪费。

而云端的架构，天生就善于解决资源闲置问题。

一种解决方法是，我们可以使用可动态调整规模的集群，来应对弹性计算场景，这样可以灵活设定动态扩缩容的机制，以达到减少低谷期资源占用的目的（我会在后面的架构部分进行专门讨论）；而另一种方法则更加简单，且适用于单机，那就是采用突发性能类型（Burstable Performance Instances）。这是一种非常实用而又有趣的虚拟机类型，有时它也被称为“可突增性能实例”。

突发性能类型同样拥有指定的 vCPU 数量、内存大小等配置，但其成本显著小于类似配置的其他类型机器。它的主要区别在于，这种类型的虚拟机的 CPU 性能表现，采用的是积分制，其积分会随着时间的推移匀速累加，也会随着算力的输出而被不断消耗。

当积分充裕时，CPU 可按需跑满，达到 CPU 性能的 100%，同时会较快地消耗积分；当积分不足或耗尽时，则 CPU 只能发挥出标称值的一小部分性能。这个小部分的比例值，我们称它为性能基准，它与积分匀速累加的速度相一致。

小提示：突发性能实例的性能基准，通常在峰值的 5%~40% 不等，具体比例按不同云厂商不同实例而定，你可以查询官方文档进行确认。

我们可以把突发性能类型，理解为性能有一定折扣和弹性的机型。

当重型计算负载来临时，积分的存在和积累，使得这些机器具备自动消耗积分，并获得临时“突增”性能的能力。就像是汽车的发动机，可以通过“涡轮增压”获得短时动力，来增强汽车的输出功率一样。

积分的积累虽然会有一个上限，但一般也足够它全速计算数个小时了。下图中，我给出了一个实际场景中某突发性能 VM 实例的积分曲线，你可以看到积分额度在匀速积累、到达上限，以及开始消耗的全过程：

AWS 突增性能类型的 CPU 积分曲线示例

再回到我前面所说的波峰波谷计算场景，很显然，突发性能实例的积分制特性，恰好可以大显身手。比如，对于符合流量自然特征的互联网业务来说，在负载较低的深夜和清晨，性能突增实例处于较低的 CPU 占用率状态，同时积攒积分；当白天流量高峰到来时，CPU 则可以消耗积分，发挥其全部性能，保障业务稳定运行。

性能突增类型目前在各大云上已经比较常见了，在 AWS 和阿里云上对应的是 T 系列虚拟机，在微软 Azure 上则对应 B 系列。

从成本上来看，突发性能实例和相同配置的通用机型相比，典型情况下，其折扣大约可以达到六折或更低。所以说，性能突增类型虚拟机的引入，非常有助于提高资源利用效率，推荐你在负载具有时效性的情况下酌情选用。

省钱妙招之四：使用 ARM 实例

说到 ARM 处理器，相信你并不陌生。随着移动互联网的高速发展和智能手机的普及，ARM 早已走进千家万户。而且在庞大的手机市场的催化下，ARM 芯片的性能也在不断地取得突破，开始接近甚至达到 x86 处理器的水平。

在移动端取得了统治性的地位后，踌躇满志的 ARM 开始进军服务器端。低功耗、高性价比成为它开拓市场的法宝。而极具规模效应的云计算，又可以说是 ARM 服务器芯片的最佳试验田。

所以，使用 ARM 架构芯片的虚拟机实例，已经成为云计算 IaaS 层不容忽视的新潮流。

同时，因为 ARM 是一个相对开放的架构，具备芯片设计和制造能力的大厂商，就纷纷开始自建芯片。厂商通过自行定制，就可以针对云上场景和需求进行优化，进一步降低单位算力的成本，巩固自己的竞争优势。

举个例子，AWS 近些年就在大手笔地投入它自家基于 ARM 的 Graviton 处理器。在 re:Invent 2018 大会上，推出了第一款基于 Graviton 的 A1 类型 EC2 实例，而在 re:Invent 2019 大会上，AWS 更是再接再厉，发布了基于第二代 7 纳米 Graviton 芯片的 M6g、R6g、C6g 全系列的虚拟机服务。这里的后缀 g 就代表 Graviton。

在国内，也有像阿里、华为这样具备端到端硬件研发能力的巨头，在进行芯片自研，并在云端开始落地商业化。比如，华为在 2019 年发布了基于 ARM 的鲲鹏 920 处理器，性能十分强大，也达到了世界领先水平。与之匹配，华为云也推出了搭载鲲鹏处理器的 KC1 系列的虚拟机。

那么，使用 ARM 处理器的机型，对用户来说有什么吸引力呢？

答案同样是成本。根据厂商的测算，输出相同性能的 ARM 机型，能够帮助用户节省 30%~40% 的成本，这当然也是得益于 ARM 处理器的高性价比特点。所以说，它是我们节约成本的又一个有力手段。

今天我们的实操部分，就来尝试一下风头正劲的鲲鹏云虚拟机。

我在华为云的北京四区创建了一台 kc1.large.2 的双核 4G 机型，操作系统选择了 Ubuntu 18.04 的 ARM 版。创建的过程和普通 x86 虚拟机类似，这里就略去不表了。

机器启动后，我们通过 SSH 登录上去，查看系统信息：

root@ecs-kc1-large-2-linux-20200115174501:~# uname -a
Linux ecs-kc1-large-2-linux-20200115174501 4.15.0-70-generic #79-Ubuntu SMP Tue Nov 12 10:36:10 UTC 2019 aarch64 aarch64 aarch64 GNU/Linux

嗯，这是如假包换的 ARM 架构！用 Linux 自带的 bc 命令来简单算个 Pi 值，跑个分：

root@ecs-kc1-large-2-linux-20200115174501:~# time echo "scale=5000; 4*a(1)" | bc -l -q
3.141592653589793238462643383279502884197169399375105820974944592307\
81640628620899862803482534211706798214808651328230664709384460955058\
...
...
74351362222477158915049530984448933309634087807693259939780541934144\
73774418426312986080998886874132604720

real    0m22.325s
user    0m22.316s
sys     0m0.009s

我们可以看到，机器仅用了 22 秒就完成了精确到小数点后 5000 位的 PI 值，成绩还是相当不错的。

注意：这里使用 bc 命令以及其中的三角函数来计算 Pi 值，只是直观展示 CPU 能力的简便方法。结果仅供参考，不推荐这个方法作为严肃性能测试的依据。

不过，你可能会有点担心 ARM 在服务器端的软件生态。诚然，ARM 体系结构下的软件，的确比不上 x86 架构那样丰富，但在近年相关厂商的大力推动下，其实已经取得了长足的进展。比如，在我们这台 KC1 服务器的 Linux 操作系统中，已经默认安装了 Java、 Python 等语言和运行环境。你甚至可以使用 apt 包管理器来安装 Docker，并在 ARM 服务器内运行 Docker 容器，你可以参考下面给出的示例：

root@ecs-kc1-large-2-linux-20200115174501:~# docker run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
...
...

For more examples and ideas, visit:
 https://docs.docker.com/get-starte

这简直太棒了，这意味着 ARM 服务器同样可以支撑容器，我们可以在上面跑微服务！这会为各种应用在 ARM 上的部署打开方便之门。

所以说，云计算让 ARM 服务器这个看起来比较遥远的事情，变成了触手可及的现实。随着华为鲲鹏等相关计算生态的不断成熟，基于 ARM 的虚拟机系列，也会越来越成为我们在注重成本控制时的一个有力选择。

课堂总结与思考

今天，我们详细讨论了在云上使用虚拟机时，可以运用的一些节省成本的思路和方法。它们原理不同，各有利弊。

包年包月的付费方式是最常见的降低虚拟机使用成本的方法，它通过牺牲采购的灵活性来换取折扣。

竞价实例的机制让云端的闲置资源对外开放，基于市场竞拍的定价方式，常常能够让我们获得很大的折扣。这种方法主要是通过牺牲稳定性，来换取成本上的节约。

突发性能实例是一种特殊的使用 CPU 积分制的机型，相对标准机型成本较低，适合工作负载存在较大波动的场景。它主要牺牲的是性能。

基于 ARM 的虚拟机实例已陆续走向市场，随着生态的不断成熟，也将成为低成本机型中非常具有竞争力的选择。这种方法主要在生态和兼容性方面存在一些限制。

结合起来不难看到，第一、二种方法，是在购买模式层面的调整和创新；而第三、第四种方法，是在机型选择方面，拓宽了我们的思路。有时，这两个层面的方法是可以组合起来使用的。比如，我就曾经在 AWS 云上使用 Spot Instance 的竞价方式，启动了一批 T 系列的突发性能实例，取得了很好的业务效果。

好了，这一讲就到这里。今天我留给你的思考题是：

与包年包月类似的预付费折扣，还有一种叫做“预留实例”（Reserved Instance）的模式。你能说说它和包年包月的不同之处，以及独特的优势是什么吗？

在有些云上创建突发性能实例时，还会有一个“无性能约束模式”的高级选项。你知道这个高级选项勾选后有什么作用，能解决什么问题吗？

欢迎你给我留言，我会尽快给你反馈。如果觉得有收获，也欢迎把这篇文章分享给你的朋友。感谢阅读，我们下期再见。

05 | 云硬盘：云上IO到底给不给力？

你好，我是何恺铎。

通过前几讲的学习，我想你对云虚拟机应该有了不少的了解，也对如何根据实际情况来选择和运用虚拟机，有了一定的认识。在前面的学习过程中，我也留下了许多伏笔。其中之一，就是云虚拟机的重要组件：云硬盘。

那么今天这一讲，我们就来深入讨论一下这个话题，来帮助你了解不同云硬盘的差别，以及如何在实际场景中挑选最合适你的硬盘型号。

云硬盘是什么？

云硬盘，又叫做“云盘”或者“云磁盘”，就是云虚拟机上可以挂载和使用的硬盘。这里，它既包含了用于承载操作系统的系统盘，也包括了承载数据的数据盘。

在云计算的领域，有时，我们还会把云端磁盘服务叫做块存储（Block Storage），因为它们与 Linux 操作系统中的块设备相对应，是云上提供的“裸盘”，可以格式化并且施加文件系统。

既然是硬盘，那么它就与我们通常的认知相一致，当然是带有数据持久化功能的。这在专业上被称为“非易失性存储”（Non-ephemeral Storage），也就是说写入的数据不会丢失。即便所在虚拟机重启、关机甚至下线删除，这块云硬盘只要还存在，其中的数据也并不会被擦除。

事实上，云厂商对于云盘，不仅仅会保障数据的顺利写入，一般还会帮你在存储端同步和保留至少三份副本的数据。所以说，云硬盘的冗余度和可用性是非常之高的，一般极少发生云硬盘数据丢失的情况，你大可放心地使用。

重要提示：尽管云硬盘有良好的存储冗余，但你不能仅仅依赖它的可靠性。从数据的层面来看，你必须进行额外的备份。2018 年 7 月曾有创业公司因为云厂商故障，丢失了在云硬盘上的所有重要数据，一时成为业界的热点新闻，这个教训是非常深刻的。所以，你应当通过定期为云磁盘创建快照、异地备份数据文件等方式，来保护你的关键数据。

云硬盘与传统磁盘的真正差异在于，绝大多数的云硬盘都是远程的。我们都知道，在经典计算机的体系结构中，硬盘是通过本地机器内部主板的高速总线，与 CPU、内存等部件相连接；而在云端，你的硬盘则很可能并不在宿主机上，而是在专用的磁盘服务器阵列中，两者是通过数据中心内部的特有 IO 线路进行连接。没错，这也正是计算存储分离架构的一种体现。

理解了这样的一个结构，你就能明白，有些云上的“IO 优化实例”（AWS 上称为 EBS-Optimized）是指什么了。它就是指云虚拟机与云硬盘之间的网络传输，进行了软硬件层面的优化，这样可以充分地发挥所挂载磁盘的性能。现在较新型号、较强性能的云虚拟机，一般都自动启用了这个优化。

云硬盘的性能等级

你可能听说过一些，网上对于云硬盘性能方面的质疑。这在云计算发展的早期尤其多见，甚至成为了很多人反对上云的主要原因之一。

不错，云硬盘的确有多副本写入的开销，同时也比较依赖于远程传输。所以，早期云硬盘的确存在一些性能上的短板。不过，那都是老黄历了。

当下的云硬盘经过了多次的软硬件迭代，尤其是 SSD 的迅速发展，吞吐量和随机读写能力等各项性能指标都已经不再是问题了。在现代云计算中，已经发展出了基于不同存储介质的、丰富的性能等级选择，你已经能够找到单盘 IOPS 在数十万量级甚至达到百万的云硬盘产品了。

所以，现在的云硬盘，性能上已经非常“给力”了。你更多的是要考虑如何根据应用场景，选择合适介质的硬盘等级，同时权衡好相应的成本。

那么下面，我们就分别来看一看主流云硬盘的不同性能等级，以及它们对应的磁盘类型和存储介质。

第一个等级的云硬盘，是基于传统 HDD 硬盘构建而成的。这类云盘的性能一般，最高 IOPS 大概在数百左右。在很多的云上，已经不把它作为推荐的选择了。但它并非一无是处，成本低就是它的最大优势，在不注重性能的测试环境，或者是个人自用的服务器，它就是一个很好的选择。

第二个等级，往往是基于混合硬盘，也就是结合 HDD 和 SSD 硬盘构建的云硬盘。它会综合发挥 SSD 的性能优势和 HDD 的容量优势。比如它可以用 SSD 部分来承载热点区域数据，或是作为缓存，来提高响应性能。在这个等级下，典型的 IOPS 为数千左右，是很多云上创建硬盘的默认选项，比较适合像是操作系统启动盘这样的常规负载。

第三个等级的云硬盘，它的存储介质就是纯 SSD 硬盘了。虽然贵一些，但一分价钱一分货，这个等级下的云硬盘能够提供非常稳定的 IO 能力，IOPS 通常能够上万，也有相当不俗的吞吐量和较低的访问延时。你可以用它来承载生产环境中重要的关键业务应用，或是各类数据库等 IO 密集型应用。

第四个等级，也是当下业界的最高等级，就是进一步优化增强的最新 SSD 云盘。它一般会采用更新一代的企业级闪存硬件，配合自研或改进后的底层传输协议，和虚拟化技术栈的优化来提供服务。因此它能够达到惊人的性能水平，满足我们最为苛刻的性能场景需求，比如承载 SAP HANA（SAP 的高性能计算平台）、高并发 OLTP 数据库等等。这类 SSD 云盘的 IOPS 通常能够突破十万以上。

各个云对于不同等级云硬盘的命名方法各有不同，我把相应的产品类型和名称整理成了一个表格，方便你去了解和查询：

当然，这个表格只是一个大致的划分，仅供你作为参考。在具体的情况中，云和云必然存在一些差异，也会有一些各自的产品特点，建议你在使用时针对性地确认。比如说，AWS 的 gp2 通用型 SSD 类型，它具有比较宽广的性能指标范围，还具备 I/O 积分和性能突增机制（与性能突增 VM 实例的 CPU 类似），可以提供比较高的峰值性能，应用场景是相当广泛的。

除了云盘性能等级之外，还有一个影响云盘性能的重要因素，就是这块云硬盘的容量。不论是哪种磁盘类型，它的容量大小几乎都与性能正向相关。同等的性能等级下，云硬盘的容量越大，一般来说它的性能就越高，直到达到这个等级的上限。这是由云上磁盘能力共享的底层设计所决定的。

所以在某些时候，你可能需要刻意地增大所申请的云硬盘的容量，以获取更高的性能，即便这些额外的空间不一定能被用上。

好了，对于云盘性能的讨论就先到这里。在上面的性能讨论当中，我们主要通过 IOPS 来进行衡量。事实上，衡量 IO 性能还有吞吐量、访问延时等其他的重要指标。这些指标同样会由磁盘的类型和大小所决定，你可以查询云厂商文档来确认。这里限于篇幅，我就不详细展开了。

云硬盘实战

接下来，让我们进入实战环节，一起学习一下云硬盘的使用。在这个过程中，你也能真实地感受一下不同性能等级的区别。

这里，可以继续沿用我们在第 2 讲中创建的阿里云虚拟机，目前它是默认挂载了一个 40G 的高效云盘作为系统盘。

我们可以先用 lsblk 和 df 命令查看一下磁盘的情况：

[root@my-ecs-vm1 ~]# lsblk
NAME   MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
vda    253:0    0  40G  0 disk
└─vda1 253:1    0  40G  0 part /

[root@my-ecs-vm1 ~]# df -hT -x tmpfs -x devtmpfs
Filesystem     Type  Size  Used Avail Use% Mounted on
/dev/vda1      ext4   40G  1.6G   36G   5% /

通过命令的输出，可以清晰地看到，这台机器有一块 40G 的系统盘，挂载在根目录下。

然后，我们可以使用 fio 工具来测试一下这块系统盘的性能表现。我们通过 fio 在系统盘上创建一个 1GB 的文件，接着进行 4K 大小的随机读取实验。

[root@my-ecs-vm1 ~]# fio --name=mytest1 --filename=~/testfile1 --rw=randread --refill_buffers --bs=4k --size=1G -runtime=10 -direct=1 -iodepth=128 -ioengine=libaio

mytest1: (g=0): rw=randread, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=l
ibaio, iodepth=128
fio-3.7
Starting 1 process
mytest1: Laying out IO file (1 file / 1024MiB)
Jobs: 1 (f=1): [r(1)][100.0%][r=8560KiB/s,w=0KiB/s][r=2140,w=0 IOPS][eta 00m:00s]
mytest1: (groupid=0, jobs=1): err= 0: pid=1324: Sat Jan 25 17:03:53 2020
   read: IOPS=2154, BW=8619KiB/s (8826kB/s)(84.9MiB/10090msec)
    slat (nsec): min=2529, max=38138, avg=3080.22, stdev=575.39
    clat (usec): min=444, max=102701, avg=59394.84, stdev=46276.36
     lat (usec): min=448, max=102705, avg=59398.39, stdev=46276.34
    clat percentiles (msec):
     |  1.00th=[    3],  5.00th=[    3], 10.00th=[    4], 20.00th=[    4],
     | 30.00th=[    4], 40.00th=[    5], 50.00th=[   96], 60.00th=[   97],
     | 70.00th=[   99], 80.00th=[   99], 90.00th=[  100], 95.00th=[  100],
     | 99.00th=[  101], 99.50th=[  102], 99.90th=[  102], 99.95th=[  102],
     | 99.99th=[  103]
   bw (  KiB/s): min= 8552, max=10280, per=100.00%, avg=8645.20, stdev=384.80, samples=20
   iops        : min= 2138, max= 2570, avg=2161.30, stdev=96.20, samples=20
  lat (usec)   : 500=0.01%, 1000=0.03%
  lat (msec)   : 2=0.50%, 4=36.26%, 10=3.74%, 100=57.13%, 250=2.34%
  cpu          : usr=0.50%, sys=1.19%, ctx=20986, majf=0, minf=161
  IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=99.7%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.1%
     issued rwts: total=21741,0,0,0 short=0,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=128

Run status group 0 (all jobs):
   READ: bw=8619KiB/s (8826kB/s), 8619KiB/s-8619KiB/s (8826kB/s-8826kB/s), io=84.9MiB (89.1MB
), run=10090-10090msec

Disk stats (read/write):
  vda: ios=21399/2, merge=0/1, ticks=1266052/242, in_queue=1039418, util=81.1

实际命令输出的结果比较长，这里我们主要关注下 IOPS 的部分。你可以看到，平均 IOPS 的数值都在 2100 左右，这个跑分的成绩，和我们当初建立这块高效云盘时提示的性能目标值“2120”相当一致。

如果高效云盘还不够满足你的业务要求，你可以随时为机器添加更高规格的硬盘，这也是云硬盘的灵活性所在。

接下来，我们就来试一下动态挂载新硬盘的过程。

首先来到这个虚拟机的“本实例磁盘”管理界面，选择“创建云盘”，这里我们选择一块 300G 的 SSD 云盘，按照提示，这样我们就能够拥有 1 万的 IOPS。

之后，按照提示确认创建即可。OK，阿里云很快地为我们创建好了磁盘，但此时这块 SSD 磁盘的状态为“未挂载”，我们可以通过界面操作，把它挂载到正在运行中的目标虚拟机里。

挂载完成后，磁盘的状态开始变为“使用中”，说明磁盘已经“上线”。这时，我们再在 Linux 操作系统中用 lsblk 命令查看：

[root@my-ecs-vm1 ~]# lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
vda    253:0    0   40G  0 disk
└─vda1 253:1    0   40G  0 part /
vdb    253:16   0  300G  0 disk

你可以看到，磁盘中已经出现了一个新的块设备 vdb。

这时，我们需要将这块磁盘进行格式化，并创建 ext4 文件系统：

[root@my-ecs-vm1 ~]# mkfs.ext4 /dev/vdb
mke2fs 1.42.9 (28-Dec-2013)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
19660800 inodes, 78643200 blocks
3932160 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=2227175424
2400 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
        4096000, 7962624, 11239424, 20480000, 23887872, 71663616

Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done

好，还差最后一步，我们要在 /mnt 下，创建一个 data 目录，并将这个新的块设备挂载到该目录。

[root@my-ecs-vm1 ~]# mkdir /mnt/data
[root@my-ecs-vm1 ~]# mount /dev/vdb /mnt/data/

终于大功告成。我们再次使用 fio 工具，来测试下这块 SSD 盘 4K 随机读方面的能力。和前面不同的是，这回我们要把测试文件路径定位到“/mnt/data”目录，因为这个目录指向的是刚刚创建的新硬盘：

[root@my-ecs-vm1 ~]# fio --name=mytest2 --filename=/mnt/data/testfile2 --rw=randread --refill_buffers --bs=4k --size=1G -runtime=10 -direct=1 -iodepth=128 -ioengine=libaio

mytest2: (g=0): rw=randread, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=l
ibaio, iodepth=128
fio-3.7
Starting 1 process
Jobs: 1 (f=1): [r(1)][100.0%][r=41.1MiB/s,w=0KiB/s][r=10.5k,w=0 IOPS][eta 00m:00s]
mytest2: (groupid=0, jobs=1): err= 0: pid=1302: Sat Jan 25 16:59:30 2020
   read: IOPS=10.6k, BW=41.2MiB/s (43.2MB/s)(415MiB/10067msec)
    slat (usec): min=2, max=445, avg= 3.10, stdev= 1.49
    clat (usec): min=828, max=77219, avg=12115.14, stdev=20941.23
     lat (usec): min=841, max=77222, avg=12118.74, stdev=20941.22
    clat percentiles (usec):
     |  1.00th=[ 2737],  5.00th=[ 3326], 10.00th=[ 3523], 20.00th=[ 3687],
     | 30.00th=[ 3785], 40.00th=[ 3884], 50.00th=[ 3949], 60.00th=[ 4047],
     | 70.00th=[ 4146], 80.00th=[ 4359], 90.00th=[56361], 95.00th=[71828],
     | 99.00th=[73925], 99.50th=[73925], 99.90th=[74974], 99.95th=[76022],
     | 99.99th=[76022]
   bw (  KiB/s): min=41916, max=43600, per=100.00%, avg=42464.60, stdev=724.17, samples=20
   iops        : min=10479, max=10900, avg=10616.15, stdev=181.04, samples=20
  lat (usec)   : 1000=0.02%
  lat (msec)   : 2=0.17%, 4=55.50%, 10=29.30%, 20=0.83%, 50=3.47%
  lat (msec)   : 100=10.71%
  cpu          : usr=3.24%, sys=5.58%, ctx=96090, majf=0, minf=163
  IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=99.9%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.1%
     issued rwts: total=106300,0,0,0 short=0,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=128

Run status group 0 (all jobs):
   READ: bw=41.2MiB/s (43.2MB/s), 41.2MiB/s-41.2MiB/s (43.2MB/s-43.2MB/s), io=415MiB (435MB),
 run=10067-10067msec

Disk stats (read/write):
  vdb: ios=105123/3, merge=0/1, ticks=1265938/41, in_queue=1266532, util

上面的测试结果表明，这块 SSD 盘对 /mnt/data 目录中文件的 4K 随机读，成功地达到了 1 万 IOPS 的标称水准。也就是说，新创建的 SSD 磁盘性能还是相当给力的。

在实际的使用场景中，你就可以把一些读写较为密集的负载，比如数据库的数据目录，配置到这个 SSD 盘对应的目录下。

好了，通过上面的实验，相信你对云盘的挂载和使用有了比较直观的认识。云盘的热挂载特性让它使用起来特别灵活方便，而且大小性能任你调度。挂载后的云硬盘真正使用起来，和你熟悉的硬盘操作也并没有什么两样。

认识和使用本地磁盘

前面我们对于云虚拟机的硬盘作了许多讨论，都是围绕着“远程硬盘”这个产品形态来展开的。的确，远程云硬盘的好处很多，是计算存储分离架构的体现，也是云虚拟机硬盘的主流方式。

不过，有时我们还是会有点怀念“本地磁盘”，也就是直接位于宿主机上的硬盘。因为看似传统的本地硬盘，与远程硬盘相比起来，还是会有它自己的优点。毕竟它和计算单元离得近，而且没有三副本的负担，所以往往性能不俗，价格又相对便宜。

那么，云上能否使用本地磁盘呢？

答案是肯定的。而且本地磁盘一般不需要自行创建，只要你选择了带有本地磁盘的机型，启动后，该型号对应大小和规格的本地磁盘就会自动被挂载。

你应该还记得，我在介绍虚拟机型号的第 3 讲中，提到了“本地存储”系列的虚拟机吧？那些正是自带有大容量、高性能本地磁盘的虚拟机型号。它们或是配备了高性能的本地 NVMe SSD 磁盘，或是装备有高吞吐的先进 HDD，数量可能还不止一块。妥善使用这些本地磁盘，在合适的场景下，能够帮你发挥很大的作用。

比如，你要在云上用虚拟机自己搭建一个经典的 Hadoop 集群，要用虚拟机的磁盘组合成 HDFS（Hadoop 的分布式文件系统），并希望使用 MapReduce 或 Spark 等支持数据本地性（Data Locality）的计算框架。这时，你就应该考虑使用带有本地磁盘的机型了。

所以，当一些应用软件系统本身考虑到了硬件的不可靠性，设计了上层的存储冗余机制时，你就可以考虑采用本地磁盘。因为这种情况下，本地磁盘的可靠性缺陷得到了弥补，它的相对高性能和低成本就成为了优势。这时如果选用三副本的远程云硬盘，反倒显得有些笨重了。

还有一类，对数据丢失不敏感的临时性存储的场景，也是本地磁盘可以发挥的舞台。这些场景包括操作系统的 pagefile 或 swap 分区，以及数据库的硬盘缓存区（如 SQL Server 的 Buffer Pool Extension）等等。

不过，我还是要提醒你本地磁盘的缺点，它在本质上，还是易失性（Ephemeral）的存储，当机器关机或删除，以及出现硬件故障时，本地磁盘上的数据就可能损坏或丢失。这一点我们必须牢记，不适用的场合必须使用更可靠的远程云硬盘。

课堂总结与思考

今天我们围绕云硬盘，进行了一系列的讲解，可以简单总结如下：

云硬盘是云虚拟机的主要持久化存储，与宿主机往往是分离的；

云硬盘支持动态添加和删除，使用起来灵活方便；

云硬盘一般提供多种性能等级，最终性能会受存储介质和容量大小的共同影响；

部分虚拟机型号会自带高性能的本地磁盘，在可以容忍数据丢失风险时，是你值得考虑的一个选择。

最后，我还想补充一点，云硬盘的付费模式，同样有按量付费和包年包月之分。在很多的云上，你能够为一块云盘启用包年，长期租用的确定性也能够给你带来折扣，这和虚拟机资源的包年包月是一样的。

今天，我想和你讨论的问题如下：

我们说云硬盘可以动态地挂载和卸载，使用起来十分方便。那么更进一步的问题是，已经挂载的云硬盘能够支持在线扩容吗？

还有一种云端常见的存储类产品，如阿里云的文件存储 NAS、AWS 的 EFS 等，也可以挂载到云虚拟机。那么，你知道这种产品形态和云硬盘有什么区别，主要用于什么场景吗？

你可以在留言区和我互动。如果觉得有收获，也欢迎你把这篇文章分享给你的朋友。感谢阅读，我们下期再见。

06 | 云上虚拟网络：开合有度，编织无形之网

你好，我是何恺铎。

我们对于 IaaS 的介绍已经渐入佳境了。前面，我们主要涉及了与云虚拟机相关的计算和存储方面的内容。今天这一讲，我想要和你讨论的，则是“计算 / 存储 / 网络”三要素中的最后一项：网络。

在互联网时代，网络的重要性不言而喻，我们必须好好掌握。通过合理的网络拓扑设置，既能够帮助我们实现架构上的隔离性和安全性，又能够让各组件互联互通、有序配合。

不过网络对于许多开发者而言，有时会让人感觉是一个挺困难的话题。它复杂的设置、晦涩的术语，尤其是各种连而不通的场景，可能让你望而生畏。

请你不要担心，云上的网络经过了一定程度的抽象以后，已经为我们屏蔽了一定的复杂度。只要宏观的思路梳理得足够清晰，你很快就能够理解云上的网络组件，并让它们听你指挥、投入使用。

什么是虚拟私有网络？

虚拟私有网络（Virtual Private Cloud，简称 VPC），是云计算网络端最重要的概念之一，它是指构建在云上的、相互隔离的、用户可以自主控制的私有网络环境。虚拟私有网络有时也称为专有网络（阿里云）或虚拟网络（Virtual Network 或 VNet，Azure 的叫法）。

上面的概念解释也许不太好理解，其实用通俗的话来讲，私有网络就是一张属于你自己的内网。内网之内的服务器和设备，可以比较自由地互相通信，与外界默认是隔离的。如果外部互联网，或者其他虚拟网络需要连接，则需要额外的配置。

所以说，虚拟私有网络，就是你在云上的保护网，能够有效地保护网内的各种设施。有的时候，你可能还要同时创建多个虚拟网络，让它们各司其职，实现更精细的隔离。

小提示：在一些云上，除了私有网络，你可能还会看到“经典网络”的选项。这是上一代的云上内网基础设施，虽然它配置起来相对简单，但在隔离性、可配置性上有许多局限。现在已不推荐使用了。

虚拟私有网络麻雀虽小，但五脏俱全。在传统数据中心里，经典网络架构中的概念和组件，在虚拟网络中你几乎都能找到对应。这里比较重要的一些概念包括：

网段，私有网络的内部 IP 区段，通常用 CIDR 形式来表达，如 192.168.0.0/16。

子网，私有网络的下级网络结构，一个私有网络可以划分多个子网，这和通常意义上的子网也是对应和一致的。阿里云中把子网形象地称为“交换机”。

路由表，用于定义私有网络内流量的路由规则，决定着数据包的“下一跳”去向何方。每个子网都必须有一张关联的路由表，通常情况下，系统会自动帮你创建一个默认的路由表。

网关，是对进出私有网络的流量进行把守和分发的重要节点，根据用途的不同，有多种类型，后面我们还会讲到。

安全组，私有网络里虚拟机进出流量的通行或拦截规则，可以起到虚拟机网络防火墙的作用，我们曾经在第 2 讲中提到过它。

所以在创建虚拟网络时，你就需要对上面这些重要属性进行按需设定。

下面，我就以阿里云 VPC 为例，来带你实际操作体验一下。

首先，我们来到阿里云的专有网络管理控制台，选择新建一个 VPC，这里的网段我们选择 192.168.0.0/16：

注意：VPC 属于局域网，按照 RFC 规范，能够使用的 IPv4 区段必须为 192.168.0.0/16、172.16.0.0/12、10.0.0.0/8 这三个或它们的子集。

同时，我们还至少要创建一个子网，也就是交换机。我们选择一个子 IP 段 192.168.0.0/24，并且设置所属可用区为“可用区 D”：

我们再来创建另外一个交换机，网段设置为 192.168.1.0/24。这里的关键在于，我们可以让第二个交换机位于另外一个可用区 E：

这就说明，我们可以建立跨可用区，也就是跨同区域内不同数据中心的私有网络。这是 VPC 的一个强大的特性，能够为我们私有网络的高可用性提供保障。比如，你可以让主力集群在一个可用区工作，备用集群在另一个可用区随时待命，需要时迅速切换；你也可以把流量同时分发到不同的可用区，动态控制分发策略。

就这样，我们收获了一个包含两个交换机的 VPC。

查看一下它的路由表，你可以发现，它自动为我们包含了两个子网的路由信息：

你看，创建 VPC 其实并不困难。这里的关键还是要规划好 VPC 和各子网的网段，需要让它们既有足够的地址空间以供资源拓展，又不要安排得范围过大，以免和其他 VPC 或公司内部网络产生地址冲突，为后续的网间互联带来不必要的麻烦。

如果你在没有 VPC 的情况下直接创建虚拟机，公有云一般都会为你自动生成 VPC。在生产环境中，我强烈地建议你不要让系统自动建立 VPC，而是像我们上面的做法，先自行建立好 VPC，配置好子网和网段等重要参数，然后再创建云虚拟机“入住”。因为这样，你会事先让自己有一个明确的网络规划，对整个 VPC 的把控和理解也会更强。

私有网络中的虚拟机

让我们回到虚拟机的视角。当一个虚拟网络已经存在时，我们就可以将新创建的虚拟机放置在这个虚拟网络中。

那么，这个所谓的“放置”是怎么真正产生的呢？虚拟机和专有网络的连接点是哪里呢？

答案就在于虚拟机的网卡，又称弹性网卡（Elastic Network Interface， 简称 ENI）。虚拟机的网卡一方面是和虚拟机的本体进行绑定，另一方面则嵌入某个私有网络的子网，也会拥有至少一个私网 IP。

云上的网卡，之所以被称为“弹性”网卡，是因为它具备以下特征：

一个虚拟机可以绑定多块网卡，有主网卡和辅助网卡之分；

一块网卡隶属于一个子网，可以配置同一子网内的多个私有 IP；

辅助网卡可以动态解绑，还能够绑定到另一台虚拟机上。

这再次体现了云计算的解耦特征，在某些场景下是非常有用的。比如，有一台服务线上流量的机器，而且线上流量导向的是它的辅助网卡，那么当这台机器因故无法正常工作时，你在排查问题的同时可以考虑这样一个应急的办法：将这台机器的辅助网卡迅速解绑，并重新绑定到待命的备用机上。这样就能够比较快地先恢复对外服务。

当你在创建虚拟机的时候，向导会询问你，这台虚拟机属于哪个 VPC，以及 VPC 下的哪个子网？现在你就理解了，这个选项的实质性结果，就是新虚拟机自动生成的主网卡，接入了所选 VPC 的所选子网。

好了，网卡和私有 IP 的部分你应该已经比较清楚了。那么你可能会问，公有 IP 呢？这正是我想说的另一个比较关键的部分。

在绝大多数的云上，创建虚拟机时都会有一个选项，问你“是否同时为虚拟机分配一个公网 IP 地址”。如果你选择“是”，这样机器启动后，就会拥有一个自动分配的公网地址，便于你从自己的电脑连接到这个实例。这在很多时候都是最方便的选择。

但对于生产环境，我的推荐是，尽量不要使用和依赖这个自动生成的公有 IP。因为它本质上是一个从公有云的 IP 池中临时租用给你的 IP。如果你的机器关闭或重启，下次获得的 IP 可能就完全不同了。

这时，我们真正应该用到的是弹性 IP（Elastic IP），有些云称为 eIP。弹性 IP 一旦生成，它所对应的 IP 是固定、不会变化的，而且完全属于你所有。这非常适合需要稳定 IP 的生产环境。

请不要被它的名字迷惑，它所谓的弹性，其实是指可以非常自由地解绑和再次绑定到任意目标。你本质上是买下了这个 IP 的所有权，将这个 IP 赋予谁，是你的权利，而且你还可以动态按需切换。

所以，当你有一个域名，需要让 DNS 服务解析到某个外部 IP，你就应该建立一个弹性 IP，绑定到相关资源后，让域名解析到这个弹性 IP，而不应该使用虚拟机自动匹配的公有 IP。因为后者是不稳定的。

好，让我们继续进入实验的部分。我们在刚才的 VPC 内来建立一台虚拟机，起名为 vm1-in-vpc1，把它放置到位于可用区 E 的第二个交换机中，并且选择不自动生成公有 IP。

注意，这时它只有私有 IP，我们怎么连接它呢？我们可以创建一个弹性 IP，然后绑定到这台实例：

绑定之后，就自然可以连上刚才的这台虚拟机了。注意 VM 列表界面会有相应的显示：

尝试 SSH 连接一下，一切正常：

client@clientVM:~$ ssh root@47.102.139.39
root@47.102.139.39's password:
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-72-generic x86_64)
 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage
Welcome to Alibaba Cloud Elastic Compute Service !
root@vm1-in-vpc1:~#

如何让私有网络对外“开口子”？

在阿里云上，如果一台云虚拟机没有被赋予公有 IP，默认情况下它就失去了访问外网的能力，只能进行内网通信，这在很多时候，的确是我们想要的安全控制。但也有一些情况，我们希望内网的机器和外界并不完全隔离，一些互联网流量需要有序地引进来，一些内网机器也需要访问外网。

这就是一个如何在 VPC 上“开口子”的问题了。

当然，你可以使用前面提到的弹性 IP，绑定到相关虚拟机上。不过，如果我们需要访问外网的虚拟机数量有很多，这种办法就需要很多弹性 IP，管理上就太麻烦了，成本也不划算。还有一个问题是，弹性 IP 带来的是双向的开放，有时我们只想允许单向的连接。

这就是网关可以大显身手的场景了，它正是用来统一协调管理私有网络与外部通信的组件。随着各个公有云的发展，云上也延伸出了许多不同形式、解决不同目的的网关产品。

我们这里讨论一个常见的场景，即如何允许多台没有公有 IP 的虚拟机访问外网。这时需要使用到的网关叫做 NAT（Network Address Translation）网关，是一种常见的用来给 VPC 开口的手段。

我们继续以阿里云为例，来看下如何通过 NAT 网关让虚拟机访问外网。

我们可以事先把弹性 IP 从刚才那台虚拟机解绑，这下它现在又无法访问外网了：

root@vm1-in-vpc1:~# curl myip.ipip.net
curl: (7) Failed to connect to myip.ipip.net port 80: Connection timed out

接着我们创建一个 NAT 网关实例，并选择它对应的 VPC，然后把刚才解绑的弹性 IP(47.102.139.39) 绑定到 NAT 网关上：

这里的关键之处在于接下来我们要添加的 SNAT 条目。

SNAT 是“源地址转换”的意思，它非常适合让私有网络的主机共享某个公网 IP 地址接入 Internet。注意，这是一种从内向外的、单向的连通形式。

上面我们添加了一个 SNAT 条目，让整个交换机“test-vpc1-vsw2”下的网段都共享一个出口公网 IP。你要注意，我们的虚拟机是位于这个网段内的。

接着再回到这台虚拟机内，我们通过 curl 命令，尝试对外访问：

root@vm1-in-vpc1:~# curl myip.ipip.net
当前 IP：47.102.139.39  来自于：中国 上海 上海  阿里云/电信/联通/移动/铁通/教育网

很棒，这回成功地连通了。而且外部网站也显示，我们正在使用的外网 IP 正是那个弹性 IP(47.102.139.39)。这就是对于 NAT 网关的一个小小实验了。

还有一种网关被称为 VPN 网关，也可以帮助外界连接到 VPC，它本质上是基于你所熟知的 VPN 技术。由于 VPN 能够基于互联网提供私有加密的通信，因此非常适合用来从任意其他私有设施安全地连接到 VPC。这些私有设施可以小到一台个人电脑或手机终端，也可以大到是你本地的数据中心，还可以是另一个 VPC。

多网连接有哪些方式？

前面我们主要是从单个 VPC 的角度来进行讨论的，那么最后，我们再来讨论一下多 VPC 的场景。公有云上是允许你同时使用多个 VPC 的，这样你可以构建更加复杂的网络架构，实现模块隔离和跨区域扩展等高级需求。

如果是云端 VPC 和 VPC 的互联，我首先推荐的就是对等连接（VPC Peering）的方式。它能够在不添加额外设备的情况下，让两个 VPC 无缝地互联起来，而且操作非常简单，对等连接甚至还能够支持跨区域的私有网络互联。当然，对等连接的实施前提，是这两个 VPC 的网段没有交集，不存在冲突。

这里你需要注意对等连接的一个特点，就是它不具备传递性。也就是说，如果 A 和 B 建立了对等连接，B 和 C 建立了对等连接，那么 A 和 C 是不相通的。这是对等连接的一个局限。

如果你真的需要多个 VPC 间任意路径的互联互通，那么可以考虑使用比对等连接更为复杂和强大的专用网络设施，比如 AWS 的 Transit Gateway，和阿里云的云企业网，它们能够帮助搭建更为复杂的多 VPC 网络拓扑结构，也允许进行更精细的路由设置。如有需要，建议你仔细阅读厂商的文档进行学习和研究。

公有云中的私有网络，还可以和企业本地数据中心进行互联，形成混合云架构。你可以先考虑使用 VPN 这种轻量的方式，通过公网线路为两边建立连接渠道。但如果应用场景要求保证延迟和带宽，一般就需要专线进行连接了。绝大多数的云厂商，都提供了云端区域和本地数据中心进行高速互联的服务和解决方案，比如 AWS 的 Direct Connect、Azure 的 ExpressRoute 和阿里云的“高速通道”（云下 IDC 专线接入）等等。一般专线还会和 VPN 一起组合使用，来保证通道的高可用性。

小提示：与较为易用的 VPC 互联相比，混合云的构建是一项较为复杂的工程，通常需要由本地机房、云厂商、电信运营商三方配合进行，也牵涉到本地数据中心端的网络规划和路由设备适配。这超出了我们开发者课程的范畴。如需实施，建议你仔细咨询云厂商工作人员。

课堂总结与思考

今天，我主要为你介绍了云上虚拟网络，包括它的具体组成、使用场景和连接性问题。我还给你推荐了一些在生产环境下的最佳实践。

从某种程度上来说，虚拟私有网络的“仿真度”非常高，在软件定义网络（SDN）技术的加持下，甚至比物理网络还要更加灵活高效，更易于扩展。所以，通过合理的规划和设置，云端的网络基础设施能够让我们拥有一个健壮而强大的网络拓扑结构，对于流量的引导和控制，也完全能够做到因势利导、开合有度。

需要特别说明的是，在主体理念保持一致的情况下，各个云厂商在具体实现上，其实是各显神通的，会有一些细节存在差异。这是正常的现象，请你在实践时注意。比如说，和阿里云不同，AWS 的 VPC 中访问外网，需要经由专门的 Internet Gateway 来通行流量，路由表中也需要进行相应的设置。

好了，今天我给你留下的思考题是：

在虚拟私有网络的内部，两机互联的带宽有多大呢？可能受到哪些因素的影响？

在今天的实验中，我们通过 NAT 网关实现了流量“出网”的目的。那么，如果是反过来需要引导外界流量进入 VPC，应该使用什么方式呢？

欢迎你在留言区和我互动，我会一起参与讨论。如果觉得有收获，也欢迎你把这篇文章分享给你的朋友。感谢阅读，我们下期再见。

07 | 云端架构最佳实践：与故障同舞，与伸缩共生

你好，我是何恺铎。这一讲，我们来谈谈云上架构的注意事项和最佳实践。

云上架构最需要注意什么呢？就像我在标题所描述的那样，云端架构一方面需要处理和应对可能出现的故障，保证架构和服务的可用性；另一方面则是需要充分利用好云端的弹性，要能够根据负载进行灵活的伸缩。

面对故障，提升冗余

故障，是 IT 业界的永恒话题。故障的原因多种多样，无论是由于硬件的自然寿命造成的，还是数据中心的极端天气捣鬼，或是人工运维操作上的失误，不论我们多么讨厌它，故障似乎总是不可避免。

你也许会问，那么，云计算会有故障吗？比如说，云上创建的虚拟机，是否百分之百会工作正常呢？

很遗憾，虽然公有云们为了避免故障，在许多层面上做了冗余和封装，但云也不是可以让你永远无忧无虑的伊甸园。我们需要牢记，云端的服务仍然是有可能出故障的，只是概率上的不同而已。这也是云供应商们为云服务引入服务等级协议（Service Level Agreement，简称 SLA）的原因，它主要是用来对服务的可靠性作出一个预期和保证。

SLA 的可用性等级可能是 99.9%，也可能是 99.99%，它能够表明某项云服务在一段时间内，正常工作的时间不低于这个比例，也代表了厂商对于某项服务的信心。不过你要知道，再好的服务，即便是 SLA 里有再多的 9，也不可能达到理论上的 100%。

小提示：当实际产生的故障，未达到 SLA 的要求时，云厂商一般会给予受到影响的客户以消费金额一定比例金额的赔付。不过很多时候，赔付的金额不足以覆盖业务上的经济损失，你不应该依赖它。

所以，从架构思维的角度上来说，我们需要假定故障就是可能会发生，对于它的影响事先就要做好准备，事先就进行推演并设置相关的冗余和预案。AWS 有一个非常著名的架构原则，叫做 Design For Failure，讲的也就是这个意思。

好在云上做高可用架构同样有自己的特点和优势，我们可以轻松地调用各个层面的云端基础设施来构建冗余，规避单点的风险。

那么，云上可能出现哪些不同层面的故障？相应的故障范围和应对措施又会是怎样的呢？我们不妨从小到大，依次来看我们可能遇到的问题和解决办法。

第一种故障是在宿主机的级别，这也是从概率上来说最常见的一种故障。当宿主机出现硬件故障等问题后，毫无疑问将影响位于同一宿主机上的多个虚拟机。为了避免产生这样的影响，当我们承载重要业务时，就需要创建多台虚拟机组成的集群，共同来进行支撑。这样，当一台虚拟机出现故障时，还有其他几台机器能够保证在线。

这里需要注意的是，我们需要保证多个虚拟机不在同一台宿主机上，甚至不处于同一个机架上，以免这些虚拟机一起受到局部事故的影响。那么，要怎么做到这一点呢？

虚拟机的排布看似是一个黑盒，但其实在公有云上是有办法来对虚拟机的物理分配施加干预，让它们实现分散分布，隔开一段距离的。这一特性，在 AWS 称为置放群组（Placement Group），Azure 称为可用性集（Availability Set），阿里云对应的服务则是部署集。比如说，我们对阿里云同一个可用区内的虚拟机，在创建时选择同一个部署集，就可以保证相当程度的物理分散部署，从而最大限度地保证它们不同时出现故障了。

第二种规模更大的故障，是在数据中心，也就是可用区的层面。比如火灾、雷击等意外，就可能会导致数据中心级别的全部或者部分服务类型的停摆。有时一些施工导致的物理破坏，也会挖断光纤，影响可用区的骨干网络。

要应对这类故障，我们就需要多可用区的实例部署，这也是云抽象出可用区概念的意义所在。你的实例需要分散在多个可用区中，这样，可用区之间既可以互为主备，也可以同时对外服务，分担压力。另外，也不要忘记我在上一讲中所提到的，虚拟私有网络可以跨越可用区，这会大大方便我们多可用区架构的搭建。

第三种更严重的故障，就是整个区域级别的事故了。当然这种一般非常少见，只有地震等不可抗力因素，或者人为过失引发出的一系列连锁反应，才有可能造成这么大的影响。

区域级别的事故一般都难免会对业务造成影响了。这时能够进行补救的，主要看多区域架构层面是否有相关的预案。如果是互联网类的服务，这时最佳的做法，就是在 DNS 层面进行导流，把域名解析到另外的一个区域的备用服务上，底层的数据则需要我们日常进行着跨区域的实时同步。

再更进一步的万全之策，就需要考虑多云了，也就是同时选用多家云厂商的公有云，一起来服务业务。虽然集成多个异构的云会带来额外的成本，但这能够最大限度地降低服务风险，因为两家云厂商同时出问题的概率实在是太低了。更何况，多云还能带来避免厂商锁定的好处，现在其实也越来越多见了。

综上所述，不论是哪种级别的故障，我们应对的基本思想其实没有变化，都是化单点为多点，形成不同层面、不同粒度的冗余。当故障发生时，要能迅速地发现和切换，平滑地过渡到备用的服务和算力上。

当然，盲目地追求可用性也不可取。根据业务需求，在成本投入与可用性之间获得一个最佳的平衡，才是你应该追求的目标。试想一下，构建一个个人博客网站，和建立一个金融级系统，两者在可用性架构方面的要求显然天差地别，所以我们最后的架构选择也会大相径庭。

随机应变，弹性伸缩

弹性伸缩，这是云上架构的另一个原则，也是云端的重要优势。

由于云的本质是租用，而且它便捷的操作界面、丰富的 SDK 和自动控制选项，使得云上“租用”和“退租”的成本很低，可以是一个很高频的操作，这就为弹性伸缩在云上的出现和兴起提供了土壤。在妥善应用之下，弹性伸缩既可以提高工作负载洪峰来临时的吞吐和消化能力，提高业务稳定性，又能够在低谷期帮我们显著地节约成本。

在 IaaS 端，能够弹性伸缩的最实用的产品形态，莫过于虚拟机编组了，也就是功能相同的多个虚拟机的集合。把它们作为一个单位来创建、管理和伸缩，是一种普遍应用的最佳实践。AWS 中相关的产品命名是 EC2 自动伸缩（Auto Scaling），Azure 中是虚拟机规模集（VM Scale Set），阿里云则叫做弹性伸缩。

我们把多个虚拟机以弹性伸缩组的方式进行统一管理，能够极大地提高效率，减轻负担。因为弹性伸缩服务，会帮我们动态地创建和销毁虚拟机实例，自动根据我们指定的数量和扩缩容规则，来协调虚拟机的生命周期。我们只需要从高层进行指挥就可以了。

弹性伸缩服务，在云端还有一个最佳拍档，就是负载均衡器。它特别适合将流量均匀地，或者按照一定权重或规则，分发到多台虚拟机上，正好可以和提供计算资源的弹性伸缩服务形成配合。当负载增大、虚拟机增加时，负载均衡也能够自动动态识别，将流量分发到新创建的虚拟机上。

所以，你可以尝试使用弹性伸缩服务来实现云端弹性架构，用它来管理一组虚拟机，并与负载均衡一起配合。这特别适合处理无状态类的计算需求，因为它会为你代劳底层计算资源的管理。

高可用的弹性架构实战

结合上面的介绍，让我们进入这一讲的实战环节。

我们来模拟一个线上高可用服务的场景，来看下如何用阿里云进行服务的搭建。我会在上一讲搭建的虚拟私有网络的基础上来提供服务，并做到一定程度的故障隔离和弹性扩展。

我们先用 Node.js 来搭建一个简单的 Web 服务，用来计算著名的“斐波那契数列”。相关的源码如下，供你参考：

const express = require('express');
const ip = require('ip');
const os = require('os');
const app = express();
//使用递归计算斐波那契数列
function fibo (n) {
    return n > 1 ? fibo(n-1) + fibo(n-2) : 1;
}
app.get('/', function(req,res) {res.write('I am healthy'); res.end();} );
app.get('/fibo/:n', function(req, res) {
    var n = parseInt(req.params['n']);
    var f = fibo(n);
    res.write(`Fibo(${n}) = ${f} \n`);
    res.write(`Computed by ${os.hostname()} with private ip ${ip.address()} \n`);
    res.end();
});
app.listen(80);

我们在上一讲创建的虚拟机“vm1-in-vpc1”中安装好 Node 环境，将上述代码放入一个起名为“app.js”的文件中，用 npm 安装 express 等相关依赖后，就可以用命令“node app.js”直接运行了。然后，我们需要把这个服务设置为开机自动启动（你可以通过 npm 安装 pm2 组件来帮助实现开机自动启动），这样一个简单的 Web 服务就搭建好了。

为了让之后的外部流量能够进入到内部网络的多台虚拟机中，我们来建立对外的负载均衡实例。要注意，负载均衡器本身也需要是高可用的，我们这里主要选择华东 2 区域下的可用区 D，让可用区 E 作为备可用区，和我们的 VPC 保持一致。

然后，在负载均衡器上配置一个 HTTP 协议 80 端口的监听，后端服务器可以先指向我们的测试机 vm1-in-vpc1，然后从外部测试负载均衡器的连通性。

[client@clientVM ~]$ curl http://47.101.77.110/fibo/35
Fibo(35) = 14930352
Computed by vm1-in-vpc1 with private ip 192.168.1.80

可以看到，curl 命令的响应中，成功地返回了斐波那契数列第 35 项的结果值，以及相关服务器的名称、IP 等信息，说明负载均衡已经初步正常工作了。

接下来，我们要创建一个能够弹性伸缩的虚拟机集群，来大规模地对外输出这个计算服务。

作为准备工作，我们要先为 vm1-in-vpc1 创建一个镜像，作为新建虚拟机的“种子”：

然后，我们就可以创建弹性伸缩实例了。我们来建立一个最小数量为 2，最大数量为 10 的伸缩组。在这个过程中，你尤其需要注意，要选取上一讲中建立的 VPC 作为目标网络，同时选择两个分属不同可用区的交换机，并设置为均匀分布策略。如下图所示：

同时在这里，我们还为伸缩组和刚才建立的负载均衡器建立了关联，这样弹性伸缩实例中的机器，会自动地进入到负载均衡后端服务器的列表中。

下一步是建立伸缩配置，这里主要是指定虚拟机模板，记得选取我们刚才创建好的自定义镜像：

启用伸缩配置后，很快就能看到弹性伸缩服务为我们建立了两台虚拟机了：

在 ECS 控制台，你也可以清楚地看到，这两台机器被自动分配到了不同的可用区中，分属不同的交换机：

我们再设置一下非常重要的伸缩规则，这会告诉伸缩组何时进行自动扩缩容。这里我们选择监控平均 CPU 指标，我们希望理想状态下控制在 50% 左右。换句话说，如果平均 CPU 偏离 50% 太远，系统就会自动地为我们增加或减少机器。

回到最佳拍档负载均衡的管理界面，我们也看到弹性伸缩组中的两台机器，已经位于后端服务器列表中了（这时可以将测试机 vm1-in-vpc1 从后端服务中删去）：

我们试着来反复地访问负载均衡端的同一个入口 URL，会获得来自不同可用区中不同机器的响应，这说明负载均衡的随机分发起到作用了：

[client@clientVM ~]$ curl http://47.101.77.110/fibo/35
Fibo(35) = 14930352
Computed by iZuf68viqv1vrqntkpyihaZ with private ip 192.168.0.234
[client@clientVM ~]$ curl http://47.101.77.110/fibo/35
Fibo(35) = 14930352
Computed by iZuf67wyymbgnnd69wkf31Z with private ip 192.168.1.89

最后也是最精彩的部分，我们来使用 siege 命令来持续冲击这个负载均衡，使集群的平均 CPU 升高，看看它是否会自动扩容。

[client@clientVM ~]$ siege -c 15 -t 20m http://47.101.77.110/fibo/35
** SIEGE 4.0.2
** Preparing 15 concurrent users for battle.
The server is now under siege...
HTTP/1.1 200     0.14 secs:      88 bytes ==> GET  /fibo/35
HTTP/1.1 200     0.16 secs:      87 bytes ==> GET  /fibo/35
HTTP/1.1 200     0.28 secs:      88 bytes ==> GET  /fibo/35
HTTP/1.1 200     0.29 secs:      87 bytes ==> GET  /fibo/35
HTTP/1.1 200     0.41 secs:      88 bytes ==> GET  /fibo/35
...

果然，流量到来后，虚拟机的 CPU 飙升，伸缩组就自动地进行了新实例的创建，一直达到了我们设定的十台上限，以满足汹涌到达的计算请求。

伸缩组的峰值状态

伸缩活动历史记录

当 siege 命令停止后，平均 CPU 大幅降低，伸缩组还能自动地缩容，减少实例数量。上面的伸缩活动的截图也体现了这个过程。

至此，我们的跨可用区负载均衡的实验就大功告成了。

你也可以结合你实际的场景，来进一步地实验和拓展这个范例。比如在生产环境中，你通常需要为负载均衡的外部 IP 绑定正式的域名；或者你的 Web 服务很可能不是完全无状态的，需要依赖后端数据库；再比如，你可以尝试在别的区域再建立一个 VPC，让两个 VPC 互相连接，新 VPC 可以作为冷备，或者承担日志数据分析的工作，这样能够形成一个类似“两地三中心”的强壮架构。

课堂总结与思考

今天涉及的点比较多，我们谈到了故障范围和故障处理，也谈到了云端的弹性优势。这次的实验也相对大一些，比较完整地构造了一个负载均衡加弹性伸缩的架构。不知道你掌握得怎样，有没有相关的问题，欢迎你在这里留言，和我一起探讨。

今天我留给你的思考题是：

大多数云上负载均衡产品都有一个重要特性，叫做“会话保持”，你知道它是用来做什么的吗？它的原理又是什么呢？

默认情况下，弹性伸缩服务会使用按量计费的虚拟机。那么成本上更有优势的包年包月虚拟机，或者竞价实例的虚拟机，能够融入弹性伸缩的体系吗？

好了，今天我们就到这里。如果你觉得有收获，欢迎把这篇文章分享给你的朋友。感谢阅读，我们下期再见。

08 | 云上运维：云端究竟需不需要运维？需要怎样的运维？

你好，我是何恺铎。

谢谢你的努力和坚持，我们已经学习了 IaaS 篇中的大多数内容。今天是 IaaS 部分的最后一讲，我们来谈谈云上的运维工作。

云端需要运维吗？

既然要谈运维，我们得先回答这个必要性的问题。许多人都觉得，因为云服务大多都具有了非常高的可靠性和自动化程度，所以在云时代，运维就不那么重要了，甚至是可以省略的事情了。

这种观点有意无意地散播，其实会造成一些负面的影响。开发者会容易轻视运维工作的重要性，忽略架构设计中运维友好性问题；而从事运维方向的工程师们，可能更会有点儿焦虑，甚至于担心未来的职业生涯。

但很显然，这是一种误解。云端当然需要运维，而且云上运维很重要。因为不管在什么样的运行环境下，运维的本质和需求都没有消失，一样要为业务保驾护航，要保证系统的正常运作、应对突发情况等等。

云时代的运维，正确的理解应该是这样的：云不但没有消灭运维，反而是助推了运维的发展。

这是因为，云的引入能够让我们在更高的层面去思考和解决问题。比如说，云端基础设施的存在，可以让运维从偏硬件服务器、偏物理机房的日常繁琐工作中解脱出来，更多地基于云在软件的层面，进行部署、监控、调整。而云上的高质量、高可用的服务，也能避免我们重复建设，不用自己造轮子，也大大减轻了运维负担。

注意：底层的机房运维、基础架构运维仍然会继续存在，但会向头部的云供应商大规模集中。这属于云厂商的运维视角，是另一个宏大的话题，我们这里不多做讨论。

所以，云其实是提高了运维的效率，改变了运维的形态。

与此同时，由于云上运维的软件属性显著增强了，它就自然地和研发会有更强的融合。近期 DevOps 理念和云原生热潮的兴起，就说明了这一点。许多工作，你慢慢地会分不清它究竟是属于运维还是研发，因为两者的界限正在模糊。

另外，由于云独有的一些特点，它也会带来一些新的运维工作。比如我们课程中一直在涉及的成本控制，这也是云时代新运维所应当关注和包含的重要事项。因为云的成本消耗是动态、时刻发生着的，这和传统运维中的各类实时监控的对象，在形态上非常接近。

所以，云端需要运维吗？答案已经不言而喻了。

云时代的运维利器

工欲善其事，必先利其器。为了做好扎实的云上运维，首先我给你的一个建议是，你需要掌握云的命令行工具。现在几乎每个云都推出了自己的命令行工具，比如 AWS CLI、Azure CLI、阿里云 CLI 等等。

在前面各讲的例子中，为了便于你学习和理解，我都使用了公有云的网站门户来进行操作。但如果是在生产环境，你需要对很大规模的资源池逐个进行调整，或者同一件事情，你需要在不同时间反复地操作很多遍，那你就很可能需要将这些操作脚本化、程序化，这就需要用到云的命令行工具了。

虽然命令行工具有一定的学习曲线，但如果你熟悉了以后，其实是可以干脆利落地表达一个操作的。比如说，如果你要创建在第 6 讲的实验中，使用的虚拟机“vm1-in-vpc1”，你就可以使用下面的 aliyun ecs 命令来轻松表达：

[client@clientVM ~]$ aliyun ecs CreateInstance --ImageId ubuntu_18_04_x64_20G_alibase_20191225.vhd --InstanceType ecs.g6.large --ZoneId cn-shanghai-e --VSwitchId vsw-uf6ls7t8l8lpt35xxxxxx
{
        "InstanceId": "i-uf6hn8z47kqve3xxxxxx",
        "RequestId": "222DA83B-0269-44BF-A303-00CB98E4AB07"
}
[client@clientVM ~]$ aliyun ecs StartInstance --InstanceId i-uf6hn8z47kqve3xxxxxx
{
        "RequestId": "8E4C43CA-8F36-422C-AEF1-14ED5023856D"
}

现在各个云的 CLI 基本上都进化到了第二代，相比第一代，CLI 在易用性和表达能力上都有了很大的提升，你不妨学习尝试一下。而且这些 CLI 都能和 Shell 编程进行比较好的融合，你可以通过脚本组合多个关联的操作。

小提示：除了命令行工具，各云还都提供了开发者工具包（SDK）。如果你的资源调度逻辑相当复杂，或者需要与你自己的程序集成，那么你可以考虑使用相应语言的 SDK，来进行云上的一些资源管理操作。

如果你要频繁地在云上部署一套包含众多资源项的复杂系统，你还有另外一个得力的帮手：资源编排类云服务。属于这个领域的服务包括有 AWS CloudFormation、 Azure 的 ARM Template、阿里云资源编排服务（ROS）等等，它们都可以通过使用一个 JSON 格式的文本文件，来描述和定义一个系统中所有的组件，以及它们互相之间的关系。

这个 JSON 文件，就是一个可以自动部署、可复用的单元了。这其实就是“基础设施即代码”（Infrastructure as Code）理念在云端的实现。

下面我给出了一个 Azure 的 ARM Template 的配置文件局部示例，可以让你有一个直观的感受：

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
      "adminUsername": {
        "type": "string",
        "metadata": { "description": "This is the username you wish to assign to your VMs admin account" }
      },
      ...
    },
    "variables": {
      "nicName": "VMNic",
      "addressPrefix": "10.0.0.0/16",
      "imagePublisher": "Canonical",
      ...
    },
    "resources": [
      {
        "apiVersion": "2015-05-01-preview",
        "type": "Microsoft.Network/publicIPAddresses",
        "name": "[variables('publicIPAddressName')]",
        "location": "[parameters('location')]",
        "properties": { "publicIPAllocationMethod": "[variables('publicIPAddressType')]" }
      },
      {
        "apiVersion": "2015-05-01-preview",
        "type": "Microsoft.Network/virtualNetworks",
        "name": "[variables('virtualNetworkName')]",
        "location": "[parameters('location')]",
        "dependsOn": [
          "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
        ],
        "properties": { ... }
      },
      {
        "apiVersion": "2017-03-30",
        "type": "Microsoft.Compute/virtualMachines",
        "name": "[variables('vmName')]",
        "location": "[parameters('location')]",
        "dependsOn": [ "[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]" ],
        "properties": {
          "hardwareProfile": { "vmSize": "[parameters('vmSize')]" },
          "networkProfile": {
            "networkInterfaces": [
              { "id": "[resourceId('Microsoft.Network/networkInterfaces',variables('nicName'))]" }
            ]
          },
          ...
        }
      },
      ...
    ]
  }

注：这个文件是用于配置单机 WordPress 网站的模板，这里略去了许多内容，其全貌可以参见这个链接。

这类资源编排服务，理论上能够支持云上所有服务的组合，而且配置节点互相能够引用，功能十分强大。它还具有一定的灵活性，一般都有输入参数字段，允许你在部署时动态决定一些选项和参数值，还可以自定义结果输出字段，方便部署完成后告诉你一些结果信息。

在这类资源编排部署系统的帮助下，我们云端部署类的工作可以得到极大的自动化。

云运维由哪些工作组成？

有了趁手的工具之后，我们下一个需要讨论的问题就是，云时代的运维具体有哪些重要的工作呢？哪些是和传统运维一脉相承的事情，哪些又是在云环境下所特有的内容呢？

现在，我就和你一起来简单梳理一下。

首先，在云端，传统的运维工作仍然存在，其中包括你所熟知的监控、部署、升级、备份等等。只是操作手段会有所不同，比如在云上，我们可以利用前面说到的命令行工具和资源模板来进行部署。

监控一直是运维最核心的工作之一。几乎所有的云端服务都自带有一定的监控功能，默认提供了不少内置的维度指标和可视化图表，这些开箱即用的图表你要充分利用好，它们能够很好地帮助你了解相关服务的状态。

那么，如果自带的监控不够用怎么办？其实这些默认的统计监控的背后，往往都是由云的一个大型统一监控服务来支撑的，如 AWS 的 CloudWatch 和 Azure 的 Monitor 等等。你可以好好研究一下这类统一监控服务，通过它可以满足你更深度的自定义监控需求。

另外，这些你精心选择和设置的监控项，还能够和云上的仪表盘服务，以及报警服务联动，轻松实现运营监控的“大屏”和问题的实时报警。

Azure 上的自定义监控仪表盘示例

这里我还想再多谈一谈备份。

备份是一个简单但又很容易被我们忽视的事项。即便是在云端，尽管云厂商已经做了许多如三副本之类的防护措施，但还是会存在出故障的可能，所以我们仍然需要做好备份，尤其是重要数据的备份。总之，我们在云上需要创造多层次的冗余，而备份在创造冗余方面也承担着重要的角色，有的时候，它会是我们的最后保障。

在 IaaS 的虚拟机层面做备份，你的得力助手会是镜像和快照。

镜像我们在上一讲中已经接触过了，它可以用来恢复虚拟机；快照则是云磁盘级别对应的备份概念，它可以帮助你将某块磁盘某一时刻的状态进行封存和恢复，你还可以定期定时为一些重要磁盘自动生成快照。

注意：不要小看镜像和快照这样简单基础的操作，像在第 5 讲中提到过的创业公司严重事故，就完全可以通过简单的磁盘快照进行避免。因为快照的存储本身不依赖于云盘，这就是额外的冗余。

除了虚拟机和磁盘层面，文件层面的备份同样重要而有效。而且文件的备份最好还能以异地的方式来存储。云上的对象存储可以在这方面肩负重任，我在 PaaS 篇中会做专门讲解。

其次，你的运维工作中很可能包含迁移。

这是带有云端特色的运维任务，因为只要不是在云上创建的全新业务，传统业务在逐步上云的过程中一定会面临迁移工作。

迁移显然是非常大的一个话题，有些复杂的迁移项目，持续的时间可能长达几个月。这里我想告诉你两点最核心的建议：

第一，在生产业务切换过来之前，一定要对云上的新架构、新方案进行充分而深入的 POC 测试，不可操之过急。对于复杂场景，可能要通过不断地实践，才能够逐步进化出完善的云上解决方案。

第二，对于一些虚拟机、数据库等独立的软硬件单元，许多云厂商都提供了官方的迁移服务或工具，支持离线甚至在线迁移，妥善使用可以事半功倍。比如 AWS 的主机迁移服务 SMS（Server Migration Service）、数据库迁移服务 DMS（Database Migration Service）和阿里云的数据传输服务 DTS（Data Transmission Service）等。

所以，当你遇到一些迁移场景时，不妨先查一查云厂商是否有官方的支持。由于迁移类服务能够直接为厂商导流获客，所以云厂商一般都会比较重视，往往能给你提供相当好的用户体验。

再次，云上的运维会包含和云厂商进行对接的工作。

毕竟我们的大厦是建立在云厂商所提供的基础设施之上的。云虽然已经高度成熟，但作为一个高度复杂的系统，也总难免会有不按你所期望进行工作的时候，或者极为偶尔也会出些小 Bug，这时和云厂商的对接渠道就显得尤为重要了。

所以，我们的运维团队中需要有相应的角色对云的工单机制，以及技术支持侧的对接方式了然于胸，以备不时之需。你也要熟读文档，要吃透云计算的许多特性，这样才能更准确地与客服沟通，更快地寻求到对口的帮助，最后解决好问题。

最后，云上运维会具有很强的管理属性。

这里的管理，指的不仅仅是对云上资源的管理，更要深入到流程和制度的管理层面。比如对于云资源的命名、开通、清理等日常操作的规范，各类云上安全的控制和最佳实践，所有云资源的负责人、所属资源组和权限体系等等。这些都需要有效的管理手段，才能避免资源在云上的野蛮生长。

所以，高明的云上运维，既要为应用开发赋能，要足够高效，也要有适当的管理和约束。我们团队的组织架构和分工，最好也能够配合和适应这个需要。

好在云厂商也在不断推出和完善与云上管理相关的配套服务，比如说，Azure Policy 能够限定只有某类型号的资源可以被创建，还可以扫描和检查各种最佳实践是否得到了应用；再比如，AWS CloudTrail 能够对账户内的操作进行监控和审计。如果你的组织内用户（团队成员）较多，就值得好好探索研究一下这一类的云服务。

当然，管理层面还有一项重要事务，就是我们多次提到的成本管理。公司或团队中，应当有专人对成本进行监控和分析，以此提升每一位用户的成本意识。我自己曾使用的实践，是按月来组织资源的使用方进行成本消耗的回顾，分析资源使用的上升、下降趋势及其主要原因，同时还会检查月度账单明细，以杜绝成本浪费。

课堂总结与思考

今天这一讲，与其说是教程，不如说是和你一起探讨云上运维的相关要点。因为篇幅所限，今天我主要总结介绍了那些最重要的，和你最需要了解的内容，没有办法深入探究每一个与运维相关的细节。但你必须知道这些事务的存在，明白云上运维需要做哪些事情，这样在你需要的时候，才能有针对性地去查找资料，找到怎么做这些事情的方法。

当前业界的一个重要趋势是，运维和开发的边界正在模糊。所以我在前面提到的诸多运维工作，可能是由开发者来负责，也可能是运维人员来承担。这要根据你们公司和部门的具体情况来决定。但至少，这些工作很重要，无论由什么角色来完成，总是需要有人来扎实落地的。

所以从个人视角来看，作为开发者，你应该学习和掌握一些运维的知识和技巧，让自己变得更加全面和综合；如果作为运维人员，你也应该学习了解现代软件构建和系统架构方面的知识，尤其是学习云、掌握云，为云端架构的全面到来做好准备。

今天留给你的思考题是：

如果要执行一些云上的 CLI 命令，你当然可以在自己的机器上安装命令行工具包，但其实你还可以使用不少云都提供的非常方便的“Cloud Shell”。那你知道什么是 Cloud Shell，以及要如何使用它吗？

前面讲到云上资源管理时，我提到了“资源组”的概念。你知道资源组是什么吗？它起到什么作用呢？

好，至此我们课程 IaaS 部分的 8 篇内容就全部结束了，希望你有所收获。下一讲，我们将进入精彩的 PaaS 世界。欢迎你留言与我交流，咱们下期再见。

09 | 什么是PaaS？怎样深入理解和评估PaaS？

你好，我是何恺铎。

欢迎你来到我们《深入浅出云计算》课程的第 9 讲，这也是我们 PaaS 篇的第 1 讲。让我们继续精彩的云计算之旅。

PaaS，对你来说也许不是一个陌生的词汇，你可能早已从业界大咖或身边同事的高谈阔论中屡次听到这个字眼。不过，很多人对于 PaaS 服务的评价，可是既有“真香快来”的赞赏，也不乏“大坑勿入”的批评，面对如此两极分化的评价，你估计也有点拿不定主意。这些如雷贯耳的 PaaS 服务们，究竟靠不靠谱、好不好用呢？

作为极客时间的一名“极客”，咱们人云亦云可不行，必须要建立起对 PaaS 的系统认知。从今天开始，我们就来好好地研究一下 PaaS。

让我们先从它的定义说起。

什么是 PaaS？

在 IaaS 篇中，我们主要是侧重于基础设施类的云服务，尤其是虚拟机、云磁盘、云网络等服务。它们的特点是，和传统 IT 基础设施往往有一个对应关系，所以被称为基础设施即服务（Infrastructure-as-a-Service）。

今天我们的主角 PaaS （Platform-as-a-Service），则是指云计算提供的平台类服务，在这些平台的基础上，用户可以直接开发、运行、管理应用程序，而无需构建和维护底层的基础设施。

用更通俗的话来说，PaaS 是在 IaaS 的基础上又做了许多工作，构建了很多关键抽象和可复用的单元，让我们用户能够在更上层进行应用的构建，把更多精力放在业务逻辑上。

拿房子装修来打个比方的话，IaaS 就好像空空如也的毛坯房，我们还需要操心墙面、地板等基础性工作；而 PaaS 就好比精装修的房子，我们只要搬入自己喜欢的家具（业务逻辑），再适当装饰就可以“拎包入住”，开始美好生活了。

小提示：PaaS 本身也是基于底层 IaaS 构建出来的，使用了云上的各种基础设施。只是这个步骤云服务提供商代替我们用户完成了，还进行了一定程度的封装。

当然，随着 PaaS 服务形态种类的增多、边界的不断扩展，除了那些包含语言运行环境、可编程和可扩展的经典 PaaS 服务之外，还有更多的在云上用来辅助应用构建，或帮助运维的服务，也归入了广义上 PaaS 的范畴。这也是有道理的，因为它们同样是完整的现代应用程序生态的一部分。

PaaS 服务的核心优势是什么？

如果你去回顾云计算的历史，可能会惊奇地发现，PaaS 并不是在 IaaS 已经非常丰富和完善之后才出现的，它们甚至可以说是“同龄人”。因为在云计算发展的初期，不同公司选取了不同的发展路线，有的侧重 IaaS，有的则先押宝了 PaaS 路线。

拓展：不论是 IaaS 还是 PaaS，想要做好都不容易，需要云厂商很大的投入。如果你对于相关的早期历史有兴趣，可以参考我在 InfoQ 上发表的文章《激荡十年：云计算的过去、现在与未来》。

从某种角度讲，PaaS 其实更符合云的初衷，它代表了一种完全托管的理想主义，也更能代表人们对于研发生产力的极致追求。

所以 PaaS 服务的优势，就在于生产力，在于效率，尤其是在搭建和运维层面。比如我们课程后面会讲到大数据类的 PaaS 服务，你可以很方便地一键启动规模庞大的大数据集群，即刻开始运行分布式计算任务。想一想，如果是由你自己基于虚拟机来进行搭建的话，肯定得花上不少功夫。

注：进一步地来说，云上的各种 PaaS 服务是可以互相配合叠加的。运用得当的话，它们联合起来爆发出来的能力会非常强，效率优势会更加凸显出来。

这里我给你举一个例子，来说明一下 PaaS 服务的优势。

日志服务是我们应用程序后端不可或缺的一个组件，通常我们会组合使用 ELK（Elasticsearch+Logstash+Kibana）技术栈来自行搭建一个日志存储和分析系统。

而在云上，你可以轻松地找到 PaaS 服务来为你代劳。比如阿里云日志服务，就提供了一个端到端的日志收集、查询、分析和可视化的解决方案。在这个过程中，你不需要搭建和维护任何基础设施，只要按照产品提示进行设置就可以了。

利用阿里云的日志服务，我大概花了 1 分钟的时间，就建立了一个日志服务实例，并让它收集某个虚拟机 / data 目录下的日志文件。随后，我在目录中放置了一本小说《双城记》，很快这个文本文件就被自动传送到了日志服务，并索引起来。然后我就可以利用 PaaS 的功能，来进行各种查询分析了。

下图为我搜索单词“happiness”的效果示例：

阿里云日志服务的简单示例

怎样入手学习研究 PaaS？

由于软件构造的复杂性，用户对于可复用组件的需求是非常多的。所以经过多年的发展下来，云上的 PaaS 已经是琳琅满目、种类繁多。我们后面的课程也会陆续地讲解各种不同形式、服务不同目的的 PaaS 服务。

但在那之前，我想告诉你观察和认知 PaaS 服务的方法。这里有几个重要的维度值得你探寻和了解，让你能在清楚了它本身的业务用途之外，还可以洞察这个服务在产品设计和内部实现方面的一些信息。

第一个维度，就是服务是否带有内生的运行环境。

我个人把它称为“承载性”，即服务有没有运行时或执行环境，来承载我们具体业务逻辑的代码或配置。如果有，那么你需要去熟悉它的运行环境，了解它支持的语法，探寻各种参数设置。比如说，Web 服务可能带有 Java、.NET 等的运行时，数据库服务可能会包含 SQL 的执行引擎。

如果没有内含的运行环境，那就说明这个 PaaS 属于“开箱即用”的工具类型，也就是直接依靠自身内置功能来向你提供支持或帮助。这时它功能的完善程度，以及和你需求的匹配程度，就比较关键了。

第二个维度，是 PaaS 服务存在的位置和范围，以及给予你的控制粒度。

这个怎么理解呢？其实就是当你新建一个 PaaS 服务的实例，你一般会需要告诉系统部署的目标位置在哪里。请你注意，这个目标位置的选项是值得玩味的。比如你要仔细看看，这个服务是只能粗放地允许你指定区域，还是可以细化到可用区，以及是否能够设置为部署在具体某个私有网络之内等等。

这个维度的信息，一方面潜在地体现了 PaaS 服务的规模和可用性。比如云存储类服务一般只能让你选择区域，因为它本身冗余性方面的多可用区架构要求，决定了它无法支持指定更精细的位置。

另一方面，这个维度也反映了你对这个服务的掌控程度，你会知道它是否能够和你现有的架构进行深度集成。比如说，你很可能要求数据库 PaaS 服务必须位于你指定的 VPC 内，这样查询流量就能走内网通信，避免对公网暴露数据库。

第三个维度，在于服务是否是“有状态”的，也就是指服务是否具有较强的数据属性。

有些 PaaS 服务本身是无状态的，比如无服务器函数，这意味着它们比较容易扩展和提升规模；有些 PaaS 服务则会保存状态，或者说建立的初衷就是为了维护各种复杂的状态和数据。这对应着 PaaS 在计算存储能力输出上的不同角色和分工。

第四个维度，体现为支撑 PaaS 的虚拟机是否对外暴露，也就是会不会显示在 ECS、EC2 等虚拟机服务的门户列表中。

这是一个很有趣的视角。因为作为 PaaS 实现者，云厂商既可以选择开放，也可以不开放。有时针对同一类的服务，不同的云也可能采用不同的做法，这体现了云厂商在规划产品上的不同思路，也和它们各自的实现原理有关。

通常来说，暴露虚拟机的 PaaS 服务，拥有更高的开放程度，和 IaaS 的结合也更加紧密，甚至能够和其他 IaaS 服务配合联动。在成本方面，这种形式还可以和预付费的虚拟机兼容，让我们享受折扣。

而不暴露虚拟机的 PaaS 服务呢，往往意味着更好的独立性和封装性，说明它不希望你绕开机制来访问虚拟机，比如大多数的数据库服务。还有一种常见的可能是，这个服务需要专用硬件的配合，并非纯粹依赖虚拟机。

好了，有了上面的这些视角，相信你即便是对于一个新的 PaaS 服务，在快速研究之后，也能迅速地把握好要点并进行归类，同时形成清晰的高层次认识。对于它是否适合在你的架构中担任角色，你也会有一个大致的判断。

衡量评估 PaaS 的局限

我们都知道，软件工程的领域没有银弹。强大的 PaaS 也不例外，也有自己的局限。

PaaS 的核心理念在于封装，封装既带来了效率的优势，也同时带来了灵活性上的牺牲。我们需要在内置的设定和选项中开展工作，不能天马行空、随心所欲。PaaS 的应变能力也会差一些，比如当它出现一些 Bug 或者运营事故时，你无法自己动手去解决它，而是需要等待厂商进行修复。

这是 PaaS 诞生以来就伴随着质疑的原因，你的身边可能就有 PaaS 的反对者。有些以前只做 PaaS 的公有云公司也不得不向市场妥协，陆续开始了 IaaS 产品的研发。这和早期云市场的接受程度有关，也和当时 PaaS 自身的成熟度有关。

当然，这里我讲的局限性，不是为了奉劝你远离 PaaS，而是让你能更加客观地看待 PaaS 这个产品形态，更好地评估某项 PaaS 服务是否适用于你的场景。因为 PaaS 在带来巨大效率提升的同时，也的确要牺牲一点“自由”。

这里，我要给你介绍一些检查 PaaS 限制的方法，也是考察评估 PaaS 服务成熟度的重要思路，你需要好好参考和把握。

功能屏蔽：和自建服务相比，你需要研究 PaaS 的封装是否带来了某项功能、部分选项，还有扩展机制的屏蔽或者缺失，以及这些功能对你而言是否重要。

版本选择：你需要检查 PaaS 所提供的软件或运行环境的版本是否丰富，最早和最新的版本各是什么，还有版本粒度是否足够细致等等。我就曾经遇到过，因为所需数据库版本在 PaaS 上不存在，只能选择虚拟机进行部署的情况。

性能极限：确认 PaaS 服务所能够提供的性能极值，包括算力和存储的上限。你要和自己的需求量预测结合起来，避免“上车”后骑虎难下。

更新频率：查看 PaaS 服务的更新日志，了解云厂商和相应团队在这个 PaaS 服务上，是否还在继续做投入，是否在跟进一些最新的技术趋势。

成本陷阱：实际地通过 POC 实验，对 PaaS 服务进行试运行，注意要达到一定的量级，然后仔细查看它对应的账单，看看相关支出是否合理，你能否长期承受。

注：所以对于 PaaS 来说，其实设置界面选项越多往往越好，这也不失为一个甄别产品成熟度的简单办法。你不应该担心产品学习曲线陡峭的问题，这些不起眼的选项很可能在某个时刻被派上用场，发挥关键的作用。

我还是要再次强调，你应当理性地看待 PaaS。它肯定不是无所不能，但也绝非一无是处。更客观地学习了解它，有助于建立你对 PaaS 的理解和信任，在合适场景下，最大化地发挥它的优势和价值。

我个人对于 PaaS 还是非常看好的，它近年来日新月异的发展，已经极大地提升了竞争力。随着大量用户的不断实践和反馈，这些产品也越来越开放，突破了过去的很多限制。有时即便 PaaS 相对自建会稍微贵一些，我也会优先选择 PaaS，因为它带来的效率提升，和时间人力的节省，远远超出了贵出的那点价格。

最后我想再补充一点，当云上官方的 PaaS 不足以满足你的需求时，还有第三方 PaaS 是值得考虑的选择，你通常能够在云厂商的各种云应用市场中找到它们。比如说，大数据领域中，炙手可热的 Databricks 公司，就分别在 AWS 和 Azure 云都上架了自家的 PaaS 服务，比起内置大数据的云服务来说，也毫不逊色。

课堂总结与思考

作为 PaaS 篇的第一讲，我就先和你讨论到这里了。希望通过今天对 PaaS 的讲解，能够给你建立起一个对 PaaS 宏观层面的正确认识。同时，我今天介绍的几个观察评估要点，的确是你研究 PaaS 时值得参考的良好视角。后面在跟随课程讲到具体的各个 PaaS 服务的时候，也请你记得时不时地回看这一讲的内容，相互印证。

我自己是一个 PaaS 的乐观主义者。如果把你要构建的应用比作高楼大厦，那么 PaaS 作为大厦的基石和支柱，它是当之无愧、值得信赖的。在充分客观了解 PaaS 局限的前提下，你不妨积极大胆地拥抱 PaaS 吧。

好了，今天我留给你的思考题是：你目前接触使用最多的 PaaS 服务是哪个？它给你带来了怎样的效率提升？同时它有没有什么局限让你伤脑筋呢？

欢迎你在下方留言。如果你觉得这篇文章有帮助，欢迎你把它分享给你的朋友。我是何恺铎，感谢阅读，我们下期再见。

10 | 对象存储：看似简单的存储服务都有哪些玄机？

你好，我是何恺铎。今天起，我们展开来讲具体的 PaaS 服务。

我第一个要深入介绍的服务，当仁不让就是对象存储（Object Storage）了。因为它可以说是应用最广泛、最常见的基础性 PaaS 服务了，几乎每个云上的项目都会用到它。

对象存储，顾名思义，就是在云端，你可以存放任意对象的存储服务。你要注意，这里的“对象”指的是任意的二进制对象，保存到云上通常是以二进制文件的形式，你不要和“面向对象编程”中的对象混淆起来。

对象存储的历史，说起来和云计算一样悠久。AWS 著名的对象存储服务 S3（Simple Storage Service）早在 2006 年就发布了，甚至比它的虚拟机服务 EC2 还要早上几个月。

S3 对象存储服务从一开始发布，就以其简明易用、高可用低成本的特点，很快受到了市场的广泛欢迎。各个云计算厂商也纷纷跟进，推出了自己的对象存储产品。到现在，对象存储已经是云计算领域的“标配”了。

说到这里你可能会问，对象存储听上去的确很简单，无非就像一个文件服务器而已，需要用单独的篇幅来展开介绍吗？

答案当然是肯定的。要知道，对象存储不但注重打造存储的核心能力，还建立了一整套成熟的管理控制机制，更能够方便地与各种应用程序集成。所以，它值得我们来好好看一看。

注：对象存储是如此的成功，以至于有时候人们会用“云存储”来称呼它。但理论上来说，云存储是一个更加宽泛的概念，可以包含多种云上存储产品。我们这里还是更严谨地称之为对象存储。

初识对象存储

那么，对象存储，究竟为我们提供了什么功能呢？

通俗地解释起来，你可以这样理解，对象存储是你在云上可以创建的一种“网盘”。这个网盘可以存储任意的二进制文件，包括结构化和非结构化数据。你可以随时上传下载，也可以修改和删除。当然，云上对象存储会保证你数据的可靠性、可用性和扩展性，你不需要操心这些细节。

那么，同样是存储服务，对象存储和前面我们 IaaS 部分讲过的云硬盘有什么区别呢？

这是好问题。这两者之间，虽然都是存储服务，也都有多副本的冗余机制，但还是有相当大的区别。

第一个主要区别，在于访问的接口与形式。

云硬盘其实是挂载到虚拟机的虚拟硬盘，它是通过实现操作系统级别的底层接口，作为虚拟机的块存储设备而存在。我们也必须连接到相关的虚拟机，才能访问它里面的数据。

而对象存储，本质是一个网络化的服务，调用方主要通过高层的 API 和 SDK 来和它进行交互。不管是面向外部公开互联网服务，还是和内部应用程序对接，对象存储都是通过提供像 HTTP 这样的网络接口来实现的。所以它的独立性很强，不需要依赖其他组件就可以运作。

这也正是我们把对象存储放在 PaaS 篇，而不是 IaaS 篇中讲解的原因。虽然它的功能很“基础”，但它的产品形态是非常典型的 PaaS，因为你不需要操心下面支撑它的具体机器和可用性等等问题，只需要依赖它，在它之上构建你的应用就行了。

注意：尽管有 S3FS、OSSFS 等工具也可以模拟磁盘并挂载到虚拟机，但它们也是基于对象存储的 API 进行了封装，并不改变对象存储是网络化服务的本质。

第二个主要区别，也是对象存储的一大特征，就是对象存储内本身不存在一个真正的文件系统，而是更接近一个键值（Key-Value）形式的存储服务。

这里的键就是对象的路径（路径中包含斜杠符号“/”），这里的值就是存储对象的二进制文件。

键值系统和云硬盘上经典文件系统的核心差异，就在于文件系统保存了更多的元数据，尤其是实现了目录结构和目录操作。而键值系统中，所谓的目录其实是多个对象共享的路径前缀，可以说是用前缀模拟出了目录。

这个键值系统的设计理念，给对象存储带来的好处就是简化了逻辑和设计，可以让云厂商把更多精力放在对象存储的分布式架构和服务高可用上面。

当然相应地，这样的设计也使得对象存储中的“目录”操作代价变高了，比如说目录的删除和重命名，我们就需要对目录下所有的对象文件进行修改或删除来模拟。所以，很多对象存储系统都默认不提供目录级别的操作功能，或是性能相对较差，这一点我们需要注意。

第三个主要区别，在于对象存储的巨大容量。

作为云计算最具代表性的服务之一，它的可扩展性（Scalability）是毋庸置疑的，对象存储能够轻松地容纳上 PB 的超大容量数据，这是任何的云硬盘所不能企及的。所以对象存储是名副其实的大数据存储。

但从另一个角度说，对象存储和 HDFS 这样的大数据文件系统比起来，又有自己独到的优势：对象存储本身也是非常擅长和适合处理小文件的，即便是海量的小文件，对象存储也不会像 HDFS 那样处理起来捉襟见肘，可以说是“大小通吃”。

好的，现在我们不但把对象存储和云硬盘的区别搞清楚了，同时也理解了对象存储的最主要特征。

百闻不如一见，我们接下来进行实操。这次的实验我们使用国际版 AWS S3，当然你也可以使用阿里云 OSS 和 Azure Blob Storage 等类似服务进行体验。

首先，我们在 S3 门户创建一个基本的存储桶 geektime-hellocloud。这个存储桶，你可以认为是一个对象存储的基本容器，这里的名称一般要求全球唯一，在区域方面我们选择美国西部。

随后，我们点击进入这个存储桶实例，上传一个用于实验的文本文件，我们还是使用小说《双城记》的文本（ATaleOfTwoCities.txt）。成功上传后，能够看到文件已经存在于桶内。

点开这个文件，我们可以查看这个对象的一些基本属性，也能够进行一些基本操作。

在上图中点击“复制路径”按钮，你会得到一个 URL 为：

s3://geektime-hellocloud/ATaleOfTwoCities.txt

这是使用 S3 标准协议下的对象路径，它也是对象的唯一标识。这个路径可以在所有支持 S3 协议的场景下使用，比如 AWS 的命令行工具。

下面展示了使用 AWS CLI 的 s3 命令，把我们这个文件下载到虚拟机当前目录的方法（事先我们已使用 aws configure 登录）：

[ec2-user@ip-xx-xx-xx-xx s3test]$ aws s3 cp s3://geektime-hellocloud/ATaleOfTwoCities.txt .
download: s3://geektime-hellocloud/ATaleOfTwoCities.txt to ./ATaleOfTwoCities.txt
[ec2-user@ip-xx-xx-xx-xx s3test]$ ls
ATaleOfTwoCities.txt

注意，前面对象属性截图的底部（红框中的“对象 URL”），还提供了一个 HTTP 协议的对象路径，你一定不要把它和 S3 协议的路径混淆起来，因为这两者是用于不同的环境的。HTTP 协议的 URL 可以让通用的 Web 客户端直接访问这个对象。

不过现在如果我们直接请求这个 URL 的话，我们会吃一个闭门羹：

[ec2-user@ip-xx-xx-xx-xx s3test]$ curl -I https://geektime-hellocloud.s3-us-west-1.amazonaws.com/ATaleOfTwoCities.txt
HTTP/1.1 403 Forbidden
...

这是因为在默认情况下，这个 URL 并不对公开互联网开放，你需要手动地在权限管理 Tab 中打开这个限制：

打开公有访问权限后再次实验，我们就能够成功地访问到文件的内容了：

[ec2-user@ip-xx-xx-xx-xx s3test]$ curl -s https://geektime-hellocloud.s3-us-west-1.amazonaws.com/ATaleOfTwoCities.txt | head
﻿The Project Gutenberg EBook of A Tale of Two Cities, by Charles Dickens

This eBook is for the use of anyone anywhere at no cost and with
almost no restrictions whatsoever.  You may copy it, give it away or
re-use it under the terms of the Project Gutenberg License included
...

注意：打开对象存储的公开访问需要非常小心。历史上出现过非常多次因为误设置了公开权限而导致重要数据泄露的事故。一般来讲，更推荐使用更严格的基于身份认证的访问模式。

你看，对象存储是不是特别简明易用？而且得益于自带的冗余机制，它一般都有高达 99.999999999%（11 个 9）的数据可靠性，上传到其中的数据，几乎可以说是万无一失了。再结合它低成本的特点来看，对象存储也非常适合作为数据备份的场所。

对象存储的高级特性

学习了对象存储的基本知识和操作之后，接下来我们探讨一些它的高级特性。即便你是对象存储的熟手，这里面也很可能有一些你之前并不了解的门道。

第一个重要特性，是存储分层。

在生产环境下的对象存储，我们往往会存放大量的文件和数据，这些文件的访问频率其实是会有很大差异的。比如说，对于一些比较热门的下载文件，它可能经常需要被访问调用；而如果是一些明细的日志文件，写入后再次读取的机率通常不高，只有当排查问题时，我们才可能去访问翻看它。

所以为了应对不同的访问模式和频率，对象存储贴心地提供了分层的策略，你可以按照访问热度，设置从热到冷不同的存储级别（或者叫存储类型）。其中，存储级别为热的对象，存储空间占用的成本稍高，但访问读取不需要收取额外的费用；而存储级别越冷，则存储空间的单位成本越低，但访问读取需要收取一定的费用。到了极少访问的存档级别，数据的“解冻”可能还需要花费一些时间。

不同云的存储级别叫法有一些区别，我这里用一个表格给你做了大致的梳理：

所以，这些存储级别其实是一种在访问效率和存储成本之间的平衡。对象存储服务把这样的一个选择权开放出来，是一个非常有用的特性，能够让你根据具体的文件情况，因地制宜，选择不同的策略。而且这些策略既可以是存储桶级别的，也可以细到单个文件，非常灵活。

重要提示：同一个文件的存储类型是可以按需转换的，既可以从热到冷，也可以从冷到热。但你需要注意，这个切换动作本身可能会收取额外的费用，所以不应该经常地切换，这样会得不偿失。

可以说，存储分层的存在，让原本价格低廉的云上存储更加具有成本竞争力。给你举个例子，现在归档层的存储费用，在典型情况下大约是每 GB 每月 1 分钱左右，是不是低得惊人？所以，很多用户上云的一个应用场景就是，把原本占用大量传统磁盘的备份文件，利用对象存储的归档能力长期保存。

第二个值得称道的特性，是生命周期管理。

随着时间的推移、业务的增长，你在对象存储中的内容肯定会越来越多。当总的体量和对象的个数到达一定级别的时候，你会发现对历史内容进行清理就成为了一件非常麻烦的事情。

这时候，生命周期管理功能就可以很好地帮助我们。因为它允许你设置一定的过期规则，当对象满足规则时（通常每天判断一次），可以自动地执行一些清理操作。比如，你可以对一个存储桶或目录进行设置，要求最后修改时间超过 60 天的文件自动切换到低频访问层，超过 180 天的文件则进行归档或删除。

我曾经就在某个生产环境中，启用了这个自动清理特性，立竿见影地节省了大量成本，如下图所示。

第三个特性，则是对象的版本管理（Versioning）。

这个很好理解。同一个对象可能会被修改更新，而启用这个特性后，对象存储系统就能够自动地帮助你记录这个对象之前的多个版本。这样，当有需要时，你可以按需进行回滚和恢复，能避免不必要的损失。

此外，对象存储服务还有跨区域同步、访问日志分析等其他高级特性。前者可以帮助你自动对数据进行跨区域同步，常用于重要数据备份或热点数据分发，后者则对已经存放了海量数据的对象存储进行管理分析大有帮助。有兴趣的话，你都可以自己尝试一下。

对象存储的应用场景

我们的应用离不开数据，所以几乎到处都是对象存储可以发挥的场景。一切需要保存数据的地方，不论是原始数据的保留备份、中间结果的临时落地，还是处理结果数据的永久保存，你都可以考虑对象存储是否适用。

是的，在很多系统中，对象存储就是这样贯穿在整个系统数据流程的生命周期中，串联起了数据处理的各个环节。对象存储有时甚至还可以用来做简单的键值数据库，由于它的分布式设计，对它来说，承担大量的并发请求，也是小菜一碟。

对象存储还可以支撑大数据应用。现在各云厂商的对象存储服务，也普遍地作为分布式存储系统，与各家的大数据 PaaS 产品进行了深度的集成，也是云上各类数据湖解决方案的关键组成部分。我们后面讲到大数据 PaaS 服务时还会详细讨论。

最后，通过前面的实验，我们能看到，对象存储可以直接面向公开互联网，作为文件服务器对外提供服务。通过妥善设置对象的 HTTP 响应头，它甚至还能支撑起静态网站，免去我们创建虚拟机的麻烦。如果下载量比较大，且对带宽延时有更高要求的话，它又能无缝地与云上的 CDN 服务进行集成，作为 CDN 的回源站点。

课堂总结与思考

因为对象存储的高可用、低成本的特性，让它成为了云上最重要、最受欢迎的支柱性 PaaS 服务之一，也极大地助推了云计算本身的发展。它上手起来非常简单，而深入运用起来又很强大，可以说是产品设计上的最高境界了。

对象存储在实践中实在有太多妙用，等待着你去感受和发现。我建议你多多实际操作，探索一遍它的各个功能选项，这会比你单纯地阅读产品文档有更深入的体会。

今天给你的思考题是这样的，欢迎你在留言区和我互动：

将对象设置为完全公开是非常危险的，但如果我们要临时地分享一个对象，给特定的外部用户，应该怎样做呢？

假设你在本地数据中心，有大量的数据需要上传到云对象存储中，但互联网的带宽有限，上传需要很长的时间。对于这种情况有什么好办法吗？

好了，这一讲我们就到这里。如果你觉得有收获，也欢迎你把这篇文章分享给你的朋友。感谢阅读，我们下期再见。

11 | 应用托管服务：Web应用怎样在云上安家？

你好，我是何恺铎。今天我们来谈谈云上的应用托管服务。

从互联网诞生开始，网站就一直是人接触内容的主要窗口，是互联网应用的主要形态。所以许多的编程语言和技术栈在争夺开发者的时候，都是以支持网站应用的开发作为主要的发力点。

这个浪潮催生了各类动态网站编程技术，和各种 Web 后端框架的兴起。而随着 AJAX 应用和移动互联网的到来，Web 已经不只是网站了，它还包括各种各样的 API。我们可以把它们统称为 Web 应用。

Web 应用，显然是一个极为普遍的需求，也是一个巨大的市场。所以，作为承载一切的云计算，当然需要为 Web 应用的运行提供最好的场所、能力和辅助。

不过，你当然也可以使用虚拟机和其他 IaaS 组件来搭建你的网站。但用 IaaS，你需要操心的事情比较多，包括虚拟机的创建、运行环境的搭建和依赖安装、高可用性和水平扩展的架构等等。而且一旦应用的规模大了，每次应用的更新升级也会是件麻烦事，另外你还要操心 Web 漏洞的弥补修复。

那么，能不能有一个平台服务，来帮助我们解决所有这些基础架构问题，让我们只需要专注于应用构建本身就好了呢？当然是有的，这就是云上应用托管 PaaS 服务的由来。

什么是应用托管服务？

和每一项云服务一样，应用托管类服务也是从简单到复杂、从功能单一到丰富强大这样一路走来的。

在云计算发展的早期，就已经出现了“建站类服务”，这正是应用托管服务的雏形。当时的建站类服务，会自动为你分配好服务器，安装好相应语言的 Web 环境以供你使用。在部署层面，服务通常会开放 FTP 端口，以便你上传服务器端的代码、脚本和资源。这是应用服务的一种轻量形式。

注意：目前仍然有云厂商提供了这种轻量 Web 服务的产品形态，比如阿里云的轻量应用服务器、百度云虚拟主机服务等。这些服务仍然可用，而且由于使用简单且成本低廉，在合适的场景下（比如中小企业建站）也是不错的选择。

而更现代的应用托管服务，已经今非昔比，不但在细节选项、自动化程度上进步了许多，还包含了大量的增值服务。如果你的运用得当，它绝对是一个利器，能为你节省许多的时间精力。

这类现代应用托管服务现在是各个云上的标配，AWS 上对应的云服务为 Elastic Beanstalk，阿里云对应的服务为 Web 应用托管服务（Web+），Azure 上称之为 Azure 应用服务（Azure App Service）。

接下来，我就以国际版的 Azure 应用服务为例，把我们在第 7 讲中使用过的计算斐波那契数列的 Web 应用，移植到 Azure 云的 PaaS 服务上来。

首先，我们来创建一个应用服务的实例：

在上图中，我填写了一些重要信息，比如把这个实例称为 fibonodejs，系统会自动给它一个免费的域名 fibonodejs.azurewebsites.net。另外，我还选取了 Node 技术栈，以及 Linux 操作系统。在运行配置方面，我选取了标准 S1，对应一个 vCPU 和 1.75GB 内存的计算资源。

这里你需要注意，除了 Node 技术栈之外，一般云厂商都会提供 Java、PHP 等多个常用语言和框架的支持。你可以事先确认一下，你偏爱的语言是否在云厂商的支持列表中。下面我还列出了 Azure 应用服务支持的部分环境，可以看到，同一个语言或框架还支持很多不同的版本，所以我们的选择是很丰富的。

实例创建完毕后，就相当于我们已经建好了房子，接下来的关键就是要邀请应用入住。

我们在第 7 讲中使用过的 app.js 中的源码，在这里基本不需要修改就可以直接使用了，唯一需要适配一下的是最后监听的端口号，我们需要从固定值 80 修改为动态值 process.env.PORT。这个动态值会在应用运行时，从 PaaS 服务的环境变量中得到。

app.listen(process.env.PORT);

随后，我们只需要把应用的代码打包上传就可以了。我们这个 Node 应用比较简单，只是包含一个 app.js 和 package.json 配置文件。package.json 配置文件的内容也很简洁，只有少数包依赖，以及一个初始化的启动命令：

{
  "name": "fibo-app",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node ./app.js"
  },
  "dependencies": {
    "express": "4.0.0",
    "ip":"1.1.5"
  }
}

我们再新建一个 .deployment 文件，其中，设置 SCM_DO_BUILD_DURING_DEPLOYMENT 参数为 true。这个设置会告诉 Azure PaaS 端，在部署时帮我们自动执行 npm install 来安装依赖项。

[config]
SCM_DO_BUILD_DURING_DEPLOYMENT=true

然后，我们把上面提到的这三个文本文件一起打包为 zip：

[client@clientVM fiboapp]$ zip fiboapp.zip app.js package.json .deployment
updating: app.js (deflated 48%)
updating: package.json (deflated 30%)
updating: .deployment (stored 0%)

接下来十分关键的一步，是我们要用 Azure CLI 中的 webapp 相关命令，完成 zip 文件的上传。

[client@clientVM fiboapp]$ az webapp deployment source config-zip --resource-group geektime-hellocloud --name fibonodejs --src ./fiboapp.zip
Getting scm site credentials for zip deployment
Starting zip deployment. This operation can take a while to complete ...

我们需要做的就只有这些。当 Azure 应用服务收到 zip 包后，就会在一个隔离环境中自动解压、安装相关依赖项，并开始运行我们的应用了。

尝试一下网站服务，已经在正常地工作了：

[client@clientVM ~]$ curl https://fibonodejs.azurewebsites.net/
I am healthy
[client@clientVM ~]$ curl https://fibonodejs.azurewebsites.net/fibo/35
Fibo(35) = 14930352
Computed by 49fe1eef783e with private ip 172.16.1.4

通过这个例子，你能够看出，应用服务的本质就是为你的应用提供一个隔离的独立运行环境。作为用户来讲，你可以只专注于业务逻辑，不需要来手动创建这个环境，更不需要运维这个环境。

小提示：应用托管服务背后采用的隔离技术对用户一般是不可见的，它可能是虚拟机，可能是 Docker，或者是自研的其他容器类技术。通过查看后台日志，你可以发现，Azure App Service 在 Linux 上的后台，其实是使用了 Docker 来封装运行我们的 node.js 程序。

另外，为了便于说明操作步骤，上面的实操中，我使用了命令行的方式来进行应用的打包和部署。如果你觉得这个过程有点儿麻烦，也完全可以借助一些 IDE 工具来完成它。比如说，你可以使用 Visual Studio Code 配合 App Service 插件，来进行开发和部署。

而且，上面的打包上传等步骤，我们在集成环境中，只需要按下“Deploy to Web App”，一键就可以完成了，如下图所示：

所以，云厂商为了提高 PaaS 服务的易用性，往往会有比较成熟的开发配套工具链可以选用，这也是应用托管服务的一大优势。

应用托管的增值服务

上面我通过例子，给你演示了一下应用服务的基本功能，但它的能力远不止此。成熟的应用服务还能够提供许多增值服务，来进一步地满足我们在实际开发运维 Web 应用时，产生的各个层面的需求。

第一项增值服务就是监控，尤其是针对 Web 应用的特点而进行的 HTTP 层面的应用监控。所以，你不仅能看到计算资源的占用率，如 CPU、内存使用率等，还能看到许多应用层指标，比如总请求数、错误响应数、并发连接数、响应时间等等。这些都是你在监控应用运行时非常有帮助的信息，而这一切都是 PaaS 服务自动提供、开箱即用的功能。

而且，基于这些监控的指标，你还能够在云上制定相应的报警规则，当某些指标达到你设定的阈值时，会及时发送警报。这同样是一个非常实用的功能。

第二个方面是扩展，也就是底层计算资源和流量需求的匹配。这里既包含了底层机器配置的垂直扩展，也包含了机器数量层面的水平扩展。一旦你有调整需求，只需要动动手指发出指令，就可以随时升级相应的机器配置，并无缝切换。

特别是水平扩展的存在，它相当于同时包含了我们第 7 讲中提到的负载均衡和弹性伸缩，把它们都一股脑儿集成到了托管服务中。这意味着应用托管服务不是只能对应一台机器，而是能够创建多台机器来承接请求，并会在前端均衡地分发到多个实例上去。这里你同样可以指定自动伸缩的规则，来让应用服务自动地调整实例数量。

下面，我给出了一个实际可用的 Azure 应用服务的伸缩规则示例，它设置了 CPU 使用率的阈值，当实际 CPU 占用超出阈值后，服务会自动地增加或减少实例数量。假如我们的 fibonodejs 服务，需要面向公众正式服务的话，就可以施加类似的配置。

第三个方面是集成，这里是指与其他 PaaS 的集成。这是所有 PaaS 服务的优势，各个服务间可以互相帮助、联合作战，应用托管类服务也不例外。比如在监控数据方面，它可以和云监控系统进行衔接；再比如，有些云允许 Web 应用以目录的形式，挂载对象存储中的文件等等。

其中，应用托管类服务还有一项非常重要的集成能力，就是应用服务与云上 DevOps 组件和流程的无缝对接。它意味着应用服务可以作为整个应用生命周期管理的一部分，嵌入到持续集成的流程中去。借助和源代码管理设施的联动，你的应用就可以轻松实现自动化的部署和升级。

比如说，我可以把上面 node.js 应用程序的代码，放到 Azure Repo 或者 GitHub 这样的代码仓库中，之后只要通过满足触发条件的 git push 操作，就能够自动地触发构建，并直接更新线上的应用程序。

下图展示了 Azure App Service 中相关配置的入口：

除了我在上面列举的这三方面的增值服务，应用托管服务还有许多有用的特性我没有展开讨论，比如说远程调试和诊断、运行环境自动补丁升级、私有网络内的部署、Web 防火墙防护等等。这些都是它能够给你带来的强大附加价值。

和其他 PaaS 服务一样，对于应用托管服务，我建议你先充分地查阅文档，建立比较系统全面的认识，然后一定要通过实操，进行探索和实验，这样你就会有比较深入的理解和感受，便于你作出正确的选型决策。

课堂总结与思考

今天，我主要给你介绍了云上的应用托管服务，这也是最受欢迎的 PaaS 服务之一。你现在应该已经知道，它是用来支撑我们 Web 应用的一个平台，它既包含了应用的基础架构和运行环境，也包括了许多增值服务，大大方便了我们 Web 应用搭建和维护过程中的各种典型诉求。

到目前为止，我所说的都是它的优点和长处。那么，你可能会问，应用托管服务有没有弊端呢？

我认为，这主要取决于云服务的封装程度，以及你是否有环境定制的需求。有些人的确不喜欢受限的封装环境，觉得难以做一些细节的微调和必要的 hack，也有一定道理。

好在现代 Web 托管服务，在进行高度封装的同时，也都部分地开放了内部运行环境，甚至允许你远程登录到相应的服务器上去，开展你所需要的改动或排查。这在一定程度上减轻了封装可能带来的“黑盒”问题，比如你可以查看到一些底层操作系统级别的错误日志。

另外你需要注意的一点，就是价格。不同云厂商，对于应用托管服务的收费标准都是不同的。至于它们的收费是否合理，你可以与纯虚拟机的搭建来做一个对比。特别是如果你的网站部署规模不小的话，花一些时间来做比较是非常值得的。

不过在进行比较时，你一定不能忘记，应用托管服务能够给你带来的工作效率提升，和维护负担的减轻。因为开发、部署和维护相关的人力和时间成本，都是总体拥有成本（Total Cost of Ownership，TCO）中的一部分。这也是我在许多时候，会给应用托管服务投上一票的重要原因。

这一讲，我留给你的思考讨论题是：

Azure 应用托管服务还有一个部署槽（Deployment Slot）功能，AWS 中类似的概念则称为环境（Environment），这同样是一个非常实用的能力。你能说说这个特性是做什么的吗？如果你还了解其他好用的特性，也欢迎你和大家分享。

对于应用托管服务，通过代码打包上传来发布应用，一直是主流的方式，我在前面举例时也采用了这种形式。不过近来，通过容器来部署 Web 应用，也成为了云上应用托管服务普遍支持的形式。那你知道后者解决了前者的什么问题吗？

好了，今天我们就到这里。如果觉得有帮助，欢迎你把这篇文章分享给你的朋友。我是何恺铎，感谢你的阅读，我们下期再见。

12 | 云数据库：高歌猛进的数据库“新贵”

你好，我是何恺铎。

说起数据库，相信你一定不会陌生。从开源的 MySQL、PostgreSQL，到商业级的 Oracle、SQL Server，再到新兴的各类 NoSQL 数据库，都是我们应用架构中的常客。

而近年来随着云计算的兴起，云数据库作为一支新生力量，一路高歌猛进，打破了数据库市场的原有格局，也进入了越来越多开发者的视野当中。这类 PaaS 服务的朴素思想就是，将数据库服务搬到云上，让用户更方便轻松地使用、管理和维护数据库。

由于数据库的产品形态天生具有独立性，容易标准化封装，而且用户侧又往往有运维复杂的痛点。所以这类数据库托管服务一经推出，很快就受到了用户的广泛欢迎，也当仁不让地成为了云 PaaS 服务中的杰出代表。你一定要来认识它。

云上的关系型数据库

关系型数据库的应用在业界是最普遍的，也是云数据库首先进入的领域。这里的先行者同样是 AWS，早在 2009 年就发布了 RDS（Relational Database Service），后来其他的厂商也纷纷开始跟进。

RDS 其实并不指代单个服务，而是一般针对每个数据库引擎，都有一个对应的服务，比如 RDS for MySQL 或 RDS for PostgreSQL。并且，同一种数据库按照不同的版本，也有比较严格的分支选项，你在创建时就会被要求选定这个版本。

AWS RDS for PostgreSQL 的版本选择列表

那么，RDS 类服务和传统关系型数据库有什么区别呢？这恐怕是一个绕不开的问题。对于云数据库，我想这样回答你，它们既没有区别，又有很大的区别。

怎么理解这句看似矛盾的话呢？

所谓的没有区别，指的是云数据库在外部交互的层面上，保持了和传统“原版”数据库几乎完全一致的编程接口和使用体验。

比如说，你针对 MySQL 编写的 SQL 代码和应用层连接代码，包括你很熟悉和经常会使用的连接管理工具，除了要更改连接字符串和参数之外，都能够几乎不经修改地在云数据库的 MySQL 服务上运行。

另外，针对某个数据库的某个具体版本，云厂商们会把它的功能、内部机制完整地保留下来，以求获得最大程度的兼容性。早期比较简单的云数据库实现原理，是充分利用云上已经提供的虚拟机、云磁盘等 IaaS 层面的资源，在隔离的环境下进行数据库镜像的安装。而后来技术实力比较强大的厂商，还能够做到对数据库源码和模块的深度定制，在保证兼容性的前提下，进行许多对用户透明的云端适配和优化。

所以，云数据库尽管是一个受限的 PaaS 环境（比如它通常无法让你直接访问底层的服务器），但在使用体验上和传统数据库是相当一致的。你大可放心，之前积累的 MySQL 和 PostgreSQL 的知识，在 RDS 上也大都可以适用。在云上，你也同样能够找到和安装一些数据库的常用插件，来增强 PaaS 数据库的功能。

而同时我们又说，云数据库和传统数据库有很大的区别，这是指在搭建、运维、管理层面，云数据库提升了一个层次，实现了相当程度的智能化和自动化，极大地提升了用户友好度，降低了使用门槛。比如灵活的性能等级调整、详尽的监控体系、攻击防护机制等等，这些许多在传统数据库中需要借助额外工具或产品的功能，在云数据库服务是默认内置，可以开箱即用的。

除了这些基本能力外，我还想着重强调两个最具代表性的云上关系型数据库的高级特性。

一个是支持读写分离。当并发数量上升时，关系型数据库容易出现性能瓶颈。这时比较有用的办法，就是实现基于多库同步的读写分离。读写分离虽然是常见的架构思路，但你要是不熟悉细节的话，手工配置起来可并没有那么容易。

云数据库就帮我们解决了这个烦恼，你只要在产品后台略加操作，就可以启用这个功能：从创建从库到建立同步，再到读写流量分发，云数据库都能自动完成。看上去高大上的架构实践，在云数据库的帮助下，就轻松地“飞入寻常百姓家”了。

阿里云 RDS 中建立的读写分离

一个是支持自动调优。对于数据库来说，同样和性能有关的一个重要工作，就是性能的调优。以前我们经常需要手动地观测性能瓶颈，找出热点查询，再考虑是否有改进性能的办法。而在现代云数据库中，都自带有性能分析与改进的模块，能够自动地发现性能热点，甚至还能够智能地给出调整建议，比如进行个别语句的调整，甚至添加额外的索引等等。

这个性能分析和自动调优的能力，是将生产运行数据和服务内置的 AI 模型进行了结合，是真正的智能化运维，毫无疑问，这大大增强了云上数据库的竞争力。如果你有线上的云数据库，一定不要忘记观察它自动给出的结果和建议，很可能会给你带来惊喜和帮助。

给你举个例子，下面这张图中是 Azure SQL Database 自动给出的性能优化建议。你可以看到，它建议我在某些表的某些列创建索引，还提醒我部分查询应当进行参数化。而且它将各个建议还按照对性能影响程度的高低进行了排序，可以说是非常贴心了。

Azure SQL Database 中的自动性能调优建议

以上的种种特点，一起构成了云上关系型数据库的独特竞争力，也为它赢得了认可。

新一代云原生数据库有什么特征？

在通过 RDS 类关系型数据库服务，建立起公众对于云数据库的认知和信任以后，聪明的云计算工程师们又开始了新的征程。这次，云厂商们不满足于封装现有的数据库，而是极具野心地开始构建完全为云设计、能够充分发挥云的特点和优势的数据库。

这就是新一代云原生数据库的由来。

你可能也听说过 AWS Aurora、阿里 PolarDB、Azure Cosmos DB 这几个产品的鼎鼎大名，它们正是云原生数据库中的杰出代表。

出于生态发展和降低学习难度的需要，绝大多数的云原生数据库仍然保留了 SQL 等常见接口（有的还支持不同 SQL 方言的选择），但除此以外，云原生数据库大都进行了全面革新和重新设计，有的云会大刀阔斧地改造开源代码，有的甚至脱离了现有包袱，完全重新构建。

这样的尝试取得了巨大的成功，业界也逐渐形成了一系列不同领域的云原生数据库矩阵，大大拓展了云上数据库的范畴和影响力。

我这里也为你整理了一张表格，按照厂商和云数据库的类型进行了梳理和比较。其中，标红的部分是相当值得你关注的自研云原生数据库。

还有其他厂商也有相当出彩的云原生数据库，我没有收录到表格中，比如腾讯云的 CynosDB 和华为云的 GaussDB 等，也都是云原生数据库的杰出代表。

那么，云原生数据库在使用时，有什么优势和特点呢？

首先，更强的可扩展性。

得益于原生设计的计算存储分离架构，云原生数据库可以支撑更大规模的数据量，突破了传统关系数据库服务的单机单库限制。比如说，关系型云原生数据库能够脱离典型的数 TB 的容量上限，达到单库数十 TB 甚至百 TB 的级别。这和它单独专门为云设计的存储架构是分不开的。

算力方面也同样如此，云原生数据库可以利用云快速地进行水平扩展，迅速调整、提升数据库的处理能力。在分布式架构的加持下，它相比以前单机数据库的计算查询能力有了成倍的提升。所以，云原生数据库往往善于处理大并发的负载，可以提供很高的 QPS。

其次，更高的可用性和可靠性。

和传统 RDS 服务不同，云原生数据库往往默认就是多副本高可用的，数据同步、读写分离等高级特性是作为原生机制的一部分天生存在的。像 Amazon Aurora 中的存储部分，就自动包含了分布在 3 个可用区、多达 6 份的数据副本。

得益于原生数据同步机制的底层设计，云原生数据库还能很方便地支持跨区域的实例复制，在进一步增强冗余的同时，还能便于就近服务全球用户。比如下图所示，就是 Azure Cosmos DB 跨区域复制的设置页面，你可以在这里轻松地指定区域，让数据在全球范围流转和同步。

Azure Cosmos DB 的全球跨区域复制设置

此外，对于多种数据模型（multi-model）的支持，也是云原生数据库的一大特征。除了兼容关系型数据库外，云厂商还会针对不同的场景进行针对性的研发和优化，结合数据库业界最新的流行趋势，推出适合不同形态和查询范式的云数据库，与 NoSQL 数据库进行积极竞争。

比如说，AWS 的键值型数据库 DynamoDB 和图数据库 Neptune，都是相应领域中非常优秀的产品。而 Azure 的 Cosmos DB，则采用了另外一种做法，在一个数据库产品中同时内置了多种数据模型的支持，也同样取得了成功。

云原生数据库还往往有低成本启动的优势，它能够自然地跟随业务增长。大多数的云原生数据库，在存储上不需要你预先设置容量大小，而是会随着存储占用自动扩展；在计算上，也有部分云数据库开始推出无服务器版本，比如 AWS 的 Aurora Serverless，它不需要使用固定的计算资源，这在面对间歇偶发或者难以预测的工作负载时，非常经济实用。

云数据库为什么能够不断占领市场？

不论是封装传统关系数据库的 RDS 类服务，还是新一代的云原生数据库，都是一经推出就广受欢迎，市场占有率不断提高。而像 Oracle 这样的传统商业数据库，近几年却身影落寞，在市场上节节败退。这是为什么呢？

除了我们前面提到的易用性和丰富功能外，在云上，云厂商还能端到端地掌控影响一个数据库的设计和性能的所有因素，可以为它配备最新、最好的软硬件组合，这也是云数据拥有旺盛生命力的根本原因之一。比如说，许多的云数据库，都会使用 RDMA 远程高速访问、NVMe SSD 等先进技术。

另外，借助云计算平台，云数据库拥有非常好的流量入口。云计算平台让这些新兴的企业级数据库变得触手可及，非常方便你去学习和尝试。这和同样设计精妙，但“养在深闺人未识”的一些企业级数据库形成了鲜明对比。所以现在反过来，老牌企业级数据库需要和云来合作，这就是入口效应所驱使的。

扩展：通过云平台，云数据库还能够更快地推向市场。一旦有了新的特性，可以很快地更新发布，甚至以预览形式在早期就招募用户。这还造就了云数据库的速度优势。

所以你看，一个行业的进步和颠覆，往往是从一个更高的层面来进行的，也就是我们常说的“降维打击”。云数据库之于传统数据库，是用完全不同的研发模式、商业模式和产品形态，从另一个层面发起了挑战，从而具备了竞争优势，这就像早年汽车替代了马车一样。这也是为什么 Gartner 会大胆预测，到 2023 年，全球 3/4 的数据库会跑在云上。

回到我们用户的视角，你什么时候应该考虑使用云数据库呢？

可以这样说，云数据库现在已经进入了相当成熟的时期。所以，在云上大多数的场合，我都推荐你使用云数据库，而不是用虚拟机自建数据库。你更多需要考虑的是，如何在云数据库中选择匹配你需求的型号，同时要注意可迁移性和厂商绑定的问题。

如果是老的应用迁移，或者是其他需要与自建数据库保持高度兼容性的场合，你不妨使用经典的 RDS 服务，实现平滑上云；如果你的应用场景中数据量大、性能要求高，或者是没有历史负担，那你可以考虑直接“一步到位”，拥抱理念更加先进的云原生数据库。

课堂总结与思考

今天，我们主要学习和讨论了云数据库，它完全改变了数据库的产品形态，既大幅减轻了部署维护负担，也让云计算的弹性计算和存储能力得以充分施展。

云上的关系型数据库在保证接口兼容性的同时，还拥有智能化和自动化的特点，能够帮我们进一步地减轻管理压力，以及提出性能优化建议。而全新一代的云原生数据库，更是放开手脚实现了面向云的原生架构，在性能、可用性和可扩展性上，都展现出了巨大优势。

在前面第 9 讲关于 PaaS 服务的问题回复中，许多同学都提到了在使用云数据库，我想也正是被它的这些特点所吸引。

这一讲，我还埋下了一个伏笔。在前面的云数据库对比表格中，最后一行对应着云上的分析型数据库，这也是云数据库很重要的一个分支。在下一讲讨论云上大数据时，我会更详细地给你介绍。

今天我留给你课后思考的问题是：

近期某著名的 SaaS 服务商遭遇了人为数据删除，造成了很大损失。在这里，我们不深究这个事故的细节，但从云数据库的角度，你知道如何充分利用云数据库的特性，来尽量避免“删库跑路”的事情发生吗？

分区是传统数据库设计和性能优化的常用手段。对于能够支撑很大数据量级的云原生数据库，分区技术还有没有应用的价值和必要呢？

欢迎给我留言，如果你觉得有收获，也欢迎你把这篇文章分享给你的朋友。谢谢你的阅读，我们下期再见。

13 | 云上大数据：云计算遇上大数据，为什么堪称天作之合？

你好，我是何恺铎。

今天我们来讨论和学习云计算中的大数据产品与技术，这也是我自己最喜爱的话题之一。

我们都知道，云计算以存储、计算规模和弹性著称，而大数据方面的业务需求，恰恰需要大量的存储，和呼之即来的澎湃算力。所以，云可以说是最适合运行大数据工作负载的平台了。同时，云计算时代数据规模空前扩大，因此大数据也成为了云上最需要解决的重要场景之一。

正因为两者的关系如此紧密，又几乎处于同一个时代，以至于早年有一段时间，很多开发者产生了概念上的混淆，把“云计算”一词当作大数据技术的代称。但事实并非如此，你需要注意甄别。

在当今的技术语言体系中，我们应该这样来理解：大数据主要是技术手段，是一系列处理海量数据的方法论和技术实现的总称；而云是一种资源和能力的载体，也是一种商业存在，是可以运行大数据负载和应用的平台。

举个例子来形容两者的区别：你可以把云比作一艘航空母舰，是一个大型综合作战平台，而大数据呢，就好比战斗机这个武器门类，在航母上就成了舰载机，依托航母可以达到更大的作战纵深和更强的投递能力。

当大数据和云计算交汇，就自然诞生了云上的大数据 PaaS 产品，它们是云对大数据技术进行了封装和产品化的成果。也正是我们这一讲的主角。

云上大数据的体验

和其他 PaaS 服务类似，云上大数据的发展，也是从对经典大数据技术的封装开始的。这从一些相关服务的命名中就可以看出来，比如 AWS 早在 2009 年，就发布的大数据服务 Elastic MapReduce（简称 EMR）。虽然 EMR 的服务能力早已不限于 MapReduce 这个早期技术，但这个名字一直被保留了下来，这是时间给它打上的烙印。

从技术上讲，云上大数据服务其实一直在迅速跟进着社区的发展，也在不断地延伸自己的服务范围。从早期的 MapReduce，到 Hive 和 HBase，再到后来异军突起的 Spark，都逐渐地纳入到了它的服务体系，现在可以说已经拓展到了整个 Hadoop 和开源大数据的生态。

所以，你在云上能够找到的，不是一个单体的技术组件，而是一系列的大数据服务的组合。下图就展示了 AWS EMR 服务的 5.29.0 版本中，内置支持的丰富组件：

注：从另一个角度来讲，云上大数据服务对开源社区新版本跟进的速度快不快、版本细不细，也是我们评估衡量云服务的一个重要指标。

云上大数据服务最大的特点就是简便易用，方便管理。尤其是，我们可以把一个之前可能需要几天时间，来进行安装部署和环境设置的创建集群任务，缩减到短短几分钟，大大降低了我们学习和应用大数据技术的门槛。

说得好不如做得好，接下来我就带你进入实验环节，来帮助你对大数据服务形成一个直观的认识。我们要使用国际版 AWS 中的 EMR 服务，运行一段 Spark 程序，来统计小说《双城记》中的单词词频。

首先，我们需要创建一个 EMR 的集群实例。在创建过程中，除了像上面那样指定所需要的组件以外，最重要的一步是选择集群的配置：

我选择了 m5.xlarge 这个型号的虚拟机，作为底层基础设施的机器。细心的你可能还发现了，用于执行计算任务的机器组，在这里你可以选择价格相当低廉的竞价实例。这是一个很有用的节省成本的特性，因为很多时候，大数据服务是用于后台离线计算的，我们可以牺牲一些可用性上的要求。

根据向导，等集群创建完成进入运行状态后，就可以使用了。按照产品提示，我们使用 SSH 就能够成功地连上集群的主节点：

client@clientVM:~$ ssh -i ~/awskvpair-california-north.pem hadoop@ec2-52-53-xxx-xxx.us-west-1.compute.amazonaws.com
Last login: Sat Feb 15 13:10:50 2020

       __|  __|_  )
       _|  (     /   Amazon Linux AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2018.03-release-notes/

EEEEEEEEEEEEEEEEEEEE MMMMMMMM           MMMMMMMM RRRRRRRRRRRRRRR
E::::::::::::::::::E M:::::::M         M:::::::M R::::::::::::::R
EE:::::EEEEEEEEE:::E M::::::::M       M::::::::M R:::::RRRRRR:::::R
  E::::E       EEEEE M:::::::::M     M:::::::::M RR::::R      R::::R
  E::::E             M::::::M:::M   M:::M::::::M   R:::R      R::::R
  E:::::EEEEEEEEEE   M:::::M M:::M M:::M M:::::M   R:::RRRRRR:::::R
  E::::::::::::::E   M:::::M  M:::M:::M  M:::::M   R:::::::::::RR
  E:::::EEEEEEEEEE   M:::::M   M:::::M   M:::::M   R:::RRRRRR::::R
  E::::E             M:::::M    M:::M    M:::::M   R:::R      R::::R
  E::::E       EEEEE M:::::M     MMM     M:::::M   R:::R      R::::R
EE:::::EEEEEEEE::::E M:::::M             M:::::M   R:::R      R::::R
E::::::::::::::::::E M:::::M             M:::::M RR::::R      R::::R
EEEEEEEEEEEEEEEEEEEE MMMMMMM             MMMMMMM RRRRRRR      RRRRRR

[hadoop@ip-172-31-1-100 ~]$

小提示：这时如果你去到 EC2 的产品界面查询，你会看到组成这个集群的所有虚拟机都出现在列表中。这体现了 EMR 的一种开放性设计，也方便用户登录到机器上进行测试、排查甚至定制。

你还记得在第 11 讲中，我们《双城记》文本文件在 S3 存储桶中的位置吧？在这里，我们使用 hadoop fs 命令来尝试查看一下：

[hadoop@ip-172-31-1-100 ~]$ hadoop fs -ls s3://geektime-hellocloud/
Found 1 items
-rw-rw-rw-   1 hadoop hadoop     804335 2020-02-07 14:45 s3://geektime-hellocloud/ATaleOfTwoCities.txt

你看，通过使用 S3 协议头，EMR 创建的集群是能够自动地和我们的 S3 对象存储“打通”的，相当于把 S3 挂载为了一个文件系统。这为应用程序的访问和存储数据提供了极大的便利。

接下来，进入到集群为我们安装准备好的 spark-shell（Spark 的交互式命令行工具），我们可以直接运行一个基于 Spark 的经典 WordCount 程序。（为节约篇幅，这里省去了一些准备性语句和一些打印输出）

val book = sc.textFile("s3://geektime-hellocloud/ATaleOfTwoCities.txt")
val wordCounts = book.flatMap(l => l.split(" ")).filter(_.length>0).map(w => (w, 1)).reduceByKey((a,b) => a+b)
wordCounts.toDF("word", "count").write.parquet("s3://geektime-hellocloud/ATaleOfTwoCities-WordCount")

程序顺利执行后，由于我们把计算结果用 Parquet 列存储格式，落地存储到了 S3 中，你可以到 S3 的相关界面里确认。在这里，你可以看到目录已经生成了：

点击进入目录，可以看到其中的 Parquet 文件，说明程序已经生成了结果：

为了证明结果的正确性，我们再使用另外一段 Spark 脚本，来读取刚才的结果文件，列出小说中出现频率最高的 5 个单词及出现次数：

scala> spark.read.parquet("s3://geektime-hellocloud/ATaleOfTwoCities-WordCount").orderBy(desc("count")).take(5).foreach(println)
[the,7514]
[and,4745]
[of,4065]
[to,3458]
[a,2825]

EMR 中再次成功地执行了我们的操作，返回了正确的结果，我们的实验圆满完成。

在这个实验中，虽然我们用的数据规模比较小，但流程是比较完整的，这也充分体现了云上大数据服务的易用性。

云上大数据的特点

从刚才的例子中可以看出，在使用体验层面，云上大数据看上去和你熟悉的大数据技术栈没什么两样。这也是 PaaS 服务的设计目标之一，也就是尽可能地保证兼容性。

不过如果我们深入探究，会发现云上大数据服务并不仅仅是做了开源大数据技术的移植和搬运，还是融入了自己的特色，尤其是进一步地解耦了大数据架构中的计算和存储。

对于存储端，在上面的实验中，我们已经看到这种解耦的体现，应用程序直接把对象存储服务，作为大数据架构的数据源和计算结果的存储位置，它可以不需要使用和依赖本地的 HDFS 文件系统。

当然，这并不是 AWS 的专利，事实上几乎所有厂商的云端大数据服务，都与对象存储服务进行了深度的集成和适配，正好匹配对象存储大容量、高吞吐的特点，形成了一对黄金搭档。所以在云上大数据的存储端，对象存储一般都是优先选择的存储方式。

提醒：在一些大数据服务中，比如 Azure 的 HDInsight，会将对象存储默认挂载为 Hadoop 的根文件系统’/’，你可以查看 fs.defaultFS 参数来确认。这样使用起来，你就无需存储协议前缀，更加接近传统 HDFS 的体验。

在计算端，你同样可以从解耦中受益。得益于云端的弹性，你可以按需地对大数据集群的规模进行动态的调整，来满足不同计算规模和交付时间的要求。

计算端的另一个常用的最佳实践是，集群可以动态地创建，做完工作后立刻将集群删除。

这种按需启停的使用方式，让你可以专门为一个目的，甚至一个任务来创建集群，完成后就可以关闭删除。这样不但最大限度地节省了资源，也通过集群专用，解决了不同大数据任务间资源抢占和冲突的问题。要知道，这在云时代之前是不太可能的，因为安装和设置大型集群非常花时间。

一般云上大数据服务还会带有很多增值服务，除了常见的性能监控之外，值得一提的是许多云都自带了 Jupyter Notebook（一种交互式笔记本），能让你快速方便地和集群交互。另外，有些大厂商还会对大数据框架本身进行改进，以进一步增强自己的竞争力。比如说，AWS 从 EMR 5.28 版本起，就引入了 EMR Runtime for Apache Spark，这个运行时在实现接口和 API 兼容性的前提下，优化了很多场景下的运行性能。

另外，还有一类大数据服务，更是计算存储解耦的终极体现，那就是无服务器查询服务，典型的有 AWS 的 Athena，和阿里云的 Data Lake Analytics（DLA，数据湖分析）等。它们甚至不需要你事先申请计算资源，而是可以即查即用，直接查询对象存储中的数据。然后，你也可以“用完即走”，不必操心服务的关闭。这类服务在成本上也很独特，和 EMR 这样的按照集群规模和在线时长计费不同，它只按照读取扫描的字节数收费，非常适合偶发的数据分析需求。

举例来说，前面我们已经有处理好的 Parquet 文件，位于 geektime-hellocloud 存储桶下的 WordCount 目录。现在我们可以在 Athena 中，创建一个外部表指向这个存储地点：

CREATE DATABASE athenadb1;
CREATE EXTERNAL TABLE athenadb1.wordcount_s3 (
  word string,
  count int
) STORED AS PARQUET
LOCATION 's3://geektime-hellocloud/ATaleOfTwoCities-WordCount';

然后，我们就可以在 Athena 的交互界面中轻松查询数据了。比如说，我们仍然查询小说中频率最高的 5 个单词，也可以通过 SELECT 语句很快得出结果：

分析型数据库的崛起

除了 MapReduce 和 Spark 这样的计算框架，在大数据技术领域，还有另外一个发展思路和重要分支，那就是 MPP（Massively Parallel Processing）数据库，现在也常被称为分析型数据库。高压缩比的列式存储和分布式并行查询处理是它的两大法宝。

由于和关系型数据库有着千丝万缕的关系，分析型数据库乍看上去有些“复古”，它使用的是 SQL 这种声明式的表达。但也正是因为这一点，使得它降低了大数据技术的门槛，可以让广大熟悉关系型数据库的用户能够用自己习惯的方式，来查询和处理大数据。常见的分析型数据库有 Greenplum 和 Teradata 等等。

毫无疑问，云计算也积极地进入了这一领域，甚至唱起了主角。AWS 的 Redshift、阿里云的 AnalyticDB 等，都是非常优秀的云上分析型数据库。

云上分析型数据库，不仅保有了 MPP 数据库的特点，而且云端的生态结合得很好。这里我们继续进行上面的实验，使用 AWS 著名的 Redshift 服务，来实际地说明这一点。

小提示：这里我们略过 Redshift 服务本身创建的过程，你可以选择一个最小集群的规模来做实验。

前面我们已经有处理好的 Parquet 文件，位于 S3 中 geektime-hellocloud 存储桶下的目录当中。Redshift 中，同样支持通过外部表的方式来访问 S3 上的文件，这一特性被称为 Redshift Spectrum。通过它，我们可以很方便地引用不在 Redshift 自有存储中的数据。

方便起见，这里我们直接创建一个指向前面 Athena 中数据库的外部 Schema，这样前面在 Athena 中定义的外部表 wordcount_s3，就可以被 Redshift 识别和利用了：

create external schema athenadb1
from data catalog database 'athenadb1'
iam_role 'arn:aws:iam::5085xxxx8040:role/mySpectrumRole'

注：这里的 mySpectrumRole 赋予了 Redshift 访问 S3 的权限。相关细节在这里不展开了，你可以参阅 AWS 的相关文档。

然后，我们就能在 Redshift 中直接查询 wordcount_s3 表了。但你也可以把这张外部表的数据拉取过来，并落地到 Redshift 自己的存储中。我们使用 CTAS 语句来实现这一点：

create table wordcount distkey(word) sortkey(count) as
select word, count from spectrum.wordCount_s3;

小提示：这里我们在创建内部表 wordcount 时，通过 distkey 和 sortkey 指定了用于分布和排序的字段，充分体现了 Redshift 的分布式数据库特点。合理地设置这些字段，有利于查询性能的提高。

接着就可以查询这张新表了。一般来讲，查询内部表的响应会更快，也能支持更高的并发。

client@clientVM:~$ psql -h my-redshift-cluster-1.cwq9zgi6xxxx.us-west-1.redshift.amazonaws.com -d testdb1 -U awsuser -p 5439 -c "select * from wordcount order by count desc limit 5;"
 word | count
------+-------
 the  |  7514
 and  |  4745
 of   |  4065
 to   |  3458
 a    |  2825
(5 rows)

我们还是查询小说中频率最高的 5 个单词，成功地得出了同样结果。值得注意的是，我使用了 psql 命令行工具来进行查询，这是一个通用的 PostgreSQL 的客户端。这证明了 Redshift 在接口层面和 PostgreSQL 关系型数据库的兼容性，你可以复用相关的工具链和生态。

好，我们的实验就进行到这里。总得来说呢，云上的分析型数据库，是基于 MPP 架构的云原生数据库，它非常易用而又性能强大，也能够存储和处理很大规模的数据。与云端其他大数据生态的整合，更让它如虎添翼。这也是为什么，云分析型数据库在云上获得了越来越多的关注，也成为了最热门的云上 PaaS 服务之一。

课堂总结与思考

数据是现代应用的核心，也是普遍的需求。云上大数据服务的出现和发展，让我们在云上存储、处理和查询大数据变得简单而高效，它也把云计算的计算存储分离特性，体现得淋漓尽致。所以它们两者呢，真的可以说是天作之合。

云计算落地大数据的形式，既有拿来主义、消化吸收，也有推陈出新、自研改进。这也是我喜欢云的一点，它没有代替你做技术上的选择，而是同时给你提供了多种各具特色的解决方案。

在今天的实操环节，我们主要是通过 AWS 的相关服务来进行的。事实上，在大数据这个领域，各个云厂商都是重兵集结、投入很大，现在的产品服务能力也都比较丰富和成熟了。为了便于你了解和比对，我这里也用一个表格，把不同云的相关服务进行了分类说明：

通过以上产品和服务的有机组合，你就可以轻松地构建出非常强大的数据仓库和数据湖解决方案了。如果再加上云上的数据管理和数据集成类服务一起配合，比如 AWS Glue、阿里云 DataWorks 等，那几乎就形成一个更广义、更完整的数据平台了。

今天我留给你的思考题是：

在 Hadoop 的黄金时代，它最受推崇的一个架构特点就是实现了数据的就近访问（Data Locality），这个特性能够将计算移动到数据所在的地方，以获取最高的性能。现在在云上，如果使用远端的对象存储，是否和这个思想背道而驰了呢？背后是什么样的因素在推动这个转变呢？

Hadoop 体系中的 Hive，也是一种常用的分布式数据仓库，云上大数据服务中一般也都包含了这个组件。那既然有了 Hive，为什么还要研发 Redshift 这样的分析型数据库呢？它们的应用场景有什么不同？

欢迎你在留言区和我互动。如果觉得有收获，也欢迎你把这篇文章分享给你的朋友。感谢阅读，我们下期再见。

14 | 云上容器服务：从Docker到Kubernetes，迎接云原生浪潮

你好，我是何恺铎。

容器，毫无疑问是近年来的又一个技术热词。容器化技术的诞生和兴起，以及它所催生的微服务架构、DevOps、云原生等技术理念，都对软件行业产生了深远的影响。

容器的优点有很多了，完善的封装、便捷的部署、轻量的启动和调度，这些都是容器技术受到欢迎的原因。与编排系统配合后，它能让我们的应用程序容易管理和迭代，即便是再复杂的系统也不在话下。同时呢，容器应用还能做到非常好的可迁移性，环境中只要有符合标准的容器运行时就可以顺利运行。

我相信你对容器其实有一定的了解，也知道 Docker 和 Kubernetes 分别是容器技术和容器编排的事实标准。甚至，不少同学已经有过一些实践的经验。

那么在容器这一讲中，我们主要关心什么问题呢？我认为，你需要重点搞清楚两个问题：

容器和云是什么关系呢？

在云上运行容器有哪些方式，它们各自又有什么特点呢？

让我们顺着容器上云的发展历程，来了解这两个问题的答案。

容器上云：从 Docker 到 Kubernetes

轻量的容器和富有弹性的云计算，互相之间其实是非常契合的。容器对于运行环境的极强适应性和快速启动的能力，配合云上动态扩展的庞大资源规模，让云端的容器应用可以在短时间内拓展到成千上万个实例。所以，云可以说是容器应用的最佳载体，容器应用也非常适合在云上运行和扩展。

其实在 Docker 技术家喻户晓之前，云厂商已经在研究和使用类似容器的技术了，因为云本身是多租户的，需要运行环境的隔离性。所以云本身也是容器技术的用户和受益者，只是部分厂商会考虑进行自研，未必直接使用 Docker 而已。

补充：比如说第 11 讲提到过的 AWS 的 Elastic Beanstalk，它就使用了类似容器的私有技术，以实现 Web 应用之间的隔离。当然后来呢，它也直接支持了 Docker 容器封装的应用。

而当 Docker 兴起之后，各大公有云都不约而同地开始对外提供容器相关的标准 PaaS 服务，并持续地进行改进。如果我们梳理容器 PaaS 服务的发展脉络，就会发现它经历了一系列的发展阶段。

在初期，云上容器平台把 Docker 容器在云上的顺畅运行，作为首要的目标。产品服务的主要目的是帮助用户创建底层虚拟机集群，免去了用户自己手动管理虚拟机的麻烦。然后呢，随着容器应用的复杂化，编排逐渐成为了用户最急迫的需求，所以各厂商又纷纷推出和加强容器编排方面的解决方案。

在那个编排框架群雄并起的年代，有的厂商选择了多点开花，比如微软当时的 Azure Container Service，可以支持 Docker Swarm、Apache Mesos（DC/OS）和 Kubernetes 等多种编排系统；也有的厂商呢，选择了自己的编排方式，以便更好地和自己其他的云服务集成，比如 AWS 的 Elastic Container Service（ECS）。

当然，后来编排框架大战的结果你已经都知道了，Kubernetes 最终一统天下，成为了事实标准。所以各大厂商又很快地调转方向，纷纷为云上 Kubernetes 的支持加码，推出面向 Kubernetes 的专属服务了，比如 AWS 的 Elastic Kubernetes Service（EKS）和 Azure 的 Azure Kubernetes Service（AKS）。阿里云呢，同样也逐渐停止了旗下容器服务对 Swarm 的支持，而把发展重点聚焦在容器服务 Kubernetes 版（ACK）上。

你看，云对容器技术的支持，是伴随着容器生态发展而发展的，所以很多时候，云也是容器生态重要的参与者和推动者。就像 Google Cloud 中的 GKE（Google Kubernetes Engine），由于“根正苗红”，也一直是云上 Kubernetes 服务的标杆之一。

补充：如果说之后的技术潮流还有什么变化，我想你在云上也一样会看到领域内的最新进展。比如 Service Mesh（服务网格），也有越来越多的云服务正在探索和提供相关的支持与服务。这也是云与时俱进的魅力所在。

所以，就现在最新的形势而言，如果要容器上云，那我想你几乎不用犹豫，直接选择各大云上最新的针对 Kubernetes 的服务即可。

关于 Kubernetes 本身，它是一个非常庞大的技术体系，我建议你通过专门的课程来系统学习。但在这里你需要重点了解一下，相对于自建 Kubernetes 集群，云上 Kubernetes 服务的几个独有特点。

首先，很多云上的 Kubernetes 服务，由于云端的多租户特性，可以免除你在 Master 节点方面的开销。换句话说，你只需要创建 Worker 节点，并为之付费就行了。云平台会统一为你提供和托管 Master 节点，降低你的资源和运维成本。

另外，我们都知道 Kubernetes 虽然复杂性较高，但抽象设计出色，能够支持大量灵活的扩展。所以云厂商在这个方面花了很多功夫，能够让很多云平台上的 IaaS 或 PaaS 功能组件，渗透到 Kubernetes 的体系中来，这样可以让两边有一个更紧密的集成。

比如说，在常用来引导外部流量的 Ingress Controller（入口控制器）方面，就有 AWS 的 ALB Ingress Controller，和 Azure 的 AKS Application Gateway Ingress Controller 等基于云上负载均衡器的控制器实现。它们会创建相应的 PaaS 服务实例，来为 Kubernetes 集群服务。

再比如，我们可以在 Kubernetes 中定义动态存储卷分配策略的 StorageClass 层面，指定使用云端的块存储服务，来按需创建和挂载持久化存储。下面的配置文件片段（注意它的 provisioner 和 parameters 字段），就展示了一个使用 AWS EBS 服务来提供的 SSD 云硬盘的例子。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: standard
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2

云和 K8s 集成的方面还有很多，权限认证、日志集成、私有网络等许多方面，这里就不一一展开讨论了。这些集成共同构成了 K8s 在云上运行，以及和云全方位融合的坚实保障。

目前，AWS 还正在积极地研发推进 AWS Service Operator for Kubernetes，它把 S3、RDS 等有状态的 AWS 云服务，以自定义资源的形式纳入到了 Kubernetes 中。这让我们能够通过使用云服务来扩展 Kubernetes 的能力，并反过来使用 Kubernetes 来管理这些云资源。我们可以预期，类似 Service Operator 这样的服务，未来将会不断走向成熟，也能够进一步加快容器和云一体化架构的发展。

从架构灵活性的角度来看，云上 Kubernetes 服务还带来了另一个好处：多集群。

由于建立 K8s 集群的门槛大大降低了，如果业务间的关联较小，你是可以考虑为不同的业务单独创建 K8s 集群的。这样，不同的集群之间就有了更好的隔离性，也可以单独地扩展。

容器镜像服务

容器方面的另一种常见而且又很重要的云服务，就是容器镜像服务（Container Registry）。我们知道，容器的镜像是容器化程序封装后的基本单位，在云上，你肯定需要一个可以存储和管理自己程序镜像的地方，就像 Docker Hub 管理了很多公开镜像一样。

所以，在大多数云上都提供了自己的容器镜像服务，如 AWS 的 ECR、Azure 的 ACR 等。它们能让你建立私有的镜像仓库，支持镜像的推送和拉取，还可以进行版本管理等操作。镜像服务虽然看上去简单，却是云上容器体系中不可或缺的一环，容器的运行肯定要和它打交道。

全托管的容器实例服务

上面我们所讨论的容器服务，一般还是能够看到虚拟机的，在云虚拟机的层面都有相应的集群被创建。这其实是一种半托管的 PaaS 模式。

那么，有没有更加方便易用，不用关心底层基础设施的容器服务呢？

答案是肯定的，这也是近期云计算在容器领域的另一个特点和趋势：容器实例服务。常见的有 AWS 的 Fargate、阿里云的弹性容器实例、Azure 的 Azure Container Instance 等等。它们都是“全托管”思想在容器服务上的体现。

如果你只是有一个容器镜像，想要尽快地在云上跑起来，那么这类服务很可能就是你的最佳选择。因为它简便易行，成本低、速度快，而且你不需要操心底层的虚机和集群，也可以绕开复杂的编排系统，只需要关注 Pod 运行层面的目标就可以了。这是容器实例类云服务很大的卖点，尤其对于无状态的应用非常适合。

接下来，我就举一个实际的例子，把第 11 讲中，我们计算斐波那契数列的 Node.js 程序容器化，并且把它搬到云上的容器实例服务。我们这里使用 Azure 云上的容器实例（Azure Container Instance）来完成这个实验。

首先，要把我们之前的 Node 程序用 Docker 封装起来，相关的 Dockerfile 如下：

FROM node:10
WORKDIR /usr/src/app
COPY package.json ./
COPY app.js ./
RUN npm install
ENV PORT=80
EXPOSE 80
CMD [ "node", "app.js" ]

可以用一个简单的打包命令，来获得本地的 Docker 镜像，我们就叫它 fiboapp：

docker build --rm -f dockerfile -t fiboapp:1.0.0 .

然后，我们在 Azure 上新建一个容器注册表，也就是前面提到的容器镜像服务。云上会为我们分配一个镜像服务器的域名：

接着我们就可以用标准 Docker 命令登录，并且将镜像上传到这个私有的镜像仓库：

docker login geektimehellocloud.azurecr.io
docker tag fiboapp:1.0.0 geektimehellocloud.azurecr.io/fiboapp:1.0.0
docker push geektimehellocloud.azurecr.io/fiboapp:1.0.0

推送完成后，界面上就显示出了这个镜像的信息。

然后，我们就可以创建一个容器实例，并且指向相关的镜像了：

随后通过一些特别简单的配置，我们就可以让容器在云上跑起来了。它还贴心地“赠送”给我们一个域名：fiboapp.japaneast.azurecontainer.io。

这就大功告成了。我们用 curl 工具测试一下运行在云容器中的斐波那契服务，一切正常：

client@clientVM:~$ curl http://fiboapp.japaneast.azurecontainer.io/fibo/30
Fibo(30) = 1346269
Computed by wk-caas-3fa7a6b99b-7703b0c1f33ab2xxxxxxxx with private ip 10.244.32.63

至此，我们把斐波那契数列应用就成功地迁移到了容器实例服务上。你可以看到，这个服务为我们准备好了容器运行所需的一切环境，我们需要做的，就只是简单地把镜像打包上传而已。

课堂总结与思考

从 Docker 到 Kubernetes，容器生态不断的发展，云原生的技术浪潮已经袭来。不单是我们开发者要学习和拥抱容器技术，各个云计算厂商也都想把自己变成运行容器的最佳场所。所以，云平台们推出了各种各样的容器相关服务，以争夺云上的容器用户。

相信通过今天的介绍，你能够回答这一讲开头提出的两个问题了。容器和云是相辅相成的，云承载着容器的运行，容器生态也驱动着云的发展。从运行方式上来看，你既可以轻量方便地在云上运行容器，也可以在云上 Kubernetes 服务的帮助下创建集群，进行较大规模的编排和部署。

我这里还整理了各大云的容器相关服务名称和缩写，你可以参考下面的表格：

不知道你有没有注意，其实容器与云还有一层微妙的关系，那就是容器与厂商力推的一些云服务，存在一定的竞争和替代关系。

就像部分 PaaS 的功能，能够使用 IaaS 来实现一样，容器由于它极高的构建自由度和便捷的封装部署机制，也可以一定程度地替代部分云上的可复用组件（就像我们的实验中，用容器完成了第 12 讲中类似效果的应用部署）。而且，它可以作为系统的一部分参与编排，还是避免厂商绑定的“神器”。

注：从资源编排的角度来看同样如此，K8s 的各种 yaml 配置，和第 8 讲中提到过的 ARM Template 和 AWS CloudFormation 等私有的资源描述方式，同样存在能力交集。

这就是为什么你会发现，像 Google 这样在云计算领域相对后发的厂商，会更热衷于云原生生态的建设，并积极创立和发展 CNCF（Cloud Native Computing Foundation，云原生计算基金会）这样的组织。因为以厂商中立为特点的云原生阵营若能崛起，有助于挑战已经在云计算产品体系中占据优势的老玩家。这是有商业考量的。

当然，不论背后的商业用意如何，业界从碎片化的私有技术到统一的技术标准上面来，这本身就是云原生带来的一种进步，有着非常积极的意义。对我们开发者也是好事情，它帮我们保证了应用的可迁移性。

所以尽管容器一定程度地威胁到了部分云服务，不过云计算再一次体现了技术中立性，云平台们都大大方方地支持和承载了容器的运行，甚至作为重点服务来进行发展。把选择权留给用户，这是云的胸怀所在。

K8s 还在快速地发展，云上各种 IaaS/PaaS 服务也是实力雄厚，两者亦敌亦友，又相互渗透。未来的走向究竟如何，十分值得关注，让我们拭目以待。

好了，今天同样留给你两个思考题，欢迎你参与讨论：

后半篇所讲的容器实例类服务，与前半篇讲到的云上 Kubernetes 编排服务，其实并不是割裂的关系。通过集成和调度，不少云上 Kubernetes 服务中的 Pod 能够在容器实例服务中运行。你知道它是通过 K8s 中什么机制来完成的吗？

对于最后讨论的容器与云的微妙关系，你是怎么看的？你觉得未来更多是以 K8s 为中心、云原生吞噬一切，还是云自身的 IaaS/PaaS 产品体系更为强大，K8s 只是云中的一个服务呢？

这一讲我们就到这里。如果你觉得有收获，欢迎你把这篇文章分享给你的朋友。感谢阅读，我们下期再见。

15 | 无服务器计算：追求极致效率的多面手

你好，我是何恺铎。

和前一讲提到的容器和云原生一样，毫无疑问，“无服务器”（Serverless）是近年来的又一个技术潮流，它也是伴随着云计算的兴起而获得了迅猛的发展。这一讲，我们就一起来游览和认知无服务器的世界。

什么是无服务器计算？

“无服务器”是云计算中资源抽象的极致体现。从它的命名上你就可以看出，所谓“无服务器”就是想让用户感觉不到服务器的存在，这是因为有一朵巨大的云在底层进行着支撑。这样你可以完全专注于业务逻辑的编写，而不再关心任何基础设施。

我们在前面课程的讨论中，其实已经接触到了一些广义上的无服务器 PaaS 服务，比如第 13 讲中的无服务器查询服务和第 14 讲中的无服务器容器服务。甚至第 9 讲中的对象存储服务，它理论上来说也是符合无服务器特征的，因为你不用关心究竟是什么样的机器和多少机器在背后支撑它。

今天我们要来专门讨论的，是经典的无服务器计算服务（Serverless Computing）。“无服务器”这个名称，就是从这种灵活的计算服务起源的。

如果把无服务器计算和容器类服务一起比较的话，这两种云上计算类服务有着共同的优势和特点，比如说，它们都支持细粒度封装和易于大规模扩展。但这两者也有很不一样的地方。

如果说容器是给予了我们很大的定制空间，让你更加容易地按照自己的需要，来进行应用程序的拆分和封装；那么无服务器则是完全屏蔽了计算资源，它是在真正地引导你不再去关心底层环境，你只要遵循标准方式来直接编写业务代码就可以了。

而且在粒度上，无服务器会允许你拆分得更细致、更轻量。你甚至可以把每一个具有独立功能的函数，来作为一个单独的服务进行部署和运行。这也是为什么，在有些云计算的分类方法下，无服务器计算能够单独“开宗立派”，被称为函数即服务（Function-as-a-Service，FaaS）的原因。

你的第一个 Serverless 应用

百闻不如一见，我们就先直接通过实践来认识一下无服务器计算。

我们还是沿用前面几讲中的计算斐波那契数列的例子，因为它简单纯粹的特点，其实也非常适合利用无服务器的云函数来进行实现。所以接下来，我们就尝试把之前的 Node.js 程序迁移到无服务器环境上来。

各大云厂商现在都已经推出了各自的无服务器计算服务，比如 AWS 的 Lambda、阿里云的函数计算，和微软 Azure 的 Azure Functions。在国内的云厂商中，腾讯云也是在无服务器计算上投入较早、产品较为成熟的厂商。今天我们就以腾讯云的云函数为例，来运行我们的斐波那契计算服务。

首先，我们来到腾讯云的云函数产品中，在函数服务菜单下选择“新建”。这里需要填写一下函数名称，我们命名为 fibo，然后运行环境选择 Node.js。

小提示：这里我们选择的是空白函数模板。你也可以选择系统内置的一些常用模板作为基础，以获得一些上手帮助。

然后，我们简单地填写描述，并选取云函数所运行的角色（角色定义了云函数的一些访问权限，如是否能够访问对象存储等），然后选择“完成”即可创建函数。

函数实例建立后，我们点击进入，来到它的代码编辑模块。我们就直接在内置的代码编辑器中进行代码输入，只需要把前几讲的代码略作改动就可以适配云函数了：

补充：这里你可能会惊奇地发现，内嵌在云产品界面中的代码在线编辑并不是一个“花瓶”，包括智能提示在内的功能其实还相当好用。是的，现在云 IDE 的发展也很迅速，在云端直接进行代码编写已经不是痴人说梦了。

图中完整的代码详情我把它贴出来，如下所示：

'use strict';
exports.main_handler = (event, context, callback) => {
    var input = parseInt(event.path.split('/').pop());
    return `Fibo(${input}) = ${fibo(input)}`;
};
function fibo (n) {
    return n > 1 ? fibo(n-1) + fibo(n-2) : 1;
}

可以看到，用云函数表达的代码逻辑非常简洁。这里主要是遵循腾讯云的规范，以标准的形式定义和暴露了一个 main_handler 方法，它也就是云函数的执行入口了。

另外，这里你需要注意的是重要的输入参数 event，因为以后具体访问请求的详细信息，就会体现在这个 event 参数的各个字段中。这里我们主要取出 path 字段，来获得 fibo 函数输入参数 n 的值。

为了让这个云函数能够对外服务，我们接下来就需要为它添加一个 API 网关触发器，这样当 API 被外界访问时，这个云函数就会被触发执行并返回结果给网关。

我们可以直接在“触发方式”Tab 下选择“新建 API 服务”，这样云函数会为我们创建一个配套的 API 网关实例。

API 网关是一个独立的 PaaS 服务，它可以和云函数联动使用。它的作用是为外界访问提供一个端点，并引流到我们的后台计算服务。这有点类似第 7 讲中使用过的传输层负载均衡，但 API 网关是工作在网络的应用层，它的后端可以连接指向云函数等多种服务。另外，API 网关还能够提供不少应用层的实用功能，比如访问鉴权、限流熔断、版本控制等等。

OK，回到我们的实验当中。网关自动建立并和云函数关联后，我们就可以请求网关提供的访问路径，来触发调用云函数了：

client@clientVM:~$ curl https://service-8h29d5wp-1258170967.sh.apigw.tencentcs.com/release/fibo/35
"Fibo(35) = 14930352"

好，通过上面的测试，我们获得了正确的结果，迁移到云函数的工作就这样轻松地完成了。

你看，对于我们的斐波那契数列应用来说，是从 IaaS 篇使用负载均衡和虚拟机搭建，到改为使用应用托管服务和容器封装，再到这一讲使用无服务器计算。我们所经历的这个过程，可以说是从底层到高层，从具体到抽象，同时相应的实现也越来越简单，有一种腾云而上、渐入佳境的感觉。

值得注意的一点，在上面创建过程中，我们可没有指定任何像 CPU 核数这样的计算资源，因为我们根本不需要操心和感知这些问题。这是真正的“无服务器”计算，它会根据我们的负载情况，依托云端庞大的规模自动地进行支撑和扩展。

补充：你不需要为云函数事先划定资源池，但对于单个函数执行单元的计算资源，还是能够进行一定控制的。最常见的是可以根据云函数的需要来选择运行环境的内存大小。

也正因为底层没有固化的资源，无服务器计算的计费机制是与众不同的。它一般会按照调用次数和调用时长这两个指标来计费。这其实是非常灵活轻量的一种计费方式（部分云厂商计时已经可以精确到毫秒了），从成本上来看尤其适合那些偶尔触发、短时间运行的工作。这会比专门设立一台虚拟机来做同样的事情要划算很多。

另外，现在很多厂商为了鼓励用户去尝试使用无服务器计算，一般也都会提供每月的免费使用额度。对于一些轻量的任务，一个月下来可能都不需要你花一分钱。

从开发模式的角度来说，如果你对在网页上直接开发 Serverless 程序的方式还不太习惯，或者考虑到这样不方便进行代码管理的话，你当然也可以采用本地编辑代码然后上传的方式。而且，在本地可以配合厂商支持的 IDE 工具，会让你的无服务器计算的开发体验更加顺滑高效。

举个例子来说，对于腾讯云的云函数，你可以配合使用 Visual Studio Code 和腾讯云 Serverless 插件，来实现在本地编写、运行云函数，还可以一键和云端进行同步。如下图所示：

使用 VSCode 和腾讯云 Serverless 插件开发云函数

为什么说无服务器计算是多面手？

无服务器计算所能做的，可远远不止充当快速的 Web 开发工具。事件模型是无服务器的核心编程模型和运行逻辑，所以它非常适合相当广泛的事件驱动开发场景。

事件的起始，要依靠触发器。

云上 Serverless 服务一般都配套提供了多种多样的触发器，包括 API 触发器、对象存储触发器、队列触发器等等。比如上面的实验中，我们用的就是API 触发器，它的触发条件为 API 网关带来的外部 Web 请求。

较为常用的还有对象存储触发器。比如当用户上传了一个文件，后台程序把它保存到对象存储中，这时相应的无服务器函数会被这个新对象触发，你就能对这个新上传的文件进行必要的处理了。

此外，你还值得了解相当实用的定时触发器，它可以按照设置的条件周期性触发。通过它和云函数的配合，可以在一定程度上代替操作系统中 crontab 类工具起到的作用，也许能帮你节省一台专门触发运行定时任务的虚拟机。

如果说触发器是无服务器计算的上游的话，那么各种各样的外部交互方式，也让无服务器计算能够对外访问，并向下游输出。云端的 Serverless 环境中，一般都能够提供一系列重要类库和 SDK，让你能够在函数内访问其他云服务，尤其是像数据库、消息队列这样的外部存储。

比如说，你可以改进我们上面的实验代码，引入外部 Redis 作为缓存层，在函数中通过对 Redis 的读写，实现数列计算结果的复用。有兴趣的话，你可以动手试试看。

补充：无服务器计算本身是无状态的，所有的持久化需求都要借助外部存储来实现，所以经常需要和数据库、对象存储等服务配合，这既是常用手法，也是必然选择。

所以，在云端，一个常见的场景和架构范式是，云函数可以和消息队列服务形成一对黄金搭档：当队列中有新的消息进入，队列触发器就会触发云函数，并将消息作为事件参数传递给云函数；然后云函数进行及时处理，处理结果还能够再写入另外一个队列；队列又可以触发下一个云函数。如此层层传递，就可以形成一个流式数据的处理管道，实现数据的实时处理和分发。

无服务器函数们，还可以用另一种方式联合起来，发挥出它更大的威力，这也是现在无服务器业界发展的又一个热点：即允许你按照业务逻辑的控制处理流程，以工作流的方式，进行云函数等事件处理单元的组合和编排。

AWS 的 Step Functions 和 Azure 的 Logic Apps，以及阿里云的函数工作流，都是这种类型的云服务的代表。它们能够让你用配置文件或图形化的方式，来设置表达一个复杂的事件处理步骤和逻辑，这是架构在云函数之上的更高层调度框架。

你可以不用把 if/else、顺序执行、并发等调度控制逻辑写在一个臃肿的函数中，而是可以分开解耦，通过工作流进行组装。这时，每一个 Serverless 函数，作为处理流程的一个环节，可以只专注做一件事情。

一个用于出行订票的函数工作流示例

（来自阿里云内置示例项目）

工作流服务会来负责事件响应的回收、条件的判断和下一步的触发执行。为了做到这一点，这类服务每次的运行其实都自动维护了一个状态机，来帮助你记录和跟踪状态。

这种通过工作流组合使用云函数的方式，进一步拓展了无服务器应用的场景，让它能够轻松表达和应对更加复杂的事件处理逻辑。比如通过工作流服务，你可以无服务器化你的后端 ETL 流程。

重要提示：你应当注意这里云函数工作流服务，和前面基于队列的流式处理的区别。工作流服务构建的是控制流，定义事件发生的先后次序和条件依赖；而队列流式处理是数据流，是数据的传递和流向。

综上所述，在事件机制和工作流服务的加持下，无服务器计算就成为了一个真正的多面手。它在很多环节都能够扮演恰当的角色，除了自己承担的计算任务之外，它还擅长串联很多云端组件，成为系统组件间的胶水层。

课堂总结与思考

通过技术上的推陈出新，不断提高研发效率，是业界一个永恒的话题，也值得我们永无止境地努力。无服务器计算技术，以其简洁、易用、高效的特点，通过极致的抽象，完全屏蔽了底层基础设施，让用户可以专注业务逻辑的实现，所以成功脱颖而出，成为了亮眼的新星。

不需要指定硬件配置、完全按需服务，这个产品逻辑说起来简单，但绝非所有的运行环境都可以这样“托大”的，只有云才有可能做到这一点。云端巨大的规模是无服务器函数可以稳定可靠运行的有力保障，无愧于是无服务器诞生和发展的最佳土壤。

你可能想问，就目前而言，究竟能否在实际生产场景中全面应用无服务器技术？

我觉得，问题的答案取决于你业务的性质和形态。无服务器计算的技术成熟度已经没有问题，而且它的灵活轻量、便于迭代，都是显而易见的好处，所以非常适合中小公司或创新业务，你不妨大胆一试。比较可行的方式是，前期你可以先小规模使用，摸清它的脾性，如果一切顺利，再逐步加大应用的范围。

当然，说了无服务器计算这么多好话，我们还是要记得恪守冷静客观的原则。所以，你一定不要忽略了 Serverless 服务的限制，毕竟它的本质是受限的环境。冷启动的延时、内存的限制、云函数的运行时长、并发数上限等等，这些都是你大规模深入应用之前需要评估考虑的问题。虽然云厂商一直在改进，这些客观限制在当下对于你的场景是否造成了实质性障碍，也是你目前是否选择 Serverless 计算的一个重要依据。

还有一个你应当小心的地方，在于应用的可迁移性。如果我们看看腾讯云的云函数、阿里云的函数计算和 AWS 的 Lambda，它们的编写形式虽然大体相同，但在接口定义、参数结构、SDK 设计等各方面，还是会有不少的细节差异。所以除非你对于厂商绑定不敏感，否则代码的复用性也会是你不得不考虑的一个因素。

拓展：为了解决厂商绑定问题，业界也涌现出了像 Serverless Framework 这样的厂商中立的第三方技术框架。通过和多个主流云厂商合作和集成，实现“一套代码，多处运行”，对于无服务器计算来说也不是梦想了。你可以重点关注一下它的后续发展。

有人说，无服务器计算将是继虚拟机、容器之后的第三代通用计算技术，它代表着未来的发展趋势，这个说法不无道理。随着生态的不断成熟，和运行限制的不断改善，无服务器计算技术接下来很可能迎来爆发，前景令人期待。

今天，我留给你的思考题是：

我们实验中使用的 JavaScript 是解释型语言，非常轻量，能够在云 IDE 中编程并作为云函数直接执行。那么，对于 Java/C# 这样的编译型语言，无服务器计算能够支持吗？

从编程模型上来看，云函数一般都支持同步或者异步两种模式，我们实验中使用的是同步模式。那么，异步模式在使用上有什么区别？适合什么样的场景呢？

好了，这一讲就到这里。欢迎你在专栏下方留言，我非常愿意和你一起探讨。如果觉得有收获，也欢迎把这篇文章分享给你的朋友。

感谢阅读，我们下期再见。

16 | 云上AI服务：云AI能从哪些方面帮助构建智能应用？

你好，我是何恺铎。

欢迎来到我们课程中 PaaS 篇的最后一讲，今天，我们来讨论云上的 AI 服务。

近十年以来，从机器学习到深度学习，AI 技术的理论体系和软件生态获得了跨越式的大发展，也把很多不可能变成了可能，开始深刻地影响着我们的生活。2016 年谷歌的 AlphaGo 和李世石的巅峰对决，更是让“人工智能”声名大噪、家喻户晓。

技术的突破催生出了巨大的市场和需求，所以各大云计算厂商都非常重视在 AI 这方面的投入，致力于全方位地为人工智能应用赋能。不少云计算品牌在自己的名称中也加上了“智能”二字，对于 AI 的重视程度可见一斑。

我猜你也一定被云 AI 铺天盖地的广告宣传轰炸过。不过作为开发者，我们不能仅仅停留于宣传口径的话术，而是要切实地了解云上 AI 究竟有哪些能力，知道怎样让它与应用程序的开发和运行集成。

那么，云 AI 能从哪些方面帮助我们构建智能应用呢？

可以这样说，云对于 AI 的支持，是从不同层面以多种形式体现的。比如在基础设施的层面，我们在第 3 讲中也提到过，带有强悍 GPU 的虚拟机机型已经纷纷登场了。你可以随时用上最新最酷的 GPU 硬件，再配合一些云厂商预置的专用虚拟机镜像（比如 Azure 的 Data Science Virtual Machine 和 AWS 的 Deep Learning AMI），就可以用单机开展一些 AI 方面的工作了。

当然，我们这一讲的重点，是 AI 相关的 PaaS 服务。它们其实也大致分为两类：一类是各种成熟能力的开放，是云厂商已经构建好的现有模型和 API；另一类则是机器学习的全生命周期管理支撑平台，可以帮助你构建属于自己的机器学习模型。

开箱即用的 AI 服务

我们先来看一看，云上可以“拿来即用”的现成 AI 能力。

各家云都推出了很多不同种类、适合不同场景的内置 AI 服务，比如在 Azure 云上，它们被统称为 Azure 认知服务（Cognitive Services)。这类服务使用起来非常方便，门槛较低，你不需要掌握那些高深的模型构建知识，就可以站在巨人的肩膀上，把这些高大上的能力接入你的应用程序。

这类服务的特点，一般是将非结构化数据处理分析的通用需求场景，进行了封装和开放。你可以通过云端标准的 API 和 SDK 来进行调用，一般会按调用次数进行收费。

这里所谓的非结构化数据，指的是图像、视频、语音、文本等包含丰富信息的常见数字化内容。对于这些内容的理解，用传统的程序逻辑很难解决，但这恰好是人工智能的强项，它可以深入分析这些内容，并进行信息提取和转换。

不同的非结构化数据类型，对应着不同的人工智能研究领域，也对应着相关的各种云上 AI 服务。

比如计算机视觉，就擅长处理图形图像，它衍生出了人脸识别、物体检测、OCR（光学字符识别）、安全扫描等很多细分的能力，也催生出了多种多样的云上图片分析服务。你可以想象，从线下的安防监控和门禁闸机，到线上对用户上传图片证照的扫描和处理，图片服务的应用场景是非常广泛的。

在近期疫情肆虐的背景下，有云厂商还迅速推出了人脸口罩检测的 AI 服务，体现了云厂商的快速应变能力和社会责任感。下面的 Java 代码片段，就展示了通过官方 SDK 来调用阿里云上人脸口罩检测 API，这可以判断给定图片中的人物有没有佩戴口罩。

//设定账号的AccessKey和地域信息
DefaultProfile profile = DefaultProfile.getProfile("cn-shanghai", "<accessKeyId>", "<accessSecret>");
IAcsClient client = new DefaultAcsClient(profile);
//构造人脸口罩识别请求
DetectMaskRequest request = new DetectMaskRequest();
request.setRegionId("cn-shanghai");
//设置待识别的图片路径
request.setImageURL("http://yourbucket.oss-cn-shanghai.aliyuncs.com/mytestimage1.jpg");
//发送请求，获取识别结果
DetectMaskResponse response = client.getAcsResponse(request);
System.out.println(new Gson().toJson(response));

这段并不复杂的调用代码，也大致说明了使用一个云上 AI 服务的过程，主要就是设置好输入的图片和一些辅助参数，然后就能通过 Web 请求来进行图片分析了。这里我测试了一张网络上路人佩戴口罩的照片，执行之后的结果输出如下所示：

{
    "RequestId": "F24CXXXX-14B6-4E46-AAF8-C11E2E54XXXX",
    "Data": {
        "Mask": 2,
        "FaceProbability": "0.76107993841171265"
    }
}

可以看到，返回的 JSON 格式结果中，Mask 字段的值为 2，就说明了图片中检测出了人脸并且佩戴了口罩。

补充：该 API 返回值为 0 代表未检出人脸，1 代表人脸未佩戴口罩。甚至它还能判断有口罩但没有正确佩戴的场景，相应的返回值为 3。具体请参见阿里云相关文档。

自然语言处理（Natural Language Processing，NLP），也是一大类非常热门的 AI 服务，它主要处理的对象是文本。借助这方面的云上能力，你能够进行情感判断、命名实体识别、机器翻译等和文本分析有关的复杂功能，非常有助于构建舆情监测、用户评论分析之类的应用程序。

由于语言之间的显著差异，在调研这类 NLP 服务时，你要注意它们对于不同语种的具体支持情况。不同厂商的服务，可能在语言上面有不同的侧重。一般来说，国际厂商会先强化对于英语的支持，而国内厂商则通常会很重视处理中文文本的能力。

语音类智能服务，同样是一个很受关注的领域，它能识别声音中的内容信息，尤其是把音频转换成文字。还有一种有趣的反向转换服务是语音合成，也就是把文本转化为语音，现在也已经是越来越成熟的技术。

比如说，AWS 技术博客上的大多数文章，网页上方基本都有一个音频的版本，它的朗读效果非常接近真人，但它其实都是用 AWS 上的 Amazon Polly 服务来自动生成的。

人工智能服务还可以处理视频信息。你可以把视频分解为一帧一帧的图片和一段一段的音频，然后通过组合上述的各类服务来进行处理和整合；你也可以使用一些直接支持视频内容的云 AI 服务，如 AWS Rekognition 和阿里云“视频内容分析”来进行视频分析。这些视频分析服务，能输出视频中的场景、文本、面孔和各类物体或常见标识，你可以用在监控视频分析、用户内容审查等常见的应用场景。

当然，对于每一个细分领域的模型，想要训练成一个成熟准确的智能模型，其实都很不容易，这需要大量的训练数据，和旷日持久的调优与迭代。这些开箱即用的服务如果满足你需求的话，其实是非常简单而有效的选择。你也不需要对模型的内部实现有任何了解，把它放心地交给云厂商就好了。

构建你自己的 AI 模型

前面提到的那些现成的 AI 服务，大多是以黑盒的形式来提供能力的。所以，当这些内置服务不能满足我们需求的时候，那就需要我们“自己动手，丰衣足食”了。

我还是拿口罩识别的场景来给你举个例子。假如你不仅需要识别口罩，还想进一步判断口罩的类型，看它是普通医用口罩，还是高防护级别的 N95 口罩，这样的需求恐怕就需要你自己来定制了。

所以说，按照特定的需求来构建自己的定制模型，也是普遍而常见的场景，它也有助于应用端形成自己的特色和核心竞争力。

补充：有的时候，成本也是一个驱动应用端自行训练模型的因素，尤其当业务需求规模大、调用次数相当频繁的时候。这时内置 AI 服务的按次付费模式就会显得比较昂贵了。

很多的公司都选择了组建自己的团队，有针对性地构建自有模型。不过呢，在尝试 AI 工作一段时间以后，大家普遍容易遇到的现实问题，就是 AI 工作的随意性，没有形成体系和章法。比如，构建过程的信息分散而混乱，核心代码和脚本存储在个人 PC 上；数据和模型得不到妥善的管理，甚至会因人员离职导致丢失；还有 GPU 训练资源紧张，模型成品部署困难、运行不稳定等等。

当云厂商们发现这些痛点之后，就逐渐地开始对云上的机器学习基础设施服务进行布局和投入，致力于帮助用户构建自己的模型。现在这一块已经成为了云厂商们新的争夺热点，代表性的服务，就有 AWS 的 SageMaker，Azure 的 Machine Learning，以及阿里云的机器学习平台 PAI 等。

无论你想要构建哪种模型，包括经典机器学习和深度学习，它们共性的地方在于，都有一个类似的流程和步骤，包括数据准备和标注、模型训练、模型部署等。云上机器学习服务，它的目标就是非常精准地支撑和赋能这些重要环节，帮助你进行贯穿全生命周期的模型构建和管理。

所以，这类平台非常适合数据科学家和算法工程师日常使用，也很适合团队的管理者了解和把控 AI 研发端的总体情况。

那么，这类平台究竟是如何服务机器学习任务中的各个主要步骤的呢？

首先是数据准备的环节。

机器学习服务能够让你注册、管理和标注数据集，这些数据集通常位于对象存储当中。尤其是数据标注工作，你应该知道，它是机器学习工作中极为重要的一个步骤，是一切模型构建的基础。可是数据标注又偏偏非常枯燥，而且往往需要多人协作、交叉验证，才能保证标注结果的质量。

好在，机器学习平台为我们集成了数据标注相关的功能，让这件复杂的事情变得十分简单。你可以直接在云提供的网站门户中，来进行数据标注的工作，甚至可以组织团队分配任务，并回收那些正确的结果。这些功能的存在，几乎能够抵得上一个小小的“众包平台”了。

为了给你一个直观的印象，我在 AWS S3 中上传了几张口罩的图片，然后用 AWS SageMaker 的标注模块 Ground Truth 创建了一个“标注口罩”的图片标注任务。你可以参考下面这个真实的工作台截图：

AWS SageMaker Ground Truth 图片标注功能示例

其次，是尤为关键的模型训练环节。

在这个环节，机器学习平台一般都提供了许多内置的常见机器学习和深度学习算法，分别适用于不同的应用场景。你可以基于这些内置算法，使用自有数据训练出符合你需要的模型。

你可以在平台提供的类似 Jupyter Notebook 的开发环境中撰写编程脚本，来控制模型选择、参数配置和训练数据输入等在模型训练中，一系列的关键逻辑和设置。这些工作大多是使用 Python 语言，厂商也一般会提供相应的 Python SDK，来帮助你和云上机器学习平台交互。

补充：也有部分厂商提供了可视化的环境，允许你在画布上拖拉控件和使用流程图的方式来训练模型，比较适合机器学习的初学者和没有编程背景的用户。

接下来，我就以 AWS SageMaker 为例，带你看下如何调用内置的算法来进行模型训练。

from sagemaker.amazon.amazon_estimator import get_image_uri

# 获取内置算法对应的镜像
training_image = get_image_uri(region_name, 'builtin-algorithm-name')
# 创建Estimator实例
estimator = sagemaker.estimator.Estimator(training_image,
    role,
    train_instance_count=1,
    train_instance_type='ml.c4.xlarge',
    output_path=s3_output_location,
    sagemaker_session=sess)
# 设置模型训练的超参数
estimator.set_hyperparamters(...)
# 将训练数据喂送给模型进行训练
estimator.fit('s3://bucket/path/to/training/data')

即使你是第一次接触使用 SageMaker 这样的工具，也很容易理解上面代码片段中语句的含义。其中，SageMaker 的核心概念 Estimator，就是模型生命周期管理的主要抓手，你可以用它进行高层的语义操作，比如算法的选择、超参数的设置、训练数据的输入等等。这些高层次的方法使用起来清晰明了，它们会为你代劳与云平台底层资源的交互。

注意：为了便于讲解说明以及突出重点，我对脚本中调用参数等处进行了适当简化。下面的举例同样如此。实际使用时，你可以根据具体使用的模型类型，参考云厂商的详细文档。

除了可以使用厂商内置的机器学习算法，云上 AI 平台也兼容开源的机器学习和深度学习框架，比如著名的 Scikit-learn、TensorFlow、PyTorch、MXNet 等等。使用开源机器学习框架，能够让你彻底地控制你的底层算法和模型结构，也便于相关代码在不同平台的复用。

你也许会很好奇，像 SageMaker 这样的厂商自有机器学习体系，它是怎么集成和支持这些开源框架的呢？我们来观察下面的代码示例：

from sagemaker.tensorflow import TensorFlow

tf_estimator = TensorFlow(entry_point='tf-train.py',
    role=role,
    train_instance_count=2,
    train_instance_type='ml.p2.xlarge',
    framework_version='2.1.0',
    py_version='py3',
    distributions={'parameter_server': {'enabled': True}}))

tf_estimator.fit('s3://bucket/path/to/training/data')

可以看到，和前面的自有算法一样，这里同样使用了 Estimator 的概念，来管理和控制训练过程。不过你要注意一下这里的 TensorFlow 类，它不是指 TensorFlow 框架本身，而是一个在 SageMaker 中，用于管理封装 TensorFlow 相关模型的 Estimator。秘密包含在作为 entry_point 参数的脚本文件 tf-train.py 中，在这个脚本里，你才会编写真正的 TensorFlow 代码。

小提示：当然，为了能在 SageMaker 环境中顺利运行，你的 TensorFlow 脚本需要遵循一些 AWS 规定的标准，比如环境变量设置、输入输出的路径和格式等。

所以说，SageMaker 是通过将控制层和算法实现层分离的方式，来同时支持自有算法和开源框架的。无论你是使用什么算法和模型，它的上层仍然是统一使用 Estimator 的接口，实现了对具体算法的抽象。

另外值得注意的是，云上机器学习平台能够很容易地让你调动云上的计算资源（比如通过上面的 train_instance_type 和 train_instance_count 参数），不需要我们手动来进行创建和维护。尤其是那些支持分布式训练的模型算法，在云端充足的 CPU/GPU 资源和弹性分配机制的加持下，你可以很容易地对模型训练进行充分的并行化，这大大缩短了模型训练所需的时间。

最后，则是模型发布和部署的环节，也就是我们需要把训练完成的模型进行保存和管理，以及进行线上的发布和运行，有时这也被称为推理（Inference）阶段。

同样借助上面的 Estimator 对象，这里我们只要简单地调用一下 deploy 方法，就可以把训练好的模型部署到生产环境中，并通过新生成的 predictor 对象来进行模型调用了，如下所示：

# 将前面fit方法生成的模型部署到SageMaker端点上进行服务
predictor = estimator.deploy(initial_instance_count=1, instance_type='ml.p2.xlarge')

# 通过predict方法进行模型调用
response = predictor.predict(data)

甚至对于大批量数据的场景，你还可以借助 transformer 机制，离线地进行模型的批量调用。

transformer = estimator.transformer(instance_count=1, instance_type='ml.p2.xlarge')
# 批量调用数据
transformer.transform('s3://my-bucket/batch-transform-input')
transformer.wait()
# 随后可以从transformer.output_path中下载结果数据

你看，SageMaker 的这些功能还是很贴心的，它大大地简化了模型的部署和推理调用，相当程度地解决了模型开发者未必熟悉的 Web 服务的工程性问题。

好了，对于机器学习基础设施服务，我们就讨论到这里。你可以通过下面的 SageMaker 架构流程图，来加深对这个支撑体系的印象。这一类云服务在你构建自有模型时，能帮你提供一站式的解决方案，能在多个核心环节给予你鼎力的支持。

AWS SageMaker 架构流程图（来自AWS 官网）

课堂总结与思考

当今世界的现代应用程序，如果其中没有一点 AI 的元素，恐怕都会不好意思发布了。与这样的趋势相匹配，云平台都希望成为构建和运行新一代智能应用程序的最佳平台。

你可以根据自己的需求，直接使用云上 AI 服务中琳琅满目的内置模型，也可以利用云上机器学习平台，来高效地构建你自己的智能模型。云上 AI 平台还提供了很好的管理手段，来保存和使用公司的数据和模型资产，让你的 AI 工作朝着规范化、工程化的方向发展。

AI 技术博大精深，你当然需要通过专门的课程去系统学习。而我们这一讲的价值在于，主要关注了云对于 AI 任务在不同层面的结合点和支撑点，包括模型、数据、算法、计算资源、部署推理等等。通过今天的介绍，希望你在云上实践时，能够知道如何按图索骥，在某个细分的 AI 场景进行深入的尝试。期待你的下一个智能应用。

最后作为惯例，我们还是要谈一谈这里的风险，主要仍旧是厂商绑定的问题。如果你比较关注可迁移性，那么在使用云上 AI 服务时，你就需要注意甄别，哪些是云的自有生态，哪些是开源组件。当然，云厂商其实也在不断升级，努力地让云上 AI 服务从完全内置的黑盒到逐渐走向开放和兼容。最终让每一个环节能够拆开单独使用并且互相解耦，这是未来的一个发展趋势。

补充：我们也不要“谈绑色变”，绑定是正常的商业选择，也常会给用户带来效率的提升。云计算的很多服务和开源世界的若即若离，其本质是在生态发展和客户黏性，在技术普惠和商业利益中，不断进行着博弈和平衡。

这一讲，我留给你的课后问题是：

作为模型构建的重要组成部分，还有一个“调参”（Hyperparameter Tuning）的阶段，它也是一件困难而又麻烦的事情。你知道调参具体是指什么意思吗？在这方面，云上 AI 服务能够提供帮助吗？

前面我们谈到了可迁移性的问题，它不仅是指代码，也包括训练好的模型。那么，外部训练好的模型能够放置到云上 AI 服务中吗？在云上训练好的模型，又能不能取下来，放到本地环境中运行呢？

欢迎你给我留言和参与讨论。如果你觉得今天的内容有帮助，也欢迎把这篇文章分享给你的朋友。

好了，至此我们 PaaS 篇的内容就全部结束了。我是何恺铎，感谢你的阅读和陪伴。我还有许多想说的话，让我们在结束语中再见。

结课测试｜这些云计算知识，你都掌握了吗？

你好，我是何恺铎。

恭喜你已经顺利学习完了《深入浅出云计算》课程中的所有内容。从 IaaS 到 PaaS，云计算的内涵和能力可以说是非常宽广，不知道你掌握得怎么样呢？

我给你准备了一套结课测试题。它既是对你课程学习效果的一个检验，你也可以把它作为一个对于课程的系统性回顾。

我们的测试题目一共包括 12 道单项选择题和 8 道多项选择题，每题 5 分，满分 100 分。当你完成测试以后，也可以看到我为你附上的参考答案和题目解析，希望能够帮助到你。

好了，请开始你的测试吧。加油！

结束语 | 与云计算一起，迈向未来

你好，我是何恺铎。

时间过得真快，我们《深入浅出云计算》专栏已经进行到了尾声。在课程的 IaaS 篇和 PaaS 篇中，我为你精选和剖析了云上最具代表性的各项能力，希望能够切实地帮助你全面了解云计算，也为你的云上实践打下基础。

借着这个宝贵的机会，在此我想特别感谢所有参与我们专栏的各位同学，感谢你的一路坚持和陪伴。为了讲解云计算这个技术、产品、商业多领域交叉的综合话题，我在课程中没有只介绍技术，还在内容中融合了历史、解读、实战和感悟。所以，我也要感谢你的支持和包容，能让我用这样一种有点特别的形式，来撰写这个专栏。

云是如此的博大和宽广。出于篇幅的原因，我也有很多的领域没有详细覆盖到，比如云上的 IoT 服务、区块链服务、DevOps 服务等等。你可以秉承专栏“宏观解读、实验入手”的方法论，进一步自行探索这些未知的领域。我也会不定期地更新专栏，在加餐中和你一起，继续向云计算海洋的深处航行。

今天这一讲，是我们整个课程的结束语。让我们回归云计算的内核和本质，也一起展望未来。

再看云计算

早在开篇词发布的时候，就有不少同学提问，云计算的定义和实质究竟是什么？云计算到底是一个产品，一项技术，还是一个服务呢？

当课程系统地介绍了这么多核心能力和应用场景之后，我想在你的脑海中，云计算应该已经从一个虚拟的概念，逐渐成为了一个具象化的实体了。那么现在，我们也就终于可以回到起点，来精准地回答云计算的定义问题：

云计算已经成为一个无所不包的信息技术服务平台，它抽象了多个大型数据中心内的海量计算存储资源，对外提供了从基础设施到托管平台不同层次、不同粒度的在线服务和组件，同时也是各个领域最新前沿技术和架构理念的最佳载体。

补充：另外，云计算还是一种行之有效的商业模式，是一门好的生意，能够持续有效地获得巨大营收和利润。这也是云计算行业得以聚拢人才、持续发展的原因。

你看，如果我一开始就摆出这个严谨的定义，其实未必容易理解。但现在，跟随专栏内容进行了解读和实战之后，你再回过头来看就很清楚了，云计算其实是一个载体和平台。这个平台之上承载着从 IaaS 到 PaaS 林林总总的能力，每项能力中既包含了资源，也体现了技术，并且以产品和服务的形态开放。云的承载性是云得以包罗万象，并且与时俱进的根本原因。

所以在第 13 讲中，我们曾把云计算比作成航空母舰，这是很形象的比喻。如果再要打一个比方的话，云计算还像是一个琳琅满目的武器库，十八般兵器样样俱全。不论你要完成什么任务，或大或小，都能在这里找到称手的兵器。而当江湖上开始流行什么厉害的新式武器的时候，这个兵器库中，也会很快出现这种武器的“同款”甚至“改进款”，让你紧跟时代的潮流。

另一个和云计算密切相关，而且我们开发者普遍关心的问题就是：什么是云原生？

云原生的本质是用于构建现代云端应用的一系列架构理念，以及帮助这些理念落地的技术支撑和最佳实践。云原生的核心理念包括无状态、分布式、服务化、弹性扩展等等。

需要注意，在不同的时代、不同的话题背景和场合下，云原生其实会指代或延伸出不同的含义。常见的一种狭义的云原生定义，特指的是容器化、容器编排和微服务架构。各类厂商在宣传 Kubernetes 服务和产品时所说的“云原生”，包括我们第 14 讲讨论云上容器语境下的“云原生”，都属于这一类定义。

不过从更广义的视角来看，只要是适合在云上运行，具备和符合云上架构特点的应用，都可以说是属于“云原生”范畴。如果你通过优雅地结合使用对象存储、云数据库、无服务器计算等云端组件，开发了一个弹性可扩展的应用程序，那它当然也完全称得上是“云原生”应用。说起来开设这门课程的初衷，也正是为了帮助你构建“云原生”应用。

与云计算一起，迈向未来

最后，我也想为学习完这个专栏之后的你，提供一些面向未来的建议。是的，我们的学习之路永无止境。

云就像一艘正在高速航行的时代巨轮，此时此刻，它也在不断地发展和进化着。在行业领先的云平台上，每年会发布多达数千项的服务和更新。这对于我们个人来讲，既是学习上的挑战，更应该视为发展的机遇。

我建议你，跟随着云的发展脚步来不断提升自己。借助云平台，我们可以与时俱进，更快、更有效地学习新技术和应用新技术。这对于我们的职业生涯发展也是大有裨益的。

你可以考虑参加一些云的考试和认证，或者参加业内有影响力的云计算大会，不断强化你对于云的认识。你还可以积极参与到云生态当中，分享和发表相关内容，以及向云厂商反馈你对于产品的意见和建议，帮助云变得更好。

当然，最终的着眼点，还是在于业务。请用云来构建和开展你的业务吧，让云在你的手中发挥最大的作用和价值。如果市场上的友商花了很多精力在“造轮子”，你不妨抓住机会全面上云，用极致效率赢取竞争优势。祝你好运！

好了，我们的结束语就到这里。虽然这是专栏的最后一讲，但我们对于云的探索不会停止。我会继续通过加餐来丰富课程的内容，期待到时候能给你惊喜。如果你有了新的问题或思考，仍然可以通过留言和我交流。我也会把更多的云上实操和细节研究，放在我的公众号“云间拾遗”中进行探讨。

咱们有始有终，这一讲我照例给你留下一个课后问题吧：

推荐你阅读一下我在 InfoQ 上发表的长文《激荡十年：云计算的过去、现在和未来》。你可以跟随它，系统地回顾云计算的发展历程，并且把我们的课程内容有机地串联起来。在这篇文章的最后，对云计算的未来发展进行了探讨和预测，谈到了“创新、垂直、混合、生态”这四个大的趋势。对于云的未来，你有什么看法呢？欢迎分享你的观点。

另外，这里还有一份毕业问卷，题目不多，希望你能抽出几分钟时间填写一下。我非常愿意听听你对这个课程的反馈和建议，请在问卷中畅所欲言。

最后，用一句诗来结尾吧：长风破浪会有时，直挂“云”帆济沧海。谢谢，我们不说再见。