Jimmy Song's Blog

Kubernetes TLS bootstrap引导程序

按照 kubernetes-handbook 安装 kubernetes 集群的第一步是什么?没错,创建 TLS 证书和秘钥!作为第一步已经这么繁琐和容易出错,很多人就望而却步了,单纯的按照说明执行命令而不了解这样做的目录和命令的含义无法帮助我们进行问题排查和纠错。 Bootstrap 是很多系统中都存在的程序,比如 Linux 的bootstrap,bootstrap 一般都是作为预先配置在开启或者系统启动的时候加载,这可以用来生成一个指定环境。Kubernetes 的 kubelet 的启动时同样可以加载一个这样的配置文件,这个文件的内容类似如下形式: 02b50b05283e98dd0fd71db496ef01e8,kubelet-bootstrap,10001,"system:kubelet-bootstrap" 下面将为您详细解释 TLS bootstrap 是如何配置和生成的(下文是 kubernetes 官方文档的中文版)。 TLS Bootstrap 本文档介绍如何为 kubelet 设置 TLS 客户端证书引导(bootstrap)。 Kubernetes 1.4 引入了一个用于从集群级证书颁发机构(CA)请求证书的 API。此 API 的原始目的是为 kubelet 提供 TLS 客户端证书。可以在 这里 找到该提议,在 feature #43 追踪该功能的进度。 kube-apiserver 配置 您必须提供一个 token 文件,该文件中指定了至少一个分配给 kubelet 特定 bootstrap 组的 “bootstrap token”。 该组将作为 controller manager 配置中的默认批准控制器而用于审批。随着此功能的成熟,您应该确保 token 被绑定到基于角色的访问控制(RBAC)策略上,该策略严格限制了与证书配置相关的客户端请求(使用 bootstrap token)。使用 RBAC,将 token 范围划分为组可以带来很大的灵活性(例如,当您配置完成节点后,您可以禁用特定引导组的访问)。 Token 认证文件 Token 可以是任意的,但应该可以表示为从安全随机数生成器(例如大多数现代操作系统中的 /dev/urandom)导出的至少128位熵。生成 token 有很多中方式。例如:

Cloud Native Python—使用Python和React构建云原生应用

继 Cloud Native Go 之后又一本关于 Cloud Native 的力作已经登上了我的写作日程,这次是基于 Python 构建微服务和云原生 Web 应用程序,书名叫作 Cloud Native Python。 下面是它的英文原版书(感谢电子工业出版社)跟它已出版的好兄弟 Cloud Native Go 在一起的合影。 这本书跟 Cloud Native Go 的内容由很大部分的重合,目录结构也基本一致,所用的技术栈也很类似,不过内容更详实,图片和步骤介绍更多一些,跟我看的另一本由印度人写的 Kubernetes Management Design Patterns: With Docker, CoreOS Linux, and Other Platforms 的风格很像。 Cloud Native Python 介绍 随着当今商业的迅速发展,企业为了支撑自身的迅速扩张,仅仅通过自有的基础设施是远远不够的。因此,他们一直在追求利用云的弹性来构建支持高度可扩展应用程序的平台。 这本书能够帮助您一站式的了解使用Python构建云原生应用架构的所有信息。本书中我们首先向您介绍云原生应用架构和他们能够帮助您解决哪些问题。然后您将了解到如何使用REST API和Python构建微服务,通过事件驱动的方式构建Web层。接下来,您将了解到如何与数据服务进行交互,并使用React构建Web视图,之后我们将详细介绍应用程序的安全性和性能。然后,您还将了解到如何Docker容器化您的服务。最后,您将学习如何在AWS和Azure平台上部署您的应用程序。在您部署了应用程序后,我们将围绕关于应用程序故障排查的一系列概念和技术来结束这本书。 本书中涵盖哪些内容 第1章 介绍云原生应用架构和微服务,讨论云原生架构的基本概念和构建应用程序开发环境。 第2章 使用Python构建微服务,构建自己的微服务知识体系并根据您的用例进行扩展。 第3章 使用Python构建Web应用程序,构建一个初始的Web应用程序并与微服务集成。 第4章 与数据服务交互,教您如何将应用程序迁移到不同的数据库服务。 第5章 使用React构建Web视图。 第6章 使用Flux创建可扩展UI,帮助您理解如何使用Flux创建可扩展的应用程序。 第7章 事件溯源和CQRS,讨论如何以事件形式存储合约(transaction)。 第8章 保护Web应用程序,让您的应用程序免于受到外部威胁。 第9章 持续交付,应用程序频繁发布的相关知识。 第10章 Docker容器化您的服务,讨论容器服务和在Docker中运行应用程序。 第11章 将应用程序部署到AWS平台上,教您如何在AWS上构建基础设施并建立应用程序的生产环境。 第12章 将应用程序部署到Azure平台上,讨论如何在Azure上构建基础设施并建立应用程序的生产环境。

Linkerd 使用指南

前言 该文章已归档到 kubernetes-handbook 第五章【领域应用】中,一切内容以 kubernetes-handbook 为准,该文档可能不会及时更新。 以下内容参考:A Service Mesh for Kubernetes Linkerd 作为一款 service mesh 与kubernetes 结合后主要有以下几种用法: 作为服务网关,可以监控 kubernetes 中的服务和实例 使用 TLS 加密服务 通过流量转移到持续交付 开发测试环境(Eat your own dog food)、Ingress 和边缘路由 给微服务做 staging 分布式 tracing 作为 Ingress controller 使用 gRPC 更方便 以下我们着重讲解在 kubernetes 中如何使用 linkerd 作为 kubernetes 的 Ingress controller,并作为边缘节点代替 Traefik的功能,详见 边缘节点的配置。 准备 安装测试时需要用到的镜像有: buoyantio/helloworld:0.1.4 buoyantio/jenkins-plus:2.60.1 buoyantio/kubectl:v1.4.0 buoyantio/linkerd:1.1.2 buoyantio/namerd:1.1.2 buoyantio/nginx:1.10.2 linkerd/namerctl:0.8.6 openzipkin/zipkin:1.20 tutum/dnsutils:latest 这些镜像可以直接通过 Docker Hub 获取,我将它们下载下来并上传到了自己的私有镜像仓库 sz-pg-oam-docker-hub-001.

迁移到云原生应用架构指南

迁移到云原生应用架构 本书是 Migrating to Cloud Native Application Architectures 的中文版。 本书托管地址:https://github.com/rootsongjc/migrating-to-cloud-native-application-architectures Gitbook 阅读地址:https://rootsongjc.gitbooks.io/moving-to-cloud-native-archtecture 译者序 云时代的云原生应用大势已来,将传统的单体架构应用迁移到云原生架构,你准备好了吗? 俗话说“意识决定行动”,在迁移到云原生应用之前,我们大家需要先对 Cloud Native(云原生)的概念、组织形式并对实现它的技术有一个大概的了解,这样才能指导我们的云原生架构实践。 Pivotal 是云原生应用的提出者,并推出了 Pivotal Cloud Foundry 云原生应用平台和 Spring 开源 Java 开发框架,成为云原生应用架构中先驱者和探路者。 原书作于2015年,其中的示例主要针对 Java 应用,实际上也适用于任何应用类型,云原生应用架构适用于异构语言的程序开发,不仅仅是针对 Java 语言的程序开发。截止到本人翻译本书时,云原生应用生态系统已经初具规模,CNCF 成员不断发展壮大,基于 Cloud Native 的创业公司不断涌现,kubernetes 引领容器编排潮流,和 Service Mesh 技术(如 Linkerd 和 Istio) 的出现,Go 语言的兴起(参考另一本书 Cloud Native Go)等为我们将应用迁移到云原生架构的提供了更多的方案选择。 Jimmy Song 简介 当前很多企业正在采用云原生应用程序架构,这可以帮助其IT转型,成为市场竞争中真正敏捷的力量。 O’Reilly 的报告中定义了云原生应用程序架构的特性,如微服务和十二因素应用程序。 本书中作者Matt Stine还探究了将传统的单体应用和面向服务架构(SOA)应用迁移到云原生架构所需的文化、组织和技术变革。本书中还有一个迁移手册,其中包含将单体应用程序分解为微服务,实施容错模式和执行云原生服务的自动测试的方法。 本书中讨论的应用程序架构包括: 十二因素应用程序:云原生应用程序架构模式的集合 微服务:独立部署的服务,只做一件事情 自助服务的敏捷基础设施:快速,可重复和一致地提供应用环境和后台服务的平台 基于API的协作:发布和版本化的API,允许在云原生应用程序架构中的服务之间进行交互 抗压性:根据压力变强的系统 关于作者 Matt Stine,Pivotal的技术产品经理,拥有15年企业IT和众多业务领域的经验。 Matt 强调精益/敏捷方法、DevOps、架构模式和编程范例,他正在探究使用技术组合帮助企业IT部门能够像初创公司一样工作。

适用于kubernetes的应用开发与部署流程详解

(题图:风和日丽@野三坡 Jul 14,2017) 本文已归档在kubernetes-handbook中的第3章【用户指南】中,一切更新以kubernetes-handbook中为准。 为了详细说明,我特意写了两个示例程序放在GitHub中,模拟应用开发流程: k8s-app-monitor-test:生成模拟的监控数据,发送http请求,获取json返回值 K8s-app-monitor-agent:获取监控数据并绘图,访问浏览器获取图表 API文档见k8s-app-monitor-test中的api.html文件,该文档在API blueprint中定义,使用aglio生成,打开后如图所示: 关于服务发现 K8s-app-monitor-agent服务需要访问k8s-app-monitor-test服务,这就涉及到服务发现的问题,我们在代码中直接写死了要访问的服务的内网DNS地址(kubedns中的地址,即k8s-app-monitor-test.default.svc.cluster.local)。 我们知道Kubernetes在启动Pod的时候为容器注入环境变量,这些环境变量在所有的 namespace 中共享(环境变量是不断追加的,新启动的Pod中将拥有老的Pod中所有的环境变量,而老的Pod中的环境变量不变)。但是既然使用这些环境变量就已经可以访问到对应的service,那么获取应用的地址信息,究竟是使用变量呢?还是直接使用DNS解析来发现? 答案是使用DNS,详细说明见Kubernetes中的服务发现与Docker容器间的环境变量传递源码探究。 打包镜像 因为我使用wercker自动构建,构建完成后自动打包成docker镜像并上传到docker hub中(需要现在docker hub中创建repo)。 构建流程见:https://app.wercker.com/jimmysong/k8s-app-monitor-agent/ 生成了如下两个docker镜像: jimmysong/k8s-app-monitor-test:latest jimmysong/k8s-app-monitor-agent:latest 启动服务 所有的kubernetes应用启动所用的yaml配置文件都保存在那两个GitHub仓库的manifest.yaml文件中。 分别在两个GitHub目录下执行kubectl create -f manifest.yaml即可启动服务。 外部访问 服务启动后需要更新ingress配置,在ingress.yaml文件中增加以下几行: - host: k8s-app-monitor-agent.jimmysong.io http: paths: - path: / backend: serviceName: k8s-app-monitor-agent servicePort: 8080 保存后,然后执行kubectl replace -f ingress.yaml即可刷新ingress。 修改本机的/etc/hosts文件,在其中加入以下一行: 172.20.0.119 k8s-app-monitor-agent.jimmysong.io 当然你也可以加入到DNS中,为了简单起见我使用hosts。 详见边缘节点配置。 在浏览器中访问http://k8s-app-monitor-agent.jimmysong.io 刷新页面将获得新的图表。

记一本关于kubernetes management design patterns的书

书名: Kubernetes Management Design Patterns: With Docker, CoreOS Linux, and Other Platforms Amazon购买链接:链接 作者:Deepak Vohra 发行日期:2017年1月20日 出版社:Apress 页数:399 简介 Kubernetes引领容器集群管理进入一个全新的阶段;学习如何在CoreOS上配置和管理kubernetes集群;使用适当的管理模式,如ConfigMaps、Autoscaling、弹性资源使用和高可用性配置。讨论了kubernetes的一些其他特性,如日志、调度、滚动升级、volume、服务类型和跨多个云供应商zone。 Kubernetes中的最小模块化单位是Pod,它是拥有共同的文件系统和网络的系列容器的集合。Pod的抽象层可以对容器使用设计模式,就像面向对象设计模式一样。容器能够提供与软件对象(如模块化或包装,抽象和重用)相同的优势。 在大多数章节中使用的都是CoreOS Linux,其他讨论的平台有CentOS,OpenShift,Debian 8(jessie),AWS和Debian 7 for Google Container Engine。 使用CoreOS主要是因为Docker已经在CoreOS上开箱即用。CoreOS: 支持大多数云提供商(包括Amazon AWS EC2和Google Cloud Platform)和虚拟化平台(如VMWare和VirtualBox) 提供Cloud-Config,用于声明式配置OS,如网络配置(flannel),存储(etcd)和用户帐户 为容器化应用提供生产级基础架构,包括自动化,安全性和可扩展性 引领容器行业标准,并建立了应用程序标准 提供最先进的容器仓库,Quay Docker于2013年3月开源,现已称为最流行的容器平台。kubernetes于2014年6月开源,现在已经成为最流行的容器集群管理平台。第一个稳定版CoreOS Linux于2014年7月发行,现已成为最流行的容器操作系统之一。 你将学到什么 使用docker和kubernetes 在AWS和CoreOS上创建kubernetes集群 应用集群管理设计模式 使用多个云供应商zone 使用Ansible管理kubernetes 基于kubernetes的PAAS平台OpenShift 创建高可用网站 构建高可用用的kubernetes master集群 使用volume、configmap、serivce、autoscaling和rolling update 管理计算资源 配置日志和调度 谁适合读这本书 Linux管理员、CoreOS管理员、应用程序开发者、容器即服务(CAAS)开发者。阅读这本书需要Linux和Docker的前置知识。介绍Kubernetes的知识,例如创建集群,创建Pod,创建service以及创建和缩放replication controller。还需要一些关于使用Amazon Web Services(AWS)EC2,CloudFormation和VPC的必备知识。 关于作者 Deepak Vohra is an Oracle Certified Associate and a Sun Certified Java Programmer.

Kubernetes中的服务发现与docker容器间的环境变量传递源码探究

(题图:雷雨@野三坡 Jul 13,2017) 前言 今天创建了两个kubernetes示例应用: k8s-app-monitor-test:启动server用来产生metrics k8s-app-monitor-agent:获取metrics并绘图,显示在web上 注:相关的kubernetes应用manifest.yaml文件分别见以上两个应用的GitHub 。 当我查看Pod中的环境变量信息时,例如kubernetes中的service k8s-app-monitor-test注入的环境变量时,包括了以下变量: K8S_APP_MONITOR_TEST_PORT_3000_TCP_ADDR=10.254.56.68 K8S_APP_MONITOR_TEST_PORT=tcp://10.254.56.68:3000 K8S_APP_MONITOR_TEST_PORT_3000_TCP_PROTO=tcp K8S_APP_MONITOR_TEST_SERVICE_PORT_HTTP=3000 K8S_APP_MONITOR_TEST_PORT_3000_TCP_PORT=3000 K8S_APP_MONITOR_TEST_PORT_3000_TCP=tcp://10.254.56.68:3000 K8S_APP_MONITOR_TEST_SERVICE_HOST=10.254.56.68 K8S_APP_MONITOR_TEST_SERVICE_PORT=3000 我们知道Kubernetes在启动Pod的时候为容器注入环境变量,这些环境变量将在该Pod所在的namespace中共享。但是既然使用这些环境变量就已经可以访问到对应的service,那么获取应用的地址信息,究竟是使用变量呢?还是直接使用DNS解析来发现?下面我们从代码中来寻求答案。 如果不想看下面的文字,可以直接看图。 探索 docker的docker/engine-api/types/container/config.go中的Config结构体中有对环境变量的定义: // Config contains the configuration data about a container. // It should hold only portable information about the container. // Here, "portable" means "independent from the host we are running on". // Non-portable information *should* appear in HostConfig. // All fields added to this struct must be marked `omitempty` to keep getting // predictable hashes from the old `v1Compatibility` configuration.

Awesome Cloud Native

这是一份记录关于Cloud Native的软件、工具、架构以及参考资料的列表,是我在GitHub上开的一个项目,地址是https://github.com/rootsongjc/awesome-cloud-native。 初步划分成以下这些领域: Awesome Cloud Native API Containers CI-CD Database Logging Message broker Monitoring Networking Orchestration and scheduler PaaS Proxy and load balancer Service mesh Service registry and discovery Storage Tracing Tools Tutorial 今后会不断更新和完善该列表,不仅是为了本人平时的研究记录,也作为Cloud Native届的人士的参考。

企业迁移到云生应用架构时所需做出的变革

本文译自Migrating to Cloud Native Application Architectures第二部分,归档到https://github.com/rootsongjc/migrating-to-cloud-native-application-architectures 。 在变革中前行 从客户给我们下达订单开始,一直到我们收到现金为止,我们一直都关注时间线。而且我们正在通过删除非附加值的废物来减少这个时间表。 —— Taichi Ohno Taichi Ohno被公认为精益制造之父。 虽然精益制造的实践无法完全适用于软件开发领域,但它们的原则是一致的。 这些原则可以指导我们很好地寻求典型的企业IT组织采用云原生应用程序架构所需的变革,并且接受作为这一转变所带来的部分的文化和组织转型。 文化变革 企业IT采用云原生架构所需的变革根本不是技术性的,而是企业文化和组织的变革,围绕消除造成浪费的结构、流程和活动。 在本节中,我们将研究必要的文化转变。 从信息孤岛到DevOps 企业IT通常被组织成以下许多孤岛: 软件开发 质量保证 数据库管理 系统管理 IT运营 发布管理 项目管理 创建这些孤岛是为了让那些了解特定领域的人员来管理和指导那些执行该专业领域工作的人员。 这些孤岛通常具有不同的管理层次,工具集、沟通风格、词汇表和激励结构。这些差异启发了企业IT目标的不同范式,以及如何实现这一目标。 开发和运维分别对软件变更持有的观念就是个经常被提起的关于这些矛盾模式的例子。 开发的任务通常被视为通过开发软件功能为组织提供额外的价值。 这些功能本身就是向IT生态系统引入变更。 所以开发的使命可以被描述为“交付变化”,而且经常根据有多少次变更来进行激励。 相反,IT运营的使命可以被描述为“防止变更”。 IT运营通常负责维护IT系统所需的可用性、弹性、性能和耐用性。因此,他们经常以维持关键绩效指标(KPI)来进行激励,例如平均故障间隔时间(MTBF)和平均恢复时间(MTTR)。与这些措施相关的主要风险因素之一是在系统中引入任何类型的变更。 那么,不是设法将开发期望的变更安全地引入IT生态系统,而是通过将流程放在一起,使变更变得痛苦,从而降低了变化率。 这些不同的范式显然导致了许多额外的工作。项目工作中的协作、沟通和简单的交接变得乏味和痛苦,最糟糕的是导致绝对混乱(甚至是危险的)。 企业IT通常通过创建基于单据的系统和委员会会议驱动的复杂流程来尝试“修复”这种情况。企业IT价值流在所有非增值浪费下步履瞒珊。 像这样的环境与云原生的速度思想背道而驰。 专业的信息孤岛和流程往往是由创造安全环境的愿望所驱动。然而,他们通常提供很少的附加安全性,在某些情况下,会使事情变得更糟! 在其核心上,DevOps代表着这样一种思想,即将这些信息孤岛构建成共享的工具集、词汇表和沟通结构,以服务于专注于单一目标的文化:快速、安全得交付价值。 然后创建激励结构,强制和奖励领导组织朝着这一目标迈进的行为。 官僚主义和流程被信任和责任所取代。 在这个新的世界中,开发和IT运营部门向共同的直接领导者汇报,并进行合作,寻找能够持续提供价值并获得期望的可用性、弹性、性能和耐久性水平的实践。今天,这些对背景敏感的做法越来越多地包括采用云原生应用架构,提供完成组织的新的共同目标所需的技术支持。 从间断均衡到持续交付 企业经常采用敏捷流程,如Scrum,但是只能作为开发团队内部的本地优化。 在这个行业中,我们实际上已经成功地将个别开发团队转变为更灵活的工作方式。 我们可以这样开始项目,撰写用户故事,并执行敏捷开发的所有例程,如迭代计划会议,日常站会,回顾和客户展示demo。 我们中的冒险者甚至可能会冒险进行工程实践,如结对编程和测试驱动开发。持续集成,这在以前是一个相当激进的概念,现在已经成为企业软件词典的标准组成部分。事实上,我已经是几个企业软件团队中的一部分,并建立了高度优化的“故事到演示”周期,每个开发迭代的结果在客户演示期间被热烈接受。 但是,这些团队会遇到可怕的问题:我们什么时候可以在生产环境中看到这些功能? 这个问题是我们很难回答,因为它迫使我们考虑我们无法控制的力量: 我们需要多长时间才能浏览独立的质量保证流程? 我们什么时候可以加入生产发布的行列中? 我们可以让IT运营及时为我们提供生产环境吗? 在这一点上,我们意识到自己已经陷入了戴维·韦斯特哈斯(Dave Westhas)所说的scrum瀑布中了。 我们的团队已经开始接受敏捷原则,但我们的组织却没有。所以,不是每次迭代产生一次生产部署(这是敏捷宣言的原始出发点),代码实际上是批量参与一个更传统的下游发布周期。 这种操作风格产生直接的后果。我们不是每次迭代都将价值交付给客户,并将有价值的反馈回到开发团队,我们继续保持“间断均衡”的交付方式。 间断均衡实际上丧失了敏捷交付的两个主要优点: 客户可能需要几周的时间才能看到软件带来的新价值。 他们认为,这种新的敏捷工作方式只是“像往常一样”,不会增强对开发团队的信任。 因为他们没有看到可靠的交付节奏,他们回到了以前的套路将尽可能多的要求尽可能多地堆放到发布版上。 为什么? 因为他们对软件能够很快发布没有信心,他们希望尽可能多的价值被包括在最终交付时。 开发团队可能会好几周都没有得到真正的反馈。虽然演示很棒,但任何经验丰富的开发人员都知道,只有真实用户参与到软件之中才能获得最佳反馈。这些反馈能够帮助软件修正,使团队去做正确的事情。反馈推迟后,错误的可能性只能增加,并带来昂贵的返工。 获得云原生应用程序体系结构的好处需要我们转变为持续交付。 我们拥抱端到端拥抱价值的原则,而不是Water Scrum Fall组织驱动的间断平衡。设想这样一个生命周期的模型是由Mary和Tom Poppendieck在《实施精益软件开发(Addison-Wesley)》一书中描述的“概念到现金”的想法中提出来的。 这种方法考虑了所有必要的活动,将业务想法从概念传递到创造利润的角度,并构建可以使人们和过程达到最佳目标的价值流。

什么是云原生应用架构

本文译自Migrating to Cloud Native Application Architectures第一部分,归档到https://github.com/rootsongjc/migrating-to-cloud-native-application-architectures 。 第1章 云原生的崛起 软件正在吞噬这个世界。—Mark Andreessen 近些年来,在一些长期由领导者支配的行业中,这些领导者的领先地位已经岌岌可危,这都是由以这些行业为核心业务的软件公司造成的。像Square、Uber、Netflix、Airbnb和特斯拉这样的公司能够持续快速增长,并并拥有傲人的市场估值,成为它们所在行业的新领导者。这些创新公司有什么共同点? 快速创新 持续可用的服务 弹性可扩展的Web 以移动为核心的用户体验 将软件迁移到云上是一种自演化,使用了云原生应用架构是这些公司能够如此具有破坏性的核心原因。通过云,任何能够按需、自助弹性提供和释放计算、网络和存储资源的计算环境。云的定义包括公有云(例如 Amazon Web Services、Google Cloud和Microsoft Azure)和私有云(例如 VMware vSphere和 OpenStack)。 本章中我们将探讨云原生应用架构的创新性,然后论证云原生应用架构的主要特性。 为何使用云原生应用架构 首先我们来阐述下将应用迁移到云原生架构的动机。 速度 天下武功,唯快不破,市场竞争亦是如此。想象一下,能够快速创新、实验并交付软件的企业,与使用传统软件交付模式的企业,谁将在市场竞争中胜出呢? 在传统企业中,为应用提供环境和部署新版本花费的时间通常以天、周或月来计算。这种速度严重限制了每个发行版可以承担的风险,因为修复这些错误往往跟发行一个新版本有差不多的耗时。 互联网公司经常提到它们每天极版次发布的实践。为什么频繁发布如此重要?如果你可以每天实现几百次发布,你们就可以几乎立即从错误的版本恢复过来。如果你可以立即从错误中恢复过来,你就能够承受更多的风险。如果你可以承受更多的风险,你就可以做更疯狂的试验——这些试验结果可能会成为你接下来的竞争优势。 基于云基础设置的弹性和自服务的特性天生就适应于这种工作方式。通过调用云服务API来提供新的应用程序环境比基于表单的手动过程要快几个数量级。然后通过另一个API调用将代码部署到新的环境中。将自服务和hook添加到团队的CI/CD服务器环境中进一步加快了速度。现在,我们可以回答精益大师Mary Poppendick提出的问题了——“如果只是改变了应用的一行代码,您的组织需要多长时间才能把应用部署到线上?“答案是几分钟或几秒钟。 你可以大胆想象 一下,如果你也可以达到这样的速度,你的团队、你的业务可以做哪些事情呢? 安全 光是速度快还是不够的。如果你开车是一开始就把油门踩到底,你将因此发生事故而付出惨痛的代价(有时甚至是致命的)!不同的交通方式如飞机和特快列车都会兼顾速度和安全性。云原生应用架构在快速变动的需求、稳定性、可用性和耐久性之间寻求平衡。这是可能的而且非常有必要同时实现的。 我们前面已经提到过,云原生应用架构可以让我们迅速地从错误中恢复。我们没有谈论如何预防错误,而在企业里往往在这一点上花费了大量的时间。在追寻速度的路上,大而全的前端升级,详尽的文档,架构复核委员会和漫长的回归测试周期在一次次成为我们的绊脚石。当然,之所以这样做都是出于好意。不幸的是,所有这些做法都不能提供一致可衡量的生产缺陷改善度量。 那么我们如何才能做到即安全又快速呢? 可视化 我们的架构必须为我们提供必要的工具,以便可以在发生故障时看到它。 我们需要观测一切的能力,建立一个“哪些是正常”的概况,检测与标准情况的偏差(包括绝对值和变化率),并确定哪些组件导致了这些偏差。功能丰富的指标、监控、警报、数据可视化框架和工具是所有云原生应用程序体系结构的核心。 故障隔离 为了限制与故障带来的风险,我们需要限制可能受到故障影响的组件或功能的范围。如果每次亚马逊的推荐引擎挂掉后人们就不能再在亚马逊上买产品,那将是灾难性的。单体架构通常就是这种类型的故障模式。云原生应用程序架构通常使用微服务。通过将系统拆解为微服务,我们可以将任何一个微服务的故障范围限制在这个微服务上,但还需要结合容错才能实现这一点。 容错 仅仅将系统拆解为可以独立部署的微服务还是不够的;还需要防止出现错误的组件将错误传递它所的依赖组件上造成级联故障。Mike Nygard 在他的《Release It! - Pragmatic Programmers》一书中描述了一些容错模型,最受欢迎的是断路器。软件断路器的工作原理就类似于电子断路器(保险丝):断开它所保护的组件与故障系统之间的回路以防止级联故障。它还可以提供一个优雅的回退行为,比如回路断开的时候提供一组默认的产品推荐。我们将在“容错”一节详细讨论该模型。 自动恢复 凭借可视化、故障隔离和容错能力,我们拥有确定故障所需的工具,从故障中恢复,并在进行错误检测和故障恢复的过程中为客户提供合理的服务水平。一些故障很容易识别:它们在每次发生时呈现出相同的易于检测的模式。以服务健康检查为例,结果只有两个:健康或不健康,up或down。很多时候,每次遇到这样的故障时,我们都会采取相同的行动。在健康检查失败的情况下,我们通常只需重新启动或重新部署相关服务。云原生应用程序架构不要当应用在这些情况下无需手动干预。相反,他们会自动检测和恢复。换句话说,他们给电脑装上了寻呼机而不是人。 弹性扩展 随着需求的增加,我们必须扩大服务能力。过去我们通过垂直扩展来处理更多的需求:购买了更强悍的服务器。我们最终实现了自己的目标,但是步伐太慢,并且产生了更多的花费。这导致了基于高峰使用预测的容量规划。我们会问”这项服务需要多大的计算能力?”然后购买足够的硬件来满足这个要求。很多时候我们依然会判断错误,会在如黑色星期五这类事件中打破我们的可用容量规划。但是,更多的时候,我们将会遇到数以百计的服务器,它们的CPU都是空闲的,这会让资源使用率指标很难看。 创新型的公司通过以下两个开创性的举措来解决这个问题: 它们不再继续购买更大型的服务器,取而代之的是用大量的更便宜机器来水平扩展应用实例。这些机器更容易获得,并且能够快速部署。 通过将大型服务器虚拟化成几个较小的服务器,并向其部署多个隔离的工作负载来改善现有大型服务器的资源利用率。 随着像亚马逊AWS这样的公有云基础设施的出现,这两个举措融合了起来。虚拟化工作被委托给云提供商,消费者只需要关注在大量的云服务器实例很想扩展它们的应用程序实例。最近,作为应用程序部署的单元,发生了另一个转变,从虚拟机转移到了容器。 由于公司不再需要大量启动资金来部署软件,所以向云的转变打开了更多创新之门。正在进行的维护还需要较少的资本投入,并且通过API进行配置不仅可以提高初始部署的速度,还可以最大限度地提高我们应对需求变化的速度。 不幸的是,所有这些好处都带有成本。相较于垂直扩展的应用,支持水平扩展的应用程序的架构必须不同。云的弹性要求应用程序的状态短暂性。我们不仅可以快速创建新的应用实例;我们也必须能够快速、安全地处置它们。这种需求是状态管理的问题:一次性与持久性相互作用如何? 在大多数垂直架构中采用的诸如聚类会话和共享文件系统的传统方法并不能很好地支持水平扩展。 云原生应用程序架构的另一个标志是将状态外部化到内存数据网格,缓存和持久对象存储,同时保持应用程序实例本身基本上是无状态的。无状态应用程序可以快速创建和销毁,以及附加到外部状态管理器和脱离外部状态管理器,增强我们响应需求变化的能力。当然这也需要外部状态管理器自己来扩展。大多数云基础设施提供商已经认识到这一必要性,并提供了这类服务的健康菜单。