数据专栏

智能大数据搬运工,你想要的我们都有

科技资讯

科技学院

科技百科

科技书籍

网站大全

软件大全

「深度学习福利」大神带你进阶工程师,立即查看>>> 摘要: KubeEdge 是首个基于 Kubernetes 扩展的,提供云边协同能力的开放式智能边缘计算平台,也是 CNCF 在智能边缘领域的首个正式项目。依托 Kubernetes 强大的容器编排和调度能力,实现云边协同、计算下沉、海量设备接入等。
边缘计算场景与挑战
边缘计算是一种分布式计算概念,拥有去中心化处理能力的分散型开放 IT 架构,数据由设备本身或本地计算机或服务器处理,无需传输到数据中心,也可在更靠近终端的网络边缘上提供服务。
但边缘计算无法单独存在,它必定要和远程数据中心 / 云打通,以 IoT(Internet of Things,物联网)场景为例,边缘设备除了拥有传感器收集周边环境的数据外,还会从云端接收控制指令,因此边缘计算与云计算二者是相依而生、协同运作的。
据2020边缘计算状态报告显示,到2022年,75%的数据将通过边缘分析和处理。 这种数据处理的流动性,将伴随有4大边缘技术演进方向: 人工智能的实用性增强,从云端渗透到边缘 物联网设备的数量呈指数级增长 5G时代的快速到来 边缘计算中心逐步克服分布式设施复杂性和单位成本经济性的问题
结合边缘计算的场景与技术演进方向,可以总结出当前边缘计算领域面临的几个挑战: 云边协同 :逐步从云端渗透到边缘的AI/安全等业务,在云和边的智能协同、弹性迁移; 网络 :边缘网络的可靠性和带宽限制; 设备管理 :呈指数级增长的物联网设备,边缘节点与边缘设备的管理; 扩展 :高度分布和大规模的可扩展性; 异构 :边缘异构硬件和通信协议。
Kubernetes构建边缘计算平台的优势与挑战
Kubernetes 已经成为云原生的事实标准,并且能够在任何基础设施上提供一致的云上体验。我们经常能够看到“容器 + Kubernetes”的组合在 DevOps 发挥 10X 效率。基于Kubernetes的技术架构与生态优势,近几年也有越来越多的将Kubernetes 运行在数据中心外(边缘)的需求。
基于Kubernetes构建的边缘计算平台,将会具备众多天然的优势:
(1)容器化应用封装 :容器的轻量化和可移植性非常适合边缘计算的场景,边缘容器应用Build一次,可以运行在任何边缘节点上。
(2)通用的应用抽象定义 :Kubernetes的应用定义已成为云原生业界的事实标准,被广泛接受。通过原生的Kubernetes应用API,用户可以将云上与边缘的应用统一管理。例如用户可以使用熟悉的 kubectl 或者 helm chart管理云上与边缘的应用。
(3)平台易扩展性 :Kubernetes 已经被证明具备良好的可扩展性,基于CRD可以自定义API,如边缘设备管理;基于CRI、CNI、CSI等插件可以扩展各种边缘自定义插件。
(4)强大的技术生态圈: 围绕 Kubernetes 已经形成了一个强大的云原生技术生态圈,诸如:监控、日志、CI、存储、网络都能找到现成的工具链。
然而 Kubernetes 毕竟原生是为云数据中心设计的,要将Kubernetes 的能力扩展到边缘,必须解决以下问题:
(1)边缘设备资源有限 :很多设备边缘的资源规格有限,特别是 CPU 处理能力较弱,内存资源较少,因此无法部署完整的 Kubernetes。
(2)边缘网络的不稳定性 :Kubernetes依赖数据中心稳定的网络,边缘场景下网络通常又是不稳定的。
(3)边缘节点离线自治 :Kubernetes依赖 list/watch 机制,不支持离线运行,而边缘节点的离线又是常态,例如:设备离线重启。
(4)海量边缘设备管理 :如何使用Kubernetes管理指数级增长的海量边缘设备以及产生的数据。
另外,关于如何在边缘使用 Kubernetes,Kubernetes IoT/Edge WG 组织的一个调查显示,30% 的用户希望在边缘部署完整的 Kubernetes 集群,而 70% 的用户希望在云端部署 Kubernetes 的管理面并且在边缘节点上只部署 Kubernetes 的 agent。
边缘容器开源现状
Kubernetes社区很早就已经关注到边缘计算场景,早在2018年社区就已经成立专门的Edge工作组来研讨边缘相关场景。而2018年底, 华为在业界首次开源Kubernetes边缘项目KubeEdge,将华为云智能边缘平台产品IEF(Intelligent EdgeFabric)核心代码开源,并于19年初捐献给CNCF基金会,成为CNCF迄今为止唯一边缘计算官方项目 。随后,Rancher、阿里云也陆续跟进,开源了K3s、OpenYurt等项目,边缘容器这个领域真正进入到快速发展期。下面,我们对这三个代表性的K8s@Edge的项目进行一些简要分析。
KubeEdge架构分析
KubeEdge 是华为云于2018年11月开源,2019年3月捐献给 CNCF 的开源项目。KubeEdge 是首个基于 Kubernetes 扩展的,提供云边协同能力的开放式智能边缘计算平台,也是 CNCF 在智能边缘领域的首个正式项目。KubeEdge 的名字来源于 Kube + Edge,顾名思义就是依托 Kubernetes 强大的容器编排和调度能力,实现云边协同、计算下沉、海量设备接入等。
KubeEdge架构上分为云、边、端三个层次。云端中心管控边缘节点与设备,边缘节点实现边缘自治,云上管控边缘节点的架构也符合Kubernetes IoT/Edge WG 调查结果中大多数用户的诉求。KubeEdge完整的打通了边缘计算中云、边、设备协同的场景,整体架构如下图。
针对边缘特定的场景,KubeEdge 重点解决的问题是:
云边协同 :KubeEdge 通过 Kubernetes 标准 API 在云端管理边缘节点、设备和工作负载的增删改查。边缘节点的系统升级和应用程序更新都可以直接从云端下发,提升边缘的运维效率;在边缘AI场景下,云端训练好的模型可以直接下发到边缘节点,进行推理等,实现边缘AI的云边一体化。
边缘自治 :KubeEdge 通过消息总线和元数据本地存储实现了节点的离线自治。用户期望的控制面配置和设备实时状态更新都通过消息同步到本地存储,这样节点在离线情况下即使重启也不会丢失管理元数据,并保持对本节点设备和应用的管理能力。
极致轻量 :KubeEdge 则是保留了 Kubernetes 管理面,对Kubernetes的节点端组件进行重组,达到极致轻量的目的,节点组件可以运行在内存256M的边缘节点上。
海量边缘设备管理 :KubeEdge了可插拔式的设备统一管理框架,在云端基于Kubernetes的CRD能力,自定义了设备管理的API,完全符合Kubernetes的原生标准,用户可以在云端通过API来管理海量边缘设备;在边缘可根据不同的协议或实际需求开发设备接入驱动,当前已经支持和计划支持的协议有:MQTT,BlueTooth,OPC UA,Modbus 等,随着越来越多社区合作伙伴的加入,KubeEdge 未来会支持更多的设备通信协议。
K3s架构分析
K3s 是 Rancher于2019年2月开源的一个自己裁剪的 Kubernetes 发行版,K3S 名字来源于 K8s – 5,这里的“5”指的是 K3S 比 Kubernetes 更轻量使得它能更好地适配 CI,ARM,边缘技术,物联网和测试这 5 个场景。K3S 是 CNCF 官方认证的 Kubernetes 发行版,开源时间较 KubeEdge 稍晚。K3S 专为在资源有限的环境中运行 Kubernetes 的研发和运维人员设计,目的是为了在 x86、ARM64 和 ARMv7D 架构的边缘节点上运行小型的 Kubernetes 集群。K3S 的整体架构如下所示:
K3S 就是基于一个特定版本 Kubernetes(例如:1.17)直接做了代码修改。K3S 分 Server 和 Agent,Server 就是 Kubernetes 管理面组件 + SQLite 和 Tunnel Proxy,Agent 即 Kubernetes 的数据面 + Tunnel Proxy。
为了减少运行 Kubernetes 所需的资源,K3S 对原生 Kubernetes 代码做了以下几个方面的修改:
删除旧的、非必须的代码。 K3S 不包括任何非默认的、Alpha 或者过时的 Kubernetes 功能。除此之外,K3S 还删除了所有非默认的 Admission Controller,in-tree 的 cloud provider 和存储插件;
整合打包进程。 为了节省内存,K3S 将原本以多进程方式运行的 Kubernetes 管理面和数据面的多个进程分别合并成一个来运行;
使用 Containderd 替换 Docker, 显著减少运行时占用空间;
引入 SQLite 代替 etcd 作为管理面数据存储 ,并用 SQLite 实现了 list/watch 接口;
将所有Kubernetes原生进程打包在同一个进程中。
K3s项目本质上是一个K8s的“轻量化”版本,而不是一个真正意义上的“边缘”版本。 从架构上看,K3s 的所有组件(包括 Server 和 Agent)都运行在边缘侧,这意味着 K3S 并不是一个去中心化的部署模型,每个边缘都需要额外部署 Kubernetes 管理面,因此不涉及云边协同。也缺乏针对边缘网络不稳定性的边缘自治能力,也不涉及边缘设备的管理。
此外,如果 K3s 要落到生产,在 K3s 之上应该还有一个云上的统一集群管理方案负责跨集群的应用管理、监控、告警、日志、安全和策略等,遗憾的是 Rancher 尚未开源这部分能力。
OpenYurt架构分析
OpenYurt是阿里云于2020年5月开源的云原生边缘计算项目,跟KubeEdge架构基本相似,OpenYurt也是依托原生Kubernetes的容器编排及调度能力,提供云边协同能力的边缘计算平台。OpenYurt 也是依托 Kubernetes 强大的容器应用编排能力,实现云-边一体化的应用分发、管控的诉求,也是从云端集中管控边缘节点,OpenYurt 的整体架构如下所示:
项目目前还未发布0.1版本,从已开源部分可以看出,OpenYurt架构与KubeEdge类似,也是打通了云边协同的场景。提供的能力也与KubeEdge类似,包括边缘自治、云边协同、单元化管理能力(未开源)等。
OpenYurt并未对Kubernetes进行改造,而是通过Addon(插件化)的形式提供边缘计算所需要的管控能力 ,边缘端的YurtHub,作为节点上的临时配置中心,在网络连接中断的情况下,持续为节点上所有设备和客户业务提供数据配置服务。这种简化的架构,重点在于解决“离线自治”问题,且比较有利于保留现有K8s的完整功能,但由于未对Kubelet进行修改,因此OpenYurt无法运行在资源有限的边缘设备中;物联网场景中的对于边缘设备的管理,OpenYurt也不涉及;并且一些边缘场景下涉及到Kubelet原生不支持的高级特性比如离线自愈、自调度等无法实现。
边缘容器总结与展望
对比三个开源项目, K3s 最让人印象深刻的特点在于其对 Kubernetes 进行了轻量化、部署便捷化做的尝试,通过剪裁了 Kubernetes 一些不常用功能并且合并多个组件到一个进程运行的方式,使得一些资源较充足的边缘节点上能够很方便的获得与Kubernetes一致的体验。但是从测试数据看K3s 的资源消耗还是很高,而且动辄几百 MB 的内存也不是大多数设备边缘节点所能提供的,而且目前只适合运行在边缘,不具备云边协同、边缘自治等边缘计算领域的核心诉求。
OpenYurt通过非侵入的插件化形式在原生Kubernetes的基础上提供边缘计算能力,虽然提供了云边协同、边缘自治等能力,但是未做轻量化改造,只能运行在资源充足的边缘节点,无法运行在大量资源有限的边缘节点上,并且也未提供边缘计算中海量边缘设备管理的能力。
KubeEdge是一个从云到边缘再到设备的完整边缘云平台,100% 兼容Kubernetes的原生API,基于Kubernetes解决了边缘计算领域的核心诉求, 包括云边协同、边缘网络不稳定、边缘自治、边缘轻量化、海量边缘设备管理以及异构扩展等问题。
未来边缘容器技术仍将聚焦于解决边缘计算领域所面临的云边协同、网络、设备管理、扩展及异构等挑战,KubeEdge 已经是 CNCF正式项目,未来将持续与社区合作伙伴一起制定云和边缘计算协同的标准,解决边缘计算领域的难题,结束边缘计算没有统一标准和参考架构的混沌状态,共同推动边缘计算的产业发展。

点击关注,第一时间了解华为云新鲜技术~
云计算
2020-07-21 14:29:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
作者 | 不瞋 阿里云高级技术专家
**导读:**用户需求和云的发展两条线推动了云原生技术的兴起、发展和大规模应用。本文将主要讨论什么是云原生应用,构成云原生应用的要素是什么,什么是 Serverless 计算,以及 Serverless 如何简化技术复杂度,帮助用户应对快速变化的需求,实现弹性、高可用的服务,并通过具体的案例和场景进行说明。
如今,各行各业都在谈数字化转型,尤其是新零售、传媒、交通等行业。数字化的商业形态已经成为主流,逐渐替代了传统的商业形态。在另外一些行业里(如工业制造),虽然企业的商业形态并非以数字化的形式表现,但是在数字孪生理念下,充分利用数据科技进行生产运营优化也正在成为研究热点和行业共识。
企业进行数字化转型,从生产资料、生产关系、战略规划、增长曲线四个层面来看: 生产资料:数据成为最重要的生产资料,需求/风险随时变化,企业面临巨大的不确定性; 生产关系:数据为中心,非基于流程和规则的固定生产关系,网络效应令生产关系跨越时空限制,多连接方式催生新的业务和物种; 战略规划:基于数据决策,快速应对不确定的商业环境; 增长曲线:数字化技术带来触达海量用户的能力,可带来突破性的增长。
从云服务商的角度来看云的演进趋势,在 Cloud 1.0 时代,基础设施的云化是其主题,采用云托管模式,云上云下的应用保持兼容,传统的应用可以直接迁移到云上,这种方式的核心价值在于资源的弹性和成本的低廉;在基础设施提供了海量算力之后,怎么帮助用户更好地利用算力,加速企业创新的速度,就成为云的核心能力。
如果仍在服务器上构建基础应用,那么研发成本就会很高,管理难度也很大,因此有了 Cloud 2.0,也就是云原生时代。在云原生时代,云服务商提供了丰富的托管服务,助力企业数字化转型和创新,用户可以像搭积木一样基于各种云服务来构建应用,大大降低了研发成本。
云原生应用要素
云原生应用有三个非常关键的要素:微服务架构,应用容器化和 Serverless 化,敏捷的软件交付流程。
1. 微服务架构
单体架构和微服务架构各有各的特点,其主要特点对比如下图所示。总的来说,单体架构上手快,但是维护难,微服务架构部署较难,但是独立性和敏捷性更好,更适合云原生应用。
单体架构 VS 微服务架构
2. 应用容器化和 Serverless 化
容器是当前最流行的代码封装方式,借助 K8s 及其生态的能力,大大降低了整个基础设施的管理难度,而且容器在程序的支撑性方面提供非常出色的灵活性和可移植性,越来越多的用户开始使用容器来封装整个应用。 Serverless 计算是另外一种形态,做了大量的端到端整合和云服务的集成,大大提高了研发效率,但是对传统应用的兼容性没有容器那么灵活,但是也带来了很大的整洁性,用户只需要专注于业务逻辑的编码,聚焦于业务逻辑的创新即可。
3. 敏捷的应用交付流程
敏捷的应用交付流程是非常重要的一个要素,主要包括流程自动化,专注于功能开发,快速发现问题,快速发布上线。
Serverless 计算
1. 阿里云函数计算
Serverless 是一个新的概念,但是其内涵早就已经存在。阿里云或者 AWS 的第一个云服务都是对象存储,对象储存实际上就是一个存储领域的 Serverless 服务;另外,Serverless 指的是一个产品体系,而不是单个产品。当前业界云服务商推出的新功能或者新产品绝大多数都是 Serverless 形态的。阿里云 Serverless 产品体系包括计算、存储、API、分析和中间件等,目前云的产品体系正在 Serverless 化。
阿里云 Serverless 计算平台函数计算,有 4 个特点: 和云端无缝集成:通过事件驱动的方式将云端的各种服务与函数计算无缝集成,用户只需要关注函数的开发,事件的触发等均由服务商来完成; 实时弹性伸缩:由系统自动完成函数计算的弹性伸缩,且速度非常快,用户可以将这种能力用在在线应用上; 次秒级计量:次秒级的计量方式提供了一种完全的按需计量方式,资源利用率能达到百分之百; 高可用:函数计算平台做了大量工作帮助用户构建高可用的应用。
那么,阿里云函数计算是如何做到以上 4 点呢?阿里云函数计算的产品能力大图如下图所示,首先函数计算产品是建立在阿里巴巴的基础设施服务之上的产品,对在其之上的计算层进行了大量优化。接着在应用层开发了大量能力和工具,基于以上产品能力,为用户提供多种场景下完整的解决方案,才有了整个优秀的函数计算产品。函数计算是阿里云的一个非常基础的云产品,阿里云的许多产品和功能均是建立在函数计算的基础上。目前阿里云函数计算已经在全球 19 个区域提供服务。
阿里云函数计算产品能力大图
2. Serverless 帮助用户简化云原生应用高可用设计、实施的复杂度
云原生应用的高可用是一个系统的工程,包括众多方面,完整的高可用体系构建需要很多时间和精力。那么 Serverless 计算是如何帮助用户简化云原生应用高可用设计、实施的复杂度呢? 如下图所示,高可用体系建设要考虑的点包括基础设施层、运行时层、数据层以及应用层,且每一层都有大量的工作要做才可以实现高可用。函数计算主要是从容错、弹性、流控、监控四方面做了大量工作来实现高可用,下图中蓝色虚线框所对应的功能均由平台来实现,用户是不需要考虑的。蓝色实线框虽然平台做了一些工作来简化用户的工作难度,但是仍需要用户来进行关注,而橘红色的实线框代表需要用户去负责的部分功能。结合平台提供的功能和用户的部分精力投入,可以极大地减轻用户进行高可用体系建设的难度。
函数计算高可用
函数计算在很多方面做了优化来帮助用户建设高可用体系。下图展示了函数计算在可用区容灾方面的能力。从图中可知,函数计算做了相应的负载均衡,使得容灾能力大大提升。
函数计算多可用区容灾
下图展示的是函数计算对事件的异步处理,其处理流水线主要包括事件队列、事件分发、事件消费三个环节,在每一个环节上都可以进行水平伸缩,其中一个比较关键的点是事件的分发需要匹配下游的消费能力。另外,通过为不同函数指定不同数量的计算资源,用户能方便地动态调整不同类型事件的消费速度。此外,还可以自定义错误重试逻辑,并且有背压反馈和流控,不会在短时间内产生大量请求时压垮下一个服务。
函数计算事件异步处理
在函数计算的可观测性上面,提供了日志收集和查询功能,除了默认的简单日志查询功能外,还提供了高级日志查询,用户可以更方便地进行日志分析。在指标收集和可视化方面,函数计算提供了丰富的指标收集能力,并且提供了标准指标、概览信息等视图,可以更方便用户进行运维工作。 下图是应用交付的一个示意图,在整个应用的交付过程中,只有每个环节都做好,才能够建设一个敏捷的应用交付流程,其核心是自动化,只有做到了自动化,才能提升整个流水线的效率和敏捷度。
▲ 敏捷的应用交付流程
下图展示了自动化应用交付流水线在每个环节的具体任务。其中需要注意的是做到基础设施即代码,才能进行模板定义和自动化设置应用运行环境,进而实现自动化的持续集成等。
自动化应用交付流水线
做到了应用的自动化交付之后,对整个研发效率的帮助是非常大的。在 Serverless 应用上,阿里云提供了多种工具来帮助用户实现基础设施即代码。Serverless 的模型有一个很好的能力,就是同一份模板可以传入不同的参数,进而生成不同环境的定义,然后通过自动化地管理这些环境。
对于应用本身不同服务版本的交付和灰度发布,函数计算提供了服务版本和服务别名来提供相应的服务,整个应用的灰度发布流程可以简化成一些 API 的操作,大大提升业务的效率。通过 Serverless 计算平台提供的这些能力,整个软件应用的交付流水线自动化程度得到了大幅度的提高。
函数计算还有一个很有用的功能——对存量应用的兼容性。通过 Custom runtime,能够适配很多的流行框架,兼容传统应用,使其能够很容易地适配到 Serverless 平台上面,由控制台提供应用的创建、部署、关联资源管理、监控等一系列服务。
除了函数计算,还可以用 Serverless 工作流对不同的应用环节、不同的函数进行编排,通过描述性的语言去定义工作流,由其可靠地执行每一个步骤,这就大幅度降低用户对于复杂任务的编排难度。
应用场景案例
函数计算有几个典型的应用场景,一个就是 Web/API 后端服务,阿里云已经有包括石墨文档、微博、世纪华联在内的多个成功应用案例。
函数计算的另外一个应用场景就是大规模的数据并行处理,比如往 OSS 上面上传大量的图片、音频、文本等数据,可以触发函数做自定义的处理,比如转码、截帧等。这方面的成功案例包括虎扑、分众传媒、百家互联等。
函数计算还有一个应用场景就是数据实时流式处理,比如不同的设备产生的消息、日志发送到消息队列等管道类似的服务中,就可以触发函数来进行流式处理。
最后一个应用场景就是运维的自动化,通过定时触发、云监控事件触发、流程编排等方式调用函数完成运维任务,大大降低运维成本和难度,典型的成功案例有图森未来等。
图森未来是一家专注于 L4 级别无人驾驶卡车技术研发与应用的人工智能企业,面向全球提供可大规模商业化运营的无人驾驶卡车技术,为全球物流运输行业赋能。在路测过程中会有大量数据产生,而对这些数据的处理流程复杂多变,即使对于同一批数据,不同的业务小组也会有不同的使用及处理方式。如何有效管理不同的数据处理流程、降低人为介入频率能够大幅的提高生产效率。
路测不定时运行的特点使得流程编排任务运行时间点、运行时长具有极大的不确定性,本地机房独自建立流程管理系统难以最大优化机器利用率,造成资源浪费。而图森未来本地已有许多单元化业务处理脚本及应用程序,但因为各种限制而无法全量的迁移上云,这也对如何合理化使用云上服务带来了挑战。
针对上述情况,图森未来开始探索数据处理平台的自动化。阿里云 Serverless 工作流按执行调度的次数计费,具有易用易集成、运维简单等诸多优点,能够很好地解决上述场景中所遇到的问题,非常适合这类不定时运行的离线任务场景。
Serverless 工作流还支持编排本地或自建机房的任务,图森未来通过使用 Serverless 工作流原生支持的消息服务 MNS 解决了云上云下的数据打通问题,使得本地的原有任务得到很好的编排及管理。
除了调度外,Serverless 工作流也支持对任务的状态及执行过程中所产生的数据进行维护。图森未来通过使用任务的输入输出映射及状态汇报机制,高效地管理了流程中各任务的生命周期及相互间的数据传递。
在未来,随着业务规模的扩大,图森未来将持续优化离线大数据处理流程的运行效率及自动化水平。通过各种探索,图森未来将进一步提升工程团队的效率,将更多的精力和资金投入到业务创新中去。
总结
Serverless 工作流是阿里云 Serverless 产品体系中的关键一环。通过 Serverless 工作流,用户能够将函数计算、视觉智能平台等多个阿里云服务,或者自建的服务,以简单直观的方式编排为工作流,迅速构建弹性高可用的云原生应用。
自 2017 年推出函数计算起,该服务根据应用负载变化实时智能地弹性扩缩容,1 分钟完成上万实例的伸缩并保证稳定的延时。目前已经支撑微博、芒果 TV、华大基因、图森未来、石墨科技等用户的关键应用,轻松应对业务洪峰。
课程推荐
为了更多开发者能够享受到 Serverless 带来的红利,这一次,我们集结了 10+ 位阿里巴巴 Serverless 领域技术专家,打造出最适合开发者入门的 Serverless 公开课,让你即学即用,轻松拥抱云计算的新范式——Serverless。
点击即可免费观看课程: https://developer.aliyun.com/learning/roadmap/serverless “ 阿里巴巴云原生 关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”
云计算
2020-07-21 14:11:00
「深度学习福利」大神带你进阶工程师,立即查看>>> 摘要: 9个步骤通过API创建云服务器。
事情是这样的,公司成立了一个新项目,要给项目建官网,并搭建一个web服务器。按照我的习惯,搭建一个本地虚拟机就好了,部署简单方便还好配置,云服务器嘛,写了10年代码,还是不习惯那玩意儿。
我这刚开始动手,就看见实习生屁颠屁颠地跑过来,我心想这小子肯定是想来学虚拟机搭建部署的,这么简单的事都不会,真是白瞎了他那985的学校了。
可是...万万没想到啊,小实习生跑到我老大那里邀功去了!!!远远地听见他说:“公司新项目跑在云服务器上了,以后可以根据访问量随时进行弹性扩展,安全稳定还快。”
啥?云服务器?这小子居然会配置云服务器?听完汇报,老大看向了我,带着小实习生往我这边走过来……
“哼,叫你邀功,撞枪口上了吧,我就说云服务器配置没那么容易,还不是得来找我~”这么想着有点得意,老大走过来拍拍我的肩膀,说:“你跟他学一下怎么配置云服务器,别再用虚拟机了,以后都是麻烦事。”
我...他...让我跟一个实习生学???
实习生冲我微微一笑,就走了,没过一会扔给我一份文档,上面写着:“创建弹性云服务器流程详解”。打开粗略扫了一眼,代码都直接贴上来了?瞧不起谁?感觉有被冒犯到。
技术人嘛,看到代码还是没忍住跑一遍,等我发现bug或跑不通,再给他上上课!
首先免费领取了1台云服务器,然后开始跑代码
结果……真香。
内容是这样的:
通过API创建云服务器的9个步骤(以指定镜像方式创建云服务器为例)
步骤一:确定待创建云服务器所在的可用区。
1、查询可用区。
(1)接口相关信息
URI格式:GET /v2.1/{project_id}/os-availability-zone
(2)请求示例
GET: https://{endpoint}/v2.1/74610f3a5ad941998e91f076297ecf27/os-availability-zone
(3)响应示例
{ "availabilityZoneInfo": [ { "hosts": null, "zoneState": { "available": true }, "zoneName":"zone_01" }, { "hosts": null, "zoneState": { "available": true }, "zoneName": "zone_01" } ] }
2、根据实际需要选择可用区,并记录可用区的zoneName。
步骤二:确定待创建云服务器的规格。
1、查询云服务器规格信息。
(1)接口相关信息
URI格式:GET/v2.1/{project_id}/flavors/detail{?minDisk,minRam,is_public,sort_key,sort_dir}
其中,“?”后的字段为查询规格时可选的查询检索参数。
(2)请求示例
GET: https://{endpoint}/v2.1/74610f3a5ad941998e91f076297ecf27/flavors/detail
(3)响应示例
{ "flavors": [ { "name": "c1.2xlarge", "links": [ { "href": "https://xxx/v2.1/74610f3a5ad941998e91f076297ecf27/flavors/c1.2xlarge", "rel": "self" }, { "href": "https://xxx/74610f3a5ad941998e91f076297ecf27/flavors/c1.2xlarge", "rel": "bookmark" } ], "ram": 8192, "OS-FLV-DISABLED:disabled": false, "vcpus": 8, "swap": "", "os-flavor-access:is_public": true, "rxtx_factor": 1, "OS-FLV-EXT-DATA:ephemeral": 0, "disk": 0, "id": "c1.2xlarge" } ] }
2、 根据实际需要选择规格,并记录规格的ID。
步骤三:确定待创建云服务器使用的镜像。
1、查询镜像。
(1)接口相关信息
URI格式:GET /v2.1/{project_id}/images/detail
(2)请求示例
GET: https://{endpoint}/v2.1/74610f3a5ad941998e91f076297ecf27/images/detail
(3)响应示例
{ "images": [ { "OS-EXT-IMG-SIZE:size": 0, "metadata": { "__os_type": "Linux", "hw_vif_multiqueue_enabled": "true", "__imagetype": "gold", "__quick_start": "true", "virtual_env_type": "FusionCompute", "__support_xen": "true", "__support_kvm": "true", "__image_source_type": "uds", "__platform": "EulerOS", "__os_version": "EulerOS 2.2 64bit", "__os_bit": "64", "__isregistered": "false" }, "created": "2018-05-14T06:13:50Z", "minRam": 0, "name": "DBS-MySQL-Image_2.1.3.3", "progress": 100, "links": [ { "rel": "self", "href": "https://None/v2.1/74610f3a5ad941998e91f076297ecf27/images/11e8f727-d439-4ed1-b3b8-33f46c0379c4" }, { "rel": "bookmark", "href": "https://None/74610f3a5ad941998e91f076297ecf27/images/11e8f727-d439-4ed1-b3b8-33f46c0379c4" }, { "rel": "alternate", "href": "https://None/images/11e8f727-d439-4ed1-b3b8-33f46c0379c4", "type": "application/vnd.openstack.image" } ], "id": "11e8f727-d439-4ed1-b3b8-33f46c0379c4", "updated": "2018-05-14T06:13:52Z", "minDisk": 40, "status": "ACTIVE" } ] }
2、根据需要选择镜像,并记录镜像ID。
步骤四:确定云服务器的网络信息。
1、查询网络。
(1)接口相关信息
URI格式:GET /v2.1/{project_id}/os-networks
(2)请求示例
GET: https://{endpoint}/v2.1/74610f3a5ad941998e91f076297ecf27/os-networks
(3)响应示例
{ "networks": [ { "id": "07a9557d-4256-48ae-847c-415a9c8f7ff6", "label": "b_tt3_td1b", "broadcast": null, "cidr": null, "dns1": null, "dns2": null, "gateway": null, "netmask": null, "cidr_v6": null, "gateway_v6": null, "netmask_v6": null } ] }
2、根据需要选择网络,并记录网络ID。
步骤五:设置密钥对登录方式。
如需设置为密码登录方式,请直接跳转至步骤七。
1、创建密钥对。
(1)接口相关信息
URI格式:POST /v2.1/{project_id}/os-keypairs
(2)请求示例
POST: https://{endpoint}/v2.1/74610f3a5ad941998e91f076297ecf27/os-keypairs
Body:
{ "keypair": { "type": "ssh", "name": "demo1", "user_id": "fake" } }
(3)响应示例
{ "keypair": { "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCrR5Gcwlh5ih7JOvzIUuQxS5qzWWPMYHeDXkDKSQ9W5pumOV05SiO3WCswnaQ5xMdOl31mNiHtwlwq9dJi7X6jJBB2shTD+00G5WuwkBbFU4CLvt1B44u0NUiaTJ35NAvW2/4XvpXm9OwiQ3B5ge6ZY7Esi38Unh+pkbhPkYxNBCK8yoOlojQhWs75abdxZBi811/8RwLcNiFiocA2RGxtRjBdpEScj+1TU+OcfZdQnr0AFbO11z7yxfIygwwzVTgUuJNbMbKHStQqRbklfMlHY4RBPQgb7RN/YaXKTQSXT84k+D9xlDNo7Wj4fwOJTOz/s/PvbIOqjRHt9D6Y4IKd Generated-by-Nova\n", "private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEogIBAAKCAQEAq0eRnMJYeYoeyTr8yFLkMUuas1ljzGB3g15AykkPVuabpjld\nOUojt1grMJ2kOcTHTpd9ZjYh7cJcKvXSYu1+oyQQdrIUw/tNBuVrsJAWxVOAi77d\nQeOLtDVImkyd+TQL1tv+F76V5vTsIkNweYHumWOxLIt/FJ4fqZG4T5GMTQQivMqD\npaI0IVrO+Wm3cWQYvNdf/EcC3DYhYqHANkRsbUYwXaREnI/tU1PjnH2XUJ69ABWz\ntdc+8sXyMoMMM1U4FLiTWzGyh0rUKkW5JXzJR2OEQT0IG+0Tf2Glyk0El0/OJPg/\ncZQzaO1o+H8DiUzs/7Pz72yDqo0R7fQ+mOCCnQIDAQABAoIBAA6/c9dGmK2mae4z\nyQ5KrOFdvC1TNhej+sZx+CwyzEJUSvSuHcvQCXFBAz8FY92hhvPKcX66jINXZ+4/\nCmWAQ5YyhcRiow0Y91HvsS0bywoknX3q6kxBFodmyyCWFkgd5iMTADb1Lx0a27Y7\njlS4Dl5gyiGmxUN2Ng24wWEAjE8ZNuI0lrtr5IZKp+s5IAi/rb5AG/mL7EzicE8c\nmGP+QAa+nzwhAwNhFwVID230xen/ZcoL1d77hxeARNqJUxoR25gwJd6Ebg2y9pDW\nVu6cbbzgdGUCfQYlMEoAamAkCswOsDpVDBXwQnt2A537n6Wq2bgYIKusHr9thtxP\n/5ubQLUCgYEA4zYuBG2vtLHnvce26P8o2j1xcJS9K0ozkah9JFl3hqFN0sAqLlz7\n/Fm1jA4kzHJS3d0UqP3AMDxY3HkIqCn4Be7lqeAAe2AfqkOZpt9MDNv4VwKe9sPb\nViW1qjL3FxziLC/YWTRNSlpwRjqJJGhA+UQt8rOia1k/zXmrEs7bXLcCgYEAwPsu\nK3j5QoAiziYVMYf5iCzWwAM9Ljpf9gw23lefTdIzhhfFtJplVRSyxRGU0UZ84GMI\nTd5zmcIF/1KUfhqmeiQzz6NIPEYEReahjpQ/sOH/Gk5Rwr3QwYPrwAu5x+kk/SRi\nKPkqw7APTR0sMQBcUq+ZYwGYLGPMdd1zUdLfb0sCgYBkuz11iydtxb3G/obSD2WO\nM9VaIycmzRPFzNwGRH/gOR0mhTluKp0wyJjbSd34oeqpH/2r2ivddrOysxoqa8jg\n4IQDZyLvj7MaKjQxrieqP89+y9Or9TMFo1xB46x2G8EN8/xHuA9YGnZSPFtWv72m\nhRqV0hv82amWsA0vHnRUSwKBgDsKHXvrTMbNkNhkykMXCH5iyWiBFSyZa1ZJMlgf\nknsqfdzeVPwF6E55QKAN2uuTlwzG/3ljPxahR1hvmUJjQN9JSBiUKbtW6GPCRVbr\nf/jLi1Iu99COZdluVKeybqn8Z/aSNP24DR9FM8kxzZ1IMPaTBmhFypp6BclhcLBt\nxTG1AoGAfcrkVbV1SOy7fECUtMpUECcw0yU4GWj3sR2RbII63C500RVYQlUpUaRR\naANbASHTVR4myOKtGSxEUhAQHlxFDwsDL7W3gzAqTFbEDp1xAAUyT/nkOAhQjEm4\nORFdDETeXLQG1KMUj+8AdnhfYp3JTdft6rmPpZEBUFiCAUMAvb0=\n-----END RSA PRIVATE KEY-----\n", "user_id": "f79791beca3c48159ac2553fff22e166", "name": "demo1", "fingerprint": "57:a7:a2:ed:5f:aa:e7:54:62:2e:bb:e7:92:22:cb:40" } }
2、导入密钥。
(1)接口相关信息
URI格式:POST /v2.1/{project_id}/os-keypairs
(2)请求示例
POST: https://{endpoint}/v2.1/74610f3a5ad941998e91f076297ecf27/os-keypairs
Body:
{ "keypair": { "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDY8wMTdBYiJgi62o6eShoOlSKx3CZ3cE6PHisDblfK3Y0Bg7EHV7iV9c74pqsrIhK0xuGUuO1NxDQWbkwLTPN4F9Iy5CIYohLuMIpbln6LDtfRPpdhEh3lxL8MM61gyfpKzeKkwkEpSFj27Rgh6zCyJgBpkA2A0HTP737UlitahL4faCWDIS+Vj6mbcfkWiMhuMCzTZgSKAZ4PfoG4B5HJhR52C6A4XLiQFT9heh9gnIsIG+uTogTKUbcJKuN7M6AraJpul6eHhV9YI4433sDmuiBF/njvreVPWwAHlAkgT9I8q1T/cfEFiwzXpdGbkK5O8NC7K+qNbbdKihlahONt Generated-by-Nova\n", "type": "ssh", "name": "demo2", "user_id": "fake" } }
(3)响应示例
{ "keypair": { "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDY8wMTdBYiJgi62o6eShoOlSKx3CZ3cE6PHisDblfK3Y0Bg7EHV7iV9c74pqsrIhK0xuGUuO1NxDQWbkwLTPN4F9Iy5CIYohLuMIpbln6LDtfRPpdhEh3lxL8MM61gyfpKzeKkwkEpSFj27Rgh6zCyJgBpkA2A0HTP737UlitahL4faCWDIS+Vj6mbcfkWiMhuMCzTZgSKAZ4PfoG4B5HJhR52C6A4XLiQFT9heh9gnIsIG+uTogTKUbcJKuN7M6AraJpul6eHhV9YI4433sDmuiBF/njvreVPWwAHlAkgT9I8q1T/cfEFiwzXpdGbkK5O8NC7K+qNbbdKihlahONt Generated-by-Nova\n", "user_id": "f79791beca3c48159ac2553fff22e166", "name": "demo2", "fingerprint": "dd:44:45:49:d9:f6:4f:c0:24:2d:81:aa:c4:4b:83:c2" } }
2、 记录响应消息体中的name信息。如本例中为“demo2”。
步骤六:创建密钥对登录鉴权的云服务器。
(1)接口相关信息
URI格式:POST /v2.1/{project_id}/servers
说明:
本示例是指定image创建云服务器,因此:
● block_device_mapping_v2.1中,“source_type”需设置为“image”,“uuid”设置为选择的镜像ID,“destination_type”设置为“volume”,“boot_index”设置为“0”。
● “volume_size”应大于等于镜像元数据中指定的最小值。
(2)请求示例
POST: https://{endpoint}/v2.1/74610f3a5ad941998e91f076297ecf27/servers
Body:
{ "server": { "flavorRef": "c1.large", "name": "zttestvm1", "block_device_mapping_v2.1": [{ "source_type": "image", "destination_type": "volume", "volume_type": "SATA", "volume_size": "40", "delete_on_termination": "true", "uuid": "11e8f727-d439-4ed1-b3b8-33f46c0379c4", "boot_index": "0" }], "networks": [{ "uuid": "fb68519f-a7c0-476e-98d4-2e4cf6de6def" }], "key_name": "demo2", "availability_zone": "az_test_01" } }
(3)响应示例
{ "server": { "security_groups": [ { "name": "default" } ], "OS-DCF:diskConfig": "MANUAL", "links": [ { "rel": "self", "href": "https://None/v2.1/74610f3a5ad941998e91f076297ecf27/servers/6d311127-bce1-48db-bf0f-cac9f8f7f077" }, { "rel": "bookmark", "href": "https://None/74610f3a5ad941998e91f076297ecf27/servers/6d311127-bce1-48db-bf0f-cac9f8f7f077" } ], "id": "6d311127-bce1-48db-bf0f-cac9f8f7f077", "adminPass": "WcC4QoVZPXpV" } }
步骤七:设置密码登录方式。
(1)使用非cloud-init镜像创建云服务器时,Windows和Linux系统都使用“adminPass”参数实现密码注入。
(2)使用cloud-init镜像创建云服务器时:
l 对于Linux系统,只能使用“user_data”进行密码注入,“user_data”字符串长度小于65535,且必须是base64加密的;
l 对于Windows系统,只能通过元数据“admin_pass”进行密码注入。
步骤八:创建密码方式登录鉴权的弹性云服务器。
说明:
本示例是指定image创建弹性云服务器,因此:
(1)block_device_mapping_v2.1中,“source_type”需设置为“image”,“uuid”设置为选择的镜像ID,“destination_type”设置为“volume”,“boot_index”设置为“0”。
(2)“volume_size”应大于等于镜像元数据中指定的最小值。
1、创建非cloud-init镜像、密码方式登录鉴权的弹性云服务器。
(1)接口相关信息
URI格式:POST /v2.1/{project_id}/servers
(2)请求示例
POST: https://{endpoint}/v2.1/74610f3a5ad941998e91f076297ecf27/servers
Body:
{ "server": { "flavorRef": "c1.large", "name": "zttestvm1", "adminPass":"NOVAGLANCEI@123", "block_device_mapping_v2.1": [{ "source_type": "image", "destination_type": "volume", "volume_type": "SATA", "volume_size": "40", "delete_on_termination": "true", "uuid": "11e8f727-d439-4ed1-b3b8-33f46c0379c4", "boot_index": "0" }], "networks": [{ "uuid": "fb68519f-a7c0-476e-98d4-2e4cf6de6def" }], "availability_zone": "az_test_01" } }
(3)响应示例
{ "server": { "security_groups": [ { "name": "default" } ], "OS-DCF:diskConfig": "MANUAL", "links": [ { "rel": "self", "href": "https://None/v2.1/74610f3a5ad941998e91f076297ecf27/servers/73991cff-37c6-491a-9a8a-377397729fce" }, { "rel": "bookmark", "href": "https://None/74610f3a5ad941998e91f076297ecf27/servers/73991cff-37c6-491a-9a8a-377397729fce" } ], "id": "73991cff-37c6-491a-9a8a-377397729fce", "adminPass": "NOVAGLANCEI@123" } }
2、创建cloud-init镜像(以Linux为例)、密码方式登录鉴权的弹性云服务器。
(1)接口相关信息
URI格式:POST /v2.1/{project_id}/servers
(2)请求示例
POST: https://{endpoint}/v2.1/74610f3a5ad941998e91f076297ecf27/servers
Body:
{ "server": { "flavorRef": "c1.large", "name": "zttestvm2", "user_data":"IyEvYmluL2Jhc2gKZWNobyAncm9vdDokNiRuaERlcUIkajBkelVMbkFrbWo4bWlFREFzT0VONkVPdGg1RmdqWnQybUVWZVRocC5OVDJXelZVdzFuNzhnL3dNdDE0dVpSQ1V3LzhHS3VGdEViQ0lPQS5vN1BZQzEnIHwgY2hwYXNzd2QgLWU7", "block_device_mapping_v2.1": [{ "source_type": "image", "destination_type": "volume", "volume_type": "SATA", "volume_size": "40", "delete_on_termination": "true", "uuid": "11e8f727-d439-4ed1-b3b8-33f46c0379c4", "boot_index": "0" }], "networks": [{ "uuid": "fb68519f-a7c0-476e-98d4-2e4cf6de6def" }], "availability_zone": "az_test_01" } }
(3)响应示例
{ "server": { "security_groups": [ { "name": "default" } ], "OS-DCF:diskConfig": "MANUAL", "links": [ { "rel": "self", "href": "https://None/v2.1/74610f3a5ad941998e91f076297ecf27/servers/7c11f362-cc96-4306-85b6-b432a639ca5e" }, { "rel": "bookmark", "href": "https://None/74610f3a5ad941998e91f076297ecf27/servers/7c11f362-cc96-4306-85b6-b432a639ca5e" } ], "id": "7c11f362-cc96-4306-85b6-b432a639ca5e", "admin_pass": "J3xMSivHCuq5" } }
步骤九:确认云服务器创建成功。
(1)接口相关信息
URI格式:GET /v2.1/{project_id}/servers/{server_id}
(2)请求示例
GET: https://{endpoint}/v2.1/74610f3a5ad941998e91f076297ecf27/servers/0c71c0da-8852-4c56-a1d1-3a9b9bcb6da6
其中:
0c71c0da-8852-4c56-a1d1-3a9b9bcb6da6为创建的云服务器UUID。
(3)响应示例
{ "server": { "tenant_id": "74610f3a5ad941998e91f076297ecf27", "addresses": { "2a6f4aa6-d93e-45f5-a8cb-b030dbf8cd68": [ { "OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:88:01:1b", "OS-EXT-IPS:type": "fixed", "addr": "192.168.2.192", "version": 4 } ] }, "metadata": {}, "OS-EXT-STS:task_state": null, "OS-DCF:diskConfig": "MANUAL", "OS-EXT-AZ:availability_zone": "az_test_01", "links": [ { "rel": "self", "href": "https://None/v2.1/74610f3a5ad941998e91f076297ecf27/servers/0c71c0da-8852-4c56-a1d1-3a9b9bcb6da6" }, { "rel": "bookmark", "href": "https://None/74610f3a5ad941998e91f076297ecf27/servers/0c71c0da-8852-4c56-a1d1-3a9b9bcb6da6" } ], "OS-EXT-STS:power_state": 1, "id": "0c71c0da-8852-4c56-a1d1-3a9b9bcb6da6", "os-extended-volumes:volumes_attached": [ { "id": "b551445a-e749-4d53-932a-638a455cb6c3" } ], "OS-EXT-SRV-ATTR:host": "pod1_test_01", "image": { "links": [ { "rel": "bookmark", "href": "https://None/74610f3a5ad941998e91f076297ecf27/images/11e8f727-d439-4ed1-b3b8-33f46c0379c4" } ], "id": "11e8f727-d439-4ed1-b3b8-33f46c0379c4" }, "OS-SRV-USG:terminated_at": null, "accessIPv4": "", "accessIPv6": "", "created": "2018-05-25T01:47:11Z", "hostId": "b2792bef989888d2df1f51bff81de5ac58a4117f4e9ec3059c1a0410", "OS-EXT-SRV-ATTR:hypervisor_hostname": "nova001@36", "key_name": null, "flavor": { "links": [ { "rel": "bookmark", "href": "https://None/74610f3a5ad941998e91f076297ecf27/flavors/c1.large" } ], "id": "c1.large" }, "security_groups": [ { "name": "default" } ], "config_drive": "", "OS-EXT-STS:vm_state": "active", "OS-EXT-SRV-ATTR:instance_name": "instance-001883cd", "user_id": "f79791beca3c48159ac2553fff22e166", "name": "zttestvm1", "progress": 0, "OS-SRV-USG:launched_at": "2018-05-25T01:47:55.755922", "updated": "2018-05-25T01:47:55Z", "status": "ACTIVE" } }
按照步骤指示,我很快完成了云服务器的搭建,不禁有些惊讶,这小子怎么懂这么多?等等...华为云API Explorer? 打开 华为云API Explorer的官网 ,我好像打开了新世界的大门,有很多已配置好的环境和接口,直接调用调试就可以了,以后怕是没有什么能够难住我了!
目前API Explorer平台已开放EI企业智能、计算、应用服务、网络、软件开发平台、视频等70+云服务,共上线2000+个API、6000+个错误码。在前期试运行期间,华为云API Explorer平台上的API接口也已被多家企业成功接入。
点击查看详情: 《华为云一站式API解决方案平台API Explorer上线》
据悉,华为云API Explorer平台在未来几个月会实现更多功能,比如支持SDK示例代码、CLI等特性,同时也会开放更多的云服务API接口,连接更多开发者实现创新、拓宽创新边界。

点击关注,第一时间了解华为云新鲜技术~
云计算
2020-07-20 14:13:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
作者 | 汪吉
【Arthas 官方社区正在举行征文活动,参加即有奖品拿~ 点击投稿 】
一、入门步骤
1. 安装
https://arthas.gitee.io/install-detail.html
上述命令会下载启动脚本文件 as.sh 到当前目录: curl -L https://alibaba.github.io/arthas/install.sh | sh
or
as.sh 启动: curl -sk https://arthas.gitee.io/arthas-boot.jar -o ~/.arthas-boot.jar && echo "alias as.sh='java -jar ~/.arthas-boot.jar --repo-mirror aliyun --use-http'" >> ~/.bashrc && source ~/.bashrc
2. 在线教程体验
https://alibaba.github.io/arthas/arthas-tutorials?language=cn
当然也可以自己本地体验一下~自己通过下载一个 arthas-idea-plugin 的体验 demo 直接本地上手。
https://github.com/WangJi92/arthas-plugin-demo
全局命令说明 -x 是展示结果属性遍历深度,默认为 1 -n 是执行的次数 ,q 退出 -c classloader 的hash值 退出 q ,关闭 stop
3. 了解最常用的trace、watch的功能
watch和trace 是arthas 诊断中对于开发人员解决线上的问题最常用的功能!
trace
基本示例 trace com.wangji92.arthas.plugin.demo.controller.CommonController getRandomInteger -n 5 '1==1'
https://arthas.gitee.io/trace.html 性能优化~ 调用的这个方法,走的具体流程是咋样的!可以通过调用链看出来。 有异常了可以查看异常的堆栈。
高级的功能
trace命令只会trace匹配到的函数里的子调用,并不会向下trace多层。因为trace是代价比较贵的,多层trace可能会导致最终要trace的类和函数非常多。
trace -E xxxClassA|xxxClassB method1 | method2 trace -E com.wangji92.arthas.plugin.demo.controller.CommonController|com.wangji92.arthas.plugin.demo.service.ArthasTestService traceE|doTraceE -n 5 '1==1'
watch
https://arthas.gitee.io/watch.html
wathc 从字面上理解就是观察值的信息,可以查看入参、返回值、异常、可以执行表达式获取静态变量、target.xxx调用目标实施的字段、方法等等都行~只要你想得到没有做不到的~
基本示例 watch com.wangji92.arthas.plugin.demo.controller.CommonController traceE '{params,returnObj,throwExp}' -n 5 -x 3 '1==1'
4、arthas 表达式核心变量 public class Advice { private final ClassLoader loader; private final Class clazz; private final ArthasMethod method; private final Object target; private final Object[] params; private final Object returnObj; private final Throwable throwExp; private final boolean isBefore; private final boolean isThrow; private final boolean isReturn; // getter/setter }
从watch 和 trace 中看到 后面的 '1==1' 执行的是一个条件表达式 当值为true 的时候通过执行了一个 ognl 表达式 ,watch 观察 params,returnObj,throwExp 入参、返回值、是否异常 这个也是一个表达式,那么这个到底是咋回事?
spring el 表达式
没有学习过ognl 使用多年的 spring 一定知道他的el 表达式 ,el 表达式中也有一种概念叫做【Context 上下文,和表达式】 如下所示,因为有了simple这个上下文 才能解析 "booleanList[0]" 这个脚本的含义~ 这个很熟悉,很好理解,那么ognl 表达式一样不难了。 class Simple { public List booleanList = new ArrayList(); } Simple simple = new Simple(); simple.booleanList.add(true); StandardEvaluationContext simpleContext = new StandardEvaluationContext(simple); // false is passed in here as a string. SpEL and the conversion service will // correctly recognize that it needs to be a Boolean and convert it parser.parseExpression("booleanList[0]").setValue(simpleContext, "false"); // b will be false Boolean b = simple.booleanList.get(0);
ognl 表达式
arthas 也是一样的,只是使用了一个叫做ognl的脚本,核心变量就是他的上下文,可以直接获取到这些字段。watch 观察的这几个字段 params,returnObj,throwExp 也就是我们所谓的上下文的概念,观察参数、返回值、和异常的信息。
如下是arthas 源码中 表达式评估和watch 观察值执行的代码!Advice 就是一个上下文,这里还增加了一个变量 const。知道了这些那不是很简单??
com.taobao.arthas.core.advisor.ReflectAdviceListenerAdapter#isConditionMet /** * 判断条件是否满足,满足的情况下需要输出结果 * @param conditionExpress 条件表达式 * @param advice 当前的advice对象 * @param cost 本次执行的耗时 * @return true 如果条件表达式满足 */ protected boolean isConditionMet(String conditionExpress, Advice advice, double cost) throws ExpressException { return StringUtils.isEmpty(conditionExpress) || ExpressFactory.threadLocalExpress(advice).bind(Constants.COST_VARIABLE, cost).is(conditionExpress); } protected Object getExpressionResult(String express, Advice advice, double cost) throws ExpressException { return ExpressFactory.threadLocalExpress(advice) .bind(Constants.COST_VARIABLE, cost).get(express); }
表达式实践
arthas 群经常有人问重载方法如何判断,无非就是评估条件? 参数的个数、第一个参数是什么?返回值的类型等等都可以作为你评估的条件。如下的watch 前面的一段是观察的值、后面这一段是表达式评估 ,满足了条件才执行。
入参长度大于0 watch com.wangji92.arthas.plugin.demo.controller.CommonController traceE '{params,returnObj,throwExp}' -n 5 -x 3 'params.length >0'
返回值为String 且长度大于5 watch com.wangji92.arthas.plugin.demo.controller.CommonController traceE '{params,returnObj,throwExp}' -n 5 -x 3 'returnObj instanceof java.lang.String && returnObj.length>5'
条件表达式+异步任务 只有特定的场景才会有bug ,如何排查bug? 一天只出现一两次如何解决?
条件表达式主要是用来过滤使用,比如某些场景只是在特定的参数才会出现,肯能会花费很多的时间去等待,这个时候可以使用条件表达式过滤 + 异步任务 更多参考博客
5、ognl 表达式
https://arthas.gitee.io/ognl.html 从上面看,ognl 在watch、trace上面无所不能啊,其实还有 tt 也是 使用ognl 表达式执行逻辑的. @xxxClas@xxxStaticField 是静态变量的语法糖 ognl的,好好看一下官方的文档。OGNL特殊用法请参考: https://github.com/alibaba/arthas/issues/71
获取静态变量
静态变量由于 一个jvm 中可能被多个classloader加载,jvm 认定为一个实例是一个classloader加载哦,所以需要知道当前静态类的hash 值(sc -d com.wangji92.arthas.plugin.demo.controller.StaticTest)可以通过这个命令获取。 ognl -x 3 '@com.wangji92.arthas.plugin.demo.controller.StaticTest@INVOKE_STATIC_DOUBLE' -c e374b99
调用spring 方法?
watch 执行ognl 语法中获取spring context 然后进行调用bean的方法 watch -x 3 -n 1 org.springframework.web.servlet.DispatcherServlet doDispatch '@org.springframework.web.context.support.WebApplicationContextUtils@getWebApplicationContext(params[0].getServletContext()).getBean("commonController").getRandomInteger()'
ognl 执行静态的一个spring context 然后调用bean 的方法 ognl -x 3 '#springContext=@com.wangji92.arthas.plugin.demo.common.ApplicationContextProvider@context,#springContext.getBean("commonController").getRandomInteger()' -c e374b99
有没有起飞的感觉,无所不能!前提是你要掌握一些ognl的一些简单的语法!
6、完毕
对于线上排查问题,我感觉这几个命令够你用了,还有一些其他的反编译、火焰图、.. 时间隧道、logger 等级修改,jvm环境信息等等感觉是有频率都没有上面的高,毕竟jvm信息有专门的监控~即使没有arthas 你也可以找到更好的工具去分析堆栈,jvm故障。
一些特殊的用户案列值得学习思考: https://github.com/alibaba/arthas/issues?q=label%3Auser-case
完了? 啊?这么多命令 记不住啊 还有一些高级的ognl的语法凉了... 让你获取一下所有的spring的环境变量咋办?trace、watch 这两个命令我还没有体验够呢?更加高级的让我如何是好啊!好了,请看下文。
二、进阶
前提
前提是你对于arthas 有了大概的理解,基本上的命令都有点概念了,ognl 简单的语法能够看懂了.. 简单的条件表达式会用了。 之前我们所过arthas的命令这么多 要记住小本本少不了啊!难受想哭~ 不要急,汪小哥来给你解决问题!
目前Arthas 官方的工具还不够足够的简单,需要记住一些命令,特别是一些扩展性特别强的高级语法,比如ognl获取spring context 为所欲为,watch、trace 不够简单,需要构造一些命令工具的信息,因此只需要一个能够简单处理字符串信息的插件即可使用。当在处理线上问题的时候需要最快速、最便捷的命令,因此arthas idea 插件还是有存在的意义和价值的。
arthas idea plugin
这个插件的意义不是处理协议层面的问 题,主要解决命令生成的问题,由于工程在idea 里面管理,你想想你要watch 哪个类,这个插件是知道的,帮助你更方便、更加快捷的构建命令。使用arthas idea 插件 这一点一定要理解哦!主要解决你如何构造命令的问题! 更多查看文档
解决的问题 spring 环境变量优先级问题 获取静态变量 火焰图集成 logger 命令集成 反编译集成 trace -E 集成 tt 集成
....... 基本上你能够在arths 上面看到的功能都集成到了这个上面!直接在idea 里面搜索arths idea 即可安装。
常用特殊用法问题
静态变量
可以直接获取 ognl 获取 ognl -x 3 '@com.wangji92.arthas.plugin.demo.controller.StaticTest@INVOKE_STATIC_DOUBLE' -c e374b99
可以通过watch 获取 (光标放置在字段上) watch com.wangji92.arthas.plugin.demo.controller.StaticTest * '{params,returnObj,throwExp,@com.wangji92.arthas.plugin.demo.controller.StaticTest@INVOKE_STATIC_DOUBLE}' -n 5 -x 3 '1==1'
一般的变量
可以通过spring context.getBean().field 获取(这个是要配置一个静态的spring context 看使用文档)
tt 、watch 也是可以的哦~ 一样的原理 ognl -x 3 '#springContext=@com.wangji92.arthas.plugin.demo.common.ApplicationContextProvider@context,#springContext.getBean("staticTest").filedValue' -c e374b99
watch 获取 放置在字段上即可 watch com.wangji92.arthas.plugin.demo.controller.StaticTest * '{params,returnObj,throwExp,target.filedValue}' -n 5 -x 3 'method.initMethod(),method.constructor!=null || !@java.lang.reflect.Modifier@isStatic(method.method.getModifiers())'
选择的配置项的值
springContext.getEnvironment() (这个是要配置一个静态的spring context 看使用文档) ognl -x 3 '#springContext=@com.wangji92.arthas.plugin.demo.common.ApplicationContextProvider@context,#springContext.getEnvironment().getProperty("custom.name")' -c e374b99
获取所有的配置项的值
watch 获取spring context tt 、static 也是可以的哦~ 一样的原理 watch -x 3 -n 1 org.springframework.web.servlet.DispatcherServlet doDispatch '#springContext=@org.springframework.web.context.support.WebApplicationContextUtils@getWebApplicationContext(params[0].getServletContext()),#allProperties={},#standardServletEnvironment=#propertySourceIterator=#springContext.getEnvironment(),#propertySourceIterator=#standardServletEnvironment.getPropertySources().iterator(),#propertySourceIterator.{#key=#this.getName(),#allProperties.add(" "),#allProperties.add("------------------------- name:"+#key),#this.getSource() instanceof java.util.Map ?#this.getSource().entrySet().iterator.{#key=#this.key,#allProperties.add(#key+"="+#standardServletEnvironment.getProperty(#key))}:#{}},#allProperties'
视频
有兴趣可以看一下视频~ 操作起来更流畅,基本上不用记忆啥。 arthas 入门到精通最佳实践
三、更多
还想了解更多关于arthas-idea-plugin 的内容可以联系我 可以通过 右键查看arthas-idea-help 找到代码地址和使用说明文档,更重要的是提一下好的idea 让arthas的使用更加的方便哦!插件地址: https://plugins.jetbrains.com/plugin/13581-arthas-idea
Arthas 征文活动火热进行中
Arthas 官方正在举行征文活动,如果你有: 使用 Arthas 排查过的问题 对 Arthas 进行源码解读 对 Arthas 提出建议 不限,其它与 Arthas 有关的内容
欢迎参加征文活动,还有奖品拿哦~ 点击投稿 “ 阿里巴巴云原生 关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”
云计算
2020-07-16 18:45:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
作者 | 张羽辰(同昭)阿里云交付专家 导读 :如今,几乎所有的事情都离不开软件,当你开车时,脚踩上油门,实际上是车载计算机通过力度感应等计算输出功率,最终来控制油门,你从未想过这会是某个工程师的代码。
当我们谈论架构时,我们到底在谈论什么?
面向对象编程?函数式?模块化设计?微服务?这些词汇貌似都和架构这个 buzzword 有点关系,的确我们这个领域充满了很多难以理解的词汇,这些词汇从英语翻译到中文已经丧失了部分上下文,再随着上下文的改变使得意义彻底扭曲,比如:引擎、框架、架构、应用、系统……诚然大家都或多或少对这些词语达成共识,在工作中使用这些词汇进行沟通,某时就是指“我们都懂的那个东西”,但是在我深入的想聊聊架构或者说软件架构时,的确不得不问自己这个问题,我们到底是谈论什么?
事实上,架构这个词根据上下文所确定的范围较为固定,建筑学上的架构指代房屋结构、整体设计、组合构成等,而这些 high-level 设计往往并不需要全面了解底层,就像使用 RestTemplate 进行 WebService 调用时,我们也不关心 socket 是在四层连接的一样, 因为细节被隐藏了 。
但是,建筑学上的架构与软件架构却又极大的不同之处,问题出现在“软件”这个词上,按照 software 的词解,ware 是指产品一样的东西,而 soft 则强调易变,这是与 hardware 所对应的。我们希望“软件”能够进行快速的修改,应该能够快速响应甲方或者客户的需求,所以软件架构必然不像建筑架构一样,建筑一经建成,修改的成本极高, 而软件应该走对应的方向,发挥易于修改的特点。
“现在的大多数软件非常像埃及金字塔,在彼此之间堆建了成千上万的砖块,缺乏结构完整性,只是靠蛮力和成千上万的奴隶完成。” —— Alan Kay。 笔者认为,虽然这句话表达的意思我很赞同,但实际上,金字塔作为帝王的陵墓,是有着完整的设计逻辑,并且随着好几座金字塔的迭代的,以及逐渐完备的施工管理,后期金字塔是非常杰出的建筑代表,并作为地球上最高的人造建筑持续了好几千年。关于金字塔是否由奴隶建造还是存有争议。(图片来自 Isabella Jusková @ Unsplash)。
作为工程师,我们一方面关注软件产品的能力和行为,这往往是一个项目的起点,另一方面我们需要关注软件的架构设计,因为我们希望设计有着弹性、易于维护、高性能、高可用的系统,更希望系统能够不断演进,而不是在未来被推倒重做。所以,回正我们的视野,当我们决心要设计一个好的架构时,我们需要明确, 架构往往决定的是软件的非功能性需求 。这些非功能性需求有: 易于开发 :我们希望工程师一进入团队就可以立刻开始进行研发工作,我们希望代码易于阅读与理解,同时开发环境足够简单统一,说到这里大家可以回想下当你进入项目时,学习上下文的痛苦。当我们开始采用 docker 辅助开发时,时任架构师提出了一个要求,只要一行命令就可以使用 docker 启动本地测试环境,而且必须所有的微服务都要做到这一点。痛苦的改造完成后,三年后进入项目的同学只需要安装好 docker,再在 ternimal 中运行一句 ./run-dev.sh 就能够获取一个具有完整依赖的本地环境,提效明显。 方便部署 :如果系统的部署成本很高,那使用价值就不会很高了,我们很多企业都存在那种动也不敢动,改也不敢改,停也不敢停的系统,除了祈祷它别挂掉好像没有别的办法,或者很多企业都采用了 K8s 这种先进的编排系统,但是在应用部署和上线时,还是走的每周四变更的路子。现代的发布方式 AB、金丝雀、灰度无法采用是因为改造成本过高,或者没有足够的自动化测试来保证改动安全,更别提将发布做到 CI\CD 里面了。 易于运维 :DevOps 的初衷是建立一种缩短运维与研发距离的文化,让出现问题后更容易处理,希望让大家将视野放在产品上而不是限定自己的工种,这并不是期望运维的同学能够成为 Java 专家,迅速的进行 heap 分析发现问题,我们强调的是运维时的闭环能力。在软件产品层面,我们也希望产品是足够独立的、自治,可以独立部署,能够做到横向扩展,有着完整的可观测性,毕竟当今的硬件成本很多时候是远远小于人力的。 维护成本 :随着时间的推移,给软件增加新功能就会变的越来越难,越是运行长久的项目就会陷入重写还是重构的苦恼。往往风险在与,修改代码会增加破坏已有功能的风险,而且技术债也会越来越多难以偿还,即使是重写某些功能和模块,我们也很难确定是否真的覆盖到了所有的功能,简而言之,don't break anything 的确很难做到。 以及最重要的一点, 演进能力 :良好的架构设计应该能让系统处于易于演进的状态,能够实现给飞驰的汽车换轮胎的能力,而不会被框架、底层的某种数据库、操作系统或者其他东西所绑架,但是这太难以做到了。的确,在项目进行技术选型时,因为某种数据库的特性而有倾向,但是在上层设计中,我们必须保证不依赖于数据库的特性,而将使用这些特性的地方放到底层细节中。我们也需要考虑,不使用 Spring 提供的 Dependency Injection,我们该如何组织我们的 beans,也要考虑将来系统的前端是 web 还是 mobile 还是都要支持?
这里引用 Robert C·Martin(Uncle Bob)的原语,“软件产品是有两方面的价值,一方面是实现功能的价值,另一方面是架构的价值, 而架构的价值可能更重要一些,因为它代表着软件 soft 的特性。 ”
本书例子过少,而且缺乏现有流行框架的重构或者改进建议,有点形而上,但是在方法论层面笔者还是认为值得一读。Robert C·Martin 对数据库(特指 RDBMS)的态度很值得讨论,首先他认为数据库是一种细节,在架构中应该与业务解耦,他强调业务代码与数据库的无关性。同时在我们的代码进行计算时,表格往往不是理想的数据结构,比如有些场景会使用树、DAG 等等。可以回想一下,当你需要把一个树存入数据库时,你该如何实现?
微服务是一种软件架构,不要扩展它
根据我们之前的讨论,后端系统采用微服务是不会影响到其功能上的价值,本质上微服务化和单体应用的差别并不会表达在功能上,很多微服务进展不顺利的同学会经常说到:这东西用单体写早就完事儿!的确是这样, 这侧面也印证了微服务只是一种软件架构,而不是别的神奇的东西,并不是某个业务需求必须要使用微服务完成,我们看中微服务,也是看中了架构方面的优势,即那些非功能性需求 。也有人使用 pattern 来描述它,也有人说和 SOA 基本上是一个东西,只是粒度不同,所以我们一开始就别相信这个世界有灵丹妙药,也别期望有个什么技术能够瞬间替代 Oracle。
作为开发“企业级后端应用”的同学,我们经常会面临很多非业务需求上的苦恼:有时我们需要同时支持移动端、移动 web、桌面端三种客户端;有时候我们需要支持不同的协议比如 JSON 或 XML;有时我们又需要使用不同的中间件传递消息;或者在研发时,我们知道有一个地方写的不好,我们想在未来补课重构;我们想尝试最新的技术但是代价过高;系统无法扩容,或者成本极高;系统过于复杂无法在本地运行导致极低的效率……这些苦恼才是采用微服务的主要驱动力,回到我们对软件架构的讨论之中,我们希望的是通过足够松耦合的独立服务,来降低组件之间变化的成本,也就是说今天更新发送通知的功能,并不会影响到用户查看购物车,也不会让研发人员半天改完,再等三天才能上线。
但是世界上没有免费的午餐,虽然我们知道微服务有很多很好的特性,比如组件即服务、松耦合、独立部署、面向业务、高维护性、高扩展性等等,这里并不想展开讨论它的好处,我们先考虑投入成本。假设我们每个同学都完整的学习了微服务的所有知识,对市面上的框架、产品非常熟悉,摩拳擦掌准备开始,在拆解完几个服务后,我们会发现,没有足够的自动化手段,靠手动的方式进行测试、编译、部署、监控,这是显而易见的会降低体验,如果没有优化好的部署策略,所有的服务都在某个发布日上线,那更是一种灾难。
随着规模的扩大,单体应用的代码改动成本会越来越大。很多时候我们微服务的架构实践是存在误区的,我们总认为流量经过某个 gateway 后直达某个服务,确忽视了服务之间调用的场景,理想的微服务架构应该是一张网,每个节点都是独立的、自治的服务。
一些之前使用单体很容易做到的场景,在分布式的环境下会更加困难。比如我们可以通过 RDBMS 提供的数据库事务来支撑一致性,但是如果订单服务和价格服务分离,势必要进行分布式事务来保证一致性(往往是最终一致性),而分布式事务的成本和难度就不用赘述了。在单体环境下,我们可以很轻松的使用切面进行权限验证,而在微服务的场景中,服务之间相互调用是难以控制的。
拆分服务或者服务边界划分是另一件很难做到的事情,最吃香的理论也许是根据 DDD 去进行划分,天然的领域或者子域(domain)貌似都能对应一个服务,因为足够的界限上下文(bounded context)能够保持服务的独立性,使其细节被隐藏在界限之内,听起来是个不错的主意。但是现实却十分残酷,使用 DDD 生搬硬套去进行软件开发的例子不在少数,成功例子也难以复制。
虽然我在实践中也经常使用业务领域去进行服务划分,但是我并不认为这是 DDD 的做法,没有必要规定有多少个 domain 就有多少服务,也不需要规定 sub domain 能否独立服务。 与其进行顶层设计一揽子的解决方案,我更相信演进的力量,如果你真的需要拆分一个服务,足够的基础设施与自动化工具应该允许你低成本的去做,而不是一开始就画好所有的架构图 。这就跟所有的改革一样,革命派往往不是一步功成,而是逐渐的积累的。所以使用微服务,当你能够负担的起(only you can afford it),也表示你能负担的失败一样,技术世界不存在一蹴而就,all in 非常危险。
卫报网站(Guardian)的微服务改造就是一个很好的例子,网站核心依旧是一个巨大的单体,但是新功能通过微服务实现,这些微服务调用单体所提供的 API 来完成功能。对于常常出现的市场活动(比如某个体育比赛的专用板块),这种方式能够快速实现活动页面与功能,完成业务需求,并在活动结束后删除或丢弃。我之前参与项目中,也通过等量替换与重构,慢慢绞杀(Strangler Pattern)掉一个巨大的陈旧的 JBoss 应用。
PlayStation 首席设计师 Mark Cerny 在今年的 PS5 新主机的技术分享中提到,游戏主机需要平衡好演进与革命(balance the evolution and revolution),我们不想丢掉多年来开发者的积累,在复用过去的成功经验时,我们也希望大家能够使用更先进的技术。
人人都爱\恨 Spring Cloud
看起来,在 Java 世界中,Spring Cloud 貌似是微服务的最优解了,甚至在很多同学的简历上,Spring Cloud 几乎可以和微服务划等号了,不止一次的有人告诉我说:公司的技术栈不是 Java,所以搞不了微服务很难受,并不是我没有学习精神和冒险精神云云。很遗憾,对于软件架构来说,跟可没有规定编程语言,设计模式不是也出了很多版本吗?归根结底还是 Spring Cloud 的全家桶策略更吸引人,什么事儿都不如加上几个 jar 就能拥有的神奇次时代架构更有吸引力。
不可否认,我在学习 Spring Cloud 的时候也惊叹其完整性,几乎常见的微服务需求都有足够完整的解决方案,而大多数方案是做在应用层,具有良好的适配性,比如 eurake 的注册发现、zuul 网关与路由、config service、hystrix circuit breaker 等等,通过统一的编程范式(基于 annotation 的注入与配置),足够丰富的功能选择(常用功能甚至都有两种选择),以及较好的集成方式。前有 Netflix 的成功经历,后随着微服务的浪潮,再加上足够庞大的 Java 社区,可以说是王道中的王道。但并非 Spring Cloud 没有弱点,反倒这些功能设计与随后的容器化浪潮产生了分歧,至今融合 Spring Cloud 与 Kubernetes 都是热门话题,这里我们展开说说它的不足或者限制(limitation)。
侵入性与语言绑架
这可能是最大的问题,基本只能使用 Java 作为研发语言,这一点在国内也备受争议,因为不论是作为架构师还是入门的程序员,都需要尝试新的技术栈来进行储备或是采用新的功能,而且比如使用自制的 client 去实现 ribbon 的负载均衡也是很难的,但是如果不用 Java,做到这一点也很难,不是说 Java 语言不够优秀,而是我们对未来应该有更多的选择,对于一个技术公司来说编程语言应该不会成为限制,试问这个时代谁不想学习一点 golang 或者 rust 或者 scala 呢?其他服务比如 SSO、Config Service 也过于整体,如果想进行某项适配,则必须进行大量的修改(还好是开源的)。我们很担心这种情况都会随着框架的老去而面临推到重来的境界,Ruby on Rails 可能就是前车之鉴吧。侵入性是另一个问题,还记得我们在讨论软件架构时所提倡的实践规则吗?尽量不要让顶层设计依赖底层的框架或者某种细节,但是满屏幕的 annotation 与 jar 的直接引用,无疑告诉我们想去掉它们还是非常难的。
云原生的融合问题
对于云原生,不论是 CNCF 还是 Pivotal (VMWare)都在强调容器化、微服务、面向云环境等,CNCF 围绕 Kubernetes 开始发展壮大,也随着这种先进的容器编排技术的流行人们渐渐发现它和 Spring Cloud 在功能上还是存在很多重叠,虽然 k8s 与 IaaS 没有重叠,但是现在还有多少厂商再推纯 IaaS 呢?既然有功能重叠,就有取舍,考虑到 Spring Cloud 的全家桶属性,这个分歧处理一直都不能很好的解决。
集中式的资源
不论是 Config 、Eureka 都是聚合的单点,及时它们有集群的方式达到近乎 100% 的可靠性,但在逻辑架构上,所有的微服务都依赖它们,这些集中式的资源的耦合是非常强的,它们会一直存在在你的生产环境之中,直到最后一个使用它们的系统下线。我们在架构中需要避免使用共享的实例与资源,一个应用不会因为不能写日志而崩溃,也不应该因为本地没有 eureka 而无法启动。
畏惧平台绑定
诚然,在进程之内解决服务注册发现、负载均衡是很好的,它代表了最好了平台无关性,但平台的其他能力也很难享受的到了。绑定 k8s 貌似是个更好的选择,因为相对于 Spring Cloud 它更灵活,也能做到不会被基础的云平台绑定,但也更难以掌握与运维。当然我也不是认为 K8s 必须作为微服务的选择,作为容器的编排平台,它可以做更多的事情(比如跑数据库、中间件等),运行微服务应用只是其中之一。
方法论的落地能力
2020年已经过了一半,从技术上来说,Serverless 已经进入成熟期,Kubernetes 也更加成熟,已经成为事实的标准。但是很多时候我们的方法论与架构设计是跟不上的技术发展的,很多同学可能还在经历每周的发布日,很多同学还没办法改进团队内老旧的技术,很多同学的 Jenkins 还是停留在打包的阶段,很多同学机器上还是没有安装 docker,很多时候并不是框架或者平台的问题,而是方法论还停留在过去。
保持演进
应用程序也应该践行开闭原则,对扩展开放使得我们在未来有更多的选择。 微服务是一个很好的机会能让我们真正的演进架构而不需要付出过多的代价,当我们需要组件化系统时,组件的关键特性正是可独立替换或升级,我们可以不影响其他部分去进行替换和重构,这样的成本是显然低于抛弃旧的巨型框架而重写的 。有着正确的态度和工具,我们可以更快、更频繁的控制变更,我们可以激进的选择新的技术栈,也可以合并两个耦合过紧的服务,随着服务的不断聚合、抽出,你会发现系统的逻辑架构会越来越清楚,再进行修改就会信心倍增了。我们可以针对每个服务使用不同的存储技术,我们可以使用 OSS 处理文件,而不是继续往 Oracle 里面塞图片和视频。
Istio 的解法与问题,以及 Mesh 还缺少什么
这个开幕雷击虽然槽点满满,但并没有降低社区对 Istio 的信心,反倒是渐渐发现这次的大改动使 Istio 变得有点好用了,可以在生产中采用而不需要付出太多代价了。当然,漂亮话永远好说。
2017 年的时候 Service Mesh 还是一个襁褓中的概念,现在已经成为了微服务领域的未来之选,但遗憾的是目前只有 Istio 足够成熟能代表这项技术,当然我也有幸实践过类似的 Sidecar 来进行反向代理、日志收集、性能监控、健康检查等功能,但是距离 Mesh 的愿景还是有大的差距。
今天并不想展开 Service Mesh 或者 Istio 的优势,进程之外的解决方案能够确保系统的灵活性,而流量控制、服务治理、端对端的传输安全、限流、发现注册等等, 我们希望工程师能够聚焦业务,实现架构的灵活性,聚焦真正的价值,而剩下的进行配置就好 。所以我想这也是 Serverless 被无限看好的原因,既然我们想 delegate 对基础设施的控制,那为什么还需要关心容器呢?Istio + k8s 的方案已经足够好,至少我们团队正在认真学习,在向客户提供最佳实践之前,我们依旧有很多问题需要解决,下面列出一些代表性的:
弹性与自恢复问题
使用系统度量、参数等触发弹性伸缩是常见的需求,这里我们是使用云监控?还是自己搭一套?我一直倾向数据与用途解耦,使用 pub sub 模式解决问题,比如 CPU 过高可能会触发多个行为:触发警报,触发弹性规则,展示在 dashboard 上。我们可以增加 pod 来分担服务的压力,或者因为某个 pod 异常退出后,启动新的 pod 来完成自恢复,这系列动作也是需要我们自己解决的。
监控与可观测性
日志、警报等可观测性的问题,这一方面的实践较多,唯一比较担心的是 ARMS 或者 Newrelic 这种 APM 功能目前没在目标平台上实践过,我们希望能够清晰的看到每个服务的实时性能,目前这一部分还缺乏考虑与设计。
限流与降级的实践
Istio 的流量控制能力是非常强大的,如何对服务采取降级、限流这种常见的治理操作,也是需要总结出实践经验的。避免串流错误(cascade failure)在微服务领域也很常见,也需要避免故障蔓延。
多种自动化部署
蓝绿、灰度、金丝雀,这些多样的部署方式也需要落地,我们可能会写一些 deployment util 之类的小脚本,部署的方式需要和 CICD 打通。一个部署工具,一个配置文件,一个 CICD 组成未来单个应用的部署方式。
ABAC 与 OPA
基于属性的权限控制以及 OPA 的可定制性我们是非常看好的,而且 sidecar 可以在进程之外解决权限验证问题,的确值得尝试,刚好也学习下 golang 用于定制 OPA。
Saga 与补偿事件
分布式事务是微服务实践中的大坑,我曾经也写过类似的文章,项目经验中更多的是将事务放在单一的服务内,再加上我自己也没机会写过真正的网店系统。补偿事件也是常用的最终一致性方案,总之放在一起验证。
高可用和混沌工程
基于 K8s 实现应用的高可用应该不难,容器的天生优势就是易于启动与管理,如果随机杀掉 pod 不会影响系统可用性,这就算是实现了类似于 SLB + ECS + ASG 的能力,真正危险的是其他 非业务型 pod,比如 istio 的各种 supervisor。
实践微服务,作为架构师所考虑的东西远远大于只是实现业务,但是一旦铺平道路,下来的研发与迭代将会更加顺利。
后记
如果你也对云原生架构有浓厚的兴趣,欢迎 加入钉钉交流群 与我们交流!
推荐下载
《深入浅出 Kubernetes》一书共汇集 12 篇技术文章,帮助你一次搞懂 6 个核心原理,吃透基础理论,一次学会 6 个典型问题的华丽操作!
<关注阿里巴巴云原生公众号,回复 排查 即可下载电子书>
参考资料 https://martinfowler.com/articles/microservices.html https://medium.com/swlh/stop-you-dont-need-microservices-dc732d70b3e0 https://medium.com/capital-one-tech/10-microservices-best-practices-for-the-optimal-architecture-design-capital-one-de16abf2a232 https://www.geekgirlauthority.com/what-you-need-to-know-from-sonys-the-road-to-the-ps5/ https://dev.to/bosepchuk/why-i-cant-recommend-clean-architecture-by-robert-c-martin-ofd https://istio.io/latest/blog/2020/tradewinds-2020/ https://www.openpolicyagent.org/docs/latest/
作者简介
**张羽辰(同昭)**阿里云交付专家,阿有着近十年研发经验,是一名软件工程师、架构师、咨询师,从 2016 年开始采用容器化、微服务、Serverless 等技术进行云时代的应用开发。同时也关注在分布式应用中的安全治理问题,整理《微服务安全手册》,对数据、应用、身份安全都有一定得研究。 “ 阿里巴巴云原生 关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”
云计算
2020-07-16 14:42:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
作者 | 江建明  阿里巴巴高级无线开发专家
**导读:**精英人数的增长速度持续加快后,很多人开始焦虑,我也焦虑,深知要走出焦虑不容易,我想把走出焦虑快速成长的认知和方法写成文章分享给更多人,做成【技术人成长系列】文章给更多人面对面分享,该系列总共三篇,分别是《完成自己的认知升级》、《自我成长的方法》、《学会自我培养或培养他人》。本文是快速成长第一篇:“完成自己的认知升级”,内容偏长但值得仔细阅读。
如何阅读本文? 找一个固定不被打扰时间仔细阅读 在碎片化的时间中,每次读完一段内容
最重要的是每次做到只字不差的阅读,然后停下,带着批判性思维从本文中提取出你觉得对的思考方式,并把思考方式关联和迁移到自己身上,经过实践内化成自己的认知,就是非常成功的一次阅读。
开始认识“认知升级”
第一次 :从文章中看到认知升级,认为认知升级是洗脑,是鸡汤,我对此不屑一顾,道理谁都懂,大部分人还不是过得一样,没啥区别。
第二次 :从会场里听到认知升级,一个活人站在那里讲认知升级,觉得认知升级有点意思,开始慢慢去理解认知升级,但还是不懂认知升级的价值。
第三次 :从实践中觉知认知升级,发现“鸡汤谁都懂,但依然过不好这一生”,还有另外一个版本“用好喝鸡汤的工具:汤勺,可以把这一生过得很好”,最简单的开始就是从时间管理认知升级开始,感受到认知升级的强大力量。自从换了一种时间管理思考方式之后,自己逐渐变得自律,变得有思考,成长复利慢慢变厚,感受到认知升级的价值,但还是没能力定义认知升级。
第四次 :从利 TA 中定义认知升级,开始做认知升级的 PPT 给团队,给他人分享认知升级,发现一部分人的行为、工作、思考等在慢慢发生变化,这些发生变化的同学,未来肯定会超出自己的期望,变得更加优秀,此时我想我能够比较清晰地定义认知升级。
我对认知升级的定义: 认知升级是连接,连接优秀的思维方式,连接解决问题的最短路径,连接一切优秀的方法 。比如:说到时间管理立马连接到“找到不被打扰的时间用于投资自己”、说到执行力立马连接到“先想明白,然后一步步做下去”、说到改变习惯立马连接到“在触发条件发生进入下一个行为时,做对选择题”。通过认知的改变,会激发自己做出思考,做出行为的改变,从而影响我们的判断,提升我们的能力,确切地说认知升级颠覆了自己的思考习惯,让我们超越本能思考,摆脱了旧有的直觉和经验,建立起了新的直觉和经验。
下面 10 个主题的认知分享是从我的认知升级库中挑出来的一部分我认为最重要的认知,对我的帮助和改变非常大,我相信对其他人同样有价值,大道至简,坚持这 10 个简单的认知就可以大大提升我们的成长速度,而且随着自我不断进化的同时,会不断升级和丰富自己的认知库,不断提升自己的认知升级能力。
1. 思考脑与反射脑
听精彩的演讲不止精神上会有即时的瞬间享受和满足感,更重要的是总会有那么几个关键词刺激我们的神经,让我们产生瞬间记忆,做出进一步的思考,这也是我为什么爱听牛人演讲,不是想听他创办企业的精彩故事,而是因为他演讲的内容中透露出的智慧,透露出的超时代的远见,透露出系统性的逻辑,听他的演讲总会给人一种醍醐灌顶的感觉,而所有这些演讲过程中透露出的智慧、远见,并不是在台上立马想到,是台下无数个思考最终抽象提炼出来的观点。台上演讲是反射,台下准备是逻辑是思考,所谓台上一分钟,台下 10 年功,反射和思考是什么关系呢?开始第一个认知:思考脑和反射脑。
欧洲工商管理学院教授特奥-康普诺利的《慢思考》这本书中把大脑分为反射脑、直觉脑、存储脑。简单来说:思考脑管理性,反射脑管直觉,存储脑管记忆,直觉依赖习惯,用直觉做出反应,快速,但未必正确;思考脑管理性,理性依赖逻辑,缓慢,但更加正确。
有科学家通过研究,发现一个人一天的行为中,5% 是非习惯性的,用思考脑的逻辑驱动,95% 是习惯性的,用反射脑的直觉驱动,决定我们一生的,永远是 95% 的反射脑(习惯),而不是 5% 的思考脑(逻辑)。回想自己的一天,大部分的判断和观点是不是都是靠直觉,靠习惯的,什么情况下才会用思考脑?是不是一个人的时候用思考脑比较多,而在多人对话场景中要快只能靠直觉和反射,而给别人好与不好的印象往往是在对话场景中建立起来的,可想而知,反射出来的观点或行为对我们而言是多么重要。
以学游泳举例,当在水里的那一刻,进入正念(正念:有目的,有意识的,关注和觉察当下的一切),将大脑的指令和手脚的动作关联上,大脑下达手脚标准化动作指令,手脚执行标准化动作指令,过程中大脑一直在关注和觉察手脚的动作,同时做出判断和调整,这是一个逻辑思考和强化训练的过程,把逻辑思考的过程强化成反射的过程,一旦学会,就无需进一步思考,游泳已成为自然。
放在学习和成长上也是一样,借用正念的概念,有目的有意识地关注和觉察学习时的一切,特别是在输入和输出过程中的逻辑思考过程,我特别建议做好 2 件事: 专注输入:做到只字不差地阅读,只字不差地听
只字不差地阅读、只字不差地听的过程中,我们会持续地深入理解作者文字和语言背后的逻辑,会产生自己的逻辑思考,会产生逻辑和观点的碰撞,自己的逻辑和作者的逻辑差异和共同之处在哪里,这是反复训练逻辑思考的必经之路,缺少这一步,导致的结果就是中国填鸭式教育的结果,大部分时候知道结果但是不知道原理。 专注输出:定期做 PPT 进行分享
定期做 PPT 进行分享,这是读书学习过程中无法替代的高质量逻辑训练方式,是一种更高要求的逻辑抽象的训练,同时通过输出检测学习和成长质量,训练的次数多了,书上的逻辑就变成了自己直觉反射,丰富了自己 95% 区域里有效的结构化知识。
所以对我们来说,想要没有焦虑,想要人生变得踏实,把泛读变成精细化的逻辑训练,把 95% 中的低质量习惯反射,训练成逻辑后的高质量习惯反射,训练过程会痛苦,但是一旦训练成直觉,会变得非常自然。
划重点:所谓直觉反射就是通过大量的逻辑反复训练,提升自己的直觉准确性,从狭窄的 5% 进入广阔的 95%。
2. 习以为常
把 95% 中的低质量习惯反射,训练成逻辑后的高质量习惯反射需要有很多的时间保障。但是对处于移动互联网时代的我们,电子设备对人类生活出行带来了很好的便利性,与此同时人类对其依赖程度已经到了寸步不离的地步,甚至上厕所短短几分钟,手机也是寸步不离。
手机已经成为一种生活方式,一种习惯方式,眼不离机是我们的习惯,因为手机产生了非常大的变化并固定了下来,空了玩手机、陪家人时玩手机、忍住不睡玩手机,我们的生活因此少了学习,少了阅读,少了交流,少了陪伴。
曾经,我也一直被困在电子设备这个囚笼里,好长时间无法改变这个习惯模式,难改变是因为一旦进入习惯模式,大脑的活跃程度急剧下降,不再参与决策,进入休眠状态,此时我们的行为由习惯支配。我对这种现代化的生活方式最大的感受:浏览信息的时间多了,自己思考和琢磨的时间少了,专注在无效事情上的时间多了,专注在自我成长上的时间少了。
当自己觉知到重度使用手机进行浏览和娱乐的不好习惯后,自然就产生了想改变的想法,也就是说,如果能够有一种改变习惯的有效方法,帮助自己改变重度使用手机的习惯后,意味着每天可以节省很多的时间,节省很多的注意力,节省下来的时间和注意力可以放在更重要的成长能力的迭代上。幸运的是,习以为常的认知进入到我的认知系统中,成为我的第二个认知升级。
我对习惯的认知,关键在于换种说法:“把改变玩手机的习惯,用另外一句话来替代,把学习变成习以为常的生活方式”。要解决的对象变了,前面聚焦于改变习惯,后面聚焦于把学习变成习以为常,当我们要求别人或自己改变习惯,会有压力,关键在于“改变”这个词,命令式,给人一种不自觉反抗的心里暗示;但若把学习变成习以为常,心里负担会少很多,似乎是很自然的事情。
认知变化后,能否把学习,阅读变成习以为常的事情,关键在于能否意识到突发状况,并在这些突发状况下调整自己的行为。无效的社交等突发状况出现的时候,如果能够置之不理,或者稍后再处理,那自然能够把学习和阅读变得成习以为常。注意,这是改变习惯最关键的意识切入点,一边是对无效行为的置之不理,一边是启动学习和阅读,只要做个行为替换就可以改变习惯。
谁都知道替换可以改变,但为什么这么难?其实关键在于这个意识点能不能变成触发性响应,也就是说当某个触发条件产生的时候,改变的意识能不能弹出来警告自己。
先对习惯的产生机制要有所了解,习惯并非凭空产生,他有前因后果,前因是前一件事情结束(触发条件),后果是前一件事情结束后的行为带来的一些额外奖励。比如晚上下班回家洗完澡这件事情结束后,肯定会开始下一件我们最习惯的事情,比如盯手机看剧或者刷八卦,当这件最习惯的事情结束后,大脑会产生精神上的及时享受,内容很丰富、很精彩。短期看是享受,长期看是灾难,因为对未来帮助意义不大,但是却消耗了我们大把时间。而且看剧或者刷八卦带来的信息积累只能称的上是饭后谈资,或者有些根本没机会谈。
了解习惯产生的机制后,改变习惯就变得很简单,每次在触发条件发生时,弹出一道选择题,选择做无效事情,还是学习?多次以这种方式不断强化自己做对选择题。久而久之,正确的行为被训练得多了,就成为顺其自然的习惯了。所以改变习惯,就是在触发条件发生时,让自己做对选择题,打破旧有习惯回路,建立新的习惯回路。相信这句话“精英之所以精英,是不间断的正向行为习惯的驱使”。
划重点:所谓改变习惯就是在触发条件发生进入下一个行为时,让自己做对选择题。
3. (CNI)时间管理:三八理论
在我的第 2 个认知《习以为常》中,提到养成习惯的方法就是在触发条件发生时,让自己做一道正确的选择题,打破旧有习惯回路,建立新的习惯回路。也就是说当做对选择题的时候,也就得到了用于学习和思考的时间,这是时间管理的一部分,从现有的事务中挤出时间。但是用于学习的时间不应该只有这部分,我们需要系统性认知时间管理。
世界上有 2 种人不做时间管理,一种是有时间不管理,另外一种是没时间不管理,既有主观原因,又有客观原因。客观原因是工作太忙,确实很难有时间用于学习;主观原因是做其他事情有时间,学习和思考没时间。不管哪种人,他们内心深处对于时间管理的需求一直存在,只是一直没找到好用的时间管理方法,最后放弃了。
有需求必有供给,市面上可以找到有很多时间管理的书,时间管理方法,时间管理软件。但是你有没有过这种经历,我是有过,很多方法用了,比如时间管理四象限、番茄钟、时间计划等,在坚持一段时间之后,还是回到原来的状态,原因是什么?我认为最根本的原因是太复杂了,没法用一句话改变我们的共识并建立时间管理意识。
比如很多时候我们会采用计划的方式做时间管理,什么时间做什么事,但是人毕竟不是机器,总会有意外,无法按照流程一步步执行下去,计划总会被打乱,一旦打乱可能全乱。若为了保持计划如期运作,会给自己带来非常大的负担,负担来自于为了管理该计划消耗了很多精力,而且每项计划不一定能够按预期完成,时间久了,放弃是最好的选择。
当然这些时间管理方法或番茄钟肯定有用,只是复杂的东西不适合我,可能也不适合很多人,不然不会有这么多人明知有很多时间管理方法,但还是对时间管理很焦虑,因为难执行啊。我必须找出简单的方法让我自己能够很快适应,同时不会成为负担,对时间管理的认知是我的第三个认知升级,也就是时间管理三八理论。
时间管理三八理论:每个人每天有公平的 24 个小时,第 1 个八小时用于睡觉、第 2 个八小时用于工作、第 3 个八小时用于自由支配,但人与人的差距主要是由第 3 个八小时决定的,第 3 个 8 小时用于消费、交易还是投资有着非常大的人生差别。以下班空闲时间为例解释消费、交易、投资从而理解人生差异的不同: 下班空闲时间,用于 消费 ,比如刷新闻,刷抖音,刷朋友圈,产生及时享受,没产生成长,钱还是那些钱,职位还是原来职位; 下班空闲时间,用于 交易 ,接个外快,赚点辛苦钱,产生金钱,没产生成长,钱没多多少,职位却还是原来职位; 下班空闲时间,用于 投资 ,以终为始,相信“慢慢来,成长最快”的认知,持续不断投入多维领域的学习,沉淀能力,获得成长,从成长中获得金钱,名誉的升级;
看完时间的消费、交易、投资的解释,在看《习以为常》中做选择题的重要性,做对选择题其实就是投资,投资自己的成长,投资自己的学习,人生的不同不就是因为投资自己而变得不一样吗?但是投资需要时间,时间怎么来?
“找到不被打扰的时间”。只有找到了不被打扰的时间用于投资自己的成长才能发生复利效应。如果想从工作中省点时间,想从周末挤点时间用于学习,这叫成长的断崖,我相信不能持续,学习必须是每日的必修课,必须是日拱一卒,持之以恒,有不断的输入,也有不断的输出,持续地沉淀,在关键时刻输出解决问题能力,从而获得能力认可。
分享下我如何找到不被打扰的时间用于投资自己的成长,因为每个人的工作性质不同,找到不被打扰的时间长度不一样,比如程序员这个行业,加班很多,比如我在公司时间平均有 11-12 小时,即便在这种情况下,还是能够在工作以外找到不被打扰的时间,更何况工作时间没有 12 小时的朋友呢!我的不被打扰时间: 睡前 :晚上回家到睡觉前,这段时间每个人都有,这里至少可以抽出 40 分钟学习,建议 11 点半之前必须睡觉,为了早起做准备; 早起 :这里需要重点说下,如果按照我之前 8 点起床的睡眠习惯,这个时间估计用不上,所以有魄力的人可以做些改变,就是缩短睡眠时间,比如原先 8 点起床改成 6 点,相信自己,年轻人睡 6-7 个小时是够的;这样就会产生 1~1.5 个小时学习时间,平时哪有这么长的时间用于学习啊; 晨会前 :这条适合离公司近的人,在晨会开始前,早点到公司,找到30分钟用于学习,这类短时间的学习主要是用于学习快餐知识,找知识服务平台花钱买知识,学习人家总结好的知识。
以上的作息计划会让自己产生一定的疲劳,但是中午放弃刷新闻,刷抖音,在工位补个觉,不会影响每日的精力,而且随着自己的成长,会越来越有成就感,成就感带来的精神状态反而比之前更好。
划重点:所谓时间管理就是找到不被打扰的时间用于投资自己的成长。
4. NI)最重要的财富:注意力
对我们来说,有 3 样非常非常重要的财富,分别是金钱、时间和注意力,其中金钱在 3 者之中我认为最不重要,反而非实物的注意力和时间更重要,金钱没了可以通过提升能力赚回来,而且是 100% 可以赚回来的,时间和注意力是一次性消费,用了就没了,虽然第二天有新的时间和注意力补充进来,但是要知道生命在流逝,过去消耗的时间和注意力属于一次性消费。
在时间管理的认知升级中,我们已经具备了认知:“找到不被打扰的时间用于投资自己”。本节以我们的第2大宝贵财富注意力进行认知升级,让自己的注意力在不被打扰的时间里用在投资自己的成长道路上,时间是容器,注意力是武器,搭配得好,成长可期待。
先问自己 2 个问题: 昨天、上周、上月看过的内容还记得吗? 进一步区分看过的内容:哪些是成长?哪些是谈资或甚至都没有机会谈?
好的问题本身就是好的答案,回想自己过去在第 3 个八小时的自由支配时间里,注意力用在什么地方,是用于投资还是用于消费,如果意识到过去注意力用在了消费上,那么赶快把注意力用到投资自己成长上,如果还没意识到,建议只字不差阅读《时间管理》认知,进而搞清楚时间用于投资,还是消费,有着巨大的人生意义。
从问自己的 2 个问题看现在的生活方式,生活中有很多看似合理的生活现象,其实是一个巨坑,是别人在收割我们注意力变成流量产生了商业价值,但是我们竟然乐在其中,因为我们喜欢莫名其妙凑热闹,喜欢随大流,喜欢做大家正在做的事情,我们每天花了大把时间在上面,但是收获的成长却很少,因为我们都是在消费时间,消费注意力,而不是用时间投资自己成长。
我们以为做大家正在做的事,就找到了归属感,找到了安全感,但实际上真正的安全感、成就感,归属感来自自我成长,自我沉淀。对生活在信息量爆炸时代里的我们,用好自己的注意力非常难,处处都是陷阱,处处都是诱惑,处处降低我们的思考,让我们轻易获得成品,带来的结果是表面上我们懂的很多,但其实理解非常浅。
对于这些巨坑,不建议大家 100% 放弃,对于群居物种的人类来说,还是要和外面世界建立连接,和身边人有话题交流,但是我们要调整注意力,把原先可能 100% 的注意力变成 28 分配,还是 37 分配,根据自己对自己的掌控力度,让大部分注意力投资在自己的成长上,减少朋友圈,减少新闻娱乐投入。
再来解一个疑惑:“为什么看电影注意力特别好,做正事注意力集中不了”。
首先接受这个现实,医学上把这叫作注意力缺失症,基本所有人都有这种毛病,因为做正事比较枯燥、困难,让人不舒服,集中不了注意力,逃避很正常!
其次找到改善方法,我通常这么做,给自己准备一个笔记本或 Evernote,边读边思考,顺带把重要的观点记录下来,开始会觉得很困难,但是慢慢坚持下来你会发现,思考会越来越深入,注意力集中时间越来越长。或者练习只字不差的阅读,在练习过程中因为只字不差会让自己更认真地去理解内容的逻辑关系,从而达到提升注意力的目的。
注意力和时间管理的认知一旦结合,我们可以兴奋地这么说:“在不被打扰的时间里,用好注意力投资在自己成长上,我们的人生会不一样,在未来会遇到更好的自己”。
划重点:所谓提升注意力就是专注在目标事务上,直到产出预期的结果。
5. 拿结果手段:执行力
执行力和自律在我们的工作和生活中出现的频率非常高,因为这是我们成长或做成事时必须要有的 2 个关键词,但是很长一段时间里,对于提升执行力,疑惑很大。同时在工作场景中可能会被老板多次要求提升执行力,抽象又具体,但往往只有提升执行力的要求没有如何提升的方法和认知,这是普遍点到即止的现象,普遍提升不了执行力的现象。
造成这种现象的原因,是因为我们的认知很容易接受前人总结的观点,因为太有道理,所以欣然接受,然后会像传球一样,把观点再次传给其他人,但是整个传播链路上缺少形成观点的方法传播,也就是大家听到看到,很多时候只是结果,缺乏了过程的输入,看到的是别人的成功,但是看不到别人是如何成功的。
我也经常要求自己提升执行力,但一段时间后就主动放弃,后来我想通了一件事:每个人身体内至少有多个角色,从认知的角度来看,有两个角色,一个是投资者,投资自己的成长;另外一个是消费者,消费自己的时间和注意力,很少关注自己成长。我们一生一直在扮演这两个角色,互相博弈,成长者获胜持续成长,消费者获胜原地踏步。但是,往往消费者获胜,因为消费者在消费时间和注意力去刷朋友圈、看新闻娱乐,做大家正在做的事情,感觉找到了归属感,安全感,大脑能立马获得及时的奖励,而大脑又是控制我们思考和行为,一旦消费者占领了大脑,也就控制了我们日常的思考和行为。
提升执行力,首先让自己成为投资者,投资自己的成长,投资在正确的事情上,此时去认知执行力才有意义,我对执行力的认知:“想明白,然后一步一步做下去”,如果想不明白,根本谈不上执行力。同时提升执行力的时候,还需要自律,通过自律让执行力得到持续,要相信持续投资自己的成长,可以实现“慢慢来,成长最快”的复利效果。比如:
很多时候我们知道,或被提醒过,或被要求过,需要提升执行力和自律,却不知道执行力的行为指导方法,现在有了执行力背后的行为指导方法:“想明白,然后一步一步做下去”,此时的我们需要有思辨思维,通过实践“想明白,然后一步一步做下去”,内化成自己的认知和方法,指导自己的一生。
划重点:执行力就是想明白,然后一步一步做下去。
6. 贵人
阿里文化环境,技术环境,成长环境对个人成长非常有帮助,所以在阿里常说要学会感恩,感恩自己处在了最好的时代,最好的环境里、感恩身边的人、感恩帮助和改变自己的人。
这几年经历的事,遇到的人对自己的帮助和改变非常大,很多时候像是命中注定,在挑战、迷茫、委屈的事情出现时,恰好有个人在你身边,和你一起理清思路,调整思考方式,避免处在自己封闭式的思维里越思考越极端。我确实非常幸运,身边有这样的贵人,能够帮助我以终为始看问题,看自己。慢慢地,我相信一切问题源于自己,让自己变好是解决一切问题的根源。所以我把贵人作为一项认知升级,放在自己的认知库中,有机会让更多的人或自己的家人也建立贵人的思维方式。
但是很多时候我们会觉得身边缺少贵人,或者有贵人但离自己太远。产生这种认知离不开 4 个方面: 一是 自己不自信 ,不相信自己能够影响他人,导致缺乏主动沟通,长期沟通,沟通的延续性和习惯没有建立; 二是 自己心态问题 ,自己的心态若是不够积极正向,没有贵人敢进入你的思维空间,因为价值观不匹配,很难形成认知共识; 三是 职场原因 ,很多时候可能你的老板就是你的贵人,但是因为职场,因为上下级,碍于面子,碍于工作,不敢多交流,多请教; 四是 贵人来了又走了 ,有贵人帮你改变,帮你进步,但是自己不努力,抱着过去做事的心态和方法在职场上浪迹天涯,进步不明显,否定了他作为贵人的价值和意义。
如果恰好有这么一位贵人,应该懂得珍惜,珍惜的主要方式是用成长回报他,因为你的成长在未来可以帮助他。同时在平时需要建立有效沟通,首先让贵人真正地了解你,在确定贵人能够帮助你,影响你时,你应该大胆去承担一些有挑战的事情,哪怕遇到委屈,遇到压力,遇到失败,要相信此时的你才是真实的你,你的天花板,你的瓶颈就在于此,借助贵人助你提升能力,下次同样的事情来临时,自己就能够得心应手,这种能力的锻炼机会非常少,和阿里经常说的借事修人非常匹配,事情失败了没关系,但人要成,人的能力要提升。
说一个我自己从小的经历,我从小独立性很强,干过很多农活,小学开始住校,16 岁做了 2 个月童工盖楼房,高中月末回家坚持地里务农,大学勤工俭学,正因为独立性很强,很少主动向人求助,加上从小接受的父母教育:向人求助等于麻烦别人。有事没事别老是麻烦别人,欠人恩情要还的,这不是我父母的错,而是中国的报答文化,因为获得帮助需要报答别人导致心里负担太重,从而教育子女不要随便麻烦别人。长期以往性格受此影响较大,越不向人求助,性格越内向,越内向越不向人求助,与他人间的交流少了,输入少了,观点碰撞少了,思考也就少了,内敛的性格也就这样逐步养成了。
但是这几年的经历和变化,突然意识到向人求助≠麻烦别人。如果把求助当成低声下气的行为,那么跟乞丐没啥区别,把求助看成一种交易,一种有着“巨大意义”的交易,你求助时,别人之所以愿意帮助你,是因为他已经看到你的价值,这种价值帮助他确定了自己的价值(他有能力帮助你),或者未来你可以帮助他。每个人应该都经历过,在你出手相助他人的那一瞬间,你得到了最重要的回报:你有能力帮助别人,同时,在帮助他人的过程中发现了自己未来可能需要更加努力的方向。帮助别人不是你赢我输,而是一个共同进步的过程,在帮助别人的过程中,巩固自己知识的同时可以发现自己理解上的偏差。
贵人就应该紧紧抱住,通过和贵人建立关系,贵人的观察,反馈,双向沟通,对话,辅导等,可以帮助自己从互动的信息中生成自己的思考,行为和观点,这些思考,行为和观点会影响自我,完善自我。
自我稳定性 :让自我的容器变得强大,在受到挑战,职责,委屈时候能够容纳对方的批判,情绪。
自我灵活度 :容忍对方的情绪后,可以及时调整自我状态,因为相信一切问题源于自己,让自己变好是解决一切问题的根源。
自我疆界 :当做出自我状态调整后,看事物的角度变了,能力提升了,自我的疆界在逐渐扩张。
自我力量 :自我疆界扩张后,形成的成就感,会让自我的力量变得更强大。
自我组织力 :当一个人在高压下感觉要散架的时候,或者被击溃而瓦解的时候能够自我重组。
划重点:贵人就是可以持续陪你输出高质量的人。
7. 会议
“输出倒逼输入”很多人都听过,但是有哪些输入方式,而且效果比较好,很多时候我们真的没认真想过。这种现象的原因是我们潜意识里常用的输入就应该是看书、思考,反馈这 3 类,所以很多时候我们会对其他高质量的输入方式不重视,甚至忽略。此时,自己安静细想讨论过程中的输入效果?肯定会有自己的答案。而我认知“讨论过程中的输入效果最好”,是因为讨论过程能够刺激自己大脑快速做出反应,好像 CPU 被超频,同时也能够从对方的问答中获得更好的输入,这就好比 2 个人在模拟机器学习,通过正反馈的方式不断优化讨论结果,算出最优解。
实际工作中,大家对会议的看法普遍不太好,大家眼中的会议是这样的:会太了多,会议很低效,同样的内容反复开了几遍,自己是很小的配合者却要参加 2 个小时的会议。
而且我观察过很多会议,很多人,绝大部分人都是开着电脑开会,忙着自己的键盘,特别是我们程序员,虽然会议上编写代码有可能提升项目开发进度,但是在有讨论,有分享的环境里让自己非常专注写代码还是非常困难的,同时我在团队中做过一个统计,统计了一个月大家的会议情况,大概每双周会议投入时间平均在 10%~15%,也就是说双周 1 天到 1.5 天的会议时间,从会议消耗来看,会中处理事务并不一定有非常大的效率提升,倒不如每时每刻集中注意力专注于一件事,效率也许更高。
所以在参会时,有些会议我尽量不带电脑,让自己的大脑处于思考状态,随时接收会议中的信息进行思考,训练自己的观点产出能力,训练自己的总结归纳能力,同时也要求团队同学在没有紧急事情的情况下,尽量合上电脑,让自己专注投入到听别人讨论,听别人分享,然后自己思考,总结,提炼观点,当然也可以自己参与到讨论中,成为主角。
会多不一定是坏事,反而可能成为你训练思考,训练总结归纳,训练逻辑表达的地方。好比机器学习,喂给机器大量的数据进行模型训练,对训练的结果进行应用、验证,如果效果不好再次训练调优,整个过程是一次正反馈不断强化训练的过程。回到参与会议也是一样,通过聆听,讨论不断验证自己的观点正确与否,再次聆听,讨论,通过一次次的正反馈验证自己的逻辑和观点是否正确。
而且用什么样的身份参与会议,或者在过程中角色如何切换,也是非常重要。我一般用 3 种角色参加: 作为参与者 ,认真聆听,快速提炼自己想表达的逻辑,然后参与讨论; 作为聆听者 ,仔细聆听,认真输入,在脑中组织思路,组织逻辑; 作为中断者 ,发现有些会议真的没有继续的必要了,出于好意,提示会议的重心或者结束会议。
划重点:参与会议讨论就是在模拟机器学习,通过正反馈来优化自己的逻辑和观点。
8. 跳出舒适区
为什么感觉看了那么多的书,工作了那么多年,写了那么多代码,自己在一开始的进步明显后,到现在基本停止进步?我想是因为在舒适区呆的太久了,看再多的书,写再多的代码,可能只是以一种舒适的方式进行工作和生活而已,这种舒适方式一直没有被很多人认识到,等回头反思的时候发现做了很多事,看了很多书,但成长的预期和现实不符。
于是,我们开始想,究竟哪里出问题了?避难就易是人的本性,困难和容易之间,我们总是习惯选择容易,但若选择困难,导致无法接受困难下的挑战我们还是会回到舒适区中。回想过去,自己好像也是这样的,心血来潮时突然感觉能量爆棚要学很多东西,一段时间后又回到原位。
抛开自身看身边认识的人,几年不见,成长非常明显。就好比我们人类快速的进化和进步,是因为我们掌握了智慧,而这些智慧来源于前辈们的发现和经验的总结。比如舒适区,心理学家把我们可能面对的学习内容分成了三个区,分别是舒适区、学习区和恐慌区。舒适区太容易,待太久了,总想跳出去看看。恐慌区太难,太难带来恐惧,就像梁宁在产品思维中讲同理心时,恐惧会产生束缚也会产生动力,就看安全边界有没有被侵犯,如果无法战胜挑战,恐惧就产生了束缚,退回到舒适区。
所以跳出舒适区,不是说跳到恐慌区,而是跳到两者之间的学习区,在学习区中达到困难和能力的平衡状态,引用米哈里.契克森米哈赖在《心流:最优体验心里学》这本书提到的:要想在工作中达到心流状态,这项工作的挑战和你的技能必须形成平衡,如果工作的挑战大大低于你的技能,你会觉得工作很无聊。如果工作的挑战大大超出你的技能,你会感到焦虑。
需要让难度和技能正好匹配,在你接受挑战时你还不知道该怎么做,但是调动自己最高水平的技能,再稍微努力突破一点,你正好能解决这个问题,就是心流的体验,这是一个奇妙的感觉,你沉浸在工作之中忘记了时间的流动,甚至可能忘记自身的存在。
跳出舒适区,进入学习区,进入困难和能力相对平衡的学习区,才能让我们快速成长起来,但是进入学习区后,还需要配套的学习方法才能逐渐锻炼自己,很多人有自己的学习方法。
划重点:跳出舒适区就是进入学习区,平衡挑战和技能从而达到心流体验。
9. 职业规划
我对职业规划有个人不同的理解,我认为大部分人其实不需要做职业规划,只有那些有梦想,个人基础素质非常好的人才需要职业规划,他们会为一个目标持续不断努力多年,直到目标实现。而大部分人不需要职业规划,是因为很多时候,我们做的职业规划只是个梦想,虽然梦想还是要有的,但很多时候只是被别人实现了而已,若是恰巧因为幸运被自己实现了,可能是个误会,因为能力没到,在新的岗位和角色上会比那些早已准备好的人要付出更多的努力和汗水。
过去被一些非阿里系的人问过,应该怎么做职业规划?展开交流后,发现很多人在做职业规划的时候,更倾向于把职业规划放在某个岗位,某个角色上。比如会把目光聚焦于经理岗位、经理能力,或者架构师角色,但是他们怎么走上该岗位,获得该角色,背后做了哪些努力,用了哪些方法,沉淀了哪些能力,一脸茫然。确实,职业规划非常难,难在他是未来的一个想象空间,这个想象空间能否实现,和当下做的事情,努力的程度分不开。
在聊完后,我一直在反思,如果自己做职业规划应该怎么做?经过不断抽丝剥茧,我找到了自己的答案,我认为职业规划不是某个岗位,某个角色,而是工作能力的提升。针对自己岗位需要的能力,职场需要的能力,然后用专家思维,多维视角重点突破 3-4 项能力,抱着 120% 的努力拿到结果,甚至是超出期望的结果,事情成了,能力也就被认可了,所谓的角色,岗位只是顺其自然的结果。但是真能这样做的人少之又少,既然是少之又少,成为少之又少的人才是你的机会。
划重点:所谓职业规划,就是工作能力提升。
10. 时间换空间
时间换空间,还有另外一种认知的说法:“慢慢来,持之以恒,成长最快”。不管哪种说法,其实是在告诉我们,成长无法急于求成,无法急功近利,唯有每日在不被打扰的时间中不断投资自己,通过不断输出确认自己成长上的不足,循环弥补不足之处。通过把自己逼近成长临界点,然后跨过临界点的那一刻,自己立马可以体会到自己的变化,自己的成长。
而自己一旦体会到成长,我们会把前一段时间的成长过程进行总结,抽象总结出自己的成长最佳实践,再次践行,把自己逼向下一个成长临界点,然后再次跨过去,以此反复循环,慢慢提升自己的多元能力,跨界能力。所有这些能力的提升,在未来某个机会来临的时候,因为具备足够的能力去驾驭他,此时我们要做的是,抱着120%的努力把事做成功,事情成功了,能力也有了,空间自然会有,也就被认可了。
所谓时间换空间,就是让我们无法看清未来是什么样子的时候,把注意力聚焦在当下,做成长该做的事。
划重点:所谓时间换空间,就是慢慢来,持之以恒,成长最快。
总结
认知升级很鸡汤,虽然好喝但不易消化,在通过学习提升自己认知的同时,自己需要有批判性的思维,把自己认可的认知,通过自己的践行,沉淀出自己的最佳实践,让自己具备自我进化能力,形成自己的认知系统,这是成长根本。以上10个认知升级,分别用一句话进行总结,完成自我认知升级: 所谓 直觉反射 ,就是通过大量的逻辑反复训练,提升自己的直觉准确性,从狭窄的 5% 进入广阔的 95%; 所谓 习以为常 ,就是在触发条件发生进入下一个行为前,做对选择题; 所谓 时间管理 ,就是找到不被打扰的时间用于投资自己; 所谓 注意力 ,就是专注在目标事务上,直到产生期望结果; 所谓 执行力 ,就是让自己先想明白,然后一步一步走下去; 所谓 贵人 ,就是能够持续陪你一起输出高质量内容的人; 所谓 会议 ,就是模拟机器学习思路,通过参与讨论获得正反馈来验证自己的观点; 所谓 跳出舒适区 ,就是先跳出,然后进入学习区,平衡挑战和能力达到心流的体验; 所谓 职业规划 ,就是提升工作需要的能力; 所谓 时间换空间 ,就是慢慢来,持之以恒,成长最快; “ 阿里巴巴云原生 关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”
云计算
2020-07-13 16:49:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
作者 | 箫逸  阿里文娱高级技术专家
关注“阿里巴巴云原生”公众号,回复 架构 即可查看清晰知识大图!
**导读:**架构图是什么?为什么要画架构图?如何画好架构图?有哪些方法?本文从架构的定义说起,分享了阿里文娱高级技术专家箫逸关于画架构图多年的经验总结,并对抽象这一概念进行了深入地讨论。内容较长,同学们可收藏起来细细阅读。
什么是架构图?
如何画好一张架构图,要做好这件事情首先要回答的就是什么是架构图。我们日常工作中经常能看到各种各样的架构图,而且经常会发现大家对架构图的理解各有侧重。深入追究到这个问题,可能一下子还很难有一个具象的定义,如果我们把这个问题进行拆分,理解起来就会容易一点。 架构图 = 架构 + 图
按照这个等式,我们可以把问题转换: 架构是什么? 图是什么?
图是什么?这个比较容易回答,图是一种信息的表达方式,所以 架构图,即表达“架构”的图,也就是一种架构的表达方式 。也即: 架构图=架构的表达=表达架构的图 。
按照这种思路我们需要回答: 什么是架构?要表达的到底是什么? 如何画好一张架构图?
接下来的内容基本上就是按照这两个维度来做分析。
什么是架构?要表达的到底是什么?
Linus 03 年在聊到拆分和集成时有一个很好的描述: I claim that you want to start communicating between independent modules no sooner than you absolutely HAVE to, and that you should avoid splitting things up until you really need to, because that communication complexity often swamps the complexity of the actual pieces involved in it.(让我们认识到一种现象,把 复杂系统 拆分成模块,似乎并没有降低 整个系统 的复杂度。它降低的只是 子系统 的复杂度。而整个系统的复杂度,反而会由于拆分后的模块之间,不得不进行 交互 ,变得更加复杂。)
我理解这里描述的系统拆分就是架构的过程, 基本出发点是为了效率 ,通过架构的 合理拆分(无论是空间还是时间上的拆分) , 最终目的让效率最大化 。那到底什么是架构,其实没有完全统一且明确的定义,如下三个定义可以参考。
在百度百科上的定义: 架构,又名软件架构,是有关软件 整体结构与组件 的 抽象描述 ,⽤于指导⼤型软件系统各个方面的设计。
在 Wikipedia 上的定义: **Architecture **is both the process and the product of planning, designing, and constructing buildings or any other structures.
ISO/IEC 42010:20072 中对架构有如下定义: The fundamental organization of a system, embodied in its components, their relationships to each other and the environment, and the principles governing its design and evolution. 
这三个定义也是见仁见智,但是我们基本可以得出: 架构体现的是整体结构和组件之间的关系。
1. 架构的本质
这里引用三个观点来探讨架构的本质: 架构的本质是为了管理复杂性; 架构的本质就是对系统进行 有序化重构 ,不断减少系统的“熵”,使系统不断进化; 架构的本质就是对系统进行 有序化重构 ,以符合当前业务的发展,并可以快速扩展。
上述三个观点提到的内容, 基本表达了架构的核心目的:管理复杂性,效率最大化。以及架构的两个主要变化来源:一个是以改善软件质量为目的的内在结构性变化;另外一个是以满足客户需求为目的的外在功能性变化。
无论是何种变化,在我看来架构都是在不断的判断和取舍,在业务需求和系统实现之间做权衡,从而来应对未来变化的不确定性,如下图可以比较粗浅直观的表达这种理解。
2. 要表达的是什么?
在 EA 架构领域,有两种常见架构方法 RUP 和 TOGAF,这两个框架也是我们常常了解架构分类的两个维度。从个人的角度,我自己觉得 TOGAF 的分类方式更加广泛使用(如下右图)。
结合日常的业务开发,其实我们更多的是关注业务架构和应用架构,所以把上边的表达式进一步的拆解,在回答如何画好一张架构图之前,我们需要关注业务架构和系统架构,讨论清楚如何进行业务架构和系统架构。
3. 架构的过程其实就是建模的过程
我们都知道现实世界到软件世界或者面向对象的世界的过程,是一个不断抽象的过程,这其中的方法就是不断的建立模型。从现实世界到业务模型,从业务模型到概念模型,从概念模型到设计模型,通过不断的抽象去粗取精,形成对现实世界的层层抽象,所以架构的过程其实就是建模的过程。至此,我们有必要了解一下什么是建模。
百度百科定义: 建模就是 建立模型 ,就是为了理解事物而对事物做出的一种 抽象 ,是对事物的一种无歧义的书面描述。
《Thinking in UML》定义: 建模(Modeling),是指通过对客观事物 建立一种抽象的方法 用以表征事物并获得对事物本身的理解,同时把这种 理解概念化 ,将这些 逻辑概念组织起来 ,构成一种对所观察的对象的内部结构和工作原理的便于理解的表达。
从上述两个定义上基本可以了解到建模就是抽象,对业务或现实世界的抽象,虽然不足以帮我们理解架构本身,但是可以将我们上述关注的业务架构和系统架构进一步向下 Down 一层,架构的过程是建模的过程,我们转换成两个简单的问题:模是什么?如何建?
4. 模是什么?如何建?
这是两个比较容易陷入理论性的问题,我们跳出来从结果看过程。接下来通过已经产出的一些架构图来反向看这些架构图是如何产出的,同时来回答这两个问题。
1)业务建模
回到当下业务本身,对我而言也是全新的,在最初接触的时候凭仅有的行业背景去理解,结合了大量的文档阅读最终产出了如下图示的《业务核心流程图》和《业务功能模块图》。这两张图基本上就涵盖了所有的业务内容。左边的业务流程图得到了这个行业 20 多年从业经验专家认可,他认为这就是 20 多年所从事的业务内容。
图片源于网络,为示意图,侵删
回溯整个过程,特别是左侧的业务核心流程图,今天我们看这张流程图很容易构架起一个基本逻辑来,纵向是不同的业务角色和系统,横向是时间的推进,特别容易理解。但我想说最开始的理解和分析是极其耗时和压力极大的过程。这个过程中我所用的方法就是: “把书读厚”:大量的信息输入,同时探求可能性; “把书读薄”:归类汇总,形成大图; 逻辑对照,确保理解和分析的正确性。
把书读厚:
下图基本涵盖“把书读厚”的过程,汇聚大量的文档信息,尝试用多维度去形成逻辑。这个维度可能是依据历史经验,也可能是依据文档内容,比如在形成业务大图的过程中,我曾按可能的场景逻辑、可能的系统或领域逻辑分别把多个文档中的内容归类,探求可能性。
这个过程会很枯燥,特别是涉及一些业务的术语内容,理解起来就会很困难。我的方式就是把自己当做一名“探索者”,如同我们玩游戏一样,常常问自己“我的游戏地图全部点亮了吗?”未必要照顾到所有细节,但是需要力求覆盖整体内容。仔细想想,似乎也和日常的读书类似,这期间值得注意的是: 重点关注一些业务概念被界定的地方、一些与自己逻辑推理有出入的地方; 不断的调整自己阅读过程中记录的维度,矫正自己的分析方向; 老老实实用文档中的原话来记录和呈现(这点很重要,特别是阅读英文材料,最好原汁原味的记录,有助于提升自己的专业性)。
把书读薄:
这个时候的重点是建立“大局观”,尝试梳理自己的逻辑主线,常规逻辑上讲都会划分为横纵,或者矩阵式的框架,当然这需要建立在前期的理解和分析上,**这里常常隐含一个最最重要的假设:系统一定是给人用的,一定是解决客户问题的,否则毫无存在的意义。所以核心的套路是:谁?用什么样的服务/功能/能力?解决什么样的问题?从而刻画出:参与者角色、系统能力、交互关系,需要常常问自己的是:边界是什么?输入输出是什么?**逐步的通过用例来梳理出业务功能,形成角色—>主流程—>分支流程,进而通过不断的归纳演绎形成最终的业务抽象描述“一张图”。
一个小的细节是不能妄图通过这些过程迅速在大脑里完成大图的绘制,还是需要从小的环节做起,把一部分小的业务闭环做成一个个的小组块,不要让它再占用大脑的空间,然后逐步的整体思考和把握,渐进式的形成大图;与此同时,大图的样式美观先完全忽略,走通逻辑再细致调整。之所以强调这个细节,是因为尝试通过“一张图”去描述一个非常大的业务本身就是件很有挑战的事情,如果不这么做容易让自己变得焦虑和急躁,这是一个慢功夫,需要耐心,需要在关键阻塞的地方慢下来,甚至一遍一遍的反复才能最终完成。
逻辑对照:
这是一个闭环封装的过程,把前期“读厚”过程中的记录,一些逻辑细节、关键流程都要逐一放到大图里去对照验证,确保业务理解的完整性和准确性,确保业务抽象能够覆盖所有已知的业务用例,甚至能够支持可能的业务场景。这个环节也是必不可少的部分。 
总结一下业务建模(如下图),通过上述三个主要的过程,我们基本可以产出一些业务架构的大图、框图、流程图、用例图等等,是什么样的图并不重要,重要的是这个图面对的是谁?主要用来做什么?我后边也会讲到画图角度的问题。从我们目前的业务场景上看, 业务架构图的核心目的是统一共识、减少沟通成本,无论是项目中的哪个角色大家都能讲一样的话,描述一样的事情。这就是建立对话能力和对话语境,特别是有大量外部客户的时候,一方面体现我们自己专业性很重要,另外一方面这种与客户对话的能力更重要,这也是上文中提到为什么要尽可能用原汁原味的文字去呈现一张图的目的。
2)系统建模
通过业务建模完成了从现实世界到业务模型的构建,在此基础上,如何通过抽象完成业务模型到设计模型的映射,这是系统建模要解决的问题。从研发实现的角度,这个阶段会产出各种各样的模型图,比如实体模型图、时序图、状态图、各个层次的架构图等等,但是 无论何种角度,何种层次,系统建模一定是在业务建模的基础上,完成业务需求到系统模型之间的映射 ;这其中涉及业务功能到系统能力、业务流程到数据流程的映射;系统建模更强调职责、依赖、约束关系,用于指导研发的落地实现。
抛开具体的时序图、状态图不谈,简单看一下如下几个维度的架构图:
图片源于网络,为示意图,侵删
上述几张图的视角、层次和面向用户各不相同,基本上都能看到整体,但是细节程度不同,侧重表达的信息也完全不同。那么系统建模时应该如何去做呢,这个过程中我常常用的方法是(不尽然如此): “剥洋葱式”的由大到小,由粗到细,覆盖所有已知和未来可能业务场景;善于利用各种模型表述:自然语言、关系模型、时序图、状态图、流程图、各种层次架构图等等进行模型表述,充分表达各种业务场景并不断验证; 核心实体抽取:抓住核心概念,核心关系完成核心模型建立; 终极武器:所有的设计/逻辑模糊的点,将所有已知场景分别套入,自己讲给自己。
“剥洋葱”:
在业务建模结果的基础上进行“剥洋葱”。这是一个不断拆解的过程,这个过程中的拆解非常重要的方式是就系统分工。如何分工?哪个模块负责什么?模块的输入和输出是什么?内部提供什么样的服务和能力?这几个问题在后文关于抽象的部分回答。一句话总结“剥洋葱”就是:从业务建模的“大局观”去按职责分工拆解成多个子系统、多个子模块、然后在模块能进行细分,层层剥解。
核心实体抽取:
关于核心实体的抽取,这里的关键问题是:哪些是实体?如何判断核心实体?如何抽取?抽取后的结果是什么样的?很难用一种方法论的形式去描述,我也没有完全形成我自己一成不变的方法论,但是我觉得如下三种方式可以供大家参考。 对象的分析方法 实体(Entity):客观存在并可相互区别的事物称之为实体。实体可以是具体的人、事、物,也可以是抽象的概念或联系。
从这个概念理解,和我们面向对象万物兼对象的理解是基本一致的。所以实体的抽取也可以借鉴对象分析的方法:独立、可抽象、有层次性、在单个层次上又具备原子性。如下图是《Thinking in UML》中关于对象的分析方法。
用例分析的方法
通过从业务用例中,去提取其中的关键词,不同的关键词可能表达了实体、关系、属性等等内容,从而完成模型分析与建立。这里引用六铢老师在《问题空间领域模型基本抽象方法》中的的内容,简述如下: 一句完整的用例描述中,首先找名词,以「主语」和「宾语」为主,这些名词基本可以确定我们的实体;其次找形容词,存在于「定语」和「状语」中,找到形容词基本可以确定对应属性的值;然后通过对用例的补充,细化,对 名词 进行定义,慢慢的,我们会得到我们的领域模型和对应的属性。最后通过动词&形容词(存在于【谓语】,【状语】,【定语】)来确定他们之间的关联关系。 问题分析的方法
这是《聊聊架构》中提的方式,具体讲就是通过寻找问题的主体,然后分析主体的生命周期,进而通过区分生命周期里的关键活动来聚焦主体的关键属性和关键关系。推荐大家阅读前 9 章的内容,总计才 40 页的内容,可能会有所体会。这里举一个书中的例子: 一个笑话:一位女士对老公说:把袋子里的土豆削一半下锅;结果所有土豆都下锅了,而且每个土豆被削了一半。
作者指出,这里其实就没有清晰的设别主体,这个主体不单是土豆,而是隐含的人要吃土豆,包括人和土豆两个实体,这两个实体之间的关系就是要解决的业务场景:怎样吃?如何吃?为什么吃?所以主体识别不清楚,可能会导致整体实现的偏离。当然实际过程中不会犯这么愚蠢的错误,但是也侧面说明核心实体的抽取是非常关键的。
终极武器 - 自己讲给自己:
实际的业务开发中,往往一种业务设计实现要满足上层N个业务场景,这其中有共性也有个性化诉求,这个过程中我们很容易被多场景之间的异同搞混乱,要么逻辑不清晰、要么过度设计、要么考虑不周。我观察过很多同学包括我自己,在一定的业务复杂度时容易失去设计的焦点。我的做法与业务建模类似,一定要逻辑对照:在所有的设计/逻辑模糊的点,将所有已知场景 分别套入 ,自己讲给自己。请注意这里是“分别套入”,在当前的设计层次下一个场景验证完再去验证下一个场景,找出阻塞的、模糊的点,重新梳理再优化设计。系统建模的结果指导我们软件设计实现,所以一定要反复梳理打通,这个反复的过程其实也是提升架构能力的过程,累积到一定程度就会自然通透。
回到开始的那个问题:
**模是什么?**通过上面业务建模和系统建模的描述,简单来讲模就是业务的映射,这个映射的结果是业务模型、概念模型或设计模型,但是所有的出发点都是业务需求:客户是谁?核心诉求是什么?
**如何建?**上面通过业务建模和系统建模两个维度,从个人实践角度大概讲了常规的套路,建模的本质其实一个抽象的过程,但是上述业务和系统建模抽象的过程其实还有两个问题并没有完全说清楚: 业务建模中“把书读薄”归类汇总,建立「大局观」,形成大图,这里按什么维度去归类?如何判断归类是正确的? 系统建模中“剥洋葱”怎么拆?按什么拆?上述架构图中的层次、领域如何划分层次?边界在哪里?
说回抽象
Haskell 语言的设计者之一 Paul Hudak 曾说过一句略带夸张的话:编程中最重要的三件事是: 抽象,抽象,抽象 。 **"abstraction, abstraction, abstraction"**are the three most important things in programming.
如果要问程序员最重要的能力有哪些,我相信抽象一定是其中最重要的之一。那到底什么是抽象?
百度百科定义: 从具体事物抽出、概括出它们共同的方面、本质属性与关系等,而将个别的、非本质的方面、属性与关系舍弃,这种思维过程,称为抽象。
如果更精炼的概括:抽象就是做减法和做除法。通过舍弃非本质和无关紧要的部分,着眼于问题的本质,去粗取精;通过透过现象看本质,发现不同事物之间的共同之处,异中求同,同类归并,也就是做除法。上文中建模过程是共性抽象,通过不断的抽象达到某个状态为止,我理解这个状态没有确定性的答案,核心就是满足业务场景的需要,其实这背后也有一个边界的问题。
1. 抽象的角度
生活中处处都是抽象,但是我们似乎少了为什么是这样或那样抽象的思考。抽象是有角度之分的。
生活中我们常常说“我的观点是…”,其实这里的“观点”就是一个角度问题,从一定的立场或角度出发,对事物或问题所持的看法。以生活中的常见的实物来说(如下图),我们是否能快速的说出其中的相同点和不同点。
如图中已经标注的,我们从功用的角度对它们定义了椅子、桌子、凳子和柜子这样的区分,但显然很有很多很多角度,比如:物料、文字、高矮等等维度,从不同维度看过去,会有完全不同的相同点和不同点表述,所以,本质是什么?本质是: 抽象角度其实也是分类的角度,角度不同,会导致完全不同建模方向和结果; 抽象的角度就是建模的方向和目的(“屁股决定脑袋”)。
重新回到我们前边的两个问题,业务建模中我们谈到了归类,按什么去归类,答案呼之欲出,按我们的业务流程去归类、按客户的角色去归类,又回到了那个最初始的问题:客户是谁?核心诉求是什么?
同时,上文中我们提到,模是业务的映射,基于对抽象的理解,我们可以进一步展开: 模是在确定抽象角度下的业务映射 。
2. 抽象的层次
Wikipedia 关于抽象的定义中有一个关于报纸的例子: 我的 5 月 18 日的《旧金山纪事报》 5 月 18 日的《旧金山纪事报》 《旧金山纪事报》 一份报纸 一个出版品
这五句话中,我们可以感受到抽象的层次,抽象层次越高,细节越少,普适性越强。再比如下图中关于网络模型的抽象,关于操作系统内核的抽象,我们可以明显的看到不同层次的抽象,就是过滤不同的信息,最终留下来的信息才是当前抽象层次所需要的信息。从系统设计实现上来说, 抽象层次越高,越接近设计,越远离实现,同时抽象的模型越不受细节的羁绊,稳定性越高,普适性越强,可重用性就越高 。
那么这里抽象的划分层次的依据是什么?原则又是什么?我的经验是, 划分抽象层次的依据 主要包含两个: 以抽象角度分层(可能一层是多角度的聚合) 面对变化分层(用层次隔离变化)
其实这个也不能完全解释如何分层,原则是什么?我觉得这是几个 最通用的原则 : 公用的往下走 个性的往上走 下层可以独立于上层存在 控制下层的变化
考虑抽象层次的好处是不论在哪一个层次上,我们只需要面对有限的复杂度,从而专心考虑这个层次上的抽象是什么,要表达的信息是什么。
3. 抽象的边界
除了角度、层次之外,我们还需要考虑的抽象的边界。如果说层次考虑的是纵向维度的表达,那么边界考虑的是横向维度的表达。如何确定边界,**一个总的原则是按照职责进行划分,这里的职责其实也就是分工。**一旦职责确定,我们在做建模分析时就不需要把整个业务大局放进来从头到尾去分析一遍,我们只需要考虑当前分工下的上游和下游即可,这样的信息量大大减少,自然的我们面对的领域复杂度也会降低到一定程度。
如果一定要给出边界的定义,我的理解是: 边界是在确定抽象角度下,通过寻找核心的业务活动,抽取核心实体,进一步确定实体核心生命周期的结果。可能有一点点绕,关键词是:核心业务活动、核心实体、核心实体生命周期。
以现场娱乐行业为例,如下这张图包含了最高抽象层次下业务的全生命周期,这个抽象层次下的主体是什么,我的理解是票,项目生产的结果是票,分销或电商服务是对票的销售,现场是对票的核验,至此以票为核心实体的生命周期结束。
如果我们往下 Down 一层,从项目生产这一个业务活动去看,整个业务流程是这样: 项目管理->场馆座位分销->票房预测->场次管理->配额管理->绘座->票房规划
从生产这个视角去看,核心的实体不是票,而是场次(确定时间、确定地点、确定内容的一场演出或赛事),所有的关键业务活动都是以场次为维度,生产领域里需要考虑的主要就是场次的核心生命周期。
所以,在不同的抽象角度、不同的抽象层次,根据分工的不同会有不同的核心业务活动、不同的核心实体、边界的确定关键在寻找核心的生命周期。寻找生命周期的过程,就是发现内聚的过程;将所有关于生命周期的业务活动累积,就可以提升领域或模块的内聚性。
4. 抽象的评估
前边我们基本说清楚了抽象的角度、层次和边界,从三个维度确定了抽象的结果。那么如何评估抽象结果的好坏呢?答案是“高内聚,低耦合”,当然还有更多的原则,但是单从实践的角度,我觉得这是最最重要的。 · 耦合是软件结构中各模块之间相互连接的一种度量; · 内聚是一个模块内部各成分之间相关联程度的度量。
“高内聚,低耦合”从内部、外部两个视角去评估抽象结果的好坏。这其中也有对应的原则和方法论,常规的套路是: 每次从一个角度来切分,然后换多个角度来审视 通过组合、拆分来精化、优化模型与设计(抽象的结果) 关键的审视点:耦合性:减少模块间通信量;内聚性:功能单一化;变化的隔离性:减少信息依赖,建隔离层、虚拟层。
5. 抽象的方法论(套路)
我想,至此,我们说清楚了前面的那两个问题: 业务建模中“把书读薄”归类汇总,建立“大局观”,形成大图,这里按什么维度去归类?如何判断归类是正确的? 系统建模中“剥洋葱”怎么拆?按什么拆?上述架构图中的层次、领域如何划分层次?边界在哪里?
总结前面说的所有关于抽象的内容,形成 抽象的方法论(套路) : 抽象有两种方法,一种是自顶向下,另一种是自底向上; 业务建模,是从小到大,从局部到整体,自底向上的归纳、演绎的抽象过程; 系统建模,是从大到小,从整体到局部,自顶向下的拆解、切分的抽象过程; 但不绝对,自上而下和自下而上,往往在过程中是随意切换的。
下面这张图来自于《Thinking in UML》,我觉得这个循环的过程可以表达上面这四个点,供大家参考。
如何画好一张架构图?
回到主题,如果上边的问题说清楚了,接下来的事情就相对简单了。对于架构图是什么这个问题,我们可以把之前的等式进行延展:**架构图 = 架构的表达 = 架构在不同抽象角度和不同抽象层次的表达,这是一个自然而然的过程。**不是先有图再有业务流程、系统设计和领域模型等,而是相反,用图来表达抽象的思考和内容。
那么架构图有什么用?给谁看?回答这个问题需要讲清楚为什么要画架构图,同时也需要考虑一个问题就是:架构图是不是越多越好,越详细越好?
1. 画架构图是为了什么?
A picture is worth a thousand words (一图胜千言),从 Why 层面讲,我觉得就是如下两点: 解决沟通障碍:达成共识、减少歧义; 提升协作效率:团队内部和团队之间的协作、沟通、愿景和指导。
但是上述两点其实是非常笼统的信息,如果放在 What 层面,我们必须要考虑架构图面对的“客户”,不同的客户有不同的诉求(其实也就是角度和层次),在不同的抽象层次架构图所表达的信息内容可以完全不一样。以目前团队做的事情为例,架构图的目标客户至少有几类: 参与项目的各团队各角色(业务、产品、开发、测试、安全、GOC) 项目之外的客户(外部客户,外部评审专家) 各层次 TL(汇报,跨 BU,跨团队协作沟通)
所以画架构图,我们必须首先明确沟通交流的目的和面向的客户,只有明确了这两个点才能更加有针对性的达成上边所说的那两点目标:解决沟通障碍,提升协作效率。
2. 怎么画?
1)先说分类
架构图分类,本质上是从不同的视角,不同的抽象角度去看,作出清晰、简化的描述,涵盖特点方面忽略无关方面。
从业务应用开发的维度,一般的抽象层次可以分为: 业务全域—>子域—>模块—>子模块—>包—>类—>方法
这其中: 较低层次的抽象:应用内部包图、类图;某个领域:实体图、时序图、状态图、用例图等等; 较高层次的抽象:具有一定的复杂性,比如微服务架构,系统间的交互图,领域/子领域架构图,整个系统架构图等等。
当然,还有很多其他的分类方式,比如:RUP 4+1,GOGAF9 等等分类方式。**单从实践的角度,我觉得何种分类不是最重要的,最重要的是想清楚面向谁和解决什么诉求,然后思考架构图到底从哪个角度、哪个层次去抽象。**我们目前所做的项目,有很时候要去和国外的业务专家、技术专家去沟通,大家也并没有一个明确的标准定义,表述清楚问题,达成共识这是最最关键的,至于架构图的粒度、类别、内容可以逐步的去完善,去粗取精,迭代优化。
2)再说构图
构图的部分,我们大家都用 UML 画过类图,涉及泛化、聚合、组合、依赖等等关系,分别用不同的虚实线、箭头样式进行表达。所以画架构图需要考虑架构图的组成元素,要保证符合一贯理解,架构图的组成元素可能涉及: 方框、各种形状、虚实线、箭头、颜色(不同颜色代表什么意思)和文字内容; 虚实线表达什么?组件类型,模块类型,层,服务,需要考虑是否已经实现等?不同状态的标识怎么传递? 箭头表达什么?数据流或关联关系? 交互类型可以是同步或异步的;关联类型可以是指依赖、继承、实现。
构图最最重要的是需要考虑内容术语一致性问题、碎片化问题、信息粒度大小的问题,以及图表的外观问题。
3. 如何评判架构图的好坏
架构图的好坏,我理解主要是两个方向,一个是需要跳出图本身去看,业务领域的抽象设计合理性,是否符合“高内聚,低耦合”的要求,这个需要回到前文的业务建模、系统建模和抽象过程去寻找答案。另外一个方向是图本身,以下几个点供参考: 内容术语一致、信息粒度大小一致,图例清晰,颜色类型统一,美观; 图中的信息与相应的抽象级别相关,且满足利益相关者(合作方)的需求; 一张好的架构图不需要多余的文字解释!受众有没有准确接收到想传递的信息;如果它所导致的疑问比它能解释的问题还要多,那么它就不是一张好的架构图; 架构图应该帮助每个人看到大局,了解周围的环境,适当的上下文信息; 架构图应该避免“只见树木,不见森林”。
但是,终归还是那句话, “一张图片胜过千言万语”。不管好坏,不管是否美观,人是视觉动物,用图表达可以极大的提升沟通效率,先画起来吧!
最后也聊聊架构师
这是来自于阿白老师的文章《架构师到底是做什么的?》,越是琢磨,越觉得深以为然。其中提到了好的架构师的画像和不好的画像,如下图,与大家共勉。
从我个人的成长经历看,**架构师很重要的一点要学会“权衡”,既要兼顾当下痛点也要符合未来一定时间的发展,既要保留未来的可扩展性也要避免过度设计。选择什么样的时间节点、什么样的业务场景以及什么样的架构迭代策略至关重要,这些决策的关键在于判断和取舍,需要结合深刻的业务思考乃至组织架构去做权衡落地。**一点点不算经验的经验:
1. 快速学习
快不是一个速度问题,也是一个判断或者标准问题。面对一个全新业务场景,如何能够识别20%的关键业务路径,关键业务痛点,如何短时间把自己变成业务专家这是一个架构师基本的素质。我的一点经验就是要去「吸金式」的思考,带着问题主动思考,客户是谁?有什么诉求?需要解决什么样的问题?我们能提供什么样的价值?多问为什么?这也需要长时间的刻意训练。
2. 不要屁股决定脑袋
要跨角色、跨层级去看待业务问题,这个点容易陷入说教,说实话我自己做得也未必到位。但是时刻提醒自己的思考是否被局限,在哪一个维度,是 Have-do-be,还是 be-do-Have 等等;同时也不断的在提醒自己永远不要屁股决定脑袋。
3. 提升思考能力和对于技术原理或本质的理解
我觉得这是最底层的能力,业务开发中我觉得最大的两个难点:一是逻辑的复杂性,二是需求的变化性。我们不应该大部分时间花在寻找解决方案上,而应该花更多的时间在选择解决方案上。这就要求我们对业务全局、行业深度、技术视野、技术深度、业务共性、个性特征等等形成自己的认知。权衡取舍,取什么舍什么?该怎么取怎么舍?那个度在哪里?唯有思考,自驱,累积和坚持,勇猛精进,志愿无倦。
最后的最后
希望这篇文章对大家有帮助,附上最初在考虑这个主题时的构思过程及思考路径,供大家参考。
参考文档: 为什么我们需要架构图( https://new.qq.com/omn/20190131/20190131A16MWK.html ) 软件架构图的艺术 ( https://www.infoq.cn/article/crafting-architectural-diagrams ) 逻辑架构和物理架构 ( https://www.cnblogs.com/dinglang/p/4565378.html ) 一篇文章读懂分层架构 ( https://zhuanlan.zhihu.com/p/40353581 ) TOGAF & RUP( https://www.ibm.com/developerworks/cn/rational/rationaledge/content/feb07/temnenco/index.html ) 如何自底向上推导应用逻辑架构?+如何自顶向下构建架构?(节选)( https://developer.aliyun.com/article/727436 ) 《大象:Thinking in UML》 《聊聊架构》
关注“阿里巴巴云原生”公众号,回复“架构”即可查看清晰知识大图!
课程推荐
为了更多开发者能够享受到 Serverless 带来的红利,这一次,我们集结了 10+ 位阿里巴巴 Serverless 领域技术专家,打造出最适合开发者入门的 Serverless 公开课,让你即学即用,轻松拥抱云计算的新范式——Serverless。
点击即可免费观看课程: https://developer.aliyun.com/learning/roadmap/serverless “ 阿里巴巴云原生 关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”
云计算
2020-06-16 13:26:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
作者 | 子白(阿里云开发工程师)、溪恒(阿里云技术专家)
<关注阿里巴巴云原生公众号,回复 排查 即可下载电子书>
《深入浅出 Kubernetes》一书共汇集 12 篇技术文章,帮助你一次搞懂 6 个核心原理,吃透基础理论,一次学会 6 个典型问题的华丽操作!
Kubernetes 集群中,业务通常采用 Deployment + LoadBalancer 类型 Service 的方式对外提供服务,其典型部署架构如图 1 所示。这种架构部署和运维都十分简单方便,但是在应用更新或者升级时可能会存在服务中断,引发线上问题。今天我们来详细分析下这种架构为何在更新应用时会发生服务中断以及如何避免服务中断。
图1 业务部署图
为何会发生服务中断
Deployment 滚动更新时会先创建新 pod,等待新 pod running 后再删除旧 pod。
新建 Pod
图 2 服务中断示意图
中断原因 :Pod running 后被加入到 Endpoint 后端,容器服务监控到 Endpoint 变更后将 Node 加入到 SLB 后端。此时请求从 SLB 转发到 Pod 中,但是 Pod 业务代码还未初始化完毕,无法处理请求,导致服务中断,如图 2 所示。 解决方法 :为 pod 配置就绪检测,等待业务代码初始化完毕后后再将 node 加入到 SLB 后端。
删除 Pod
在删除旧 pod 过程中需要对多个对象(如 Endpoint、ipvs/iptables、SLB)进行状态同步,并且这些同步操作是异步执行的,整体同步流程如图 3 所示。
图 3 Deployment 更新时序图
Pod pod 状态变更:将 Pod 设置为 Terminating 状态,并从所有 Service 的 Endpoints 列表中删除。此时,Pod 停止获得新的流量,但在 Pod 中运行的容器不会受到影响; 执行 preStop Hook:Pod 删除时会触发 preStop Hook,preStop Hook 支持 bash 脚本、TCP 或 HTTP 请求; 发送 SIGTERM 信号:向 Pod 中的容器发送 SIGTERM 信号; 等待指定的时间:terminationGracePeriodSeconds 字段用于控制等待时间,默认值为 30 秒。该步骤与 preStop Hook 同时执行,因此 terminationGracePeriodSeconds 需要大于 preStop 的时间,否则会出现 preStop 未执行完毕,pod 就被 kill 的情况; 发送 SIGKILL 信号:等待指定时间后,向 pod 中的容器发送 SIGKILL 信号,删除 pod。
中断原因 :上述 1、2、3、4步骤同时进行,因此有可能存在 Pod 收到 SIGTERM 信号并且停止工作后,还未从 Endpoints 中移除的情况。此时,请求从 slb 转发到 pod 中,而 Pod 已经停止工作,因此会出现服务中断,如图 4 所示。
图 4 服务中断示意图
解决方法 :为 pod 配置 preStop Hook,使 Pod 收到 SIGTERM 时 sleep 一段时间而不是立刻停止工作,从而确保从 SLB 转发的流量还可以继续被 Pod 处理。
iptables/ipvs
中断原因 :当 pod 变为 termintaing 状态时,会从所有 service 的 endpoint 中移除该 pod。kube-proxy 会清理对应的 iptables/ipvs 条目。而容器服务 watch 到 endpoint 变化后,会调用 slb openapi 移除后端,此操作会耗费几秒。由于这两个操作是同时进行,因此有可能存在节点上的 iptables/ipvs 条目已经被清理,但是节点还未从 slb 移除的情况。此时,流量从 slb 流入,而节点上已经没有对应的 iptables/ipvs 规则导致服务中断,如图 5 所示。
图 5 服务中断示意图
解决方法 : Cluster 模式:Cluster 模式下 kube-proxy 会把所有业务 Pod 写入 Node 的 iptables/ipvs 中,如果当前 Node 没有业务 pod,则该请求会被转发给其他 Node,因此不会存在服务中断,如 6 所示;
图 6 Cluster 模式请求转发示意图 Local 模式:Local 模式下,kube-proxy 仅会把 Node 上的 pod 写入 iptables/ipvs。当 Node 上只有一个 pod 且状态变为 terminating 时,iptables/ipvs 会将该 pod 记录移除。此时请求转发到这个 node 时,无对应的 iptables/ipvs 记录,导致请求失败。这个问题可以通过原地升级来避免,即保证更新过程中 Node 上至少有一个 Running Pod。原地升级可以保障 Node 的 iptables/ipvs 中总会有一条业务 pod 记录,因此不会产生服务中断,如图 7 所示;
图 7 Local 模式原地升级时请求转发示意图 ENI 模式 Service:ENI 模式绕过 kube-proxy,将 Pod 直接挂载到 SLB 后端,因此不存在因为 iptables/ipvs 导致的服务中断。
图 8  ENI 模式请求转发示意图
SLB
图 9  服务中断示意图
中断原因 :容器服务监控到 Endpoints 变化后,会将 Node 从 slb 后端移除。当节点从 slb 后端移除后,SLB 对于继续发往该节点的长连接会直接断开,导致服务中断。 解决方法 :为 SLB 设置长链接优雅中断(依赖具体云厂商)。
如何避免服务中断
避免服务中断可以从 Pod 和 Service 两类资源入手,接下来将针对上述中断原因介绍相应的配置方法。
Pod 配置 apiVersion: v1 kind: Pod metadata: name: nginx namespace: default spec: containers: - name: nginx image: nginx # 存活检测 livenessProbe: failureThreshold: 3 initialDelaySeconds: 30 periodSeconds: 30 successThreshold: 1 tcpSocket: port: 5084 timeoutSeconds: 1 # 就绪检测 readinessProbe: failureThreshold: 3 initialDelaySeconds: 30 periodSeconds: 30 successThreshold: 1 tcpSocket: port: 5084 timeoutSeconds: 1 # 优雅退出 lifecycle: preStop: exec: command: - sleep - 30 terminationGracePeriodSeconds: 60
注意:需要合理设置就绪检测(readinessProbe)的探测频率、延时时间、不健康阈值等数据,部分应用启动时间本身较长,如果设置的时间过短,会导致 POD 反复重启。 livenessProbe 为存活检测,如果失败次数到达阈值(failureThreshold)后,pod 会重启,具体配置见 官方文档 ; readinessProbe 为就绪检查,只有就绪检查通过后,pod 才会被加入到 Endpoint 中。容器服务监控到 Endpoint 变化后才会将 node 挂载到 slb 后端; preStop 时间建议设置为业务处理完所有剩余请求所需的时间,terminationGracePeriodSeconds 时间建议设置为 preStop 的时间再加 30 秒以上。
Service 配置
Cluster 模式(externalTrafficPolicy: Cluster) apiVersion: v1 kind: Service metadata: name: nginx namespace: default spec: externalTrafficPolicy: Cluster ports: - port: 80 protocol: TCP targetPort: 80 selector: run: nginx type: LoadBalancer
容器服务会将集群中 所有节点 挂载到 SLB 的后端(使用 BackendLabel 标签配置后端的除外),因此会快速消耗 SLB quota。SLB 限制了每个 ECS 上能够挂载的 SLB 的个数,默认值为 50,当 quota 消耗完后会导致无法创建新的监听及 SLB。
Cluster 模式下,如果当前节点没有业务 pod 会将请求转发给其他 Node。在跨节点转发时需要做 NAT,因此会丢失源 IP。
Local 模式(externalTrafficPolicy: Local) apiVersion: v1 kind: Service metadata: name: nginx namespace: default spec: externalTrafficPolicy: Local ports: - port: 80 protocol: TCP targetPort: 80 selector: run: nginx type: LoadBalancer # 需要尽可能的让每个节点在更新的过程中有至少一个的Running的Pod # 通过修改UpdateStrategy和利用nodeAffinity尽可能的保证在原地rolling update # * UpdateStrategy可以设置Max Unavailable为0,保证有新的Pod启动后才停止之前的pod # * 先对固定的几个节点打上label用来调度 # * 使用nodeAffinity+和超过相关node数量的replicas数量保证尽可能在原地建新的Pod # 例如: apiVersion: apps/v1 kind: Deployment ...... strategy: rollingUpdate: maxSurge: 50% maxUnavailable: 0% type: RollingUpdate ...... affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: deploy operator: In values: - nginx
容器服务默认会将  Service 对应的 Pod 所在的节点 加入到 SLB 后端,因此 SLB quota 消耗较慢。Local 模式下请求直接转发到 pod 所在 node,不存在跨节点转发,因此可以保留源 IP 地址。Local 模式下可以通过原地升级的方式避免服务中断,yaml 文件如上。
ENI 模式(阿里云特有模式) apiVersion: v1 kind: Service metadata: annotations: service.beta.kubernetes.io/backend-type: "eni" name: nginx spec: ports: - name: http port: 30080 protocol: TCP targetPort: 80 selector: app: nginx type: LoadBalancer
Terway 网络模式下,通过设置 service.beta.kubernetes.io/backend-type: "eni" annotation 可以创建 ENI 模式的 SLB。ENI 模式下, pod 会直接挂载到 SLB 后端,不经过 kube-proxy,因此不存在服务中断的问题。请求直接转发到 pod,因此可以保留源 IP 地址。
三种 svc 模式对比如下表所示。
图 10 Service 对比
结论
Terway 网络模式 (推荐方式)
选用 ENI 模式的 svc + 设定 Pod 优雅终止 + 就绪检测。
Flannel 网络模式   如果集群中 slb 数量不多且不需要保留源 ip:选用 cluster 模式 + 设定 Pod 优雅终止 + 就绪检测; 如果集群中 slb 数量较多或需要保留源 ip:选用 local 模式 + 设定 Pod 优雅终止 + 就绪检测 + 原地升级(保证更新过程中每个节点上至少有一个 Running Pod)。
Reference 容器生命周期钩子 Configure Liveness, Readiness and Startup Probes 通过负载均衡访问服务 Kubernetes 最佳实践:优雅的中止 Kubernetes 社区相关讨论 : Create ability to do zero downtime deployments when using externalTrafficPolicy: Local , Graceful Termination for External Traffic Policy Local 容器服务 kubernetes(ACK)中应用优雅上下线
课程推荐
为了更多开发者能够享受到 Serverless 带来的红利,这一次,我们集结了 10+ 位阿里巴巴 Serverless 领域技术专家,打造出最适合开发者入门的 Serverless 公开课,让你即学即用,轻松拥抱云计算的新范式——Serverless。
点击即可免费观看课程: https://developer.aliyun.com/learning/roadmap/serverless “ 阿里巴巴云原生 关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”
云计算
2020-06-03 13:25:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
作者 | 张磊,阿里云高级技术专家、CNCF 官方大使,CNCF 应用交付领域 co-chair,Kubernetes 项目资深维护者
最近,Kubernetes 社区里有一个关于“Kubernetes is the new database”的论述,引起了很多人的关注。当然,这个论述更确切的含义,指的是 Kubernetes 项目本身的工作原理类似于数据库 ,而不是说你应该把 Kubernetes 当数据库用。
粗看起来,这个 “Kubernetes 是一个数据库” 的论述还是比较匪夷所思的。毕竟我们平常所说的 Kubernetes 的工作原理,比如控制器模式、声明式 API 等等,好像跟“数据库”这个东西并没有什么直接关系。但实际上,这个论述背后却有着其非常本质的含义。这里的缘由,得从 Kubernetes 项目里一个最基础的理论谈起。
Kubernetes 声明式应用管理理论基础
在我们讨论 Kubernetes 的时候,往往会提到这样一个概念,叫做“声明式应用管理”。实际上,这也是 Kubernetes 项目跟其他所有基础设施项目都不一样的一个设计,是 Kubernetes 所独有的一个能力,那么,你有没有思考过,声明式应用管理在 Kubernetes 中具体的表现到底是什么呢?
1. 声明式应用管理不仅仅是“声明式风格的 API”
如果我们回顾一下 Kubernetes 的核心工作原理,我们其实就不难发现这样一个事实:Kubernetes 里面的绝大多数功能,无论是 kubelet 执行容器、kube-proxy 执行 iptables 规则,还是 kube-scheduler 进行 Pod 调度,以及 Deployment 管理 ReplicaSet 的过程等等,其实从总体设计上都是在遵循着我们经常强调过的“控制器”模式来进行的。即:用户通过 YAML 文件等方式来表达他所想要的期望状态也就是终态(无论是网络、还是存储),然后 Kubernetes 的各种组件就会让整个集群的状态跟用户声明的终态逼近,最终达成两者的完全一致。这个实际状态逐渐向期望状态逼近的过程,就叫做 reconcile(调谐)。而同样的原理,也正是 Operator 和自定义 Controller 的核心工作方式。
这种通过声明式描述文件,以驱动控制器执行 reconcile 逼近两个状态的工作形态,正是声明式应用管理最直观的体现。需要注意的是,这个过程其实包括了两层含义: **声明式描述的期望状态。**这个描述必须是严格意义上使用者想要的最终状态,如果你在这个描述里面填写的是某个中间状态,或者你希望动态的调整这个期望状态,都会破坏这个声明式语义的准确执行; **基于 reconcile 的状态逼近过程。**Reconcile 过程的存在,确保了系统状态与终态保持一致的理论正确性。 确切地说,Reconcile 过程不停的执行“检查 -> Diff -> 执行”的循环,才使得系统能够始终对系统本身状态与终态直接的差异并能够采取必要的行动。而相比之下,仅仅拥有声明式的描述是不充分的。这个道理很容易理解,你第一次提交这个描述时系统达成了你想要的期望状态,并不能代表、也不能保证一个小时后的情况也是如此。很多人会搞混“声明式应用管理”和“声明式风格的 API” ,其实就是对 Reconcile 必要性没有正确的认识。
你也许会比较好奇,采用这种声明式应用管理体系,对于 Kubernetes 来说有什么好处呢?
2. 声明式应用管理的本质:Infrastructure as Data
实际上,声明式应用管理体系背后的理论基础, 是一种叫做 Infrastructure as Data (IaD)的思想 。这种思想认为,基础设施的管理不应该耦合于某种编程语言或者配置方式,而应该是纯粹的、格式化的、系统可读的数据,并且这些数据能够完整的表征使用者所期望的系统状态。
注:Infrastructure as Data  有时也被称作 Configuration as Data,背后的意思是一样的。
而这样做的好处就在于,任何时候我想对基础设施做操作,最终都等价于对这些数据的“增、删、改、查”。而更重要的是,我对这些数据进行“增、删、改、查”的方式,与这个基础设施本身是没有任何关系的。所以说,我跟一个基础设施交互的过程,不会被绑定在某种编程语言、某种远程调用协议、或者某种 SDK 上。只要我能够生成对应格式的“数据”,我就能够“天马行空”地使用任何我喜欢的方式来完成对基础设施的操作。
这种好处具体体现在 Kubernetes 上,就是如果我想在 Kubernetes 上做任何操作,我只需要提交一个 YAML 文件,然后对这个 YAML 文件进行增删改查即可。而不是必须使用 Kubernetes 项目的 Restful API 或者 SDK 。 这个 YAML 文件里的内容,其实就是 Kubernetes 这个 IaD 系统对应的 Data(数据)。
所以说,Kubernetes 从诞生起就把它的所有功能都定义成了所谓的“API 对象”,其实就是定义成了一份一份的 Data。这样,Kubernetes 使用者就可以通过对这些 Data 进行增删改查来达成自己想要的目标,而不是被绑定在某种具体的语言或者 SDK 上。更重要的是,相比于专有的、命令式的 API 或者 SDK,以 YAML 为载体的声明式数据能够更简单的完成对底层实现的屏蔽,从而更容易对接和集成现有的基础设施能力,这其实也是 Kubernetes 生态能够以惊人的速度蓬勃发展到今天的一个秘密武器:IaD 思想带来的声明式 API 与控制器模式,让整个社区更愿意为 Kubernetes 编写插件和对接各种能力,并且这些插件和能力的通用性和可移植性也非常高,这是其它项目比如 Mesos 和 OpenStack 所望尘莫及的。可以说,IaD 正是 Kubernetes 能够达成 “The Platform for Platform” 这个目标的核心战斗力所在。
说到这里,大家估计也就明白了:这种 IaD 设计中的 Data 具体表现出来,其实就是声明式的 Kubernetes API 对象;而 Kubernetes 中的控制循环,则是确保系统本身能够始终跟这些 Data 所描述的状态永远保持一致。 从这一点上来说,Kubernetes 本质上其实是一个以数据(Data)来表达系统的设定值、通过控制器(Controller)的动作来让系统维持在设定值的调谐系统。
等一下,这个“让系统维持在设定值”的理论,听起来好像有点耳熟?
实际上,Kubernetes 背后的这门基础课,可能绝大多数工科背景的读者都是学过的,它叫做《控制理论》。
是不是感觉豁然开朗了呢?
在明白了 Kubernetes 的这个本质之后,我们回过头来再看原本一些比较难以理解的设定,可能会更容易体会到一些本质的东西。
比如,今天我们在使用 Kubernetes 的时候之所以要写那么多 YAML 文件,其实是因为我们需要通过一种方式把 Data 提交给 Kubernetes 这个控制系统。而在这个过程中,YAML 只是一种为了让人类能够格式化的编写 Data 的一个载体。如果做一个类比,那么 YAML 就像我们小时候作业本里的“田字格”,而“田字格”里写的那些文字,才是 Kubernetes 真正关心的 Data 和整个系统运转的核心。
细心的读者此时应该已经想到了,既然 Kubernetes 需要处理这些 Data,那么 Data 本身不是也应该有一个固定的“格式”这样 Kubernetes 才能解析它们呢?没错,这里的格式在 Kubernetes 中就叫做 API 对象的 Schema。如果你经常编写自定义 Controller 的话,可能就会对这个 Schema 的体感比较深刻:CRD 就是一个专门用来定义 Schema 的一个特殊的 API 对象。
YAML 工程师?不,你是数据库工程师!
**上述 Kubernetes 的 IaD 的本质,决定了它的工作原理其实更类似一个“数据库”,而不像传统意义上的分布式系统。**这个差异,也是导致 Kubernetes 学习成本比较陡峭的一个根本性原因。
而从这个角度来讲,Kubernetes 为你暴露出来的各种 API 对象,实际上就是一张张预先定义好 Schema 的表(Table)。而我们绞尽脑汁编写出的那些 YAML 文件,其实就是对这些表中的数据(Data)进行的增删改查(CURD)。而 YAML 这个工具本身,则好比 SQL 一样是一个帮助你对数据库中的数据进行操作的工具和载体。而唯一跟传统数据库不太一样的是,Kubernetes 在拿到这些数据之后,并不以把这些数据持久化起来为目的,而是希望通过这些数据来驱动 Controller 执行某些操作,从而将整个系统的状态逐步调整为跟数据中声明的终态一致,这就回到我们前面所说的“控制理论”部分了。
也正是由于  Kubernetes 这样整套体系都围绕着“数据”这个一等公民运转的设定,才使得“编写和操作 YAML文件”成为了 Kubernetes 工程师的几乎唯一的日常工作。不过,在理解了本文今天介绍的 IaD 的思想之后,你其实大可以把自己比作一个“数据库工程师”了,而且这个 TItle 确实要比“YAML 工程师”更加贴切一些。
Kubernetes 项目的“视图层”
正如前文所述,如果你从一个“数据库”的角度重新审视 Kubernetes 设计的话,就不难发现 Kubernetes 的很多设计背后其实有着非常精妙的思想。比如: 数据模型 -  Kubernetes 的各种 API 对象与 CRD 机制 数据拦截校验和修改机制 - Kubernetes Admission Hook 数据驱动机制 - Kubernetes Controller/Operator 数据监听变更与索引机制 - Kubernetes 的 Informer 机制 ……
另外一方面,随着 Kubernetes 基础设施越来越复杂,第三方插件与能力越来越多,社区的维护者们也发现 Kubernetes 这个“数据库”内置的“数据表”无论从规模还是复杂度上,都正在迎来爆炸式的增长。所以  Kubernetes 社区很早就在讨论如何给 Kubernetes  设计出一个“数据视图(View)”出来,即:
而这样一个构建在 Kubernetes 内置 API 资源之上的“视图层”给 Kubernetes 使用者带来的好处,跟数据库中的“视图”是非常类似的,比如: 简化和更改数据格式和表示
Kubernetes 的视图层,需要能够给研发和运维暴露更简洁的、经过抽象后的应用层 API 对象,而不是原始的基础设施层 API 对象。而一个视图层对象具体如何定义,自由度应该完全在用户手中,不需要拘束在底层 Kubernetes 内置对象的 Schema 上。 简化复杂的数据操作(简化 SQL )
经过抽象后产生的视图层对象,不仅在 UI 上需要更加简单,还需要可以定义和管理非常复杂的底层 Kubernetes 资源拓扑,从而降低用户管理 Kubernetes 应用的复杂度和心智负担。 保护底层数据表
研发和运维直接操作的是视图层对象,所以底层的 Kubernetes 原始对象是被保护起来的。这使得这些 Kubernetes 的原始对象可以在用户无感的情况下进行任意变更和升级。 复用数据操作(复用 SQL)
由于视图层对象与底层基础设施是完全解耦的,所以一个通过视图层声明的应用或者运维能力可以在任意 Kubernetes 集群漂移,而不必担心这些集群支持的能力是不是有差异。 视图依然是表,支持标准的表操作
Kubernetes 的视图层对象必须依然是标准的 Kubernetes 对象,这样 Kubernetes 对 API 对象的所有操作和原语对,才会对视图层对象适用。我们不能在 Kubernetes API 模型上引入额外的心智负担。
给 Kubernetes 设置视图层的想法虽然最终没有在 Kubernetes 上游落地,但是却成为了社区中大多数大规模玩家的主流做法。比如 Pinterest 就在 Kubernetes 之上设计了一个 PInterestService 的 CRD 来描述和定义 Pinterest 的应用,这个 CRD 其实就是一个视图层对象。但这个做法对于绝大多数企业来说,还是太过简陋了。要知道,数据的“视图”并不只是数据的简单抽象和翻译,在真正的生产环境中要大规模使用视图层,至少需要解决几个关键问题: 如何定义和管理视图层对象与底层 K8s 对象之间的映射关系?注意这里绝不是简单的一对一映射,一个视图层对象可能会对应多个 K8s 对象。 如何对“运维能力”进行建模和抽象?一个真正的应用,绝不只是简单的 Deployment 或者 Operator,它一定是待运行程序与相应的运维能力的有机组合(比如一个容器化应用和它的水平扩展策略)。这些运维能力如何通过在应用定义里体现出来?全定义成 annotation 可行吗? 如何管理运维能力同待运行程序之间的绑定关系?如何将这个绑定关系映射成底层 K8s 当中真正的执行关系? 如何通过视图层对象标准化的定义云资源,比如一个阿里云的 RDS 实例? ……
上述这些问题,正是 Kubernetes 上游最终没能将“视图层”落地的重要原因之一,同时也是诸如  Open Application Model (OAM) 这样的 Kubernetes 应用层开源项目主要的关注点。需要指出的是,仅靠一个 OAM 这样一个“规范”是依然不足以解决上述所有问题的,Kubernetes 视图层的建立,必须借助标准的视图层依赖库在实现层予以保证,才能真正在 Kubernetes 中享受到“数据视图”带来的优势和便捷。目前社区中比较强大的 Kubernetes 视图层依赖库,是来自 Crossplane 团队的 oam-kubernetes-runtime : https://github.com/crossplane/oam-kubernetes-runtime 。
总结
Kubernetes 这个以 IaD 为核心的、类似“数据库”设计,正是这个社区繁荣发展背后的重要理论基础。然而,IaD 的思想本身也是一把双刃剑,它催生出来的蓬勃发展的社区的另一面,是无数个“各自为政”的 Controller/Operator,以及一个通过这些 Controller 拼装出来的、复杂度极高的 Kubernetes 集群。这样的一个生产级别复杂度的 Kubernetes 集群,距离一个真正受研发和运维喜爱的云原生应用管理平台,差距可谓十万八千里。
在过去的 5 年里,Kubernetes 项目的巨大成功,实际上是基础设施能力(比如网络、存储、容器)在声明式 API 下逐步标准化和统一化的一个过程,而随着 OAM 等 Kubernetes 应用层技术的逐步普及,我们已经看见一个标准化应用层生态正在付出水面。越来越多的团队正在尝试通过更加用户友好的数据视图层,对最终用户暴露出喜闻乐见的 API,同时对基础设施工程师提供出更加强大的横向连通与模块化的平台能力。
与此同时,Kubernetes 这个“数据库”其他欠缺的部分,也一定会越来越多的在社区涌现出来。比如今天正在迅速成熟的 Open Policy Agent(OPA)项目,可以认为是“数据拦截校验和修改机制”这一层的不断进化结果。再比如阿里巴巴内部在“万节点”集群中推进的管控链路性能调优工作,其理论基础和实践,跟今天的数据库性能优化,更是有异曲同工之妙的。
如果你有任何关于 IaD 系统想法,非常欢迎钉钉扫码加群同我们交流!
活动推荐
美国时间 2020 年 5 月 27 日,知名复杂环境应用交付与基础设施管理项目 Crossplane 将联合 Open Application Model (OAM)社区共同举办 Crossplane Community Day。
谷歌公司 Kubernetes 项目首席布道师 Kelsey Hightower 、阿里云资深技术专家、CNCF TOC 李响 与微软杰出工程师、Kubernetes 联合创始人 **Brendan Burns **将共同出席并做关于标准化定义应用与基础设施的重要主题演讲。
在本次 Crossplane Community Day 上,你将了解到 OAM 社区同 Crossplane 项目正在展开的深度技术合作,以及世界各地的平台构建者如何通过 OAM 和 Crossplane 来配置和管理面向复杂环境的应用程序、基础架构与云服务。
在阿里巴巴云原生公众号后台回复复关键字  crossplane ,或 点击链接 直接获得线上峰会参与方式。
招人啦!
云原生应用平台团队诚邀 Kubernetes/Serverless/ PaaS /应用交付 领域专家( P7-P8 )加盟,一起参与到 OAM 建设中: 工作年限:建议 P7 三年起,P8 五年起,具体看实际能力; 工作地点:国内:北京,杭州,深圳; 岗位包含:架构师、技术专家、全栈工程师等。
简历立刻回复,2~3 周出结果,简历投递:jianbo.sjb AT alibaba-inc.com “ 阿里巴巴云原生 关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”
云计算
2020-05-21 17:28:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
本文来自 Rancher Labs
在 之前关于CI/CD的文章 中,我们简单讨论了蓝绿部署和金丝雀发布以及它们在持续交付中所扮演的角色。这些都是十分有效的方法,能够大大降低与应用程序部署相关的风险。所以,这篇文章我们来深入介绍蓝绿部署和金丝雀发布。
蓝绿部署和金丝雀发布通过让IT人员可以在发布过程中发生问题时能够还原到先前版本来减轻应用程序部署的风险。这两个方法让版本之间来回切换就像轻按开关一样容易,并且可以自动执行,从而最大程度减少了用户暴露在错误代码的时间。在我们更进一步讨论这两种方法之前,让我们先区分部署和发布。
如何将部署与发布解耦
虽然这两个词经常混淆使用,但实际上部署和发布是两个独立的过程。部署是指在特定环境(包括生产环境)安装指定软件版本的过程,更多是一种技术行为。它不一定必须与发布相关联。而发布则是指向客户群提供新功能,是一种业务决策。
传统过程中,会在发布日期前一天部署好更新或是新功能,该更新或功能发布后可能会在媒体中广泛传播。众所周知,在部署过程中可能会出错,而因为发布时间与部署时间十分相近,因此几乎没有解决问题的空间。而如果将部署和发布解耦,那么在整个功能开发过程中频繁进行生产部署可以降低IT部门的风险。那么,要实现部署和发布的解耦,需要代码和架构能够满足新功能发布不需要变更应用程序的代码。
什么是蓝绿部署
在蓝绿发布过程中,有两套生产环境:蓝环境和绿环境。蓝色是当前版本并拥有实时流量,绿色是包含更新代码的环境。无论任何时候,只有一套环境有实时流量。
要发布一个新版本,需要先将代码部署到没有流量的环境中,这是执行最终测试的地方。当IT人员确认应用程序已经准备就绪,就会将所有流量都将路由到绿色环境。那么绿色环境就已经生效,并且执行发布。
这是新代码首次在生产负载(实际流量)进行测试。在实际发布代码之前,风险仍然存在,并且永远不会消失。但是,如果出现问题,IT部门可以快速将流量重新路由回蓝色版本。因此,他们所要做的就是密切监控代码行为,甚至可以使用适当的工具将其自动化,以查看绿色环境中的版本是否运行良好或是否需要回滚。
蓝绿部署:无论何时,只有一套生产环境有实时流量
这种方法已经不是新方法了。IT部门总会创建一个新版本,然后将实时流量重新路由到该版本。而版本控制中通过组件编码提供可靠性和可重复性是这一方法的亮点。
我们应该如何获得可靠性和可重复性?开发人员将所有参数编入版本控制中,该版本控制是一个跟踪所有代码更改的系统,类似于数据库。其中包括应用程序逻辑、构建过程、测试、部署过程、升级过程以及恢复过程等。总之,包含所有影响应用程序的因素。然后,计算机执行代码,在相应的环境中部署应用程序,该环境与版本控制中编码的exact state相匹配。
在DevOps出现之前,该流程通常是手动的,并且容易出错。因为所有更改都只能记录在文档中,基于此,开发人员可以重新创建应用程序和环境。由于需要手动执行两个关键步骤,因此此过程过于不可靠,从而导致频繁出现问题。
虽然将应用程序和环境进行编码也是一项需要手动进行的任务,但是它毕竟只是开发过程的一部分,而不是单独的工作,例如创建文档。在版本控制中编入了与生产环境相同的代码。任何更改或更新都将自动触发测试,以确保代码处于可部署状态。这样,如果出现人为错误,系统也能够很快发现它。
如何理解金丝雀发布(灰度发布)
与蓝绿部署类似,金丝雀发布也是始于两套环境:有实时流量的环境以及没有实时流量但包含了更新的代码的环境。与蓝绿部署不同的是,流量是逐渐迁移到更新的代码。一开始是1%,然后10%、25%,以此类推,直至100%。通过自动化发布,当确认代码能够正确运行时,它就可以逐步推广到更大、更关键的环境中。如果在任何时候发生了问题,所有流量都会被回滚到之前的版本。这在很大程度上降低了风险,因为仅有一小部分用户会使用到新的代码。
IT不仅可以控制用户部署的比例,而且金丝雀发布还可以从不太重要的用户开始,例如使用免费账户的用户或相对来说不太重要的业务市场。
金丝雀发布:实时流量逐渐从旧版本迁移到新版本直到更新生效
Cluster Immune System
Cluster Immune System可以让金丝雀发布更进一步。它会连接到生产监控系统,当面向用户的性能偏离预定义范围(例如,错误率高出2%)时,将会自动回滚版本。这种方法可以识别通过自动测试难以发现的错误,并减少了检测和响应性能下降所需的时间。
通过将发布与部署解耦并利用蓝绿部署或金丝雀发布,风险将会显著降低。在任何时候,IT都能够将应用程序回滚到之前的版本——这已经与传统的应用程序发布流程相去甚远了。
新的技术和方法首次让这一切成为可能:版本控制、作为代码的基础架构(Infrastructure as code)、容器和Kubernetes都能在这个崭新的、灵活的、面向DevOps的IT世界中发挥着作用。
云计算
2020-04-23 20:37:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
本文来自 Rancher Labs
持续集成和持续交付(CI/CD)是DevOps背后的助推力之一。如果你的企业正在考虑使用DevOps,那么CI/CD绝对是需要考虑的其中一部分。但是CI/CD到底意味着什么?为什么它如此重要呢?为了对你的DevOps工具包和IT部署进行战略规划,深入理解CI/CD至关重要。本文中,我们将探讨CI/CD所需解决的难点、需要的工具以及预期的收益。
首先,我们从大局着手。DevOps旨在创建一个流畅的工作流程,并尽可能减少越区切换和建立快速反馈回路。这意味着什么呢?工作会从第一步开始一直向前推进,并且在理想状态中,无需倒退再进行修复,因为它们应该能够验证和修复问题。为此,开发人员需要快速的反馈回路。该反馈通过快速自动化测试提供,并且该测试将验证代码在进入下一阶段之前能否按照预期工作。
为了减少越区切换,成员较少的小组将使用较小的功能并且掌控整个流程:创建请求、提交、QA以及部署。其重点是快速推出小段代码,因为变更越小,诊断、修复和补救就越容易。
持续集成(CI)实现了从第一步到最后一步的快速流程,并通过持续交付(CD)将其扩展到实际生产部署。我们将其称为CI/CD。现在,我们开始深入了解它们。
深入探索持续集成
首先,我们关注CI/CD的CI(持续集成)部分。实际上,大部分公司仅执行了CI。而完成整个CI/CD,需要该企业已经是一个成熟的DevOps企业。
说到集成,我们指的是程序员在其本地计算机上开发的代码(包括更新或添加新特性)集成到代码库中。这一过程会面临以下3个挑战: 跟踪所有变更,以便在发生错误时仍然可以恢复到之前的状态,以最大程度地避免服务中断。 当多个开发人员同时在同一个项目中工作时需要管理冲突 将新代码添加到代码库之前需要捕捉到错误
接下来,我们将讨论可以解决以上几个痛点的3个工具。
1、 版本控制
随着代码从开发人员转移到运维人员,它会根据测试结果不断进行调整。所有的更改都会被版本控制系统捕捉。版本控制是一个软件工具可以帮助开发者管理源代码更改。在特殊类型的数据库中它会一直跟踪所有更改。
理想状态下,软件系统的所有部分都会被捕获到,包括: 源代码 资产 环境 软件开发文档 对系统中存储的文件的任何更改
2、master和开发分支
通常情况下,在同一个项目中会有多个开发人员一起工作,可能是几个人也可能是上百个程序员,因此这可能会导致混乱。为了不让稳定性遭受破坏或减轻在版本控制主分支中引入错误的风险,每个开发人员应该并行处理系统的不同部分。他们通过本地计算机上的“分支机构(branch)”执行这一操作。
但是在分支机构上工作本身并不是解决方案,每个开发人员正在处理的代码必须集成到不断扩充的代码库中。
开发人员在分支机构中工作而无需提交主分支的时间越长,与每个人在master中所做的更改进行集成和合并的难度就越大。所以,由于开发人员在不提交代码的情况下处理代码的时间越长,获得代码的难度就越大,因此从逻辑上来说就应该增加提交代码的频率。但是更好的方法是,使其持续集成。
下图描绘了如何可视化不同分支。蓝色是master分支,其他颜色都是在自己的分支上工作的单个开发人员,这些分支最终合并到master分支中。
不过,就算有分支机制也并非一帆风顺。即使开发人员每天提交代码,冲突仍然会发生。因为其他团队成员会继续做出更改,而没有考虑各方的诉求。实际上,集成问题经常需要返工,包括手动合并冲突的更改。但是比起开发团队整周或一个月都在埋头工作而不处理冲突,找出并解决一天工作中的冲突要简单很多。因此,尽管无法避免集成问题,但CI可以大大减少集成问题。
3、部署流水线和自动化测试
QA的部分工作是找出错误并确保代码是可部署的。传统流程中,在部署完成后会由一个单独的团队来负责QA。因为开发人员通常每年仅执行几次测试,因此在引入更改几个月后他们才了解到错误。到那时,因果之间的联系可能已经很难查证,导致诊断越来越困难。但是自动化测试解决了这个问题。
使用部署流水线之后,每次将代码添加到版本控制中都会触发一系列测试。流水线会自动构建和测试代码以确保它可以按预期工作,并且一旦集成到代码库中就可以继续工作。虽然在测试环境中代码可以完美执行,但它仍有可能在生产环境中不幸失败,因为生产中的环境和所有依赖项都会影响代码性能。依赖项并不属于app中的一部分,但仍需要运行它。例如数据库、数据/对象存储以及服务和应用程序可能需要调用的API。因此,开发和测试环境必须模仿生产环境。另外,必须对所有依赖项进行代码测试。
简而言之,部署代码时有3个测试阶段,每个阶段都会额外增加复杂性:
(1)验证代码本身是否按照预期工作;
(2)在代码库中继续进行验证;
(3)验证性能在具有所有依赖项的类生产环境中保持不变。
如果代码每天都被提交到版本控制中,则可以对其进行自动化测试,并且在引入代码之日会标记出任何构建、测试或集成错误,从而可以立即进行修复。这确保代码总是处于可部署和可运送的状态,称为绿色构建。
自动测试允许开发人员提高测试和集成的频率——从周期性执行到持续测试集成,并在约束最少的情况下发现问题。最糟糕的情况也不过是一天的工作都浪费了。
关于版本控制的争议
关于是否改在版本控制中存储敏感信息(如 access token、密钥和密码)进行了一些讨论。一方面,有人认为应该将一切(包括secret)都存储在这里,从而将这一方法推向极限。但是有人认为这是不良做法,并认为敏感信息应该单独存储。
版本控制允许开发人员比较、合并和还原以前的修订。通过允许他们在出现问题时将生产中的系统快速还原到以前的版本,从而将风险降到最低。为此,无论版本多小,所有更新和更改都必须在版本控制中进行跟踪。如果不是这样,生产中的代码将开发和测试环境中的代码不匹配,从而导致不一致。
简而言之,版本控制是事实的单一来源,包含了系统的预期状态以及所有以前的状态。通过将所有生产环境中的组件放置到版本控制中,开发人员可以重复可靠地重现工作软件系统中的所有组件。这是启用所谓的不可变基础架构的关键,我们将在稍后讨论。
持续交付:扩展CI以实现流畅的代码部署
即使使用了持续集成,将代码部署到生产中的过程依旧是手动、乏味且容易出错的。如果真是这样,那么显然不会频繁地将代码部署到生产中。IT部门会尽可能避免执行艰巨而危险的任务,这会导致要部署的代码与生产中运行的代码之间差异越来越大,进一步加具危险,然后形成一种恶性循环。那么解决这一恶性循环的答案是启用CI/CD中的CD部分。
CD扩展了CI,确保在将代码推广到整个用户群之前让代码在生产环境中能够平滑运行。最常见的CD方法是金丝雀和蓝绿部署。
进行蓝绿部署期间,IT会与当前版本一起部署一个新的组件或应用程序版本。新版本(绿)被部署到生产中并对其进行测试,与此同时当前版本(蓝)依旧可以使用。如果新版本的代码运行良好,那么所有用户将会切换到新版本中。
金丝雀部署也有两个版本:当前版本和更新版本。IT开始将一小部分用户请求路由到新版本。代码和用户的行为会被持续监控。如果错误率或用户投诉并没有增加,则路由到新版本的请求份额将逐渐增加(例如,1%、10%、50%最后到100%)。一旦所有请求都发送到新版本中,那么旧版本就会自动退休或删除。
通过按需环境创建自助服务
现在,我们已经研究了CI、CD及其各自的工具和方法,下面我们来讨论环境和基础架构。CI / CD需要一种创新的方法。
如我们所见,自动化测试使开发人员可以自己执行QA。为了确保一切都能在生产中正常运行,他们必须在整个开发和测试过程中使用类似于生产的环境。
传统上,开发人员必须向Ops团队请求(手动)设置的测试环境。此过程可能需要数周,有时甚至数月。此外,手动部署的测试环境通常会出现配置错误,或者与生产环境有很大差异,因此即使代码通过了所有预部署测试,仍然会导致生产问题。
CI / CD的关键部分是为开发人员提供按需类似于生产的环境,使其可以在自己的工作站上运行。为什么这很重要?开发人员只有在相同的条件下进行部署和测试时,才能知道代码在生产中的行为。如果他们在不同的环境中测试代码,则当最终将代码部署到生产环境中时,他们可能会发现代码不兼容,那么此时对客户造成了重大影响,再解决问题已经为时已晚。
不可变基础设施:牛与宠物
在讨论版本控制系统时,我们谈到了将环境与所有其他应用程序组件进行编码的需求,接下来让我们进一步讨论这些环境。
如果在版本控制中定义了环境规范并进行了编码,那么在容量增加(水平扩展)时复制环境就像按一个按钮一样简单(尽管之后它很有可能通过Kubernetes自动化了)。
扩展意味着在高峰时段增加计算能力。例如,Netflix的使用率在每个星期五晚上达到峰值,然后在午夜之后的某个时间再次恢复正常。为了确保享受无缓冲的视频,Netflix复制了其流控制组件(已在版本控制中进行了编码),以满足需求。然后,流量恢复后所有所谓的副本都被破坏,使流容量恢复正常。
为了实现这一点,至关重要的是,每当实施基础架构或应用程序更新时,这些基础架构或应用程序都会自动复制到其他地方并置于版本控制中。这将确保无论何时创建新环境,它都将与整个流水线(从dev到QA到生产)的环境匹配。例如,如果Netflix要更新其流服务而忘了捕获版本控制的更改,它将在高峰时段复制有故障或过时的组件,从而导致问题甚至服务中断。
由于掌握了版本控制中的环境编码,因此手动更改环境不是最佳实践,因为任何手动操作都容易出错。而应该将更改放入版本控制中,并从头开始重新创建环境(和代码)。这称为不可变基础架构。这些与CI / CD部分中讨论的应用于基础架构的原则相同。
你也许听过牛与宠物的比喻。这个比喻放在这里十分合适。以前,基础设施被视为宠物。如果有问题,你会尽力解决它,以便它可以生存。今天,基础设施被视为牛。如果它无法正常工作或需要更新,请杀死它并启动新环境。这非常强大,并且大大降低了问题潜入系统的风险。
发布与部署解耦
传统上,软件发布是由市场启动日期驱动的。因此,要发布的新功能会在宣布日期的前一天部署到生产中。但是,我们知道将特性或更新发布到生产中总是有风险的,尤其是如果你一次发布整个特性时。因此,将部署与发布捆绑在一起将使IT部门总是需要为失败胆战心惊。试想一下,如果在广泛推广的前一天发生了重大问题,IT团队就会感到恐慌,并且会在客户和媒体中引起巨大不良反响。
更好的方法是使部署与发布解耦。尽管这两个词经常互换使用,但它们是两个独立的过程。部署意味着将软件版本安装到任何环境(包括生产环境)中。它不一定必须与发布相关联。另一方面,发布意味着向客户群提供新功能。在整个功能开发过程中频繁进行生产部署的目的是降低服务中断的风险,该风险由IT部门承担。另一方面,何时向客户展示新功能应该是业务决策,而不是技术决策。
部署周期长会决定新功能发布的频率。如果IT可以按需部署,那么公开新功能的速度应该成为业务和市场营销的决定。
结 论
总而言之,CI要求将代码连续集成到代码库中,以在发生错误时捕获错误,从而最大程度地减少返工。要实现这种方法,需要三个工具:版本控制,以跟踪所有更改并使整个团队都可以使用最新的源代码版本;master,负责自己分支的开发人员每天合并更新;部署流水线将触发一系列测试,基本上是自动进行QA。
CD扩展了CI,以验证代码是否处于可部署状态,并自动将其释放到生产环境中。为此,需要一个成熟的DevOps组织,该组织必须先掌握CI,然后才能尝试使用CD。
如果实施得当,CI(/ CD)将大大提高你的IT团队的生产力。你的系统或应用程序在不断改进,同时将部署风险降至最低,从而增强了生产力和员工满意度的积极循环。此外,快速推出新功能和更新可推动创新,进而更快,更频繁地为用户带来价值。显然,随着越来越多的组织采用这些DevOps方法,由于传统方法无法与CI / CD竞争,因此对那些没有采用DevOps方法的企业,压力会越来越大。
附录:部署流水线测试套件 集成测试 检查应用程序如何与其他应用程序和服务交互,以确保代码与这些依赖项正确交互。远程服务的虚拟或模拟版本可用于准确地重新创建生产环境。 验收测试 会验证是否满足业务需求,以确保功能或应用程序为最终用户提供所需的价值。 性能测试 可验证该应用程序在类似生产的负载下如何在整个堆栈(代码、数据库、存储、网络、虚拟化)中工作。由架构决策或网络、数据库、存储或其他系统的意外限制引起的问题应在此处解决。 非功能测试 包括可用性、可伸缩性、性能、容量、安全性等。这些要求取决于环境的正确配置。测试将验证环境是否已正确构建和配置。 冒烟测试 验证该应用程序可以连接到所有支持系统,例如数据库、服务或信息传递系统;冒烟测试通常是手动的。
也有自动安全性测试以及探索性和其他手动或资源密集型测试。我们的目标是尽早捕获更多错误,并使用这些更耗时的测试来验证高层次的需求,并将产品完全集成到尽可能接近生产的环境中。
云计算
2020-04-16 19:40:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
导读
一定业务规模的互联网公司的基础设施的网络边界通常都呈现一定程度的复杂多分区的情况,如何进行有效的安全防护和控制会成为安全体系建设的重点和难点。面对这一挑战,爱奇艺安全团队自研了网络流量分析引擎QNSM,并将其用在各种基于流量分析的跨区安全检测和控制场景中,成为了爱奇艺安全防御体系的关键基础引擎。
互联网企业边界复杂性
上图是典型的中大型互联网公司的网络架构,通常分为:
办公网络,可能还有如右下角的众多小的分支机构,甚至还有办公机房
核心数据中心, 这些数据中心机房可能分布在全国多个地方,并通过专线实现互连,在这个基础上构建了自己的私有云。
CDN网络,这些CDN节点和核心机房也存在一定的互连。
如果使用公有云基础服务,呈现混合云的模式,这些基础服务与核心数据中心存在互连。
上述大量的分区都可能通过不同的方式接入到互联网。
最后,BYOD和各种无线热点以及手机无线热点等出现,导致呈现了大量碎片化的所谓新边界。
对企业安全防御而言,带来了各种新的挑战:
安全防御变得碎片化和多层次化,大边界内部还可能出现更多的小边界。
单个边界可能流量会非常大,特别是互联网互联的边界,100Gps以上成为常态,如果在这些边界进行流量检测,要求流量检测要具备高性能和很好的水平扩展能力,随时应对边界流量的扩展。
企业面临的内外威胁依旧很严峻,流量型攻击,漏洞型攻击,边界突破渗透,内部人员的泄露、破坏和控制都是普遍存在。
安全防御的体系也在逐步演化,从单纯的边界防御、结合多层次内部防御的纵深防御、以及立足于零信任或者假设失陷的下紧扣角色和权限的安全模型都在推动我们安全防御在不断的升级迭代来应对日益严峻的威胁。安全防御体系的演化不代表边界消失了,边界防御依旧是基础和重要一环,有效地流量分析和控制成为了新的安全防御体系重要的数据源和关节可编排的控制点。
因此,我们自研了旁路流量分析引擎QNSM(iQiYi Network SecurityMonitoring),通过对业务流量和旁路流量的协同分析,并集成多种可调度的防护能力,协同应对多种类型和多种层次的攻击,并且安全运营体系打通,从接入、预案、响应、联动、防御、溯源逐步形成闭环。
QNSM简介
全流量分析是非常重要的, 可以用来进行资产发现、网络监控和可视化,对安全而言,通过对网络流量的分析,对流量构建基线建模,从流量中可以发现异常、风险以及检测攻击,从流量中也可以实现数据内容提取,发现潜在的敏感数据流动或者泄露,还可以进行ACL策略校对,并将网络流量产出的数据特征通过机器学习和专家分析,可以挖掘更多的信息以及进行取证溯源和事件回查。
QNSM (iQIYI Network Security Monitor)设计目标是成为一个全流量,实时,高性能网络安全监控引擎,高性能、实时性、可扩展、多元特征提取是我们需要的关键特性。
高性能: 基于DPDK( https://www.dpdk.org/ )利用普通x86服务器即可高速处理10Gbps以上的流量,绕过了内核复杂的协议栈,并采用轮询的方式收发数据包,基于主从和流水线架构,无锁化设计。
扩展性强:旁路部署, 结合分光分流可以支持多机快速横向扩展,自身的流水线设计也可以方便实现自定义组件的插入,并且提供基于配置文件的统一资源管理模型,包括队列,CPU,MEMPOOL等,能够快速组建数据交换网络,加速开发进程。
多元特征: 多种维度的DDoS检测特征数据,支持基本的DFI/DPI,以库文件形式实现的Suricata IDPS集成,支持ipv4和ipv6双协议。
实时性: 集成IDPS实时检测,DDoS检测支持以10s(可调整)周期输出聚合数据,提取的多元特征可以通过Kafka和安全智能分析服务实现对接并进行后续分析。
QNSM架构设计
如上图所示,QNSM是作为服务软件运行在普通多核X86服务器上,每一个服务器可以有多块万兆网卡,并且通过分光或者交换端口镜像的方式获得要分析的网络流量,如果流量比较大,可以进一步通过分流器进行分流,将流量分散到不同的服务器上进行分析,进而QNSM利用DPDK实现了多个多核处理器和多个多队列网卡实现了高速包处理,其高性能来自于:
零拷贝(Zero-copy)
预取、批量收包来减少cache miss和提高吞吐
Share Nothing的设计模式实现无锁、无CPU切换
充分利用网卡的RSS特性,收包队列和CPU核绑定
基础库
QNSM在DPDK的基础上封装构建了各种基础库为构建上层流水线提供了基础能力,包括:
PORT:对网卡队列和核心之间ring队列的逻辑封装,是实现并行处理和线性扩展的基础。
MSG:封装了支持回调的CPU核心之间的传递的通信消息,这些消息可以是策略消息也可以是数据消息,这种无阻塞的核间消息支持一对一和一对多通信,实现数据和控制平面分开,数据集的输出和包处理分开。
ACL:是支持回调的五元组的策略描述,例如要指定满足怎么样的策略的包要聚合、处理、dump等操作。
TBL:是对DPDKrte_hash表的封装,是数据集的存储,提供CURD操作接口,实现基于mempool的表项资源分配。
SCHED:是对工作线程的封装,支持自定义的包处理,策略执行,自定义计算逻辑,消息分发和定时回调等。
流水线
QNSM构建了不同的流水线组件来满足不同场景的安全应用,为了支持更多的安全应用场景,我们可以在基础库的基础上构建更多的流水线组件,进而实现网络流量多样的处理能力。
SESSM:负责包解析,flow数据聚合和复制转发,处理策略消息等。
SIP_AGG:是对源IP进行特征聚合和输出,在攻击时通过响应策略消息打开。
VIP_AGG:实现目标VIP(需要保护的业务IP)的自学习,以及基于目标VIP的进行特征提取和向EDGE输出。
DUMP:保存数据包为PCAP文件供后续的事件回溯,在攻击时通过响应策略消息打开。
EDGE:负责将上游组件发送的多维数据输出到外部Kafka供进一步分析。
DETECT:集成Suricata库,支持IDPS的检测。
基于QNSM现有的流水线组件,我们已经将其应用在DDoS攻击检测,IDPS检测防护,流量监控以及网络DLP等多种场景,并支撑了各种上层安全产品的开发。大家可以根据自己不同安全应用的需要,设计和插入自开发的组件。
控制层
Master是整个引擎的主控,通过Kafka接收从管理平台接收策略消息,并下发到流水线组件实现对流水线的配置和处理控制。
安全应用
上图展示了在爱奇艺如何应用QNSM来满足各种安全需求,爱奇艺的QNSM服务节点分布在各个网络分区的边界上,并通过边控中心来进行管理和维护。边控中心(Aegis)是爱奇艺网络安全防护的核心服务,它有如下功能:
管理配置所有的QNSM集群,通过Kafka 和QNSM的进行控制交互
通过IDPS网关实现管理和配置QNSM集成的IDPS(Suricata)
作为爱奇艺WAF的统一服务后台,这里不做重点介绍
爱奇艺内部的安全大数据分析引擎结合威胁情报等外源数据,对从QNSM集群EDGE组件输出到Kafka的数据进行分析处理,产出的网络攻击事件会发送边控中心,边控中心会根据策略进一步和态势感知系统对接,进而和安全运营系统对接实现闭环运营。
边控中心可以按事件驱动QNSM dump网络流量成PCAP文件,并ETL进Moloch ( https://github.com/aol/moloch a largescale, open source, indexed packet capture and search system)建立包索引,方便对事件进行包级别的分析和溯源。
我们将会在后续的分享文章中具体介绍边控中心的架构和设计,这里不再赘述。下面,简单介绍我们是如何利用QNSM来满足我们DDoS攻击检测和扩展支持IDPS能力的需求。
DDoS攻击检测
业务接入边控中心,会提供要保护的VIP(Virtual IP),此外QNSM也会主动发现流量中的目标VIP并且和CMDB进行比对发现属于待保护的VIP。DDoS攻击检测方法主要是要基于受保护的VIP为目标的流量进行聚合特征数据供安全大数据分析引擎进行判断以实现DDoS检测。整体的检测思路是构建目标VIP以及所在机房的流量基线,计算流量特征,并进行多维异常检测识别攻击,常见的流量基线是包括VIP和本机房的成分基线以及机房流量基线和流量上边界,通过当前流量与基线进行实时计算,构建表示当前流量与基线的偏离的多维指标特征,并利用解释性强的模型来进行检测判断(例如评分卡模型等),并且会采取边控中心运营对事件的正负反馈来进一步修正基线和训练模型。
通过前面的多维异常检测识别出流量攻击以后,边控中心收到攻击事件和报警后会立即采取如下行动:
边控中心通过Kafka向Master组件下发各种策略消息管理和指导流水线的工作,包括dump数据包取证,攻击源IP发现,攻击源端口提取,反射攻击协议DFI等策略消息。
Master组件根据策略唤醒SIP_AGG组件,DUMP组件,其中SIP_AGG组件基于源IP聚合特征数据(可用于协助发现后续攻击来源IP), DUMP组件会进行dump数据包,dump出的PCAP文件投递到Moloch进一步索引和进行专家分析。
VIP_AGG组件基于VIP+SPORT聚合特征数据,SESSM组件也会针对被攻击VIP 做协议DFI识别,以协助识别是否存在某类协议的反射攻击。
QNSM通过EDGE组件,聚合数据进入到Kafka,可以作为安全大数据分析的数据源,并且和其他不同的安全服务进行联动。
DDoS攻击结束,边控中心通过Kafka向Master组件下发策略关闭消息管理和指导流水线中的重度组件工作。
在检测出VIP的入口流量存在攻击的情况下,通常需要进一步判断该攻击是否为反射攻击,我们会利用QNSM产出的VIP+SPORT聚合特征数据以及 SESSM组件的DFI协议识别特征数据,在安全大数据引擎计算不同的源端口的流量占比分布和包占比分布等特征进而计算熵值,熵值越小,风险越高(占比越高,风险越高, 流量和包占比如果全部集中在一个端口,熵将会是0),我们会结合多维度特征构建评分卡模型,最终给出是否是某一类协议的反射攻击的判定。
攻击确定以后,会根据应急预案进行流量牵引,爱奇艺构建了私有的流量清洗中心,并结合云清洗和运营商的近源清洗形成了三位一体的清洗能力。
IDPS能力集成
Suricata是一种基于网络流量的IDPS引擎,它有广泛的规则集来监控网络流量,并在发生入侵事件时触发警报, QNSM使用库文件的方式将Suricata集成,并通过IDPS网关接收边控中心下发更新Suricata相关检测规则,从 SESSM组件复制转发过来的包会通过 Detect组件调用Suricata进行处理,实现实时检测和触发事件和告警,并通过Kafka将事件和告警输出到安全大数据分析引擎进行进一步分析处理。通过对Suricata的集成,QNSM可以兼容大量开源和自定义的IDPS规则集,并且规则管理方式保持完全一致。
利用Suricata的DFI能力,QNSM也快速扩展支持从流量中识别各类数据库,缓存等云服务访问流量的能力,并且支持从流量中提取文件信息(包括文件名,文件大小,文件类型,MD5等),通过Kafka输出到安全大数据分析引擎,最终实现向DLP平台(绿盾)输出数据泄露和违规访问事件。
目前支持了爱奇艺内部常见的HTTP, MySQL,Redis,CouchBase, Memcached,MongoDB,Elasticsearch,Kafka,VNC,RSYNC等多种协议和相关工具的识别,支持对HTTP,SMTP,FTP文件传输通道的监控。
开源
目前QNSM 已经应用到爱奇艺包括DDOS攻击检测检测、IDPS、网络DLP等多种安全检测场景,累计部署22+集群共计130+分析节点,总分析带宽容量达到1TBps。
我们需要大家和我们一起改进QNSM,让它变得更强大,非常欢迎更多的合作和贡献,覆盖更多的甚至不限于安全应用的场景。
目前,QNSM 项目剔除了和爱奇艺内部平台深度集成部分后,核心代码开源在GitHub: https://www.github.com/iqiyi/qnsm ,欢迎使用、报告Issues 和 提交 Pull-Request。
我们采用Git work-flow的工作方式,具体可以参考开源代码中的Contributing文档,欢迎更多的开发者的参与,也欢迎通过邮件组: qnsm_devel# qiyi.com (请用@替换#)和我们进行交流。
后续规划
后续,爱奇艺安全团队针对QNSM会继续优化,开发计划如以下几部分:
增强易用性,让配置使用更加简单
进一步优化性能和降低资源占用
增加加密流量的非内容和内容特征的分析能力
高级DPI和DFI能力
支持netflow等多种标准输出
Bro/Zeek的集成以及沙箱分析的集成
旁路TAP(分流)以及串联Firewall(过滤)能力
扩展到更多场景,例如给业务安全和智能运维赋能等
逐步开放边控中心的集群管理、监控和事件处置能力
后续会逐步将最新的进展同步到开源社区。
云计算
2020-03-19 11:55:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
略谈分布式系统中的容器设计模式
谭中意
前言 :云原生(Cloud Native)不仅仅是趋势,更是现在进行时,它是构建现代的,可弹性伸缩的,快速迭代的计算网络服务的事实标准。其中容器编排系统Kubernetes和容器是基石。所以每个工程师都需要学习和了解他们。学习过程中,很多工程师可能会问: 为什么Pod而不是容器是K8S部署的最小单位 ? 基于K8S设计分布式系统有没有什么套路 ?本文针对这些问题,并参考K8S创始人的很多文档,给出了解答。本文适合进行研发工作2到3年的同学,对架构设计比较感兴趣,有一定架构设计意识,同时对容器(Docker)和容器编排系统(kubernetes)有一定了解。希望可以通过此文,让同学们更深入的了解到分布式容器系统中的几种常见模式,以便以后更好的设计和实现云原生的分布式系统。

先从一篇论文说起 :
首先介绍一篇论文,标题是《Design patterns for container-based distributed systems》,作者是Brendan Burns和David Oppenheimer,论文发表于2016年,是原原生领域系统设计的代表作。
第一作者Brenda Burns,相信熟悉云原生领域的同学都认识他,他之前是Google的工程师,是Kubernetes的三位创始人之一,他在这项目中负责系统设计,很多关键的设计决策都是出自他之手,包括声明式,Pod等。
在论文中,他介绍了基于容器的分布式系统中出现的几种设计模式:单容器模式,单节点多容器模式,以及多节点模式。像之前的面对对象模式一样,这些分布式系统中的pattern可以简化开发,并使使用他们的系统更加可靠。他感言,在google做了很多年的分布式系统设计,从web search做到后来的cloud系统,基本都是从头做起,很费力,因为没有什么成熟可重用的模块;但是进入云原生时代,随着容器(docker)和容器编排(k8s)的出现,极大的改变了分布式系统的设计和开发,从而为大规模的重用提供了巨大的可能。
系统设计是随着计算机体系的发展而发展的,计算机系统从单机发展到Client/Server再到Distributed System,而系统设计也从单一的算法Algorithm(例如Quick sort)发展到OOP(面对对象的编程语言),再发展到现在容器系统。
Design Pattern 是a repeatable solution to a problem,即对软件设计中普遍存在(反复出现)的各种问题所提出的解决方案,类似围棋中的定式(围棋爱好者应该很熟悉)。在GANG of Four的名著《Design Patters》中,对用面对对象语言实现的,针对编程语言中Interface级别的各种Design Pattern做了很深入的解释。其中一些设计原则,例如Single Responsibility对后续的系统设计也是非常适用。
为什么我们需要使用Design Pattern?因为绝大多数我们在系统开发中碰到的问题是相似的,可以借鉴别人的经验,所以站在巨人的肩上作创新;其次Design Pattern给我们提供了共享的概念和词汇,很容易沟通,例如我们一说起factory,我们就知道这是一个用来创建其他对象的对象;还有我们可以build可重用的组件。Design Pattern的核心: 解耦(Decouple) 和 重用(Reuse) 。 这两个核心原则贯穿系统设计的始终,不管我们是基于一种编程语言,使用接口来实现,还是在分布式系统设计中。
分布式系统中之前很少有pattern,mapreduce算是一个,但是在容器和容器编排成为主流后,有了大量的可重用的组件,也总结出了大量的pattern,单容器,单节点多容器,多节点等。限于篇幅,本文不介绍多节点容器设计模式,感兴趣的同学可以参考书后的资料。

先说第一个pattern,Single Container Patten.
先从最小的组件容器开始说起,容器简单来说,就是把应用程序和它所需要的依赖库打成一个包。容器(Docker)的出现,极大改变了程序打包和部署的方式,更是彻底改变分布式系统设计的最基础组件。
Container 就好比OOP Java编程语言中的Object(Class),是容器分布式系统的最基础对象。有人做过一个简单的类比,在java语言中,最基本的对象载体是Class,class被运行起来就是Object,而在容器系统中,最基本的对象载体是Container Image,当被运行起来后就是Container。Java对象有自己的初始化机制,Container中也有自己的Init Container机制。Java对象有销毁机制,Container也有preStop函数来优雅的停止。
在现实的设计中,需要把一个应用拆为多个容器来实现,这么做的理由有三个:1. 针对资源建立边界 (不同的容器需要不同的CPU和内存,根据实际需要进行限制,而且不同容器间资源隔离,互不影响。2. 建立团队归属边界 ,即一个Container有一个敏捷团队来own,最好6到8人。3. 提供兴趣隔离 (separation of concern)。容器的作用和职责应该满足Single Responsibility的原则,按照Domain Model Design的原则来进行设计,这样容易理解,也容易测试、更新和部署。那么在设计用于生产环境的容器的时候,需要设置内存和CPU的最高和最低限制,同时需要设置Liveness Probe和Readiness Probe。
在设计的时候,需要重点考虑: 解耦和重用 。不断的问自己几个问题:我的容器足够解耦了吗?是否还可以拿出部分来作为独立的容器?这些容器是否可以很方便的被重用到其他地方?
再说多个容器组合成的pattern。
同学们在学习K8S的过程中,肯定会有疑问:为什么Pod(含有一个或者多个Container)是最小的部署单元,而不能直接是容器。这里就要涉及到K8S中一个非常精巧的设计了。Pod是一组共享生命周期,并部署在同一个节点的容器的组合,他们可以通过共享的volume/network和IPC来进行通讯。之所以不是一个单一容器,而是多个容器来完成特定功能的原因在于:这些容器要完成的职责不同,根据单一职责(single responsibility)的原则,他们应该属于不同的组件;其次因为职责不同,维护他们的team也不同,迭代周期也不一样;最后其中一些容器是可以被复用在其他的环境中的。所以从“解耦”和“复用”的设计原则出发,Kubernetes通过增加一个虚拟层即POD,给系统设计带来了极大的灵活性,同时也产生了多种设计模式。即在一个POD中除了抗流量完成业务的容器(文中称之为app container)外,还存在其他的辅助容器,可以分为两类:1. Init Container 2. Sidecar container。

Init Container Pattern
就想Java语言中Object有初始化函数一样,Pod中的Init Container起的作用也是用来初始化。当app container需要满足一些前置条件才能启动,例如它依赖一些外部服务db service ready才能启动,或者需要初始化的更新文件(例如从github clone最新版本的文件)。
我们来看一个简单的例子,如上图。其中myapp-container是app container,它是来执行业务逻辑的,它的启动依赖后台的mydb和myservice两个服务。所以有两个init containers,他们分别执行nslookup来检查依赖服务是否已经启动,如果没有启动,等待2秒之后再检查,如果已经启动,则顺利启动自身容器,然后app container再启动。能看出这个例子中,app container利用init container来force wait,直到依赖的两个后台服务启动之后再启动。这样app container的启动逻辑就无需关心这两个依赖服务是否ready。
使用Init Container的注意事项如下:1. Init container的执行顺序是在pod启动过程中,最先执行,而且是顺序执行,即一个init container执行结束后,再执行下一个init containers。他没有readiness probe check,应该是逻辑简单,而且执行快速的。2. Init Container也是container,它也占CPU/内存系统资源,所以在计算资源消耗的时候,需要把它也加进去,不然调度的时候可能会有问题。

Sidecar pattern :
下面介绍Sidecar pattern。
所谓sidecar,就是类似这种摩托车。在K8S中,sidecar container是和app container同时启动,并且有自己的职责,并能在别的地方进行复用的容器。Sidecar container和app container之间共享磁盘/网络/IPC等,我们来看一个典型的例子。
App Container 是一个web server,sidecar container定期从github sync代码下来,两者通过Pod的volume来共享文件。这样做的好处是把从github定期sync代码的逻辑剥离出来,成为一个可以重用的模块,并且能用到其他的场合。而app container只需要单纯的做web服务就好,不需要考虑sync之类的逻辑。
什么时候考虑使用sidecar呢? 当这两个container需要同时部署,但是各有自己的职责,而且可以分别去迭代和演进,而且有重用的可能性。
那么什么时候不适合sidecar呢?当这两个container有不同的扩容需求时候,即两者需要独立的扩容时候,不要sidecar这种模式;另外,两者的通信可能会带来一些网络的消耗,带来一定的延迟,如果这点延迟是业务无法接受的话,也不要使用sidecar。

Ambassadaor Design Pattern :
它是一种特殊的sidecar,其实就是app container的一个proxy,它来接流量,然后进行处理,然后把流量转发给app container,让其完成真正的商业逻辑。 例如:我想给一个web server加上认证逻辑或者SSL,但是我又不想改动原来的web server或者改动比较困难,我可以在其所在pod内再部署一个proxy,让这个proxy来处理这些认证的逻辑,而原有的app container无需任何改动。如下图所示,完整的例子在 https://medium.com/@lukas.eichler/securing-pods-with-sidecar-proxies-d84f8d34be3e 。

此外,ambassador pattern还可用于shard a service或者A/B 测试。另外最近新崛起的技术热点ServiceMesh和其实现istio,都是利用sidecar的方式来做服务代理,把流量控制的逻辑下沉到基础架构层,通过ambassador的方式很方便的实现。他们的出现将极大的改变微服务架构,可能让其更关注业务逻辑的高效实现,而把流量控制(包括服务发现,服务限流,小流量等服务路由功能统一交给service mesh来解决。

Adapter Pattern :
又是一种特殊的sidecar,如果希望对外输出的内容符合下游的要求而不对app container进行修改,可以增加一个adapter的sidecar,由它来做类似日志转换的事情。例如:
App container 按照自身的要求生成日志并保存到文件系统中,另外的adapter container通过共享存储读取该日志,然后进行日志转换等工作,以便把内容输出给下游的metrics系统。
总结:
设计模式(Design Pattern)的核心是解耦和重用;在容器和容器编排的分布式系统中,有大量可重用的组件和pattern,其中Single container和multiple container又是最基本的组件。

参考资料: https://ai.google.com/research/pubs/pub45406 https://www.usenix.org/sites/default/files/conference/protected-files/hotcloud16_slides_burns.pdf
云计算
2020-03-11 11:10:00
「深度学习福利」大神带你进阶工程师,立即查看>>> 本文重点探讨下开发者使用 Serverless 时经常遇到的一些问题,以及如何解决
过去一年,我们和大量 Serverless 用户进行了线上和线下的交流,了解大家的业务场景、对 Serverless 的看法和使用体验。
大部分用户认为 Serverless 会是云计算下一阶段的必然趋势, 但不是现在。 为什么呢?因为构成 Serverless 架构的云函数尽管有引以为傲的自动扩缩能力,但是糟糕的开发体验、让人畏惧的冷启动、原有业务的改造难题等等,均降低了使用者的信心。
因此,尽管不少用户认可 Serverless 的价值,但依然认为其很难承载核心业务。
针对这些关键问题,腾讯云在今年 6 月份发布了 Serverless 2.0,全面升级了产品形态、系统调度以及开发者工具。为了便于大家理解,我们就从云函数的运行原理作为切入点,以解释问题产生的原因以及云函数的应对方法。
首先,我们看一下云函数,或者说 FaaS 和 IaaS、PaaS 的区别。
如下图所示,FaaS 不仅给用户提供了标准的 Runtime,同时在应用层也帮用户管理了请求的调度。开发者只需要聚焦在核心业务逻辑开发,按照函数的粒度去编写代码。而与底层硬件相关的资源维护,则交给更加专业的云厂商来搞定。
因此,对于用户来讲,可以把更多的精力和时间放在业务上。而 IaaS 和 PasS,则均需要用户去运维云主机或者容器集群、搭建业务所需的运行环境。
其次,我们来看下云函数如何构成 Serverless 架构,以及云函数如何帮助用户做资源管理和请求调度。
在这里我们也将解答云函数的冷启、降低核心业务迁移复杂度等问题。
如下图所示,开发者在实际使用时,可以借助 Web IDE 或者本地 IDE 完成代码开发,然后通过插件、工具等方式把代码及其相关依赖,一起打包部署到云函数平台,用户可以自行选择部署为函数形态或者服务形态。
在代码里,用户需要自己实现业务逻辑,比如访问数据库、对象存储、消息队列、第三方服务接口等。计算逻辑和后端服务共同构成了所谓的 Serverless 应用架构。而终端用户根据平台提供的请求方式,去触发部署在云函数平台上的业务代码,比如发送 http 请求,平台会根据用户的请求量去拉起相应的计算资源运行用户代码。
这里需要重点关注函数形态和服务形态的差异,因为服务的形态可以大大降低复杂业务迁移的成本。 服务形态支持直接部署基于框架开发的核心业务,如 Node.js 的 express、koa 等框架,不用为了应用 Serverless 而拆分成函数。平台会帮用户启动服务进程、端口监听,同时服务形态不会限制业务的实际运行时长。 函数形态和服务形态在收到用户请求的时候,均能实现自动扩缩。 函数形态会针对用户的每个请求都分配一个运行实例,因此所有请求的执行体验是一样的。当没有请求的时候,平台是没有实例在运行的,所以可以做到按需请求,但是这也会造成所谓的冷启动 —— 即当用户的首次请求进入平台的时候,平台会临时拉起资源,而这个过程会消耗一定的时间。为了消除冷启,云函数平台会预先初始化一批不同规格的实例放在资源池中,当用户有请求进入时,可以快速从资源池申请一个实例,直接挂载用户的代码运行,从而降低了资源申请时间。同时,针对函数形态,平台会根据历史并发数据进行预测,帮用户预留一定量的实例,这些实例会预先分配到用户的账号下并且加载好了用户的代码,从而不仅直接消除了冷启,也增加了实例复用几率。 而服务形态可以至少帮用户预留一个常驻实例,并且把用户的所有请求都投递到首个实例,根据实例的使用情况,自动的动态扩缩。
函数形态更适合新建项目,可以敏捷迭代,业务按照函数的粒度开发,不仅可以轻松实现云上多产品的联动,也可以享受函数的高并发及性能一致体验。服务形态更适合已有项目的迁移、重度复杂业务、需要长时运行的业务。
最后讲讲 Serverless 2.0 的组件架构。
如下图所示,用户虽然只需要关注绿色部分和业务相关的代码实现,但是平台也需要提供强大的开发者工具来保障开发和使用体验。如云函数推出的 Serverless 本地开发工具、VS Code 插件,与 CODING 联合推出的 Web IDE、DevOps 平台等,均能很大程度上提升开发、部署效率,实现本次开发、本地调试、联动云端调试、本地部署、版本发布等能力。
同时,云函数也完善了配套的监控和告警机制,提供如调用次数、内存使用、并发使用、超时、代码错误等多维度的监控和告警能力。这些基础设施、资源管理、安全、容灾等能力,是云函数平台必备的基础能力,也是开发者关心的核心能力。
Serverless 不仅仅是计算,还需要不断完善周边生态。
随着用户量的增加,Serverless 必然会面临更多的挑战 —— 怎么帮助用户组织管理代码,怎么解决带状态的业务诉求,怎么实现数据库连接数管理,怎么实现应用级部署等等。我们也在不断探索和优化用户的使用体验,计划提供诸如 Serverless DB、性能监控、日志分析、Serverless 框架、函数编排、高性能调用等功能。
后续的专栏文章也将陆续解读更多核心能力,帮助开发者更好地理解和使用 Serverless。
Serverless is more!
Serverless Framework 30 天试用计划
我们诚邀您来体验最便捷的 Serverless 开发和部署方式。在试用期内,相关联的产品及服务均提供免费资源和专业的技术支持,帮助您的业务快速、便捷地实现 Serverless! 详情可查阅: Serverless Framework 试用计划
One More Thing
3 秒你能做什么?喝一口水,看一封邮件,还是 —— 部署一个完整的 Serverless 应用? 复制链接至 PC 浏览器访问: https://serverless.cloud.tencent.com/deploy/express
3 秒极速部署,立即体验史上最快的 Serverless HTTP 实战开发! 传送门: GitHub: github.com/serverless 官网: serverless.com
欢迎访问: Serverless 中文网 ,您可以在 最佳实践 里体验更多关于 Serverless 应用的开发! 推荐阅读: 《Serverless 架构:从原理、设计到项目实战》
云计算
2020-02-09 20:10:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
背景
有 外文 指出,2020 年 Service Mesh 技术将有以下三大发展: 快速增长的服务网格需求; Istio 很难被打败,很可能成为服务网格技术的事实标准; 出现更多的服务网格用例,WebAssembly 将带来新的可能。
针对 Service Mesh 技术,ServiceMesher 社区治理委员会成员在 2020 新年伊始发表了他们各自的看法,并邀请云原生与服务网格领域业界大牛抒发各自的见解,汇总成文,希望能给读者们带来一些思考和启发。
正文
宋净超(蚂蚁金服)
用一句话概括 Service Mesh 近几年的发展——道阻且长,行则将至。这几年来我一直在探寻云原生之道,从容器、Kubernetes 再到 Service Mesh,从底层的基础设施到越来越趋向于业务层面,Service Mesh 肯定不是云原生的终极形式,其复杂性依然很高,且业界标准也尚未形成,它的发展也远没有同期的 Kubernetes 那么顺利,但是很多人都已意识到了服务网格价值,现在它正在远离最初市场宣传时的喧嚣,走向真正的落地。
罗广明(百度)
据了解,2020 年的 Kubecon EU 的提案中,很少有涉及服务网格落地场景,由此来看,服务网格技术离大规模生产落地还有很远的路要走。当前 Istio 架构体现出来的性能问题迟迟没有得到优化,使用原生的 Istio 大规模上生产还不太靠谱,有的公司选择将 mixer 功能下层至自研的数据面,有的公司通过向容器注入探针解决可观察性。总的来看,在当前服务网格部分落地场景中,大多都是基于 Istio 和 envoy,但对其或多或少都有改动,以满足公有云/私有云的需求。
此外,在 Service Mesh 落地的过程中,现有传统微服务应用(Spring Cloud/Dubbo 应用)如何平滑迁移到 Service Mesh,也是一个至关重要的话题。“双模微服务”的互联互通、共同治理有望成为 2020 年服务网格落地的关键技术之一,这也是国内几家典型云厂商力求打造的亮点产品。
马若飞(FreeWheel)
我个人认为 Service Mesh 想要真正发展成熟并大规模落地还有很长的一段路要走。一方面业界基于微服务构建的一系列服务治理框架和产品相当稳定和成熟,在功能上和 Service Mesh 有很多重合的地方,使得开发者对 Service Mesh 的需求并不迫切;另一方面,目前 Service Mesh 领域产品的成熟度还有待提高,冒险迁移过于激进,也容易面临兼容性的问题,这也制约了 Service Mesh 的落地。
从近半年厂商的动作来看,主要方向是提供托管的控制平面,并整合成熟的数据面(如 Envoy);同时提供多环境支持(如多云、混合云、VM 等)。这也和目前应用复杂多样的的部署现状有关,厂商的目的是先让你上云,再 Mesh 化。这也是一个相对稳妥且折中的方案。我司作为一个重度使用 AWS 服务的公司,选择了 AWS App Mesh 托管服务作为 mesh 的解决方案,使得和现有服务能更容易的整合,减少维护和迁移成本。
邱世达 (BoCloud)
目前来看,Kubernetes 已经逐步在企业中落地,服务上云已然是大势所趋。而随着云计算基础设施层的日益完备,在可以预见的未来,应用层服务治理必然成为新的焦点,也是在大规模微服务场景下必须要解决的问题。在 Service Mesh 领域,Istio 无疑是明星项目,除了具备一定自研能力的科技公司会定制开发自己的服务治理工具,大多数中小型企业通常会选择以 Istio 为代表的开源服务治理方案进行初步试水。实践过程中遇到问题并不可怕,我认为这反而是一种正向推动力,作为一种良性反馈,能更加积极地促使 Service Mesh 技术趋于成熟和稳定。拥抱服务网格,拥抱云原生,让我们期待 Service Mesh 在新的一年取得更大的发展!
孙海洲(中国科学院计算技术研究所)
对于 Service Mesh 来说,2019 年是极不平凡的一年,也是从观望走向生产落地的一年。在这一年里,以 Istio 为代表的 Service Mesh 开始加快发布周期,可以看到社区从以优雅架构到开始追求性能。最近社区里大家积极地参与到 Istio 文档的本地化工作中。在业界可以看到国内各个大厂开始有所举动,蚂蚁在双十一的成功大规模落地为 Service Mesh 走向生产打下了坚实的基础,同时也为大家提供了很多宝贵的经验,腾讯、百度、华为等云服务提供商也都纷纷发布相关的产品。关于 Service Mesh 的图书在今年也出版了几本,社区多次组织线下的 Service Mesh Meetup 场场爆满,可见大家对 Service Mesh 的热情与日俱增。2020年应该可以看到会有更多的 Service Mesh 的成功落地,但是当前还有很多企业还处于过渡时期,如何更好更便捷地解决向云原生迁移依赖值得关注。Service Mesh 社区的推广和布道工作依然任重而道远,需要我们更加积极努力地投入到 Service Mesh 事业中去。
赵化冰(中兴通讯)
在 2019 年里,我看到的一个有趣的现象是出现了各种各样的开源 Service Mesh 项目,基于开源 Service Mesh 项目的初创公司,以及各大云厂商的闭源 Service Mesh 实现。和 2018 年大部分项目围绕 Istio 搭建生态有所不同(至少大部分项目声称自己兼容 Istio),2019年整个 Service Mesh 生态出现了百花齐放,百家争鸣的趋势。这也许和 Istio 项目的进度有一定关系。Istio 在项目最开始发布时搭建了一个非常漂亮的架构,但实际开发的进展较慢。目前 Mixer V2 还没有能够正式发布(处于 alpha 版本), 其安全模型也在近期进行了较大的变动,导致除了流量管控之外的其他功能基本无法在生产中使用;除此之外,Istio 对于非 Kubernetes 环境的支持也非常有限。所有这些因素在一定程度上给其他 Service Mesh 项目留出了较大的发展空间。
在 Service Mesh 的不同实现纷纷涌现的情况下,要最大化利用 Service Mesh 提供了服务通信和管控能力,必须统一 Service Mesh 的标准接口。通过一个标准北向接口,对 Service Mesh 提供的流量控制,安全策略,拓扑信息、性能指标等基本能力进行组合,并加以创新,可以创建大量端到端的高附加值业务,例如支持业务平滑升级的灰度发布,测试微服务系统健壮性的混沌测试,微服务的监控系统等等。而采用一个标准的南向接口,则可以构建一个良好的数据面代理生态,甚至可能将一些传统的硬件代理设备纳入 Service Mesh 控制面进行统一管理。
在 2020 年里,我希望 Istio 项目在 telemetry 和 security 方面取得更多实际性的进展,并出现更多的商用案例。希望能够制定一个 Service Mesh 的标准接口,或者出现一个足够强大的事实标准,并看到建立在标准北向接口上的更多应用,这是 Service Mesh 的核心价值所在,也许会成为 Service Mesh 的下一个热点。
钟华(腾讯云)
还记得 2019 年初,我们对打磨半年之久的 Istio 新版本翘首以盼,大家对 Istio 的高度抽象模型褒贬不一,社区里偶尔会看到朋友问「到底有没有公司在生产环境落地了 Istio?」
在过去的一年里,Istio 持续发力,核心功能迭代更加稳定,发布了四个子版本,同时也更注重用户体验的优化。各大云厂商在 2019 年陆续实现了对 Istio 的支持,业界也出现了越来越多的 Service Mesh 生产实践,其中典型的是蚂蚁双十一大规模落地案例;笔者所在的腾讯云 TKE Mesh 团队,支持了数十个团队的 Service Mesh 改造过程,其中不乏一些场景复杂、体量庞大的核心系统。
Service Mesh 技术前景广阔,但远未成熟。展望 2020, 作为 Service Mesh 头号玩家的, Istio 还会持续快速发展,我个人很期待的一些演进: 支持 webassembly 扩展的数据面,真正生产可用的 Mixer V2,更易安装和运维的单体控制面 istiod,更容易理解和操纵的用户接口,以及提升 Istio 自身的可观测性。
Service Mesh 技术本质上是各种最佳实践的组合运用。Istio 试图运用精巧的模型,去联结各种平台、观测系统和用户应用。未来的 Istio,一定会更加复杂,这些「复杂」的目的,是让用户能更「简单」地使用 Service Mesh 领域的最佳实践。
William Morgan Buoyant CEO, author of Linkerd,the originator of the concept Service Mesh .
今天的服务网格处于有点不幸的状态:虽然有真实和重要的价值,但市场营销已经超过了技术本身。云供应商特别利用服务网格作为区分他们的容器产品的一种方式,而由此产生的狂热的市场推广给终端用户带来了实质性的损害。
然而,如果应用正确,服务网格确实能提供一些真正变革性的功能。从 Linkerd 的角度来看,创建服务网格的项目,我们仍然认为最小化服务网格的成本,特别是由复杂性引起的长期运营成本是最重要的。
在2020年,Linkerd 将继续专注于提供“可观察的安全性”的目标,同时最小化复杂性和使用成本 — Linkerd 的超轻、超快 Rust 代理、极简控制平面,以及“少做,而不是多做”的理念已经在这里得到了鲜明的体现。最重要的是,Linkerd 对开放治理和中立基础的承诺将确保 Linkerd 将继续成为一个为所有工程师服务的项目,而不是为某个特定云供应商的客户服务。
Christian Posta Field CTO at solo.io, author Istio in Action and Microservices for Java Developers, open-source enthusiast, cloud application development, committer @ Apache, Serverless, Cloud, Integration, Kubernetes, Docker, Istio, Envoy blogger, blog https://blog.christianposta.com/ .
回顾2019 更多的Service Mesh产品发布了!API/软件网络领域的每个人都正在实践自己的服务网格。我认为这对市场来说是一件好事,因为它表明这是有价值的,并且应该探索不同的实现方式。这也将指引我们在未来殊途同归。 越来越多的组织参与到服务网格技术中(从去年的架构讨论开始)可用性是关键!像linkerd这样的网格技术展示了如何简化使用和操作,其他产品也注意到了这一点,并尝试提高它们的可用性。 Istio已经持续的进行定期发布,这证明了它开始走向稳定并具有可预测性。 Consul推出了和consul模型无缝结合的L7路由特性。 不可忽视,虽然更多的人开始着手服务网格技术的实践,但依然有很多争议: 谁来支持? 多租户支持的不好 对现有应用不总是透明的 VM+容器支持不够好 暴露什么样的API给用户
2020年展望
服务网格在2019年引领了潮流,我期待它能变得更加强大。2020年,会有更多的组织落地服务网格,继续与现有的网格技术集成,如Istio和其他产品: 多网格的存在!虽然现在已经有很多网格实现,但最终还是会收敛的。然而,有趣的是,我不认为融合会像kubernetes那样发生(我们都落在一件事情上)。我怀疑总会有多种服务网格实现会成为主流。每个云提供商都有自己的托管网格产品,这可能与本地网格不同。因此,多集群和网格的多分布将成为主要的部署实现。 Web assembly正在流行:它提供了一种在类似Envoy这样的代理中安全地运行用户代码的方法,我们将很快看到服务网格和API网关,如istio和gloo对它提供支持。Web assembly将允许用户/供应商/组织提供功能模块,用以定制化代理并改变其默认行为。Web assembly 工具集将开始出现并对其进行管理。对于那些努力将服务网格集成到现有环境并维护组织兼容性的人来说,这将是令人兴奋的。 优化服务网格数据平面:去年我在第一个ServiceMeshCon演讲(PPT: https://www.slideshare.net/ceposta/the-truth-about-the-service-mesh-data-plane )讨论了如何在服务网格数据平面进行调优,就像直接运行你的代码一样。作为代理,和共享的代理。例如,gRPC最近增加了对 xDS API 的支持, CNCF也有一个工作组来帮助将这个“通用数据平面API”标准化以用于其他用途: https://github.com/cncf/udpa。
Service Mesh 终端用户调查
为了增加大家对 Service Mesh的了解,促进社区更好的发展,我们发起了 Service Mesh 终端用户问卷调查,请访问链接 https://wj.qq.com/s2/5258418/d5d8 ,或者扫码下面图片中的二维码,花几分钟的时间填写下这份问卷。谢谢!
关于 ServiceMesher 社区
ServiceMesher 社区是由一群拥有相同价值观和理念的志愿者们共同发起,于 2018 年 4 月正式成立。
社区关注领域有:容器、微服务、Service Mesh、Serverless,拥抱开源和云原生,致力于推动 Service Mesh 在中国的蓬勃发展。
社区官网: https://www.servicemesher.com
云计算
2020-02-04 17:44:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
1 背景
起初,在网盘快速发展期,为了快速上线,采用了服务单体化 + 主干开发模式进行研发,随着用户规模爆发式的增长以及产品形态的丰富,单体化的不足就体现出来了,于是架构上采用了微服务架构,开始对业务逻辑进行拆分部署。
服务拆分之后,也引入了新的问题,具体如下:
**请求路由:**服务部署从物理机向虚拟化方式迁移中,有大量的切流量操作,需要相关的上游都进行升级上线修改,效率低下
**故障管理:**单实例异常、服务级别异常、机房故障异常、网络异常等,严重缺失或者不完善,同时配套的故障定位也没有,服务稳定性不足
**流量转发:**不同的服务采用了不同的框架,甚至裸框架,策略不完善,导致负载不均衡
**研发效率:**相同的功能点,需要在不同的语言框架上实现一次,浪费人力,同时升级周期比较长,收敛效率低
2 解决方案 - UFC
2.1 UFC 发展史
为了解决这个问题,从2015年底开始思考解决方案,确定了解决问题的核心在于管控请求流量,在2016年开始自研网络流量转发中间件 - UFC(Unified Flow Control),业务通过同机部署的agent进行服务通信,相关的发展史如下:
2.2 UFC 和 Service Mesh的关系
后来在调研业界相关技术的时候,发现了istio(业界Service Mesh的典型代表),从而发现了Service Mesh的存在,而它的定义是在2016.9 由Buoyant 公司的CEO William Morgan 提出的: Service Mesh是一个专门用来处理服务和服务之间通信的基础设施。它复杂确保在一个由复杂服务构成的拓扑的现代云应用中,请求能够被稳定的传递。在实践中,Service Mesh通常通过一系列轻量级的代理来进行实现。这些代理和应用同机部署,而应用不需要感知到代理的存在。
A service mesh is a dedicated infrastructure layer for handling service-to-service communication. It’s responsible for the reliable delivery of requests through the complex topology of services that comprise a modern, cloud native application. In practice, the service mesh is typically implemented as an array of lightweight network proxies that are deployed alongside application code, without the application needing to be aware.
从定义上,我们不难发现UFC和Service Mesh的设计理念是一致的,都是基于sidecar模式,有着控制面板和数据面板,UFC是Service Mesh的一种实现。感慨的说,历史的发展潮流是一致的,不管你在哪里。
目前UFC应用于网盘过千个服务上,涉及虚拟化实例数量超过20W,千亿PV,机器规模10W+(网盘+其它产品线机器),10个IDC,从已知的实例规模上看,是国内最大的Service Mesh的实践落地。
2.3 基于Service Mesh 之上的服务治理
百度网盘的实践落地并不只局限于Service Mesh,首先是构建了从点延伸到线的Service Mesh进行服务通信管控,然后是在UFC这个Service Mesh的基础之上,站在全局视角对服务进行治理,保障服务的稳定性,相关能力等发展如下:
**点:**关注与下游进行通信,不关注上游的情况
**线:**加入上游的标识,基于上游做异构的通信策略
**面:**多条线组成面,站着全局视角进行服务治理
2.4 本文概要
本文将会先介绍UFC(如何实现一个Service Mesh),然后是基于UFC做服务治理(基于Service Mesh的实践应用)
3 UFC 外部视角简介
3.1 用户使用视角
只需要做两个事情: 服务注册:需要先确保自己的服务(上游)和要访问的服务(下游)已经注册过了,没注册过,则需要服务的owner进行服务注册 服务通信:用户通过单机agent进行服务通信访问下游,下图显示了用户从直接访问下游变成了通过同机agent访问下游
3.1.1 服务注册
UFC为每个注册的服务分配一个service_name,service_name 是这个服务的唯一标识。同时需要对这个service_name配置它的相关配置:比如destination来源、负载均衡、熔断、超时重试等策略
3.1.2 服务通信
访问下游的时候,只需要访问本机固定端口,带上下游服务的service_name、自身标记、trace等信息,例如下面就是一个发请求的demo例子:
curl “ http://127.0.0.1:8888/URI” -H “ x-ufc-service-name =to_service_name” –H “ x-ufc-self-service-name =from_service_name” -H “ x-ufc-trace-xxxx = xxxxx”
3.2 UFC能力视角
介绍UFC基于点和线视角的相关能力,从服务声明、请求路由、流量转发、故障处理、故障定位、安全等维度和istio做了一个比较。而istio是大部分是基于下游这个点进行相关通信能力设计,线视角能力很少(比如权限认证等)
总结来说,istio是能力全面,但是具体实现上策略比较简单,而UFC是更贴近实际的业务场景(具体的可以看后面的介绍内容)
PS: 有些能力(比如流量复制/权限管理)UFC没有,并代表百度网盘没有这方面的能力,只是因为历史原因,通过其它的方案解决了。但是故障注入这块,的确是UFC需要考虑的,有了这块的能力,混沌工程也更容易的落地。
4 UFC 内部视角简介
主要是介绍架构和相关具体能力的实现设计初衷
4.1 架构设计
整个架构和Service Mesh一样,都是采用了同机Sidecar进行了流量的转发 + 中心化控制。
4.1.1 核心流程图
UFC组件
Service-Mgr: 服务(实例)管理,提供服务的增删改查(存储到db + cache)。定期从naming服务拉取destination列表,写入cache(多个idc cache)。此外还会和paas进行协作(比如通知paas迁移异常的实例)
**Agent:**每台机器部署一个,四个功能:1)通信代理:为服务提供通信代理 2)配置同步:从同机房的meta模块同步配置 3) 上报:异常和统计数据 4)系统异常监控:接收中心的监控检测,包括agent存活和配置同步时效性
**Meta:**提供服务配置元信息的查询,多个IDC地域部署
**Monitor:**worker模式,定期发起监控系统和业务是否存在异常,系统层面监控单机agent存活率/配置同步等,业务层面监控异常实例/服务等
**Metrics:**聚会后的数据,数据来源来agent和monitor
4.1.2 相关设计说明
4.1.2.1 高可用
服务单点
Agent: 单机agent肯定会挂断,解决思路是基于如何避免请求受损出发点,1) 基于backup集群临时访问:业务使用sdk进行访问的时候,当访问本机agent失败之后,会通过访问远端的backup agent集群进行访问下游 2)基于探活屏蔽+修复: Monitor会检测单机agent 的存活性,当单机agent异常的时候,Monitor会通知meta 服务屏蔽单机上的实例,避免上游访问该机器,同时进行agent 修复
Meta: 每个IDC 独立部署,另外IDC内部通过多实例 + 无状态设计解决单点问题
Monitor: 每个IDC 独立部署,另外IDC内部通过多实例 + 分布式锁互斥设计解决单点问题
Metrics: 多实例,前面有一层proxy,将service 进行一致性hash 进行服务拆分,单机统计聚合数据
**Service-Mgr:**多实例 + 无状态设计解决单点问题
**IDC cache:**当某个IDC的cache异常之后,通过Meta切换读取backup IDC的cache解决
**机房链路故障:**会导致配置更新异常,解决方案是通过接入层将IDC流量切空,不在UFC这层考虑解决问题
**业务实例异常:**除了通过UFC 自身的故障屏蔽解决之外,还会联动paas将长期处于异常的实例通过迁移恢复,实现异常处理的闭环
4.1.2.2 扩展性
**paas扩展性:**很容易融入不同的paas平台,只需要兼容不同的naming系统即可 业务协议:支持任意业务协议,通过bypass旁路式解决(后面的能力会进行相关介绍)
4.1.2.3 监控
**系统:**各种系统的异常点,比如单机agent的存活和配置同步情况,中心配置定时器同步 业务:服务单点异常、服务实例存活率、服务sla等业务指标仪表盘监控
4.1.2.4 配置同步
单机上的配置是全量的,通过版本号进行增量同步(全局的版本号+服务级别的版本号),同时会通过monitor监控配置是否同步成功
4.1.2.5 具体实现
**数据面板:**基于OpenResty开发。从理论角度:nginx转发性能本身就好,同时在2016年的时候Go的gc问题还比较严重,从实际压测:OpenResty 要优于Go 控制面板:基于Go开发,比较好实现并发编程
4.1.2.6 实时debug
对于一个实时运行的系统,如何实时获取相关的stat数据,用于问题定位呢?比如想获取当前封禁后端列表之类的
为了满足需求,增加了一个获取数据的接口,获取内存里指定字段的数据,以^为分隔符。比如以下demo就获取了一个服务的动态数据,包括了请求次数,更新时间,失败次数等信息
request: curl -v -H "token:token" ' http://10.10.11.11:8888/bypass?command=query&ar=request_info^pcs-upload ' response: { "request_info": { "5xx_cnt": 2, "mtime": 1573456024, "request_cnt": 6, "success_cnt": 4 } }
4.2 功能设计
主要介绍UFC基于点和线的相关能力细节以及设计出发点
4.2.1 请求路由
提供相关的匹配能力,根据匹配条件进行后续相关的操作,比如设置后端的权重等进行多版本灰度测试、流量迁移等功能
4.2.1.1 基于请求匹配
基于请求特征做路由匹配,例如http request header: headers[“x-http-flow-control”],可以按随机比例 或者 等价 进行匹配
类似于istio的路由规则
4.2.1.2 基于上游匹配
基于上游匹配是从线视角出发,UFC的线视角如下:
为啥要做基于上游匹配,出发点如下:
流量等级:
不同的上游服务重要性也不一样,产生请求的重要性也不一样,于是基于上游的标志设置异构的策略就很有必要。比如网盘的用户文件列表展示服务和多端列表同步服务一样会访问数据库,显然前者比后者重要,用户直接感知,需要区别对待。而如果是重试请求,这里面的重要性又不一样了,为了简化策略配置,目前在将请求权重化,根据若干个请求因素的计算出请求权重,然后根据请求权重执行不同的策略。
具体的实践落地:请求权重可以用于细粒度的降级策略。
机房策略:
上游访问下游,默认是不关注上游请求的来源机房,也不关注下游endpoint的机房归属,流量在机房之间是混连的,那么当时候,要切空机房流量异常麻烦。基于上游请求的机房的标识设置机房路由规则就很有必要了。
具体的实践落地:可以定制机房转发策略,比如流量在同一个物理 或者 逻辑机房内转发,详见下文流量转发里的基于上游转发。
4.2.2 流量转发
从协议、负载均衡、基于上游转发、传输策略四个方面介绍
4.2.2.1 协议
Istio 只支持http/tcp/grpc协议,而业务使用的协议肯定不止这些协议,比如redis/mysql等,如果都支持这些协议以及后续的其它协议,那么兼容的研发成本将非常的高,在用户需求和研发成本之间,UFC找到了折衷的解决方案实现了支持任意协议,具体上是以穿透式和旁路式进行落地的
穿透式请求: 适用场景为http协议控制流,和istio的使用方式一样
旁路式请求: 加强版的DNS,适用场景为http 协议数据流 or 非 http 协议,业务先从UFC拿到一个后端地址,然后业务自己通过这个后端地址访问后端,最后需要回调UFC告知UFC这次通信的结果,方便UFC更新相关数据(比如该后端的访问成功率等,决策是否需要封禁之类的)。通过旁路式解决了任意协议的场景,同时对后端流量进行了管控。
4.2.2.2 负载均衡
采用了比较常见的负载均衡策略,比如轮询、随机、一致性hash(根据业务定义的字段进行hash)
4.2.2.3 基于上游转发
主要的应用在于上下游IDC流量路由上,比如设置完下面的路由表之后,就实现了同(逻辑/物理)机房的流量转发
4.2.2.4 传输策略
主要是从连接策略、超时策略,重试策略介绍的
连接策略:
上游:短连接、长连接 下游:短连接、长连接
超时策略:
基本功能:设置与下游的连接/读写超时,可以被上游请求里的指定参数覆盖超时时间 自动切换:两套超时策略配置,结合故障处理自动切换。常规下T1超时策略(客户端可覆盖),雪崩下T2超时策略。当雪崩的时候自动切换到T2超时策略。这样既可以照顾到常规情况下的请求长尾,又避免了雪崩等场景下下游服务拖跨上游访问。
重试策略:
什么场景下重试:需要分清楚重试的边界。从功能角度看,Service Mesh的功能是保障服务通信成功,所以UFC只在与后端通信失败场景(连接/写/读失败)下才重试,对于业务语义层面的错误,由业务发起重试,UFC不介入重试逻辑。另外,从性能的角度出发,也不该把业务层面的重试下沉到Service Mesh这个基础组件上来,因为涉及到对返回的body做反序列化,这个会影响其它的请求,增加请求耗时。 基本功能:设置与下游交互失败的重试次数 自动切换:两套重试策略,结合故障处理自动切换。常规下重试,雪崩下不重试,当雪崩的时候自动切换到不重试。这样既可以照顾到常规情况下少量的异常,又避免了雪崩等场景下加剧下游的雪崩,减少无意义的重试请求。
4.2.3 故障处理
从故障的范围影响上分成:
单点故障:少量后端异常,比如进程因为oom 挂掉 或者 因为机器异常导致进程异常 服务级别故障:当多个单点故障之后,就引发了服务级别的故障,比如服务雪崩。另外业务自身异常(比如全部返回5xx)不在处理范畴内
从故障处理流程上分成:
发现故障: 怎么定位故障的发生,包括单点/服务级别故障 处理故障:怎么处理使得单点/服务故障能够恢复
4.2.3.1 单点故障
故障处理具体发现故障和解决故障两方面的内容,难点在于发现单点故障的准确性,是否存在漏判
发现故障
基于请求: 单次异常:连接异常(连接超时/拒绝/Reset等)、读写异常(读写超时等) 判断标准:N次请求里M次请求异常 基于业务: 业务维度:http status code、耗时等 判断标准:单个后端和平均值(算平均值的时候需要排除掉比较对象的数据)做比较,看哪个后端严重偏离平均值,比如状态码区间比例之类的。这里没有采用单次异常判断是因为有些场景下,通过单次请求是无法判断为异常的,比如一个后端返回404的http status code,这个是符合预期的?没人知道,因为常规情况下业务也会返回404,而在LNMP架构里,如果单个实例磁盘问题导致PHP文件丢失,Nginx找不到PHP文件,也会返回404,这是一个混沌的状态。UFC的解决方案,就是和平均值进行比较,看是否偏离平均值。以 下图后端状态码区间比例统计为例子,后端2 4xx的http code达到了100%,而其它的后端这个比例也只有不到5%,那么大概率后端2 就存在问题。
解决故障
处理:初始封禁T时间 封禁收敛:后端连续封禁时间翻倍,解决异常后端被反复解封、封禁的场景 封禁闭环:长时间封禁的后端,通知paas进行异常实例的迁移 封禁backup机制:达到最大封禁比例,通知人工介入处理 恢复:当封禁时间到了之后,检测端口是否可用,可用则解封
4.2.3.2 服务故障
主要是针对雪崩过载的场景下如何尽量保障服务可用,也是从发现故障和解决故障进行介绍的,难点在于如何减少故障带来的业务流量损失
发现故障
基于通信成功率:下游服务N次请求里成功率低于X% 基于业务语义成功率: UFC没采用的原因是不能越俎代庖做自己能力之外的事情,Service Mesh 核心在于流量控制,它的能力是流量控制来避免下游过载,防止雪崩,例如业务代码bug导致的成功率下降,Service Mesh 也没有办法
解决故障
PS: 动态熔断的思想是借鉴了网络,当雪崩过载的时候,相当于发生了请求的拥塞,和网络拥塞是一样的特征行为,网络链路都带宽相当于服务的容量
4.2.4 仪表盘
仪表盘基于数据源进行分析得到以下内容
分布式服务的日志追踪 业务度量数据的收集/分析/展示
4.2.4.1 数据源
有两方面的数据源:
服务通信access日志:通过日志传输进行聚合分析 何时由上游A对下游B进行访问,请求通过了后端X1/X2进行访问,重试了N次,耗时为T1/T2等,状态码为S1/S2等 异常行为:业务层面比如服务熔断等,系统层面比如封禁计数器异常等,由agent实时上报到中心做聚合分析
4.2.4.2 distributed traces
首先基于服务通信access日志做链路分析,然后将链路信息存入Elasticsearch方便检索,比如下图就是一个链路检索
4.2.4.3 metrics
从点、线、面视角上进行数据的聚合分析
**点视角:**后端维度
服务后端异常监控:
单实例异常触发封禁 :触发封禁的后端,长时间封禁走paas迁移流程
**服务触发熔断:**触发服务动态熔断降级
**线视角:**上下游维度
**服务下游监控:**服务访问所有下游的概貌,支持按http 状态码和idc做过滤,同时支持环比(昨天/一周前)。下面以视频转码为例子,展示对若干个下游的访问概貌:
请求数: 可以根据曲线分析是否存在异常
**请求失败数:**根据失败数量可以算出上游对下游的请求sla
请求耗时: 可以比较昨天/上周的耗时数据,看是否存在异常
**服务上游监控:**服务被所有上游访问的概貌,可以按http 状态码和idc粒度进行过滤,同时支持环比(昨天/一周前)。下面以一个异步化服务为例子,被一堆的上游访问,统计这些上游的访问概貌:
请求数: 在定位服务的请求数突增,可以很容易识别出是哪个上游导致的
**请求失败数:**如果一些上游访问失败数比较高,可以联系业务进行分析定位
请求耗时: 可以比较昨天/上周的耗时数据,看是否存在异常
**面视角:**全局视角
**核心功能链路SLA监控:**当链路sla降低的时候,可以很快定位到是哪个链路分支出现的异常
**耗时维度:**全部服务里,耗时增加top 10 业务,快速知晓业务概貌
业务失败率维度: 全部服务里,失败数最多的top 10业务,快速知晓业务概貌
**机器维度:**全部机器里,请求5xx失败最高的机器 top 10,快速知晓机器异常
5 服务治理
5.1 服务治理的定义
如前文所述,服务治理是建立在Service Mesh基础能力之上的,站在全局视角统筹规划,以保障服务稳定性为出发点。
5.2 具体实践
服务治理的意义:如下图所示,百度网盘全局拓扑异常复杂,靠传统的人工套路去保障服务稳定性,效率和覆盖面都有很大的缺陷,基于流量控制的service mesh进行服务治理才是王道,具体从故障预防、故障定位和故障处理出发。
5.2.1 故障预防
故障预防从以下三个维度进行:
流量隔离:如何规避低优先级的请求流量影响高优先级的请求,避免喧宾夺主
容量管理:如何保障服务容量满足实际需求,避免容量不足导致雪崩
无效请求: 如何减少无效的请求,避免服务陷入雪崩的危机之中
5.2.1.1 流量隔离
具体落地中又分成机房流量隔离以及在离线流量隔离:
**机房流量隔离:**统一网盘所有服务逻辑IDC映射关系,UFC 自动识别上游所在机房,将请求转发到下游服务相应机房,从入口到请求终端,以逻辑IDC机房维度进行了流量隔离。当发生机房故障的时候,入口处切流量即可解决机房故障
**在离线流量隔离:**定义网盘所有服务的等级,包括在离线标记,UFC根据全局流量拓扑,可以发现是否存在在离线混连情况,避免低优先级的请求流量影响高优先级的请求,导致喧宾夺主。比如下图中,Online-a 和 Offline-a都访问Online-b服务,这样Offline-a 有可能引发Online-b服务异常,而从影响Online-a与Online-b的请求,间接影响用户请求。发现这种在离线混连的情况,需要对服务进行拆分,Online-b/Onine-c各自拆分成Onine和Offline两套服务,进行在离线流量的隔离
5.2.1.2 容量管理
具体落地中又分成容量评估以及容量压测,前置是根据链路拓扑做评估,后者是通过压测实践验证评估的准确性:
**容量评估:**通过链路上的qps,分析出每个服务需要增加的qps,进一步推算出需要扩容多少实例(PS:需要解决环路的问题)
容量压测: 通过以线上流量以机房切流量逐渐加压的方式来压测,期间监控服务sla,低于某个阈值之后,自动停止压测
5.2.1.3 无效请求
**无效请求产生的背景:**当client断开连接之后,server还在继续访问其它的后端,进行无效的请求。比如下图中,client以300ms的超时时间访问server,server在访问A和B之后,已经用掉了300ms,这个时候client已经断开了和server的连接,但是server却继续访问C和D,进行无效的请求。当这种无效请求在整个链路蔓延开,client又在大量的重试的时候,就是雪崩降临的时刻。
**解决方案 - 基本思路:**基于链路的智能超时,设置整个链路的超时时间,当发现超时时间已经到了,就不再访问其它的下游服务,避免无效请求。上游需要传递给下游执行超时时间(采用相对时间,避免机器之间的时钟不同步),用于下游判断执行时间是否已经到了
**解决方案 - 基于业务:**不需要使用service mesh,业务自己维护当前的超时时间,业务改造的成本比较大
**解决方案 - 基于service mesh:**UFC以唯一ID映射到一个请求到所有后端交互的链路上,UFC自动维护剩余的请求耗时,实现对业务近视0侵入(PS:还未用于生产环境)
5.2.2 故障定位
定位的思路为:发现异常 –> 收集系统异常点/异常时间点相关变动 –> 定位原因
除了基于service mesh采集系统的异常点,还需要联动其它的系统监控项,比如服务容量
5.2.3 故障处理
根据故障的影响面可以分成局部/全局雪崩故障
5.2.3.1 局部故障
前置条件:
部署:服务部署在多个逻辑机房 上线:服务分级发布,单点 -> 单机房 -> 全机房
场景:通过机房切流量快速解决机房硬件故障、小流量上线引发故障、后端异常封禁失败等局部异常
5.2.3.2 全局雪崩故障
前置条件:
等级:需要定义服务/流量的等级 统一降级标记:统一所有服务的降级标记
场景:通过全局动态熔断 + 异构降级 + 降级闭环策略解决服务引起的雪崩问题,尽量保障服务的可用度,具备自愈能力
6 总结与展望
在业务拆分面多众多问题的背景之下,百度网盘从2015年底开始思考解决方案,确定了解决问题的核心在于管控请求流量,在2016年开始自研网络流量转发中间件 - UFC(Unified Flow Control),业务通过同机部署的agent进行服务通信。后来通过调研借鉴业界技术的时候发现UFC和Service Mesh的设计理念是一致的,都是基于sidecar模式,有着控制面板和数据面板,UFC是Service Mesh的一种实现。经过多年的线上实践验证,UFC这个Service Mesh实现了动态熔断 + 异构降级 + 降级闭环等故障处理、结合故障/上游进行流量转发等创造性设计,满足业务的实际场景需求。但是百度网盘的实践落地并不只局限于Service Mesh,首先是构建了从点延伸到线的Service Mesh进行服务通信管控,然后是在UFC这个Service Mesh的基础之上,站在全局视角对服务进行治理,保障服务的稳定性。
未来,UFC将会加入故障注入等能力,同时基于该能力落地混沌工程,而这只是服务治理中预防的一部分。服务治理的目标是自愈,为了完成这个目标,还需要更加努力。
作者介绍
本文作者李鸿斌,百度资深研发工程师。2011 年毕业后加入百度的基础架构部门,参与了百度分布式云存储的设计与开发,支撑了百度所有业务线的对象存储。2012 年至今,作为核心研发人员参与了网盘从 0 到 1 到 N 的基础架构演进,先后参与或负责对象存储 / 个人文件存储 / runtime 基础环境 / 资源管理 / 微服务架构,设计并实现了计算混布于万级别在线存储机器的资源模型以及服务资源调度,节省下了数万台服务器的计算资源,产品线资源利用率公司第一,同时从 2016 年至今主导了自研的 Service Mesh- UFC(Unified Flow Control),实现了从点到线到面的服务治理保障了网盘服务的高可用,近期专注于边缘计算方向,此外业余时间反哺社区,php-src/hhvm/beego 等源码贡献者。 本文由百度开发者中心发布,一个面向开发者的知识分享平台,专注于为开发者打造一个有温度的技术交流社区,开发者通过平台来分享知识、相互交流。 developer 发布!
云计算
2020-01-22 11:19:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
作者 | 汤志敏,阿里云容器服务高级技术专家 在 2019 年 双11 中,容器服务 ACK 支撑了阿里巴巴内部核心系统容器化和阿里云的云产品本身,也将阿里巴巴多年的大规模容器技术以产品化的能力输出给众多围绕 双11 的生态公司。通过支撑来自全球各行各业的容器云,容器服务沉淀了支持单元化全球化架构和柔性架构的云原生应用托管中台能力,管理了超过 1W 个以上的容器集群。本文将会介绍容器服务在海量 Kubernetes 集群管理上的实践经验。
什么是海量 Kubernetes 集群管理?
大家可能之前看过一些分享,介绍了阿里巴巴如何管理单集群 1W 节点的最佳实践,管理大规模节点是一个很有意思的挑战。不过这里讲的海量 Kubernetes 集群管理,会侧重讲如何管理超过 1W 个以上不同规格的 Kubernetes 集群。根据我们和一些同行的沟通,往往一个企业内部只要管理几个到几十个 Kubernetes 集群,那么我们为什么需要考虑管理如此庞大数量的 Kubernetes 集群? 首先,容器服务 ACK 是阿里云上的云产品,提供了 Kubernetes as a Service 的能力,面向全球客户,目前已经在全球 20 个地域支持; 其次,得益于云原生时代的发展,越来越多的企业拥抱 Kubernetes,Kubernetes 已经逐渐成为云原生时代的基础设施,成为 platform of platform。
背景介绍
首先我们一起来看下托管这些 Kubernetes 集群的痛点:
1.集群种类不同:有标准的、无服务器的、AI 的、裸金属的、边缘、Windows 等 Kubernetes 集群。不同种类的集群参数、组件和托管要求不一样,并且需要支撑更多面向垂直场景的 Kubernetes;
2.集群大小不一:每个集群规模大小不一,从几个节点到上万个节点,从几个 service 到几千个 service 等,需要能够支撑每年持续几倍集群数量的增长;
3.集群安全合规:分布在不同的地域和环境的 Kubernetes 集群,需要遵循不同的合规性要求。比如欧洲的 Kubernetes 集群需要遵循欧盟的 GDPR 法案,在中国的金融业和政务云需要有额外的等级保护等要求;
4.集群持续演进:需要能够持续的支持 Kubernetes 的新版本新特性演进。
设计目标: 支持单元化的分档管理、容量规划和水位管理; 支持全球化的部署、发布、容灾和可观测性; 支持柔性架构的可插拔、可定制、积木式的持续演进能力。
1.支持单元化的分档管理、容量规划和水位管理
单元化
一般讲到单元化,大家都会联想到单机房容量不够或二地三中心灾备等场景。那单元化和 Kubernetes 管理有什么关系?
对我们来说,一个地域(比如:杭州)可能会管理几千个 Kubernetes,需要统一维护这些 Kubernetes 的集群生命周期管理。作为一个 Kubernetes 专业团队,一个朴素的想法就是通过多个 Kubernetes 元集群来管理这些 guest K8s master。而一个 Kubernetes 元集群的边界就是一个单元。
曾经我们经常听说某某机房光纤被挖断,某某机房电力因故障而导致服务中断,容器服务 ACK 在设计之初就支持了同城多活的架构形态,任何一个用户 Kubernetes 集群的 master 组件都会自动地分散在多个机房,不会因单机房问题而影响集群稳定性;另外一个层面,同时要保证 master 组件间的通信稳定性,容器服务 ACK 在打散 master 时调度策略上也会尽量保证 master 组件间通信延迟在毫秒级。
分档化
大家都知道,Kubernetes 集群的 master 组件的负载主要与 Kubernetes 集群的节点规模、worker 侧的 controller 或 workload 等需要与 kube-apiserver 交互的组件数量和调用频率息息相关,对于上万个 Kubernetes 集群,每个用户 Kubernetes 集群的规模和业务形态都千差万别,我们无法用一套标准配置来去管理所有的用户 Kubernetes 集群。
同时,从成本经济角度考虑,我们提供了一种更加灵活、更加智能的托管能力。考虑到不同资源类型会对 master 产生不同的负载压力,因此我们需要为每类资源设置不同的因子,最终可归纳出一个计算范式,通过此范式可计算出每个用户 Kubernetes 集群 master 所适应的档位。另外,我们也会基于已构建的 Kubernetes 统一监控平台实时指标来不断地优化和调整这些因素值和范式,从而可实现智能平滑换挡的能力。
容量规划
接下来我们看下 Kubernetes 元集群的容量模型,单个元集群到底能托管多少个用户 Kubernetes 集群的 master? 首先,要确认容器网络规划。这里我们选择了阿里云自研的高性能容器网络 Terway, 一方面需要通过弹性网卡 ENI 打通用户 VPC 和托管 master 的网络,另一方面提供了高性能和丰富的安全策略; 接下来,我们需要结合 VPC 内的 ip 资源,做网段的规划,分别提供给 node、pod 和 service。 最后,我们会结合统计规律,结合成本、密度、性能、资源配额、档位配比等多种因素的综合考量,设计每个元集群单元中部署的不同档位的 guest Kubernetes 的个数,并预留 40% 的水位。
2.支持全球化的部署、发布、容灾和可观测性
容器服务已经在全球 20 个地域支持,我们提供了完全自动化的部署、发布、容灾和可观测性能力,接下来将重点介绍全球化跨数据中心的可观测。
全球跨数据中心的可观测性
全球化布局的大型集群的可观测性,对于 Kubernetes 集群的日常保障至关重要。如何在纷繁复杂的网络环境下高效、合理、安全、可扩展的采集各个数据中心中目标集群的实时状态指标,是可观测性设计的关键与核心。
我们需要兼顾区域化数据中心、单元化集群范围内可观测性数据的收集,以及全局视图的可观测性和可视化。基于这种设计理念和客观需求,全球化可观测性必须使用多级联合方式,也就是边缘层的可观测性实现下沉到需要观测的集群内部,中间层的可观测性用于在若干区域内实现监控数据的汇聚,中心层可观测性进行汇聚、形成全局化视图以及告警。
这样设计的好处在于可以灵活地在每一级别层内进行扩展以及调整,适合于不断增长的集群规模,相应的其他级别只需调整参数,层次结构清晰;网络结构简单,可以实现内网数据穿透到公网并汇聚。
针对该全球化布局的大型集群的监控系统设计,对于保障集群的高效运转至关重要,我们的设计理念是在全球范围内将各个数据中心的数据实时收集并聚合,实现全局视图查看和数据可视化,以及故障定位、告警通知。
进入云原生时代,Prometheus 作为 CNCF 第二个毕业的项目,天生适用于容器场景,Prometheus 与 Kubernetes 结合一起,实现服务发现和对动态调度服务的监控,在各种监控方案中具有很大的优势,实际上已经成为容器监控方案的标准,所以我们也选择了 Prometheus 作为方案的基础。
针对每个集群,需要采集的主要指标类别包括: OS 指标,例如节点资源(CPU, 内存,磁盘等)水位以及网络吞吐; 元集群以及用户集群 Kubernetes master 指标,例如 kube-apiserver, kube-controller-manager, kube-scheduler 等指标; Kubernetes 组件(kubernetes-state-metrics,cadvisor)采集的关于 Kubernetes 集群状态; etcd 指标,例如 etcd 写磁盘时间,DB size,Peer 之间吞吐量等等。
当全局数据聚合后,AlertManager 对接中心 Prometheus,驱动各种不同的告警通知行为,例如钉钉、邮件、短信等方式。
监控告警架构
为了合理地将监控压力负担分到多个层次的 Prometheus 并实现全局聚合,我们使用了联邦 Federation 的功能。在联邦集群中,每个数据中心部署单独的 Prometheus,用于采集当前数据中心监控数据,并由一个中心的 Prometheus 负责聚合多个数据中心的监控数据。
基于 Federation 的功能,我们设计的全球监控架构图如下,包括监控体系、告警体系和展示体系三部分。
监控体系按照从元集群监控向中心监控汇聚的角度,呈现为树形结构,可以分为三层: 边缘 Prometheus
为了有效监控元集群 Kubernetes 和用户集群 Kubernetes 的指标、避免网络配置的复杂性,将 Prometheus 下沉到每个元集群内。 级联 Prometheus
级联 Prometheus 的作用在于汇聚多个区域的监控数据。级联 Prometheus 存在于每个大区域,例如中国区、欧洲区、美洲区、亚洲区。每个大区域内包含若干个具体的区域,例如北京、上海、东京等。随着每个大区域内集群规模的增长,大区域可以拆分成多个新的大区域,并始终维持每个大区域内有一个级联 Prometheus,通过这种策略可以实现灵活的架构扩展和演进。 中心 Prometheus
中心 Prometheus 用于连接所有的级联 Prometheus,实现最终的数据聚合、全局视图和告警。为提高可靠性,中心 Prometheus 使用双活架构,也就是在不同可用区布置两个 Prometheus 中心节点,都连接相同的下一级 Prometheus。
图2-1 基于 Prometheus Federation 的全球多级别监控架构
优化策略
1.监控数据流量与 API server 流量分离
API server 的代理功能可以使得 Kubernetes 集群外通过 API server 访问集群内的 Pod、Node 或者 Service。
图3-1 通过 API Server 代理模式访问 Kubernetes 集群内的 Pod 资源
常用的透传 Kubernetes 集群内 Prometheus 指标到集群外的方式是通过 API server 代理功能,优点是可以重用 API server 的 6443 端口对外开放数据,管理简便;缺点也明显,增加了 API server 的负载压力。
如果使用 API Server 代理模式,考虑到客户集群以及节点都会随着售卖而不断扩大,对 API server 的压力也越来越大并增加了潜在的风险。对此,针对边缘 Prometheus 增加了 LoadBalancer 类型的 service,监控流量完全 LoadBalancer,实现流量分离。即便监控的对象持续增加,也保证了 API server 不会因此增加 Proxy 功能的开销。
2.收集指定 Metric
在中心 Prometheus 只收集需要使用的指标,一定不能全量抓取,否则会造成网络传输压力过大丢失数据。
3.Label 管理
Label 用于在级联 Prometheus 上标记 region 和元集群,所以在中心 Prometheus 汇聚是可以定位到元集群的颗粒度。同时,尽量减少不必要的 label,实现数据节省。
3.支持柔性架构的可插拔、可定制、积木式的持续演进能力
前面两部分简要描述了如何管理海量 Kubernetes 集群的一些思考,然而光做到全球化、单元化的管理还远远不够。Kubernetes 能够成功,包含了声明式的定义、高度活跃的社区、良好的架构抽象等因素,Kubernetes 已经成为云原生时代的 Linux。
我们必须要考虑 Kubernetes 版本的持续迭代和 CVE 漏洞的修复,必须要考虑 Kubernetes 相关组件的持续更新,无论是 CSI、CNI、Device Plugin 还是 Scheduler Plugin 等等。为此我们提供了完整的集群和组件的持续升级、灰度、暂停等功能。
组件可插拔
组件检查
组件升级
2019 年 6 月,阿里巴巴将内部的云原生应用自动化引擎 OpenKruise 开源,这里我们重点介绍下其中的 BroadcastJob 功能,它非常适用于每台 worker 机器上的组件进行升级,或者对每台机器上的节点进行检测。(Broadcast Job 会在集群中每个 node 上面跑一个 pod 直至结束。类似于社区的 DaemonSet, 区别在于 DaemonSet 始终保持一个 pod 长服务在每个 node 上跑,而 BroadcastJob 中最终这个 pod 会结束。)

集群模板
此外,考虑不同 Kubernetes 使用场景,我们提供了多种 Kubernetes 的 cluster profile,可以方便用户进行更方便的集群选择。我们会结合大量集群的实践,持续提供更多更好的集群模板。
总结
随着云计算的发展,以 Kubernetes 为基础的云原生技术持续推动行业进行数字化转型。
容器服务 ACK 提供了安全稳定、高性能的 Kubernetes 托管服务,已经成为云上运行 Kubernetes 的最佳载体。在本次 双11,容器服务 ACK 在各个场景为 双11 做出贡献,支撑了阿里巴巴内部核心系统容器化上云,支撑了阿里云微服务引擎 MSE、视频云、CDN 等云产品,也支撑了 双11 的生态公司和 ISV 公司,包括聚石塔电商云、菜鸟物流云、东南亚的支付系统等等。
容器服务 ACK 会持续前行,持续提供更高更好的云原生容器网络、存储、调度和弹性能力、端到端的全链路安全能力、serverless 和 servicemesh 等能力。
有兴趣的开发者,可以前往 阿里云控制台 ,创建一个 Kubernetes 集群来体验。同时也欢迎容器生态的合作伙伴加入阿里云的容器应用市场,和我们一起共创云原生时代。
云原生实践峰会即将开幕
云计算
2020-01-20 22:06:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
在分布式系统中,为了保证数据的高可用,通常会将数据保留多个副本(replica), 这些副本会放置在不同的节点上。这些数据节点可能是物理机器,也可能是虚拟机。为了对用户提供正确的CURD等语意,我们需要保证这些放置在不同节点上的副本是一致的,这就涉及分布式事务的问题。
本文介绍分布式事务处理方案之一的两阶段提交协议。
分布式事务
分布式事务是指发生在多个数据节点之间的事务,分布式事务比单机事务要复杂的多。在分布式系统中,各个节点之间在是相互独立的,需要通过网络进行沟通和协调。由于存在事务机制,可以保证每个独立节点上的数据操作可以满足ACID。但是,相互独立的节点之间无法准确地知道其他节点的事务执行情况。所以从理论上来讲,两个节点的数据是无法达到一致的状态。如果想让分布式部署的多个节点中的数据保持一致性,那么就要保证在所有节点数据的写操作,要么全部都执行,要么全部都不执行。但是,一台机器在执行本地事务的时候无法知道其他机器中的本地事务的执行结果,所以它也就不知道本次事务到底应该commit还是rollback。所以,常规的解决办法就是引入一个"协调者"的组件来统一调度所有分布式节点的执行。
为了解决这种分布式一致性问题,前人在性能和数据一致性的反反复复权衡过程中总结了许多典型的协议和算法。其中比较著名的有二阶提交协议(Two Phase Commitment Protocol)、三阶提交协议(Three Phase Commitment Protocol)和Paxos算法。针对分布式事务,是X/Open 这个组织定义的一套分布式事务的标准X/Open DTP(X/Open Distributed Transaction Processing ReferenceModel),定义了规范和API接口,可以由各个厂商进行具体的实现。
大部分的关系型数据库通过两阶段提交(Two Phase Commit,2PC)算法来完成分布式事务,比如Oracle中通过dblink方式进行事务处理。下面重点介绍下2PC算法。
两阶段提交概述
两阶段提交协议最早是分布式事务的专家Jim Gray在1978年的一篇文章Notes on Database Operating Systems中提及。两阶段提交协议可以保证数据的强一致性,即保证了分布式事务的原子性:所有结点要么全做要么全不做。许多分布式关系型数据管理系统采用此协议来完成分布式事务。它是协调所有分布式原子事务参与者,并决定提交或取消(回滚)的分布式算法。同时也是解决一致性问题的算法。该算法能够解决很多的临时性系统故障(包括进程、网络节点、通信等故障),被广泛地使用。但是,它并不能够通过配置来解决所有的故障,在某些情况下它还需要人为的参与才能解决问题。
顾名思义,两阶段提交分为以下两个阶段: 准备阶段(Prepare Phase) 提交阶段(Commit Phase)
在两阶段提交协议中,系统一般包含两类角色: 协调者(Coordinator),通常一个系统中只有一个; 参与者(Participant),一般包含多个,在数据存储系统中可以理解为数据副本的个数。
准备阶段
在准备阶段,协调者将通知事务参与者准备提交或取消事务,写本地的redo和undo日志,但不提交,然后进入表决过程。在表决过程中,参与者将告知协调者自己的决策:同意(事务参与者本地作业执行成功)或取消(本地作业执行故障)。
协调者协议流程如下: 写本地日志“BEGIN_COMMIT”,并进入WAIT状态; 向所有参与者发送“VOTE_REQUEST”消息; 等待并接收参与者发送的对“VOTE_REQUEST”的响应。参与者响应“VOTE_ABORT”或“VOTE_COMMIT”消息给协调者。
提交阶段
在该阶段,协调者将基于第一个阶段的投票结果进行决策:提交或取消。当且仅当所有的参与者同意提交事务协调者才通知所有的参与者提交事务,否则协调者将通知所有的参与者取消事务。参与者在接收到协调者发来的消息后将执行响应的操作。
协调者协议流程如下: 若收到任何一个参与者发送的“VOTE_ABORT”消息; 写本地“GLOBAL_ABORT”日志,进入ABORT状态; 向所有的参与者发送“GLOBAL_ABORT”消息; 若收到所有参与者发送的“VOTE_COMMIT”消息; 写本地“GLOBAL_COMMIT”日志,进入COMMIT状态; 向所有的参与者发送“GLOBAL_COMMIT”消息; 等待并接收参与者发送的对“GLOBAL_ABORT”消息或“GLOBAL_COMMIT”消息的确认响应消息,一旦收到所有参与者的确认消息,写本地“END_TRANSACTION”日志流程结束。
两阶段提交状态机
下图为两阶段提交协议中的协调者及参与者的状态机。左侧a为协调者状态机;右侧b为参与者状态机。
实际案例
MySQL从5.5版本开始支持,SQL Server 2005开始支持,Oracle 7开始支持。
两阶段提交的缺陷
一般情况下,两阶段提交机制都能较好的运行,当在事务进行过程中,有参与者宕机时,重启以后,可以通过询问其他参与者或者协调者,从而知道这个事务到底提交了没有。当然,这一切的前提都是各个参与者在进行每一步操作时,都会事先写入日志。
两阶段提交不能解决的困境如下: 同步阻塞问题。执行过程中,所有参与节点都是事务阻塞型的。当参与者占有公共资源时,其他第三方节点访问公共资源不得不处于阻塞状态。 单点故障。由于协调者的重要性,一旦协调者发生故障,参与者会一直阻塞下去。尤其在第二阶段,协调者发生故障,那么所有的参与者还都处于锁定事务资源的状态中,而无法继续完成事务操作。(如果是协调者挂掉,可以重新选举一个协调者,但是无法解决因为协调者宕机导致的参与者处于阻塞状态的问题) 数据不一致。在二阶段提交的阶段二中,当协调者向参与者发送commit请求之后,发生了局部网络异常或者在发送commit请求过程中协调者发生了故障,这回导致只有一部分参与者接受到了commit请求。而在这部分参与者接到commit请求之后就会执行commit操作。但是其他部分未接到commit请求的机器则无法执行事务提交。于是整个分布式系统便出现了数据不一致性的现象。
参考引用 本文同步至: https://waylau.com/two-phase-commitment-protocol/ Distributed systems: principles and paradigms Notes on Database Operating Systems 分布式系统常用技术及案例分析: https://github.com/waylau/distributed-systems-technologies-and-cases-analysis
云计算
2019-12-11 20:00:00
部署生产级的 Kubernetes 集群,使用kubespray 项目源码, https://github.com/openthings/kubespray 国内部署, https://github.com/zhangguanzhang/Kubernetes-ansible
欢迎加入 kubernetes slack , channel #kubespray . 获得邀请从这里 here 可以部署到 AWS, GCE, Azure, OpenStack, vSphere, Oracle Cloud Infrastructure (Experimental), 或 Baremetal Highly available cluster Composable (Choice of the network plugin for instance) Supports most popular Linux distributions Continuous integration tests
快速开始
To deploy the cluster you can use :
Ansible # Install dependencies from ``requirements.txt`` sudo pip install -r requirements.txt # Copy ``inventory/sample`` as ``inventory/mycluster`` cp -rfp inventory/sample/* inventory/mycluster # Update Ansible inventory file with inventory builder declare -a IPS=(10.10.1.3 10.10.1.4 10.10.1.5) CONFIG_FILE=inventory/mycluster/hosts.ini python3 contrib/inventory_builder/inventory.py ${IPS[@]} # Review and change parameters under ``inventory/mycluster/group_vars`` cat inventory/mycluster/group_vars/all.yml cat inventory/mycluster/group_vars/k8s-cluster.yml # Deploy Kubespray with Ansible Playbook ansible-playbook -i inventory/mycluster/hosts.ini cluster.yml
Note: When Ansible is already installed via system packages on the control machine, other python packages installed via sudo pip install -r requirements.txt will go to a different directory tree (e.g. /usr/local/lib/python2.7/dist-packages on Ubuntu) from Ansible's (e.g. /usr/lib/python2.7/dist-packages/ansible still on Ubuntu). As a consequence, ansible-playbook command will fail with: ERROR! no action detected in task. This often indicates a misspelled module name, or incorrect module path.
probably pointing on a task depending on a module present in requirements.txt (i.e. "unseal vault").
One way of solving this would be to uninstall the Ansible package and then, to install it via pip but it is not always possible. A workaround consists of setting ANSIBLE_LIBRARY and ANSIBLE_MODULE_UTILS environment variables respectively to the ansible/modules and ansible/module_utils subdirectories of pip packages installation location, which can be found in the Location field of the output of pip show [package] before executing ansible-playbook .
Vagrant
For Vagrant we need to install python dependencies for provisioning tasks. Check if Python and pip are installed: python -V && pip -V
If this returns the version of the software, you're good to go. If not, download and install Python from here https://www.python.org/downloads/source/ Install the necessary requirements sudo pip install -r requirements.txt vagrant up
Documents Requirements Kubespray vs ... Getting started Ansible inventory and tags Integration with existing ansible repo Deployment data variables DNS stack HA mode Network plugins Vagrant install CoreOS bootstrap Debian Jessie setup openSUSE setup Downloaded artifacts Cloud providers OpenStack AWS Azure vSphere Large deployments Upgrades basics Roadmap
Supported Linux Distributions Container Linux by CoreOS Debian Jessie, Stretch, Wheezy Ubuntu 16.04, 18.04 CentOS/RHEL 7 Fedora 28 Fedora/CentOS Atomic openSUSE Leap 42.3/Tumbleweed
Note: Upstart/SysV init based OS types are not supported.
Supported Components Core kubernetes v1.11.3 etcd v3.2.18 docker v17.03 (see note) rkt v1.21.0 (see Note 2) Network Plugin calico v3.1.3 canal (given calico/flannel versions) cilium v1.2.0 contiv v1.1.7 flanneld v0.10.0 weave v2.4.1 Application cephfs-provisioner v2.1.0-k8s1.11 cert-manager v0.5.0 coredns v1.2.2 ingress-nginx v0.19.0
Note: kubernetes doesn't support newer docker versions ("Version 17.03 is recommended... Versions 17.06+ might work, but have not yet been tested and verified by the Kubernetes node team" cf. Bootstrapping Clusters with kubeadm ). Among other things kubelet currently breaks on docker's non-standard version numbering (it no longer uses semantic versioning). To ensure auto-updates don't break your cluster look into e.g. yum versionlock plugin or apt pin).
Note 2: rkt support as docker alternative is limited to control plane (etcd and kubelet). Docker is still used for Kubernetes cluster workloads and network plugins' related OS services. Also note, only one of the supported network plugins can be deployed for a given single cluster.
Requirements Ansible v2.4 (or newer) and python-netaddr is installed on the machine that will run Ansible commands Jinja 2.9 (or newer) is required to run the Ansible Playbooks The target servers must have access to the Internet in order to pull docker images. The target servers are configured to allow IPv4 forwarding . Your ssh key must be copied to all the servers part of your inventory. The firewalls are not managed , you'll need to implement your own rules the way you used to. in order to avoid any issue during deployment you should disable your firewall. If kubespray is ran from non-root user account, correct privilege escalation method should be configured in the target servers. Then the ansible_become flag or command parameters --become or -b should be specified.
Network Plugins
You can choose between 6 network plugins. (default: calico , except Vagrant uses flannel ) flannel : gre/vxlan (layer 2) networking. calico : bgp (layer 3) networking. canal : a composition of calico and flannel plugins. cilium : layer 3/4 networking (as well as layer 7 to protect and secure application protocols), supports dynamic insertion of BPF bytecode into the Linux kernel to implement security services, networking and visibility logic. contiv : supports vlan, vxlan, bgp and Cisco SDN networking. This plugin is able to apply firewall policies, segregate containers in multiple network and bridging pods onto physical networks. weave : Weave is a lightweight container overlay network that doesn't require an external K/V database cluster. (Please refer to weave troubleshooting documentation ).
The choice is defined with the variable kube_network_plugin . There is also an option to leverage built-in cloud provider networking instead. See also Network checker .
Community docs and resources kubernetes.io/docs/getting-started-guides/kubespray/ kubespray, monitoring and logging by @gregbkr Deploy Kubernetes w/ Ansible & Terraform by @rsmitty Deploy a Kubernetes Cluster with Kubespray (video)
Tools and projects on top of Kubespray Digital Rebar Provision Fuel-ccp-installer Terraform Contrib
CI Tests
CI/end-to-end tests sponsored by Google (GCE) See the test matrix for details.
云计算
2018-09-21 22:45:00
通过前面Clouder课程的学习,或许你已经掌握了在云服务器上发布和部署静态网页的方法,那么如何搭建一个可以随时更新内容的动态网站?通过本课程的学习,你将掌握如何在云端搭建全世界使用最多的WordPress网站的方法,并学会网站自定义、管理的操作,来实验你想要的功能。
课程链接: 网站建设:简单动态网站搭建
学员受益: 零基础建站:从零开始,一步步教你搭建可以更新内容的动态网站 举一反三:通过网站主题管理和功能添加,可以将网站扩展为个人博客、小型门户、企业网站、视频网站等 认证证书:考试通过即可获得证书,证明自己拥有云平台建站的能力
课时介绍: 课程介绍 网站搭建的类型 动态网站的实现方式 搭建网站运行环境 部署与安装WordPress网站程序 云上WordPress网站的管理 云上WordPress网站的优化 【在线实验】云上快速搭建WordPress网站
更多精品课程:
阿里云大学官网(阿里云大学 - 官方网站,云生态下的创新人才工场)
云计算
2018-09-21 14:34:00
简介
1.分布式数据库中间件 DDM
分布式数据库中间件(Distributed Database Middleware) 是解决数据库容量、性能瓶颈和分布式扩展问题的中间件服务,提供分库分表、读写分离、弹性扩容等能力,应对海量数据的高并发访问场景,有效提升数据库读写性能。
2.MySQL Router
mysql-router是mysql官方的轻量级的中间件,用于取代MySQL Proxy应用程序像访问MySQL一样访问MySQL Router,由MySQL Router将数据转发给后端的DDM节点,实现Sidecar模式负载均衡。
Sidecar模式是一种从应用程序本身剥离应用程序功能作为单独进程的方法。此模式允许我们向应用无侵入添加多种功能,从而无需向应用程序添加其他配置代码。建议MySQL Router与应用程序部署在同一台机器做Sidecar模式负载均衡,相对于服务端形式的负载均衡,Sidecar模式实现负载均衡可以缩短调用链路,减少服务端中心节点的压力,去中心化,使用更加可靠更加高效。

部署Mysql-Router服务
# 解压安装程序文件
tar -xzvf mysql-router-8.0.11-linux-glibc2.12-x86-64bit.tar.gz

# 重命名安装文件夹
mv mysql-router-8.0.11-linux-glibc2.12-x86-64bit /usr/local/mysqlrouter

# 创建日志和配置相关文件存放目录
cd /usr/local/mysqlrouter
mkdir logs
mkdir etc

# 利用模板文件创建配置文件
cp /usr/local/mysqlrouter/share/doc/mysqlrouter/sample_mysqlrouter.conf ./etc/mysqlrouter.conf

# 启动 mysql router
/usr/local/mysqlrouter/bin/mysqlrouter -c /usr/local/mysqlrouter/etc/mysqlrouter.conf &

配置文件详解
首先,获取DDM连接串,如下图所示:

下面详细介绍mysql-router三种配置方式:
01
作为中心代理节使用
mysql-router绑定IP不限制,即监听所有ip,任意节点都可以访问,作为数据库访问代理,轮询DDM各个节点。其中,destinations为上文获得的DDM连接串。
vi /usr/local/mysqlrouter/etc/mysqlrouter.conf

[DEFAULT]
logging_folder = /usr/local/mysqlrouter/log/
plugin_folder = /usr/local/mysqlrouter/lib/mysqlrouter/
config_folder = /usr/local/mysqlrouter/etc/
runtime_folder = /usr/local/mysqlrouter/run/

[logger]
level = INFO

# 负载均衡配置
[routing:balancing]
# 绑定的IP地址
bind_address=0.0.0.0
# 监听的端口
bind_port = 7002
# 连接超时时间(秒)
connect_timeout = 3
# 最大连接数
max_connections = 100
# 后端服务器地址.默认读进行轮询
destinations = 192.168.4.235:5066,192.168.4.231:5066
# 路由策略
routing_strategy=round-robin

[keepalive]
interval = 60

连接示例:
[root @xxx ]# ./mysql -uddmtest -h128.11.2.2 -P7002 -p
Enter password:

mysql>
128.11.2.2为Mysql Router所在IP。

02
作为本地数据库代理使用
mysql-router绑定本地地址127.0.0.1,作为本地数据库访问代理,仅允许当前节点访问数据库。其要求需要访问数据库的应用与router部署在同一节点,更安全可靠。
vi /usr/local/mysqlrouter/etc/mysqlrouter.conf

[DEFAULT]
logging_folder = /usr/local/mysqlrouter/log/
plugin_folder = /usr/local/mysqlrouter/lib/mysqlrouter/
config_folder = /usr/local/mysqlrouter/etc/
runtime_folder = /usr/local/mysqlrouter/run/

[logger]
level = INFO

# 负载均衡配置
[routing:balancing]
# 绑定的IP地址
bind_address=127.0.0.1
# 监听的端口
bind_port = 7002
# 连接超时时间(秒)
connect_timeout = 3
# 最大连接数
max_connections = 100
# 后端服务器地址.默认读进行轮询
destinations = 192.168.4.235:5066,192.168.4.231:5066
# 路由策略
routing_strategy=round-robin

[keepalive]
interval = 60

连接示例:
[root @xxx ]# ./mysql -uddmtest -h127.0.0.1 -P7002 -p
Enter password:

mysql>
mysql客户端与Mysql Router在同一节点。

03
作为本地数据库代理,使用Unix sockets连接(推荐)
mysql-router不绑定ip和端口,只使用Unix sockets连接,这样可以不经过tcp协议转发数据,只走操作系统socket通道,更加高效。其同样要求需要访问数据库的应用与router部署在同一节点,但是安全可靠,且高效。
vi etc/mysqlrouter.conf

[DEFAULT]
logging_folder = /usr/local/mysqlrouter/log/
plugin_folder = /usr/local/mysqlrouter/lib/mysqlrouter/
config_folder = /usr/local/mysqlrouter/etc/
runtime_folder = /usr/local/mysqlrouter/run/

[logger]
level = INFO

# 负载均衡配置
[routing:balancing]
# 绑定的IP端口
socket = /tmp/mysqlrouter.sock
# 连接超时时间(秒)
connect_timeout = 3
# 最大连接数
max_connections = 100
# 后端服务器地址.默认读进行轮询
destinations = 192.168.4.235:5066,192.168.4.231:5066
# 路由策略
routing_strategy=round-robin

[keepalive]
interval = 60
其中,destinations为上文获得的DDM连接串

连接示例:
[root @xxx ]# ./mysql -uddmtest -p -S /tmp/mysqlrouter.sock
Enter password:

mysql>
mysql客户端与Mysql Router在同一节点。
云计算
2018-09-21 10:27:00
如果您的应用程序是面向大量用户、会吸引大量流量,那么一个不变的目标一定是在高效满足用户需求的同时、不让用户感知到任何类似于“服务器繁忙!”的情况。这一诉求的典型解决方案是横向扩展部署,以便有多个应用程序容器可以为用户请求提供服务。但是,这种技术需要可靠的路由功能,需要可以有效地在多个服务器之间分配流量。本文分享的内容就是要解决负载均衡解决方案的问题。
Rancher 1.6是Docker和Kubernetes的容器编排平台,为负载均衡提供了功能丰富的支持。在Rancher 1.6中,用户可以通过使用开箱即用的HAProxy负载均衡器,来提供基于HTTP / HTTPS / TCP主机名/路径的路由。
而在本文中,我们将探讨如何在原生使用Kubernetes进行编排的Rancher 2.0平台上实现这些流行的负载均衡技术。
Rancher 2.0 负载均衡功能
通过Rancher 2.0,用户可以开箱即用地使用由NGINX Ingress Controller支持的原生Kubernetes Ingress功能进行7层负载均衡。因为Kubernetes Ingress仅支持HTTP和HTTPS协议,所以目前如果您使用的是Ingress支持,那么负载均衡仅限于上述这两种协议。
对于TCP协议,Rancher 2.0支持在部署Kubernetes集群的云上配置第4层TCP负载均衡器。后文中我们还将介绍如何通过ConfigMaps为TCP均衡配置NGINX Ingress Controller。
HTTP/HTTPS 负载均衡功能
在Rancher 1.6中,您添加了端口/服务规则以配置HAProxy负载均衡器,以均衡目标服务。您还可以配置基于主机名/路径的路由规则。
例如,下面让我们来看看一个在Rancher 1.6上启动了两个容器的服务。启动的容器正在监听私有80端口。
为了均衡两个容器之间的外部流量,我们可以为应用程序创建一个负载均衡器,如下所示。在这里,我们会配置负载均衡器,将进入端口80的所有流量转发到目标服务的容器端口,然后Rancher 1.6在负载均衡器服务上放置了一个方便的链接到公共端点。

Rancher 2.0提供了一种使用非常相似的、由NGINX Ingress Controller支持的、使用Kubernetes Ingress的负载均衡器功能。下文中我们一起来看看我们该如何做。
Rancher 2.0 Ingress Controller部署
Ingress只是一种规则,控制器组件会将这一规则应用于实际负载均衡器中。实际负载均衡器可以在集群外部运行,也可以在集群中部署。
通过RKE(Rancher Kubernetes安装程序),Rancher 2.0让用户可以开箱即用地在配置的集群上部署NGINX Ingress Controller和负载均衡器,以处理Kubernetes Ingress规则。请注意,NGINX Ingress Controller默认安装在RKE配置的集群上。通过云提供商(如GKE)配置的集群具有自己的Ingress Controller来配置负载均衡器。本文的范围仅适用于使用RKE安装的NGINX Ingress Controller。
RKE将NGINX Ingress Controller部署为Kubernetes DaemonSet——因此NGINX实例会部署在集群中的每个节点上。NGINX就像一个Ingress Controller,在整个集群中监听Ingress创建,它还会将自身配置为满足Ingress规则的负载均衡器。DaemonSet配置有hostNetwork以暴露两个端口——端口80和端口443。有关如何部署NGINX Ingress Controller DaemonSet和部署配置选项的详细信息,请参阅此处:
https://rancher.com/docs/rke/v0.1.x/en/config-options/add-ons/ingress-controllers/
如果您是Rancher 1.6用户,那么将Rancher 2.0 Ingress Controller以DaemonSet的形式部署,会带来一些你需要知悉的重要的改变。
在Rancher 1.6中,您可以在堆栈中部署可扩展的负载均衡器服务。因此,如果您在Cattle环境中有四台主机,则可以部署一台规模为2的负载均衡器服务,并通过端口80在这两个主机IP地址上指向您的应用程序。然后,您还可以在剩余的两台主机上启动另一台负载均衡器,以通过端口80再次均衡不同的服务(因为负载均衡器使用不同的主机IP地址)。
Rancher 2.0 Ingress Controller是一个DaemonSet——因此它全局部署在所有可调度节点上,以便为整个Kubernetes集群提供服务。因此,在对Ingress规则进行编程时,你需要使用唯一的主机名和路径指向工作负载,因为负载均衡器节点IP地址和端口80/443是所有工作负载的公共访问点。
现在让我们看看如何使用Ingress将上述1.6示例部署到Rancher 2.0上。在Rancher UI上,我们可以导航到Kubernetes Cluster和Project,并选择【部署工作负载/Deploy Workloads】功能,在命名空间下部署所需镜像的工作负载。让我们将工作负载的规模设置为两个副本,如下所示:
以下是工作负载选项卡上部署和列出工作负载的方式:
要达到这两个pod之间的均衡,您必须创建Kubernetes Ingress规则。要创建此规则,请导航到您的集群和项目,然后选择“ 负载均衡”选项卡。
与Rancher 1.6中的服务/端口规则类似,您可以在此处指定针对工作负载的容器端口的规则。
基于主机和路径的路由
Rancher 2.0允许您添加基于主机名或URL路径的Ingress规则。根据您的规则,NGINX Ingress Controller将流量路由到多个目标工作负载。下面让我们看看如何使用相同的Ingress规范将流量路由到命名空间中的多个服务。比如如下两个在命名空间中部署的工作负载:
我们可以使用相同的主机名但不同的路径添加Ingress来均衡这两个工作负载的流量。
Rancher 2.0还为Ingress记录中的工作负载提供了方便的链接。如果配置外部DNS以对DNS记录进行编程,则可以将此主机名映射到Kubernetes Ingress地址。
Ingress地址是您的集群中Ingress Controller为您的工作负载分配的IP地址。您可以通过浏览此IP地址来达到工作负载。使用kubectl查看控制器分配入口地址。
您可以使用Curl来测试基于主机名/路径的路由规则是否正常工作,如下所示:

以下是使用基于主机名/路径的规则的Rancher 1.6配置规范,与2.0 Kubernetes Ingress YAML规范进行比较:
HTTPS /证书选项
Rancher 2.0 Ingress功能还支持HTTPS协议。您可以在配置Ingress规则时上载证书并使用它们,如下所示:
添加Ingress规则时选择证书:
Ingress限制
尽管Rancher 2.0支持HTTP- / HTTPS-基于主机名/路径的负载均衡,但要突出的一个重要区别是在为工作负载配置Ingress时需要使用唯一的主机名/路径。原因是Ingress功能仅允许将端口80/443用于路由,负载均衡器和Ingress Controller则可作为DaemonSet全局启动。
从最新的Rancher 2.x版本开始,Kubernetes Ingress不支持TCP协议,但我们将在下一节中讨论使用NGINX Ingress Controller的解决方法。
TCP负载均衡选项 四层负载均衡器
对于TCP协议,Rancher 2.0支持在部署Kubernetes集群的云提供程序中配置四层负载均衡器。为集群配置此负载均衡器设备后,Layer-4 Load Balancer在工作负载部署期间选择for port-mapping 选项时,Rancher会创建Load Balancer服务。此服务会让Kubernetes的相应云提供商配置负载均衡器设备。然后,此设备将外部流量路由到您的应用程序pod。请注意,上述功能需要该Kubernetes云提供商满足负载均衡器服务的要求,按此文档配置:
https://rancher.com/docs/rancher/v2.x/en/cluster-provisioning/rke-clusters/options/cloud-providers/
一旦负载均衡器配置成功,Rancher将在Rancher UI中为您的工作负载的公共端点提供一个链接。 通过ConfigMaps支持NGINX Ingress Controller TCP
如上所述,Kubernetes Ingress本身不支持TCP协议。因此,即使TCP不是NGINX的限制,也无法通过Ingress创建来配置NGINX Ingress Controller以进行TCP负载均衡。
但是,您可以通过创建一个Kubernetes ConfigMap,来使用NGINX的TCP负载均衡功能,具体可参阅这里: https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/exposing-tcp-udp-services.md。您可以创建Kuberenetes ConfigMap对象,来将pod配置参数存储为键值对,与pod镜像分开,更多细节可以参考这里:
https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/
要配置NGINX以通过TCP暴露服务,您可以添加或更新命名空间tcp-services中的ConfigMap ingress-nginx。此命名空间还包含NGINX Ingress Controller pod。
ConfigMap条目中的密钥应该是您要公开访问的TCP端口,其值应为格式:。如上所示,我暴露了Default命名空间中存在的两个工作负载。例如,上面ConfigMap中的第一个条目告诉NGINX我想在外部端口上暴露运行在default命名空间上的myapp工作负载,并监听在外部端口6790上的私有端口80。
将这些条目添加到Configmap,将自动更新NGINX pod,以配置这些工作负载来进行TCP负载均衡。您可以执行部署在ingress-nginx命名空间中的这些pod,并查看如何在/etc/nginx/nginx.conf文件中配置这些TCP端口。:在NGINX配置/etc/nginx/nginx.conf更新后,应该可以使用公开的工作负载。如果它们不可访问,则可能必须使用NodePort服务来暴露TCP端口。
Rancher 2.0负载均衡的限制
Cattle提供了功能丰富的负载均衡器支持(详细介绍在此: https://rancher.com/docs/rancher/v1.6/en/cattle/adding-load-balancers/#load-balancers)。其中一些功能在Rancher 2.0中暂时没有等效功能:
当前NGINX Ingress Controller不支持SNI。
TCP负载均衡需要集群中的云提供程序启用的负载均衡器设备。Kubernetes上没有对TCP的Ingress支持。
只能通过Ingress为端口80/443配置HTTP / HTTPS路由。此外,Ingress Controller作为Daemonset进行全局部署,而不是作为可扩展服务启动。此外,用户无法随机分配外部端口来进行负载均衡。因此,用户需要确保它们配置的主机名/路径组合是唯一的,以避免使用相同的两个端口发生路由冲突。
无法指定端口规则优先级和排序。
Rancher 1.6增加了对draining后端连接和drain超时的支持。Rancher 2.0暂不支持此功能。
目前在Rancher 2.0中,不支持指定自定义粘性策略和自定义负载均衡器配置以附加到默认配置。原生Kubernetes对此有一定的支持,不过也只限于定制NGINX配置:
https://kubernetes.github.io/ingress-nginx/examples/customization/custom-configuration/README/。
将负载均衡器配置从Docker Compose迁移到Kubernetes YAML?
Rancher 1.6通过启动自己的微服务提供负载均衡器支持,该微服务启动并配置了HAProxy。用户添加的负载均衡器配置在rancher-compose.yml文件中指定,而不是标准的docker-compose.yml。Kompose工具适用于标准的docker-compose参数,但在本文的情况下,是无法解析Rancher负载均衡器配置结构的。截至目前,我们暂时无法使用Kompose工具将负载均衡器配置从Docker Compose转换为Kubernetes YAML。
结 论
由于Rancher 2.0基于Kubernetes并使用NGINX Ingress Controller(与Cattle使用HAProxy相比),因此原先Rancher 1.6中Cattle支持的一些负载均衡器的功能目前暂时没有直接等效功能。但是,Rancher 2.0支持流行的HTTP / HTTPS基于主机名/路径的路由,这种路由最常用于实际部署。还通过Kubernetes Load Balancer服务使用云提供商提供四层(TCP)支持。2.0中的负载均衡功能也具有类似的直观UI体验。
Kubernetes生态系统在不断发展,我相信我们能找到更多适合所有负载均衡细微差别的解决方案!
云计算
2018-09-20 11:20:00
9 月19 日,2018杭州·云栖大会现场,杭州城市大脑2.0正式发布,管辖范围扩大28倍,覆盖面积增至420平方公里,相当于65个西湖大小。
ET 城市大脑等数字化城市解决方案,掀开了“杭州故事”的新篇章。今天的杭州,已从千年古城变为全球领先的数字化城市样本。
“这些新杭州故事,明天将会在更多城市发生。”阿里云总裁胡晓明在大会上表示,将以杭州为起点,向全球更多城市输出数字中国的“杭州方案”。
从人文胜地到科技之都 科技改变一座城
自古以来,杭州就是人文的代名词。“江南忆,最忆是杭州”诠释着人们对杭州的全部想象。
然而,今天的杭州不只是“人间天堂”,过去几年来,杭州在中国城市竞争中异军突起,变身为一座“科技之都”。
本次云栖大会上,杭州市政府联合阿里云等企业建设的杭州城市大脑2.0 正式发布。仅一年时间,城市大脑已成为杭州新基础设施:管辖范围扩大28倍,覆盖全城420平方公里,相当于65个西湖大小。通过交警手持的移动终端,大脑实时指挥200多名交警。在城市大脑的作用下,杭州交通拥堵率从2016年时的全国第5降至2018年的全国第57名。
除了依靠大数据、人工智能摆脱拥堵,今天的杭州,还是“移动支付之城”、“移动办事之城”、“智慧医疗之城”。
在杭州,出门办事“最多跑一次”,全市59 个政府部门368.32亿条信息汇聚在基于阿里云打造的政务服务平台上,市民可凭身份证一证通办296项事务。
在杭州,超过95 %的超市便利店、超过98%的出租车、5000余辆公交车都支持移动支付,堪称全球最大的移动支付之城。
在杭州,近年来,智慧医疗让近7000 万人次在杭州市属医院看病时间平均缩短2小时以上。
在杭州,成千上万的摊贩店主不再需要每天记账本、跑银行;跑航运、港运、路运的师傅不再需要花很多时间办数不清的证件;法院审理某些案子不再需要原告被告到场,甚至不需要书记员;去医院拍片子做CT ,不再需要去固定医院就诊,也不需要将片子全部打印出来;而创业公司也不再需要自己搭建服务器、数据中心,每天可能只需几十块钱就可以享受跟大公司一样的计算服务。
在杭州,一度遭遇低潮的百货业焕发新活力,银泰转型为大数据驱动的消费解决方案提供商。商超向新零售升级,世纪联华积极拥抱新技术。杭州银行携手云计算革新用户体验,具备了互联网金融能力。以吉利汽车为代表的汽车制造从营销到生产全流程数字化。
在传统工业制造领域,通过云计算与人工智能,沉默的数据被唤醒,中策橡胶、正泰新能源等工业企业的生产流程大幅优化,良品率上升带来利润增长。随着200 家工业企业相继入驻SupET工业互联网,杭州智造正在成为“新制造”的典型样本。
曾经,西雅图走出了亚马逊和微软两大科技巨头,反过来,两者也用数字化技术铸造了全新的西雅图。今天,杭州孕育了领先全球的云计算企业阿里云,而阿里巴巴则推动着千年古城杭州在新一轮数字化变革中走在前列。
“新杭州故事”只是刚刚开始
“ 我们今天讲述的新杭州故事只是开始,阿里云希望向全球更多城市输出新杭州背后的技术和实践。”在胡晓明看来,杭州被打造成数字中国的标杆城市,但新杭州故事的意义不止于杭州。
近年来,以阿里云为代表的科技企业走向海外,正在改变国际社会对中国的认知。国际社会已经将目光投入到中国科技带来的数字化转型上,科技领域的“中国方案”受到关注。区别于传统商品为主的国际贸易,中国技术走向世界不仅能为中国企业出海铺好“数字丝绸之路”,也能为当地经济增长带去新动能。
在中东,阿里云正在和有“中东MIT ”之称的哈利法大学共同探索解决能源领域的重大前沿问题;在传统工业大国德国,阿里云正在和世界知名的企业管理方案供应商SAP扩展全球合作伙伴关系,为全球企业提供更好的数字化转型解决方案;在非洲,阿里云正在和肯尼亚政府打造智能野生动物保护平台,保护更多珍稀动物;在奥运领域,阿里云正在和奥运转播服务公司OBS打造奥林匹克转播云,用视频云技术,让更多偏远地区可以更智能的方式观看奥运比赛视频;在马来西亚,ET城市大脑在杭州率先成功的特种车辆优先调度方案被吉隆坡引入,测试显示救护车到达现场的时间缩短了48.9%。未来,“杭州红绿灯”可能成为世界全新的一种红绿灯控制系统。
中国是全球数字化转型的试验场,而杭州是中国数字化浪潮的中心。100 年前,伦敦向世界输出了地铁,巴黎输出了下水道,纽约输出了电网。今天,中国杭州携手阿里云,正向世界贡献数字化城市方案。
杭州,是阿里云技术理想和家国情怀的起点和原点。
作者: 阿里云头条
原文链接
本文为云栖社区原创内容,未经允许不得转载。
云计算
2018-09-19 16:04:00
带你了解Kubernetes架构的设计意图、Kubernetes系统的架构开发演进过程,以及背后的驱动原因。
1、背景
各种平台都会遇到一个不可回避的问题,即平台应该包含什么和不包含什么,Kubernetes也一样。Kubernetes作为一个部署和管理容器的平台,Kubernetes不能也不应该试图解决用户的所有问题。Kubernetes必须提供一些基本功能,用户可以在这些基本功能的基础上运行容器化的应用程序或构建它们的扩展。本文旨在明确Kubernetes架构的设计意图,描述Kubernetes的演进历程和未来的开发蓝图。
本文中,我们将描述Kubernetes系统的架构开发演进过程,以及背后的驱动原因。对于希望扩展或者定制kubernetes系统的开发者,其应该使用此文档作为向导,以明确可以在哪些地方,以及如何进行增强功能的实现。如果应用开发者需要开发一个大型的、可移植的和符合将来发展的kubernetes应用,也应该参考此文档,以了解Kubernetes将来的演化和发展。
从逻辑上来看,kubernetes的架构分为如下几个层次:
核心层(Nucleus): 提供标准的API和执行机制,包括基本的REST机制,安全、Pod、容器、网络接口和存储卷管理,通过接口能够对这些API和执进行扩展,核心层是必需的,它是系统最核心的一部分。
应用管理层(Application Management Layer ):提供基本的部署和路由,包括自愈能力、弹性扩容、服务发现、负载均衡和流量路由。此层即为通常所说的服务编排,这些功能都提供了默认的实现,但是允许进行一致性的替换。
治理层(The Governance Layer):提供高层次的自动化和策略执行,包括单一和多租户、度量、智能扩容和供应、授权方案、网络方案、配额方案、存储策略表达和执行。这些都是可选的,也可以通过其它解决方案实现。
接口层(The Interface Layer):提供公共的类库、工具、用户界面和与Kubernetes API交互的系统。
生态层(The Ecosystem):包括与Kubernetes相关的所有内容,严格上来说这些并不是Kubernetes的组成部分。包括CI/CD、中间件、日志、监控、数据处理、PaaS、serverless/FaaS系统、工作流、容器运行时、镜像仓库、Node和云提供商管理等。
2、系统分层
就像Linux拥有内核(kernel)、核心系统类库、和可选的用户级工具,kubernetes也拥有功能和工具的层次。对于开发者来说,理解这些层次是非常重要的。kubernetes APIs、概念和功能都在下面的层级图中得到体现。
2.1 核心层:API和执行(The Nucleus: API and Execution)
核心层包含最核心的API和执行机。
这些API和功能由上游的kubernetes代码库实现,由最小特性集和概念集所组成,这些特征和概念是系统上层所必需的。
这些由上游KubNeNETs代码库实现的API和函数包括建立系统的高阶层所需的最小特征集和概念集。这些内容被明确的地指定和记录,并且每个容器化的应用都会使用它们。开发人员可以安全地假设它们是一直存在的,这些内容应该是稳定和乏味的。
2.1.1 API和集群控制面板
Kubernetes集群提供了类似REST API的集,通过Kubernetes API server对外进行暴露,支持持久化资源的增删改查操作。这些API作为控制面板的枢纽。
遵循Kubernetes API约定(路径约定、标准元数据等)的REST API能够自动从共享API服务(认证、授权、审计日志)中收益,通用客户端代码能够与它们进行交互。
作为系统的最娣层,需要支持必要的扩展机制,以支持高层添加功能。另外,需要支持单租户和多租户的应用场景。核心层也需要提供足够的弹性,以支持高层能扩展新的范围,而不需要在安全模式方面进行妥协。
如果没有下面这些基础的API机和语义,Kubernetes将不能够正常工作:
认证(Authentication): 认证机制是非常关键的一项工作,在Kubernetes中需要通过服务器和客户端双方的认证通过。API server 支持基本认证模式 (用户命名/密码) (注意,在将来会被放弃), X.509客户端证书模式,OpenID连接令牌模式,和不记名令牌模式。通过kubeconfig支持,客户端能够使用上述各种认证模式。第三方认证系统可以实现TokenReview API,并通过配置认证webhook来调用,通过非标准的认证机制可以限制可用客户端的数量。
1、The TokenReview API (与hook的机制一样) 能够启用外部认证检查,例如Kubelet
2、Pod身份标识通过”service accounts“提供
3、The ServiceAccount API,包括通过控制器创建的默认ServiceAccount保密字段,并通过接入许可控制器进行注入。
授权(Authorization):第三方授权系统可以实现SubjectAccessReview API,并通过配置授权webhook进行调用。
1、SubjectAccessReview (与hook的机制一样), LocalSubjectAccessReview, 和SelfSubjectAccessReview APIs能启用外部的许可检查,诸如Kubelet和其它控制器。
REST 语义、监控、持久化和一致性保证、API版本控制、违约、验证
1、NIY:需要被解决的API缺陷:
2、混淆违约行为
3、缺少保障
4、编排支持
5、支持事件驱动的自动化
6、干净卸载
NIY: 内置的准入控制语义、同步准入控制钩子、异步资源初始化 — 发行商系统集成商,和集群管理员实现额外的策略和自动化
NIY:API注册和发行、包括API聚合、注册额外的API、发行支持的API、获得支持的操作、有效载荷和结果模式的详细信息。
NIY:ThirdPartyResource和ThirdPartyResourceData APIs (或她们的继承者),支持第三方存储和扩展API。
NIY:The Componentstatuses API的可扩展和高可用的替代,以确定集群是否完全体现和操作是否正确:ExternalServiceProvider (组件注册)
The Endpoints API,组件增持需要,API服务器端点的自我发布,高可用和应用层目标发行
The Namespace API,用户资源的范围,命名空间生命周期(例如:大量删除)
The Event API,用于对重大事件的发生进行报告,例如状态改变和错误,以及事件垃圾收集
NIY:级联删除垃圾收集器、finalization, 和orphaning
NIY: 需要内置的add-on的管理器 ,从而能够自动添加自宿主的组件和动态配置到集群,在运行的集群中提取出功能。
1、Add-ons应该是一个集群服务,作为集群的一部分进行管理
2、它们可以运行在kube-system命名空间,这么就不会与用户的命名进行冲突
API server作为集群的网关。根据定义,API server必需能够被集群外的客户端访问,而Node和Pod是不被集群外的客户端访问的。客户端认证API server,并使用API server作为堡垒和代理/通道来通过/proxy和/portforward API访问Node和Pod等Clients authenticate the API server and also use it
TBD:The CertificateSigningRequest API,能够启用认证创建,特别是kubele证书。
理想情况下,核心层API server江仅仅支持最小的必需的API,额外的功能通过聚合、钩子、初始化器、和其它扩展机制来提供。注意,中心化异步控制器以名为Controller Manager的独立进程运行,例如垃圾收集。
API server依赖下面的外部组件:
持久化状态存储 (etcd,或相对应的其它系统;可能会存在多个实例)
API server可以依赖:
身份认证提供者
The TokenReview API实现者 实现者
The SubjectAccessReview API实现者
2.1.2 执行
在Kubernetes中最重要的控制器是kubelet,它是Pod和Node API的主要实现者,没有这些API的话,Kubernetes将仅仅只是由键值对存储(后续,API机最终可能会被作为一个独立的项目)支持的一个增删改查的REST应用框架。
Kubernetes默认执行独立的应用容器和本地模式。
Kubernetes提供管理多个容器和存储卷的Pod,Pod在Kubernetes中作为最基本的执行单元。
Kubelet API语义包括:
The Pod API,Kubernetes执行单元,包括:
1、Pod可行性准入控制基于Pod API中的策略(资源请求、Node选择器、node/pod affinity and anti-affinity, taints and tolerations)。API准入控制可以拒绝Pod或添加额外的调度约束,但Kubelet才是决定Pod最终被运行在哪个Node上的决定者,而不是schedulers or DaemonSets。
2、容器和存储卷语义和生命周期
3、Pod IP地址分配(每个Pod要求一个可路由的IP地址)
4、将Pod连接至一个特定安全范围的机制(i.e., ServiceAccount)
5、存储卷来源:
5.1、emptyDir
5.2、hostPath
5.3、secret
5.4、configMap
5.5、downwardAPI
5.6、NIY:容器和镜像存储卷 (and deprecate gitRepo)
5.7、NIY:本地存储,对于开发和生产应用清单不需要复杂的模板或独立配置
5.8、flexVolume (应该替换内置的cloud-provider-specific存储卷)
6、子资源:绑定、状态、执行、日志、attach、端口转发、代理 NIY:可用性和引导API 资源检查点 容器镜像和日志生命周期 The Secret API,启用第三方加密管理 The ConfigMap API,用于组件配置和Pod引用 The Node API,Pod的宿主
1、在一些配置中,可以仅仅对集群管理员可见 Node和pod网络,业绩它们的控制(路由控制器) Node库存、健康、和可达性(node控制器)
1、Cloud-provider-specific node库存功能应该被分成特定提供者的控制器 pod终止垃圾收集 存储卷控制器
1、Cloud-provider-specific attach/detach逻辑应该被分成特定提供者的控制器,需要一种方式从API中提取特定提供者的存储卷来源。 The PersistentVolume API
1、NIY:至少被本地存储所支持 The PersistentVolumeClaim API
中心化异步功能,诸如由Controller Manager执行的pod终止垃圾收集。
当前,控制过滤器和kubelet调用“云提供商”接口来询问来自于基础设施层的信息,并管理基础设施资源。然而,kubernetes正在努力将这些触摸点(问题)提取到外部组件中,不可满足的应用程序/容器/OS级请求(例如,PODS,PersistentVolumeClaims)作为外部“动态供应”系统的信号,这将使基础设施能够满足这些请求,并使用基础设施资源(例如,Node、和PersistentVolumes)在Kubernetes进行表示,这样Kubernetes可以将请求和基础设施资源绑定在一起。
对于kubelet,它依赖下面的可扩展组件: 镜像注册 容器运行时接口实现 容器网络接口实现 FlexVolume 实现(”CVI” in the diagram)
以及可能依赖: NIY:第三方加密管理系统(例如:Vault) NIY:凭证创建和转换控制器
2.2 应用层:部署和路由
应用管理和组合层,提供自愈、扩容、应用生命周期管理、服务发现、负载均衡和路由— 也即服务编排和service fabric。这些API和功能是所有Kubernetes分发所需要的,Kubernetes应该提供这些API的默认实现,当然可以使用替代的实现方案。没有应用层的API,大部分的容器化应用将不能运行。
Kubernetes’s API提供类似IaaS的以容器为中心的基础单元,以及生命周期控制器,以支持所有工作负载的编排(自愈、扩容、更新和终止)。这些应用管理、组合、发现、和路由API和功能包括: 默认调度,在Pod API中实现调度策略:资源请求、nodeSelector、node和pod affinity/anti-affinity、taints and tolerations. 调度能够作为一个独立的进度在集群内或外运行。 NIY:重新调度器 ,反应和主动删除已调度的POD,以便它们可以被替换并重新安排到其他Node 持续运行应用:这些应用类型应该能够通过声明式更新、级联删除、和孤儿/领养支持发布(回滚)。除了DaemonSet,应该能支持水平扩容。
1、The Deployment API,编排更新无状态的应用,包括子资源(状态、扩容和回滚)
2、The DaemonSet API,集群服务,包括子资源(状态)
3、The StatefulSet API,有状态应用,包括子资源(状态、扩容)
4、The PodTemplate API,由DaemonSet和StatefulSet用来记录变更历史 终止批量应用:这些应该包括终止jobs的自动剔除(NIY)
1、The Job API (GC discussion)
2、The CronJob API 发现、负载均衡和路由
1、The Service API,包括集群IP地址分配,修复服务分配映射,通过kube-proxy或者对等的功能实现服务的负载均衡,自动化创建端点,维护和删除。NIY:负载均衡服务是可选的,如果被支持的化,则需要通过一致性的测试。
2、The Ingress API,包括internal L7 (NIY)
3、服务DNS。DNS使用official Kubernetes schema。
应用层可以依赖: 身份提供者 (集群的身份和/或应用身份) NIY:云提供者控制器实现 Ingress controller(s) 调度器和重新调度器的替代解决方案 DNS服务替代解决方案 kube-proxy替代解决方案 工作负载控制器替代解决方案和/或辅助,特别是用于扩展发布策略
2.3 治理层:自动化和策略执行
策略执行和高层自动化。这些API和功能是运行应用的可选功能,应该挺其它的解决方案实现。
每个支持的API/功能应用作为企业操作、安全和治理场景的一部分。
需要为集群提供可能的配置和发现默认策略,至少支持如下的用例: 单一租户/单一用户集群 多租户集群 生产和开发集群 Highly tenanted playground cluster 用于将计算/应用服务转售给他人的分段集群
需要关注的内容:
1、资源使用
2、Node内部分割
3、最终用户
4、管理员
5、服务质量(DoS)
自动化APIs和功能: 度量APIs (水平/垂直自动扩容的调度任务表) 水平Pod自动扩容API NIY:垂直Pod自动扩容API(s) 集群自动化扩容和Node供应 The PodDisruptionBudget API 动态存储卷供应,至少有一个出厂价来源类型
1、The StorageClass API,至少有一个默认存储卷类型的实现 动态负载均衡供应 NIY:PodPreset API NIY:service broker/catalog APIs NIY:Template和TemplateInstance APIs
策略APIs和功能:
授权:ABAC和RBAC授权策略方案
1、RBAC,实现下面的API:Role, RoleBinding, ClusterRole, ClusterRoleBinding The LimitRange API The ResourceQuota API The PodSecurityPolicy API The ImageReview API The NetworkPolicy API
管理层依赖: 网络策略执行机制 替换、水平和垂直Pod扩容 集群自动扩容和Node提供者 动态存储卷提供者 动态负载均衡提供者 度量监控pipeline,或者它的替换 服务代理
2.4 接口层:类库和工具
这些机制被建议用于应用程序版本的分发,用户也可以用其进行下载和安装。它们包括Kubernetes官方项目开发的通用的类库、工具、系统、界面,它们可以用来发布。 Kubectl — kubectl作为很多客户端工具中的一种,Kubernetes的目标是使Kubectl更薄,通过将常用的非平凡功能移动到API中。这是必要的,以便于跨Kubernetes版本的正确操作,并促进API的扩展性,以保持以API为中心的Kubernetes生态系统模型,并简化其它客户端,尤其是非GO客户端。 客户端类库(例如:client-go, client-python) 集群联邦(API server, controllers, kubefed) Dashboard Helm
这些组件依赖: Kubectl扩展 Helm扩展
2.5 生态
在有许多领域,已经为Kubernetes定义了明确的界限。虽然,Kubernetes必须提供部署和管理容器化应用需要的通用功能。但作为一般规则,在对Kubernete通用编排功能进行补足的功能领域,Kubernetes保持了用户的选择。特别是那些有自己的竞争优势的区域,特别是能够满足不同需求和偏好的众多解决方案。Kubernetes可以为这些解决方案提供插件API,或者可以公开由多个后端实现的通用API,或者公开此类解决方案可以针对的API。有时,功能可以与Kubernetes干净地组合在而不需要显式接口。
此外,如果考虑成为Kubernetes的一部分,组件就需要遵循Kubernetes设计约定。例如,主要接口使用特定域语言的系统(例如,Puppet、Open Policy Agent)与Kubenetes API的方法不兼容,可以与Kubernetes一起使用,但不会被认为是Kubernetes的一部分。类似地,被设计用来支持多平台的解决方案可能不会遵循Kubernetes API协议,因此也不会被认为是Kubernetes的一部分。 内部的容器镜像:Kubernetes不提供容器镜像的内容。 如果某些内容被设计部署在容器镜像中,则其不应该直接被考虑作为Kubernetes的一部分。例如,基于特定语言的框架。 在Kubernetes的顶部
1、持久化集成和部署(CI/CD):Kubernetes不提供从源代码到镜像的能力。Kubernetes 不部署源代码和不构建应用。用户和项目可以根据自身的需要选择持久化集成和持久化部署工作流,Kubernetes的目标是方便CI/CD的使用,而不是命令它们如何工作。
2、应用中间件:Kubernetes不提供应用中间件作为内置的基础设施,例如:消息队列和SQL数据库。然而,可以提供通用目的的机制使其能够被容易的提供、发现和访问。理想的情况是这些组件仅仅运行在Kubernetes上。
3、日志和监控:Kubernetes本身不提供日志聚合和综合应用监控的能力,也没有遥测分析和警报系统,虽然日志和监控的机制是Kubernetes集群必不可少的部分。
4、数据处理平台:在数据处理平台方面,Spark和Hadoop是还有名的两个例子,但市场中还存在很多其它的系统。
5、特定应用运算符:Kubernetes支持通用类别应用的工作负载管理。
6、平台即服务 Paas:Kubernetes为Paas提供基础。
7、功能即服务 FaaS:与PaaS类似,但Faa侵入容器和特定语言的应用框架。
8、工作量编排: “工作流”是一个非常广泛的和多样化的领域,通常针对特定的用例场景(例如:数据流图、数据驱动处理、部署流水线、事件驱动自动化、业务流程执行、iPAAS)和特定输入和事件来源的解决方案,并且通常需要通过编写代码来实现。
9、配置特定领域语言:特定领域的语言不利于分层高级的API和工具,它们通常具有有限的可表达性、可测试性、熟悉性和文档性。它们复杂的配置生成,它们倾向于在互操作性和可组合性间进行折衷。它们使依赖管理复杂化,并经常颠覆性的抽象和封装。
10、Kompose:Kompose是一个适配器工具,它有助于从Docker Compose迁移到Kubernetes ,并提供简单的用例。Kompose不遵循Kubernetes约定,而是基于手动维护的DSL。
11、ChatOps:也是一个适配器工具,用于聊天服务。 支撑Kubernetes
1、容器运行时:Kubernetes本身不提供容器运行时环境,但是其提供了接口,可以来插入所选择的容器运行时。
2、镜像仓库:Kubernetes本身不提供容器的镜像,可通过Harbor、Nexus和docker registry等搭建镜像仓库,以为集群拉取需要的容器镜像。
3、集群状态存储:用于存储集群运行状态,例如默认使用Etcd,但也可以使用其它存储系统。
4、网络:与容器运行时一样,Kubernetes提供了接入各种网络插件的容器网络接口(CNI)。
5、文件存储:本地文件系统和网络存储
6、Node管理:Kubernetes既不提供也不采用任何综合的机器配置、维护、管理或自愈系统。通常针对不同的公有/私有云,针对不同的操作系统,针对可变的和不可变的基础设施。
7、云提供者:IaaS供应和管理。
8、集群创建和管理:社区已经开发了很多的工具,利润minikube、kubeadm、bootkube、kube-aws、kops、kargo, kubernetes-anywhere等待。 从工具的多样性可以看出,集群部署和管理(例如,升级)没有一成不变的解决方案。也就是说,常见的构建块(例如,安全的Kubelet注册)和方法(特别是自托管)将减少此类工具中所需的自定义编排的数量。
后续,希望通过建立Kubernetes的生态系统,并通过整合相关的解决方案来满足上述需求。
矩阵管理
选项、可配置的默认、扩展、插件、附加组件、特定于提供者的功能、版本管理、特征发现和依赖性管理。
Kubernetes不仅仅是一个开源的工具箱,而且是一个典型集群或者服务的运行环境。 Kubernetes希望大多数用户和用例能够使用上游版本,这意味着Kubernetes需要足够的可扩展性,而不需要通过重建来处理各种场景。
虽然在可扩展性方面的差距是代码分支的主要驱动力,而上游集群生命周期管理解决方案中的差距是当前Kubernetes分发的主要驱动因素,可选特征的存在(例如,alpha API、提供者特定的API)、可配置性、插件化和可扩展性使概念不可避免。
然而,为了使用户有可能在Kubernetes上部署和管理他们的应用程序,为了使开发人员能够在Kubernetes集群上构建构建Kubernetes扩展,他们必须能够对Kubernetes集群或分发提供一个假设。在基本假设失效的情况下,需要找到一种方法来发现可用的功能,并表达功能需求(依赖性)以供使用。
集群组件,包括add-ons,应该通过组件注册 API进行注册和通过/componentstatuses进行发现。
启用内置API、聚合API和注册的第三方资源,应该可以通过发现和OpenAPI(Savigj.JSON)端点来发现。如上所述,LoadBalancer类型服务的云服务提供商应该确定负载均衡器API是否存在。
类似于StorageClass,扩展和它们的选项应该通过FoeClass资源进行注册。但是,使用参数描述、类型(例如,整数与字符串)、用于验证的约束(例如,ranger或regexp)和默认值,从扩展API中引用fooClassName。这些API应该配置/暴露相关的特征的存在,例如动态存储卷供应(由非空的storageclass.provisioner字段指示),以及标识负责的控制器。需要至少为调度器类、ingress控制器类、Flex存储卷类和计算资源类(例如GPU、其他加速器)添加这样的API。
假设我们将现有的网络存储卷转换为flex存储卷,这种方法将会覆盖存储卷来源。在将来,API应该只提供通用目的的抽象,即使与LoadBalancer服务一样,抽象并不需要在所有的环境中都实现(即,API不需要迎合最低公共特性)。
NIY:需要为注册和发现开发下面的机制: 准入控制插件和hooks(包括内置的APIs) 身份认证插件 授权插件和hooks 初始化和终结器 调度器扩展 Node标签和集群拓扑
NIY:单个API和细粒度特征的激活/失活可以通过以下机制解决: 所有组件的配置正在从命令行标志转换为版本化配置。 打算将大部分配置数据存储在配置映射(ConfigMaps)中,以便于动态重新配置、渐进发布和内省性。 所有/多个组件共同的配置应该被分解到它自己的配置对象中。这应该包括特征网关机制。 应该为语义意义上的设置添加API,例如,在无响应节点上删除Pod之前需要等待的默认时间长度。
NIY:版本管理操作的问题,取决于多个组件的升级(包括在HA集群中的相同组件的副本),应该通过以下方式来解决:
为所有新的特性创建flag网关
总是在它们出现的第一个小版本中,默认禁用这些特性,
提供启用特性的配置补丁;
在接下来的小版本中默认启用这些特性
NIY:我们还需要一个机制来警告过时的节点,和/或潜在防止Master升级(除了补丁发布),直到/除非Node已经升级。
NIY:字段级版本管理将有助于大量激活新的和/或alpha API字段的解决方案,防止不良写入过时的客户端对新字段的阻塞,以及非alpha API的演进,而不需要成熟的API定义的扩散。
Kubernetes API server忽略不支持的资源字段和查询参数,但不忽略未知的/未注册的API(注意禁用未实现的/不活动的API)。这有助于跨多个版本的集群重用配置,但往往会带来意外。Kubctl支持使用服务器的Wagger/OpenAPI规范进行可选验证。这样的可选验证,应该由服务器(NYY)提供。此外,为方便用户,共享资源清单应该指定Kubernetes版本最小的要求,这可能会被kubectl和其他客户端验证。
服务目录机制(NIY)应该能够断言应用级服务的存在,例如S3兼容的群集存储。
与安全相关的系统分层
为了正确地保护Kubernetes集群并使其能够安全扩展,一些基本概念需要由系统的组件进行定义和约定。最好从安全的角度把Kubernetes看作是一系列的环,每个层都赋予连续的层功能去行动。 用于存储核心API的一个或者多个数据存储系统(etcd) 核心APIs 高度可信赖资源的APIs(system policies) 委托的信任API和控制器(用户授予访问API /控制器,以代表用户执行操作),无论是在集群范围内还是在更小的范围内 在不同范围,运行不受信任/作用域API和控制器和用户工作负载
当较低层依赖于更高的层时,它会使安全模型崩溃,并使系统变得更加复杂。管理员可以选择这样做以获得操作简单性,但这必须是有意识的选择。一个简单的例子是etcd:可以将数据写入etcd的任何组件现在都在整个集群上,任何参与者(可以破坏高度信任的资源)都几乎可以进行逐步升级。为每一层的进程,将上面的层划分成不同的机器集(etcd-> apiservers +控制器->核心安全扩展->委托扩展- >用户工作负载),即使有些可能在实践中崩溃。
如果上面描述的层定义了同心圆,那么它也应该可能存在重叠或独立的圆-例如,管理员可以选择一个替代的秘密存储解决方案,集群工作负载可以访问,但是平台并不隐含地具有访问权限。这些圆圈的交点往往是运行工作负载的机器,并且节点必须没有比正常功能所需的特权更多的特权。
最后,在任何层通过扩展添加新的能力,应该遵循最佳实践来传达该行为的影响。
当一个能力通过扩展被添加到系统时,它有什么目的?
使系统更加安全
为集群中的每一个人,启用新的“生产质量”API
在集群的子集上自动完成一个公共任务
运行一个向用户提供API的托管工作负载(spark、数据库、etcd)
它们被分为三大类:
1、集群所需的(因此必须在内核附近运行,并在存在故障时导致操作权衡)
2、暴露于所有集群用户(必须正确地租用)
3、暴露于集群用户的子集(像传统的“应用程序”工作负载运行)
如果管理员可以很容易地被诱骗,在扩展期间安装新的群集级安全规则,那么分层被破坏,并且系统是脆弱的。 英文原文: https://github.com/kubernetes/community/blob/master/contributors/devel/architectural-roadmap.md 本文译者: 季向远,北京神舟航天软件技术有限公司产品经理。 本文版权归原作者所有。本文版权归原作者所有。
云计算
2018-09-19 10:05:00
kolla是从openstack孵化出的一个项目,kolla项目可以制作镜像包括openstack、ceph等容器镜像,
ansible是自动化部署工具,执行playbook中的任务。
kolla-ansible是容器部署工具,部署openstack和ceph;kolla-ansible部署的容器镜像可以是kolla构建的,也可以是从docker register下载来的(本文部署使用kolla-ansible部署ceph采用从docker register下载镜像的方式部署)。
一、节点规划
主机名 ip 角色 localhost 172.16.134.43 master节点,安装kolla-ansible
node58 172.16.134.58 ceph节点,至少有一块osd使用的磁盘
node59
node61
172.16.134.59
172.16.134.61
ceph节点,至少有一块osd使用的磁盘
ceph节点,至少有一块osd使用的磁盘
二、搭建master节点
1、安装docker yum install -y yum-utils device-mapper-persistent-data lvm2 yum install docker-ce -y
2、master和ceph节点之间解决互信
ssh-keygen
ssh-copy-id root@172.16.134.58
ssh-copy-id root@172. 16.134.59
ssh-copy-id root@172. 16.134.61
3、安装kolla-ansible依赖包 yum -y install epel-release yum install -y python-pip ansible yum install -y python-devel libffi-devel openssl-devel gcc python-setuptools git
4、修改pip源:
mkdir -p ~/.pip
tee ~/.pip/pip.conf <<-'EOF'
[global]
trusted-host= mirrors.aliyun.com
index-url= http://mirrors.aliyun.com/pypi/simple/
EOF
5、升级pip:
pip install -U pip
6、下载kolla-ansible源码并安装 git clone https://github.com/openstack/kolla-ansible.git -b stable/queens cd kolla-ansilbe pip install -r requirements.txt -r test-requirements.txt pip install . -i http://mirrors.aliyun.com/pypi/simple/
7、复制相关文件
cp -r etc/kolla /etc/kolla/
cp ansible/inventory/* /home
8、生成密码
kolla-genpwd
9、设置docker mkdir /etc/systemd/system/docker.service.d 编辑kolla.conf文件 vim /etc/systemd/system/docker.service.d/kolla.conf [Service] MountFlags=shared 编辑daemon.json文件 vi /etc/docker/daemon.json { "registry-mirrors": ["https://ebu037tr.mirror.aliyuncs.com"], "insecure-registries": ["docker-registries"] }
注意:docker-registries为docker镜像服务器,在部署过程中,kolla-ansible会从docker服务器上拉取所需要的镜像,该docker镜像服务器要有ceph各组件的镜像。
在ceph节点上也要用docker login {docker-registries},登陆到docker服务器,否则在部署过程中会出现认证错误。
10、重启docker服务 systemctl daemon-reload systemctl restart docker
11、修改/etc/hosts文件,填入ceph节点
三、ceph节点环境配置(在三个ceph节点上执行同样的操作)
1、禁用节点放火墙,安全策略等 [root@node58 ~]vim ~/init.sh #!/bin/sh sed -i 's/SELINUX=.*/SELINUX=Disabled/g' /etc/selinux/config echo '' > /etc/resolv.conf echo nameserver 114.114.114.114 >> /etc/resolv.conf echo search novalocal >> /etc/resolv.conf echo " net.ipv4.ip_forward = 1 ">> /etc/sysctl.conf&&sysctl -p yum install vim wget -y systemctl stop firewalld systemctl disable firewalld ----------------------------------------------------------- [root@node58 ~]# sh init.sh
2、节点配置时间同步 [root@node58 ~]# yum install -y chrony [root@node58 ~]# vi /etc/chrony.conf server 0.cn.pool.ntp.org iburst server 1.cn.pool.ntp.org iburst server 2.cn.pool.ntp.org iburst server 3.cn.pool.ntp.org iburst
3、给ceph节点的磁盘打标签 [root@node58 ~]# parted /dev/sdb -s -- mklabel gpt mkpart KOLLA_CEPH_OSD_BOOTSTRAP 1 -1
四、部署ceph容器服务(在master节点执行)
1、修改kolla-ansible的配置文件 [root@node58 ~]# cat /etc/kolla/globals.yml|grep -v '^#'|grep -v '^$' --- kolla_install_type: "binary" openstack_release: "queens" kolla_internal_vip_address: "ip of master" docker_registry: "{docker-registries}" docker_namespace: "queens/kolla" docker_registry_username: "admin" docker_registry_password: "Harbor12345" network_interface: "ens33" enable_ceph: "yes" enable_haproxy: "no" enable_keystone: "no" enable_glance: "no" enable_neutron: "no" enable_heat: "no" enable_nova: "no" enable_horizon: "no" ceph_pool_type: "replicated"
注意:/etc/kolla/globals.yml文件会重载/usr/share/kolla-ansible/ansible/group_vars/all.yml文件,不需要安装的服务在all.yml中改成“no”
2、修改ansible的inventory文件
在[storage]下填入ceph节点的主机名,把其余section清空
6、部署ceph节点环境
kolla-ansible bootstrap-servers -i /home/multinode
7、检查和部署
kolla-ansible prechecks -i /home/multinode
kolla-ansible deploy -i /home/multinode
8、测试(在ceph节点执行)
docker exec ceph_mon ceph -s
云计算
2018-10-22 17:03:00
我开发了一个Java应用,部署到云环境上之后,用postman测试发现不能按照我期望的工作,但是返回的消息对我没有任何帮助。
因为部署在云端的应用很难像本地Java应用一样调试,所以我打算用SLF4J在Java代码里添加一些日志,然后查看该Java应用在云端执行产生的日志来排查问题。
SLF4J的全称是Simple Logging Facade for Java, 即简单日志门面,这里的Facade实际上是面向对象的设计模式中的外观模式(Facade pattern)。SLF4J不是具体的日志解决方案,它本身不包含日志记录的具体实现,而是只提供一个外观给各种各样的日志系统,这样就给具体应用提供了很大的灵活度,使得最终用户在部署其应用时可以灵活选用其所希望的日志系统。
SLF4J的使用非常简单,在您的应用代码里将SLF4J的Logger和LoggerFactory导入: import org.slf4j.Logger; import org.slf4j.LoggerFactory;
然后在引用代码里用LoggerFactory获得logger实例:
static private Logger logger = LoggerFactory.getLogger(XCDService.class);
然后用logger.info进行日志记录。
将加了SLF4J日志记录的代码重新上传到云平台上。我用的是SAP云平台。
登录SAP云平台的控制台,点击Logging标签页:
点Configure Loggers:
因为我的应用代码放在com.sap.service包下面,所以我根据这个包名进行过滤:
将这两个Logger对应的Log Level日志级别设置成INFO:
再次用postman请求部署在SAP云平台上的服务,然后去云平台控制台上查看生成的日志文件:

点击查看按钮即可看到日志的具体内容,一下子就定位出问题的原因了。我在服务器端的HTTP响应头字段Content-type设置的值为application/json,但是返回的JSON字符串不符合JSON格式规范。把这个bug改掉之后错误就解决了。
要获取更多Jerry的原创技术文章,请关注公众号"汪子熙"或者扫描下面二维码:
云计算
2018-10-22 14:40:00
关于阿里云容器服务的详细内容: 阿里云容器服务使用教程
容器服务(Container Service)提供高性能可伸缩的容器应用管理服务,支持用 Docker 容器进行应用生命周期管理,提供多种应用发布方式和持续交付能力并支持微服务架构。容器服务简化了容器管理集群的搭建工作,整合了阿里云虚拟化、存储、网络和安全能力,打造 Docker 云端最佳运行环境。
产品功能:
集群管理,灵活的地域和网络环境选择 用户可以根据自己的需求,选择不同的地域创建和删除集群。 可选择经典网络或专有网络 VPC 环境。
多种服务器托管方式 支持授权容器服务创建云服务器加入到指定集群。 支持将已购买的云服务器添加到指定集群。
一站式容器生命周期管理 网络:支持跨宿主机容器间互联,支持通过 container name 或 hostname 定义的域名互访。 存储:支持数据卷管理,支持 OSSFS 和文件存储(Network Attached Storage,简称 NAS)。 日志:支持日志自动采集和日志服务集成。 监控:支持容器级别和 VM 级别的监控。 调度:支持跨可用区高可用和异常节点的 reschedule 等策略。 路由:支持 4 层和 7 层的请求转发和后端绑定。 子账号:支持集群级别的 RAM 授权管理。
Docker 兼容性 兼容标准 Docker API。 兼容 Docker Swarm 1.2.8。 兼容 Docker Engine CE 17.06.2。 支持 Docker Compose V1/V2/V3。
阿里云环境特有的增值能力,更好的体验 整合专有网络 VPC,提供安全、高性能、支持混合云的部署方案。 扩展 Compose 模板定义,增强生命周期管理。 整合负载均衡,提供容器的访问能力。
高可用调度策略,轻松打通上下游交付流程 支持服务级别的亲和性策略和横向扩展。 支持跨可用区高可用和灾难恢复。 支持集群和应用管理的 OpenAPI,轻松对接持续集成和私有部署系统。
容器服务的基础架构其中: 集群管理服务:提供 Docker 集群管理和调度。 服务发现:提供 Docker 的状态等元数据存储。 Agent 通信服务:提供每台宿主机和集群管理服务之间的通信服务。 集群 API:对外暴露阿里云统一的 OpenAPI 能力。 服务 API:对外暴露兼容 Docker Swarm 的 API 能力。
更多精品课程:
阿里云大学官网( 阿里云大学 - 官方网站,云生态下的创新人才工场 )
云计算
2018-10-22 14:04:00
PersistentVolume(简称PV)和PersistentVolumeClaim(简称PVC)
PersistentVolume(持久卷,简称PV)是集群内,由管理员提供的网络存储的一部分。就像集群中的节点一 样,PV也是集群中的一种资源。它也像Volume一样,是一种volume插件,但是它的生命周期却是和使用它的Pod相互独立的。PV这个API对 象,捕获了诸如NFS、ISCSI、或其他云存储系统的实现细节。
PersistentVolumeClaim(持久卷声明,简称PVC)是用户的一种存储请求。它和Pod类似,Pod消耗Node资源,而PVC消耗PV资源。Pod能够请求特定的资源(如CPU和内存)。PVC能够请求指定的大小和访问的模式(可以被映射为一次读写或者多次只读)。
PVC允许用户消耗抽象的存储资源,用户也经常需要各种属性(如性能)的PV。集群管理员需要提供各种各样、不同大小、不同访问模式的PV,而不用向用户暴露这些volume如何实现的细节。因为这种需求,就催生出一种StorageClass资源。
StorageClass提供了一种方式,使得管理员能够描述他提供的存储的等级。集群管理员可以将不同的等级映射到不同的服务等级、不同的后端策略。
供给
PV是集群中的资源,PVC是对这些资源的请求,同时也是这些资源的“提取证”。PV和PVC的交互遵循以下生命周期:
有两种PV提供的方式:静态和动态。
静态
集群管理员创建多个PV,它们携带着真实存储的详细信息,这些存储对于集群用户是可用的。它们存在于Kubernetes API中,并可用于存储使用。
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv01
namespace: sit
spec:
capacity:
storage: 100Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
nfs:
server: 10.42.0.55
path: "/opt/public"
动态
当管理员创建的静态PV都不匹配用户的PVC时,集群可能会尝试专门地供给volume给PVC。这种供给基于StorageClass:PVC必须请求这样一个等级,而管理员必须已经创建和配置过这样一个等级,以备发生这种动态供给的情况。请求等级配置为“”的PVC,有效地禁用了它自身的动态供给功能。
Kubernetes 1.4 中加入了一个 新的 API 对象 StorageClass,可以定义多个 StorageClass 对象,并可以分别指定存储插件、设置参数,用于提供不同的存储卷。这样的设计让集群管理员能够在同一个集群内,定义和提供不同类型的、不同参数的卷(相同或者不同的存储系统)。这样的设计还确保了最终用户在无需了解太多的情况下,有能力选择不同的存储选项。
这种场景比较常见的是使用在高级的私有云分布式存储或者公有云存储情况下,大多数是集成第三方的
举例:创建一个slow,另外一个fast的盘在谷歌云上
kind: StorageClass
apiVersion: storage.k8s.io/v1beta1
metadata:
name: slow
provisioner: kubernetes.io/gce-pd
parameters:
type: pd-standard
kind: StorageClass
apiVersion: storage.k8s.io/v1beta1
metadata:
name: fast
provisioner: kubernetes.io/gce-pd
parameters:
type: pd-ssd
绑定
用户创建一个PVC(或者之前就已经就为动态供给创建了),指定要求存储的大小和访问模式。master中有一个控制回路用于监控新的PVC, 查找匹配的PV(如果有),并把PVC和PV绑定在一起。如果一个PV曾经动态供给到了一个新的PVC,那么这个回路会一直绑定这个PV和PVC。另外, 用户总是至少能得到它们所要求的存储,但是volume可能超过它们的请求。一旦绑定了,PVC绑定就是专属的,无论它们的绑定模式是什么。
如果没找到匹配的PV,那么PVC会无限期得处于unbound未绑定状态,一旦PV可用了,PVC就会又变成绑定状态。比如,如果一个供给了很多50G的PV集群,不会匹配要求100G的PVC。直到100G的PV添加到该集群时,PVC才会被绑定。
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc-test01
namespace:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
使用
Pod使用PVC就像使用volume一样。集群检查PVC,查找绑定的PV,并映射PV给Pod。对于支持多种访问模式的PV,用户可以指定想用的模式。
一旦用户拥有了一个PVC,并且PVC被绑定,那么只要用户还需要,PV就一直属于这个用户。用户调度Pod,通过在Pod的volume块中包含PVC来访问PV。
kind: Pod
apiVersion: v1
metadata:
name: task-pv-pod
spec:
volumes:
- name: task-pv-storage
persistentVolumeClaim:
claimName: pvc-test01
containers:
- name: task-pv-container
image: nginx
ports:
- containerPort: 80
name: "http-server"
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: task-pv-storage
释放
当用户使用PV完毕后,他们可以通过API来删除PVC对象。当PVC被删除后,对应的PV就被认为是已经是“released”了,但还不能再给另外一个PVC使用。前一个PVC的属于还存在于该PV中,必须根据策略来处理掉。
回收
PV的回收策略告诉集群,在PV被释放之后集群应该如何处理该PV。当前,PV可以被Retained(保留)、 Recycled(再利用)或者Deleted(删除)。保留允许手动地再次声明资源。对于支持删除操作的PV卷,删除操作会从Kubernetes中移 除PV对象,还有对应的外部存储(如AWS EBS,GCE PD,Azure Disk,或者Cinder volume)。动态供给的卷总是会被删除。
参考:
https://kubernetes.io/blog/2017/03/dynamic-provisioning-and-storage-classes-kubernetes
https://kubernetes.io/docs/tasks/configure-pod-container/configure-persistent-volume-storage/
云计算
2018-04-10 11:04:00
1、 shell特殊符号cut命令
*任意个任意字符 #
?任意一个字符 #
#注释字符 #
\脱义字符 #
|管道符号 #

和管道有关的命令
cut的作用截取字符串
cut 分割,-d分隔符 -f指定段号 -c指定第几个字符
sort排序,-n 以数字排序; -r反序 -t分隔符 -kn1/kn1,n2
wc -l 统计行数 -m 统计字符串 -wl 统计词
uniq去重 , -c统计行数
tee和>类似,重定向的同时还在屏幕显示
tr替换字符, tr 'a''b',大小写替换tr '[a-z]''[A-Z]'把所有的小写变成大写的,tr'[a]' '[A]'或者tr 'a' 'A'把小写的a变成大写的A
Split切割, -b大小(默认单位字节) ,-l 行数

cut命令的实例:最后一个可以写成1-3

2、 sort_wc_uniq命令
sort实例:
加上-n,按照数字排序大小;sort -nr 1.txt可以反向排序。
使用-m统计字符串的个数
命令wc -w 2.txt统计2.txt文件的词,以空格或空行做标准
uniq去重实例:需要排序,再去重(复的)
使用命令:sort 2.txt |uniq, -c计算重复的次数

把前面的内容输出到后面去,sort 2.txt |uniq -c > a.txt , 清空的命令:>a.txt,把a.txt文件清空。

3、 tee_tr_split命令
tee 比 > 就多了一个立即显示重定向内容的好处
tr替换字符实例:tr 'a''b',大小写替换tr '[a-z]''[A-Z]'把所有的小写变成大写的,
Split切割实例:
使用find 命令把所有的后缀为conf文件,追加到a.txt的文件中,使用>>命令,missing argument是遗漏的意思。
添加前缀abc

4、shell特殊符号下
变量前缀,!$组合,正则里面表示行尾
;多条命令写到一行,用分号分割。
~用户家目录,后面正则表达式表示匹配符
&放到命令后面,会把命令丢到后台
>:把正确的重定向到一个文件中去; > >:把前面的追加到后面的文件中; 2> :2>> ; &>:把错误的正确的都输出到一个文件中去
[]指定字符中一个,[0-9],[a-zA-Z],[abc]
||和&&,用于命令之间;或者的意思
||:前面的命令执行成功了,后面的就不执行了。
&&:先执行前面的命令再执行后面的命令。
实例:
-d指定的目录,不存在就去创建,存在就不执行后面的命令了,就不创建了。
云计算
2018-04-10 15:50:00
摘要: 阿里有很多的研发团队,不同事业部使用的发布流程、分支策略并非整齐划一,但总体上看是比较规整的。其中有一种主流的发布模式以及对应的分支使用方式,称为“AoneFlow”。这套工作模式思路独特,在阿里以外的地方并不多见。本文围绕这些实践,聊一聊分支管理的话题。


引言
在阿里内部,流行着许多有意思的工程实践。有些实践通过工具和流程嵌在集团的大环境里,外界不容易复制,有些实践则是流露在大家的日常习惯里,被默默的遵守。比如分支管理这件事,其实属于工具和习惯各占一半,并且颇有阿里特色的成分,适合作为一个例子。阿里有很多的研发团队,不同事业部使用的发布流程、分支策略并非整齐划一,但总体上看是比较规整的。其中有一种主流的发布模式以及对应的分支使用方式,称为“AoneFlow”。这套工作模式思路独特,在阿里以外的地方并不多见。本文围绕这些实践,聊一聊分支管理的话题。
细数分支模式
说到分支管理模式,我们最耳熟能详的莫过于 TrunkBased 和 GitFlow。
TrunkBased 模式是持续集成思想所崇尚的工作方式,它由单个主干分支和许多发布分支组成,每个发布分支在特定版本的提交点上从主干创建出来,用来进行上线部署和 Hotfix。在 TrunkBased 模式中,没有显性的特性分支。当然实际上 Git 的分布式特征天生允许每个人有本地分支,TrunkBased 也并非排斥短期的特性分支存在,只不过在说这种模式的时候,大家通常都不会明确强调它罢了。
虽然近年来有许多不错的案例,但 TrunkBased 模式并没有一统天下。它的缺点比较明显,太多的团队同时工作在主干上,到发布的时候就可能出现灾难(尤其是多版本并行开发的情况)。弥补的措施是 FeatureToggle 以及频繁的集成和足够的测试覆盖,这对开发团队的能力提出了比较高的要求。目前 TrunkBased 模式主要用在不需要同时维护多个历史版本的 SaaS 型项目,特别是经过微服务改造的各种小型服务上。
TrunkBased 模式有两种常见演进版本。OneFlow 模式参考了 TrunkBased 的许多思想,对操作流程做了更严格的定义,增加了 Hotfix 分支等内容。多主干模式(通常是双主干,固定的开发分支和固定的发布分支),算是 TrunkBased 采用固定发布分支的特例,在提升团队的微服务落地能力这篇文章里介绍过,不再赘述。
GitFlow 模式是若干模式的集大成者,包含一个主干分支、一个开发分支、许多的特性分支、许多的发布分支和 Hotfix 分支,以及许多繁琐的合并规则。它有一个 Git 插件,不过早就没人维护了。由于对每个阶段的每项操作定义十分明确,它曾经是很多重视流程的企业眼里的香馍馍。但它使用起来并不是很容易,大量的合并冲突和对集成测试不友好也是它被诟病最多的地方。
对,还有 GithubFlow 模式,不过这种策略无非是在 TrunkBased 的基础上,增加了个人仓库和 Pull Request 合并代码的操作,与在同一个仓库里增加个人分支的做法类似,从实用的意义来说,它更合适分布式团队。GithubFlow 也有演进版本,例如强调了多环境部署和将仓库或分支与环境关联的 GitlabFlow 模式。
要么简单粗暴如 TrunkBased,要么繁琐复杂如 GitFlow。难到真没有其他选择了吗?
另辟蹊径的 AoneFlow
在 AoneFlow 上你能看到许多其他分支模式的影子。它基本上兼顾了 TrunkBased 的“易于持续集成”和 GitFlow 的“易于管理需求”特点,同时规避掉 GitFlow 的那些繁文缛节。
看一下具体套路。AoneFlow 只使用三种分支类型:主干分支、特性分支、发布分支,以及三条基本规则。
规则一,开始工作前,从主干创建特性分支。
AoneFlow 的特性分支基本借鉴 GitFlow,没有什么特别之处。每当开始一件新的工作项(比如新的功能或是待解决的问题)的时候,从代表最新已发布版本的主干上创建一个通常以feature/前缀命名的特性分支,然后在这个分支上提交代码修改。也就是说,每个工作项(可以是一个人完成,或是多个人协作完成)对应一个特性分支,所有的修改都不允许直接提交到主干。


规则二,通过合并特性分支,形成发布分支。
AoneFlow 的发布分支设计十分巧妙,可谓整个体系的精髓。GitFlow 先将已经完成的特性分支合并回公共主线(即开发分支),然后从公共主线拉出发布分支。TrunkBased 同样是等所有需要的特性都在主干分支上开发完成,然后从主干分支的特定位置拉出发布分支。而 AoneFlow 的思路是,从主干上拉出一条新分支,将所有本次要集成或发布的特性分支依次合并过去,从而得到发布分支。发布分支通常以release/前缀命名。
这条规则很简单,不过实际的玩法就相当丰富了。


首先,发布分支的用途可以很灵活。基础玩法是将每条发布分支与具体的环境相对应,比如release/test分支对应部署测试环境,release/prod分支对应线上正式环境等等,并与流水线工具相结合,串联各个环境上的代码质量扫描和自动化测试关卡,将产出的部署包直接发布到相应环境上。进阶点的玩法是将一个发布分支对应多个环境,比如把灰度发布和正式发布串在一起,中间加上人工验收的步骤。高级的玩法呢,要是按迭代计划来关联特性分支,创建出以迭代演进的固定发布分支,再把一系列环境都串在这个发布分支的流水线上,就有点经典持续集成流水线的味道了。再或者做一个将所有特性分支都关联在一起的发布分支,专门用于对所有提交做集成测试,就玩出了 TrunkBased 的效果。当然,这些花哨的高级玩法是我臆想的,阿里的发布分支一般都还是比较中规中矩。
其次,发布分支的特性组成是动态的,调整起来特别容易。在一些市场瞬息万变的互联网企业,以及采用“敏捷运作”的乙方企业经常会遇到这种情况,已经完成就等待上线的需求,随时可能由于市场策略调整或者甲方的一个临时决定,其中某个功能忽然要求延迟发布或者干脆不要了。再或者是某个特性在上线前发现存在严重的开发问题,需要排除。按往常的做法,这时候就要来手工“剔代码”了,将已经合并到开发分支或者主干分支的相关提交一个个剔除出去,做过的同学都知道很麻烦。在 AoneFlow 的模式下,重建发布分支只是分分钟的事,将原本的发布分支删掉,从主干拉出新的同名发布分支,再把需要保留的各特性分支合并过来就搞定。这一系列动作能够在很大程度上实现自动化,而且不会在仓库留下一堆剔除代码的记录,干净无污染。
此外,发布分支之间是松耦合的,这样就可以有多个集成环境分别进行不同的特性组合的集成测试,也能方便的管理各个特性进入到不同环境上部署的时机。松耦合并不代表没有相关性,由于测试环境、集成环境、预发布环境、灰度环境和线上正式环境等发布流程通常是顺序进行的,在流程上可以要求只有通过前一环境验证的特性,才能传递到下一个环境做部署,形成漏斗形的特性发布流。阿里有统一平台来自动化完成特性组合在发布分支间的迁移,在下面讲工具的部分里会再介绍。
规则三,发布到线上正式环境后,合并相应的发布分支到主干,在主干添加标签,同时删除该发布分支关联的特性分支。
当一条发布分支上的流水线完成了一次线上正式环境的部署,就意味着相应的功能真正的发布了,此时应该将这条发布分支合并到主干。为了避免在代码仓库里堆积大量历史上的特性分支,还应该清理掉已经上线部分特性分支。与 GitFlow 相似,主干分支上的最新版本始终与线上版本一致,如果要回溯历史版本,只需在主干分支上找到相应的版本标签即可。


除了基本规则,还有一些实际操作中不成文的技巧。比如上线后的 Hotfix,正常的处理方法应该是,创建一条新的发布分支,对应线上环境(相当于 Hotfix 分支),同时为这个分支创建临时流水线,以保障必要的发布前检查和冒烟测试能够自动执行。但其实还有一种简便方法是,将线上正式环境对应的发布分支上关联的特性分支全部清退掉,在这个发布分支上直接进行修改,改完利用现成的流水线自动发布。如果非得修一个历史版本的 Bug 怎么办呢?那就老老实实的在主干分支找到版本标签位置,然后从那个位置创建 Hotfix 分支吧,不过由于阿里的产品大多是线上 SaaS 业务,这样的场景并不多见。
正是这些简单的规则,组成了 AoneFlow 独树一帜的核心套路。
AoneFlow 中每一个看似简单的步骤都并非凭空臆造,而是经历大量产品团队反复磨砺后积累下来的经验。接下来,我会说说 AoneFlow 的技术门槛以及阿里内部的应对之道。
AoneFlow 的体验优化
谙熟武侠之道的人都懂得,掌握一个门派的看家武艺,除了要会招式,还得有深厚的内功和趁手的兵器。否则拿了辟邪剑谱,也只能望谱兴叹。
阿里团队的内功和兵器,实际上是良好的代码习惯和齐全的配套工具。
这里说的习惯,除了开发流程和代码分支的管理方式以外,还包括日常开发中的一些约定俗成的规约。阿里的许多开发规约是有“文献”记载的,主要收录在 《阿里巴巴 Java 开发手册》 里面。它的内容现在已经公开了,所以早就不算是秘密。
举一个具体的例子。在 AoneFlow 的流程中,每次重建发布分支的时候都会重新合并然后编译代码,产生新的部署包。然而,即使代码的内容是一样的,如果工程中依赖了一些会改变的第三方软件包,依然可能导致打包出的产品行为不完全一致。因此,在阿里的代码规约中就明确地指出了,用于线上发布的代码,不可以使用包含“SNAPSHOT 版本”(即未正式发布版本)的依赖包,从而确保每次构建出的产物都是一致的。类似这样的细节还有很多,好的开发习惯是确保软件质量的必要前提。
工具可以使得团队协作更加平滑。虽然只要弄懂原理,AoneFlow 中每个分支创建、合并、更改步骤使用单纯的 Git 命令就能玩转。但其中的一些操作(比如为每个发布分支选出恰当的特性分支组合进行合并)手工执行极易出错,而且让团队的个人重复这些日常琐事的命令操作,并不是令人愉悦的事情。
在阿里内部,使用 AoneFlow 流程的团队基本上不用自己运行 Git 来处理分支的事情,而是由阿里巴巴集团内部名叫 Aone 的协同研发平台(以下简称平台)接管。这个承担集团 80% 产品从需求和用户故事提出到部署上线完整研发流程的平台,内置了许多以服务组件的形式嵌入的研发提效工具,其中的发布组件为 AoneFlow 的用户体验添色不少。比较显著的辅助“功效”包括以下几个方面。
首先是整体流程的自动化。
由于是内部工具,平台的功能高度内聚。对于项目而言,从提出原始需求,将需求拆分为任务,然后根据任务在线创建特性分支,再聚合生成发布分支,同时根据模板自动创建测试环境,直到后期的运维保障都可以一站式的搞定。
这个流程已经远远超出了代码分支管理的范畴。但正是因为如此,平台对于 AoneFlow,向前做到了将特性分支和需求项关联起来,确保了特性分支的命名规范性;向后做到了将发布分支与部署行为关联起来,确保了各环境版本来源的可靠性。打通了端到端交付的任督二脉。
其次是发布分支的流水线。
作为一种流程自动化的手段,CI/CD 流水线是许多现代交付团队中常见的标配实践。在 AoneFlow 的代码生命周期里涉及许多分支,当这些分支被创建或更新时,往往需要伴随其他的一系列行为。流水线能够将这些日常开发过程中的代码分支与其所表达的深层意图(比如提交代码即进行集成测试)联系起来。特别是发布分支,AoneFlow 的每个发布分支通常关联具体的部署环境,当有新代码合并进分支时,就应该及时对代码进行检查和部署。
理想情况下,每条不同的分支都应该有与其作用相匹配的一条流水线来为它服务。AoneFlow 的发布分支是相对固定的,因此相比 GitFlow 更易于进行持续集成。理论上任何流水线工具都能够配合 AoneFlow 使用,不过,阿里的统一平台提供流水线对代码评审、安全检查、在线部署等功能的整合,还是为 AoneFlow 在内部团队的使用优化增色不少。
还有一项很有用的辅助是分支关联的管理。
特性分支与发布分支的关联关系维护是一个 AoneFlow 特有的问题。记住每个发布分支分别来自哪些特性分支对于需要基于现有特性组合进行改变的时候十分有意义。比如当需要将某个特性从特定发布分支退出时,通常会将除了该特性以外的其他特性所在分支进行一次合并,以替换原有的发布分支。人为的记录这些信息并不轻松,要是通过平台进行展示和辅助就会方便许多。
当某些功能组合在一个低级别的发布环境(如集成测试环境)验证完成后,我们希望将它的内容直接迁移到高级别的环境(如预发布环境)对应的发布分支上。这样可以确保线上的版本一定是经过预发验证的,预发的版本一定是经过集成验证的,以此类推,使得各个发布分支形成串联。同样的,使用普通的 Git 命令就能实现这个操作,只不过用可视化工具会让流程更加直观。
除此以外,平台提供代码仓库各个分支状况的统一展示,包括分支所对应部署环境的机器信息、操作记录等全都一览无余。正是这些“高附加值”的辅助,使得 AoneFlow 得以扬长避短,成为阿里团队支撑复杂项目首选的利器。
写在最后
代码分支模式的选择并没有绝对的正确和错误之分,关键是与项目的规模和发布节奏相匹配。阿里协同研发平台在经过众多实践历练后,总结出了一套独创的分支管理方法,通过兼备灵活高效与简单实用的流程,保障阿里旗下众多产品的交付。当你还在犹豫于琳琅满目的分支模式,既舍不得 GitFlow 的并行特性开发,又放不下 TrunkBased 的持续集成友好时,AoneFlow 也许是一个值得考虑的选择。
原文链接
云计算
2018-04-10 10:49:00
万恶的GWF导致通过官方安装地址安装minikube问题多多,阿里云社区提供了科学版的minikube,感谢阿里云!
安装hyperkit虚拟机: curl -LO https://storage.googleapis.com/minikube/releases/latest/docker-machine-driver-hyperkit \ && chmod +x docker-machine-driver-hyperkit \ && sudo mv docker-machine-driver-hyperkit /usr/local/bin/ \ && sudo chown root:wheel /usr/local/bin/docker-machine-driver-hyperkit \ && sudo chmod u+s /usr/local/bin/docker-machine-driver-hyperkit
安装minikube: curl -Lo minikube http://kubernetes.oss-cn-hangzhou.aliyuncs.com/minikube/releases/v0.25.2/minikube-darwin-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/
安装kubectl: curl -Lo kubectl http://storage.googleapis.com/kubernetes-release/release/v1.10.0/bin/darwin/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/ && chmod +x kubectl && sudo mv kubectl /usr/local/bin/
启动minikube: minikube start --vm-driver hyperkit or minikube start --vm-driver hyperkit --registry-mirror=https://registry.docker-cn.com
切换到minikube VM的docker eval $(minikube docker-env)
运行dashboard: minikube dashboard
云计算
2018-04-09 21:31:00
Rancher 2.0 Beta现已正式发布!这是在4月底Rancher 2.0 GA之前最重要的里程碑发布,Rancher 2.0主分支现已包含所有关键功能,Rancher Labs团队即将进入最终Beta阶段,将工作焦点放在测试、文档和扩展性上。
自2017年9月Rancher 2.0技术预览版I发布以来,Rancher Labs研发团队持续进行着Rancher 2.0的功能开发和代码重构工作,先后继续发布了Rancher 2.0技术预览版II和III,且收到了来自客户及开源社区的极为积极的反馈。历时一年的Rancher 2.0开发工作正式进入最终阶段,Rancher 2.0 Beta是Rancher 2.0中最后一个主要的功能集。
Rancher 2.0是一个企业级Kubernetes平台,能够让你统一管理所有云上的所有Kubernetes发行版以及所有的Kubernetes集群。Rancher 2.0由3个主要组件构成:Rancher Kubernetes引擎(RKE)、统一集群管理(Unitied Cluster Management)和工作负载管理(Workload Management)。
Rancher Kubernetes引擎(RKE)
1. 轻量级的Kubernetes安装程序
为方便希望在vSphere集群、裸机服务器以及不支持托管Kubernetes的云提供商上部署Kubernetes的用户,Rancher 2.0中嵌入了RKE。
**2. 简单的Kubernetes操作 **
Rancher支持Kubernetes集群的持续操作,例如集群升级和etcd备份。
3. 驱动Rancher服务器高可用
Rancher可以安装到现有的Kubernetes集群中,该集群可以是为了运行Rancher服务器而创建的小型RKE集群。
统一集群管理
1. 集群和节点管理
不论是由云提供商(谷歌GKE、微软AKS、亚马逊EKS、华为云、阿里云等)托管的Kubernetes集群,还是使用RKE新创建的Kubernetes集群,抑或是从他处导入的现有Kubernetes集群,Rancher 2.0平台均可支持集群和节点的统一管理。
2. 认证
Rancher支持本地认证、Github,以及针对所有GKE、AKS、EKS、RKS、导入集群的AD/LDAP认证。
3. 用户管理
Rancher支持两种默认的用户类型,admin和user,并且可以定义自定义用户类型。
4. 基于角色的访问控制
(Role Based Access Control,RBAC)。Rancher用户可以创建自己的全局集群角色,它可以轻松地分配工作给任何用户,从而管理Kubernetes集群和项目。Rancher包含所有开箱即用的Kubernetes角色,并且还可自定义自己的角色。每个角色都可以分配到全局、集群或者项目层面。
5. 项目和命名空间管理
用户可以创建命名空间并将其分配给项目。“项目”是一种新的Rancher概念,它可以让你对一组命名空间进行分组,并为这些命名空间分配用户权限。
6. Pod安全策略
Rancher 2.0可以让用户创建他们自己的pod安全策略,也可以创建应用于角色的安全策略。
7. Rancher CLI
CLI支持所有主要的Rancher 2.0功能集。
工作负载管理
1. 工作负载UI
Rancher推出了新的工作负载UI,用户可以利用它简单地创建和管理他们的Kubernetes工作负载。
2. Helm目录支持
Rancher 2.0的Catalog(应用程序目录)是建立在Helm charts上的。
3. 告警管理
Rancher 2.0利用Prometheus AlertManager向各种通知器(包括Slack、Email、PagerDuty和Webhooks)发送系统和用户级的告警。
4. 日志管理
Rancher 2.0中安装了Fluentd,来收集写入特定目录的stdout/err输出或日志。Rancher 2.0支持各种日志目标,包括ElasticSearch、Splunk、Syslog和Kafka。
5. CI/CD Pipeline
Rancher 2.0包含一个简单的集成pipeline功能,用户可在项目中创建pipeline来实现持续集成。
从Rancher 1.6迁移到Rancher 2.0
我们最初计划在Rancher 2.0中同时支持Rancher Compose文件和Kubernetes YAML模板。这样一来从Rancher 1.6迁移到Rancher 2.0就会非常简单:你可以将现有的compose文件replay在Rancher 2.0上。
然而不幸的是,我们尝试在Kubernetes上实现完全兼容的Rancher Compose体验时,遇到了巨大的技术挑战。Kubernetes支持许多类似于Cattle的概念。然而,两者之间仍经常存在着重要的差异,这使得转换工作变得非常困难。早期版本的Rancher 2.0 技术预览版I将Rancher Compose结构转换成Pod,绕过了Kubernetes编排。但是根据用户的反馈来看,这并不是最正确的解决方案。相反,我们发现有相当数量的Cattle社区用户对Kubernetes的功能非常感兴趣,而且由于Cattle和Kubernetes之间的相似性,从Rancher Compose创建Kubernetes YAML文件并不太难。
因此,我们决定专注于在Rancher 2.0中单独支持Kubernetes YAML模板,并且开发工具和实践来帮助Cattle用户在Rancher 2.0到Rancher 2.1的这一时间段内迁移到Kubernetes。当然,Rancher Labs会继续提供Rancher 1.6至少一年的支持。随着新兴容器行业的发展,我们也会持续关注Cattle用户社区的需求。
整个Rancher 2.0项目的打造过程之中,我们肩负了将Rancher从基于Docker改变为基于Kubernetes的艰巨任务。我们用Go语言重写了所有遗留的Rancher 1.6 Java模块,在此过程中还涉及到了系统中的几乎所有其他模块。Rancher Labs的数十名核心开发人员同时投入到这一项目中。事实上,这么多开发人员能够如此迅速地进行协作和行动,也是Kubernetes平台的模块化和成熟的证明。我们也更加确信,Kubernetes会成为企业应用程序的基础平台。
结语
Rancher 2.0简洁直观的界面风格及操作体验,将解决业界遗留已久的Kubernetes原生UI易用性不佳以及学习曲线陡峭的问题。而Rancher 2.0创造性的多Kubernetes集群管理功能,更是将解决生产环境中企业用户可能面临的基础设施不同的困境。加之Rancher 2.0带来的监控、日志、CI/CD等一系列拓展功能,可以说,Rancher 2.0为企业在生产环境中落地Kubernetes提供了更加便捷的途径。
秉承Rancher一贯100%开源的风格及理念,你可以直接从GitHub上下载体验Rancher 2.0最新版本: https://github.com/rancher/rancher/releases
Rancher微信公众号(RancherLabs)后台回复“架构”,可下载Rancher 2.0的架构文档!
想要观看Rancher 2.0的演示、了解更多Rancher 2.0的实际应用?欢迎加入4月19日晚的在线培训:使用Rancher 2.0管理Kubernetes集群
云计算
2018-04-09 20:13:00
大约 8个月前,
CNCF 的技术监督委员会 (TOC)
开始着手探究相对较新的
“无服务器计算”世界。
他们想知道:
行业内无服务器领域的发展现状,
以及是否应该在这个领域做些什么
来帮助社区。
为此,他们决定成立一个新工作组来做这项调查。调查涉及了以下主题:
无服务器计算是什么? 它与功能即服务以及其他 *aaS 云计算模型有何关系?何时应考虑使用无服务器计算?社区中无服务器计算的现状 – 例如,您在运行时、框架等方面使用哪些选项?

无服务器处理模型。这里主要围绕大多数无服务器平台中常见的架构进行讨论,而不关注任何特定的实施选择。主要面向那些想要了解它背后工作方式的人。
CNCF 建议。工作组拟定了 TOC 可能要考虑的后续步骤的清单。大多数都涉及到“社区建设”。

工作组认为,要想在这样一个崭新的空间迅速获得互通性案例可能会遭遇重重阻力,但是,通过选择关注现有供应商中看起来存在某种一致性的领域,我们就可能会循序渐进地朝着正确的方向迈进。 若取得成功,它将使用户的生活变得更轻松。
因此,无服务器工作组目前正围绕着定义通用事件格式制定全新的 CloudEvents 规范。
虽然此规范出自“无服务器”工作组之手,但人们已经认识到这种事件格式可以应用于任何事件,而不管处理事件的基础架构如何。

即刻点击“ 阅读原文 ”获得完整文章,让我们一起揭开无服务器计算新篇章!
云计算
2018-04-09 15:27:00
处理数据的机制称为管道。 在配置级别上,管道描述数据来源和相应的汇合点之间的耦合,用于转换和公布数据。 此功能由通知代理处理。
source是数据的生产者: samples 或 events 。 实际上, 它是一组为匹配的 meters和事件类型集合 发出数据点的通知处理程序。
每个source配置将名称匹配和映射封装到一个或多个 sinks 中以供发布。
另一方面,sink是数据的使用者,为转换和发布来自相关源的数据提供逻辑。
实际上,sink描述了一系列的处理程序。 该 chain 从零或更多的 transformers 开始,并以一个或多个 publishers 结束。 chain中的第一个transformer从对应的source传递数据, 采取一些操作, 例如 deriving变动率, 执行单位转换或聚合, 然后 publishing 。
管道配置
通知代理支持两种管道: 一个处理 samples,另一个处理events。 通过在[notifications]设置管道选项,可以启用和禁用管道。
默认情况下,每个管道的实际配置存储在单独的配置文件中: pipeline.yaml 和 event_pipeline.yaml 。配置文件的位置可以由 pipeline_cfg_file 和 event_pipeline_cfg_file 选项设置,配置文件模板查看: Ceilometer Configuration Options 。
meter pipeline 的定义如下的: --- sources: - name: 'source name' meters: - 'meter filter' sinks: - 'sink name' sinks: - name: 'sink name' transformers: 'definition of transformers' publishers: - 'list of publishers'
有几种方法可以定义管道源的meters列表。 有效计量表的清单可以在 Measurements 中找到。 有种方式可以定义所有的 meters 或者只包含或过滤部分 meters,一个 source 配置操作应该按下面方式: 包含所有的 meters 使用*号通配符。但明智的做法是只选择您打算使用的meters,以避免使用了未使用过的数据淹没了计量数据库。 要定义meters列表,可使用下列任何一种:
要包含部分meters,可使用 meter_name 语法。
要过滤部分meters,可使用 !meter_name 语法。
备注: OpenStack遥测服务在管道之间没有任何重复检查, 如果您在多个管道中添加了一个 meter,则假定重复是有意的,并且可以根据指定的接收器多次存储。
上述定义方法可用于以下组合: 只使用通配符符号。 使用 included meters。 使用 excluded meters。 通配符与 excluded 结合使用。
备注: 以上变化中至少有一种应该被包括在meters section。 Included 和excluded meters不能共存于同一管道中。 通配符和included meters 不能在同一管道定义部分中共存。
管道sink的 transformers部分提供了添加 transformers定义列表的可能性。 现有的transformers:
Transformer 的名字 配置的引用名称 Accumulator accumulator
Aggregator aggregator
Arithmetic arithmetic
Rate of change rate_of_change
Unit conversion
Delta
unit_conversion
delta
发布者部分包含发布者列表,其中样本数据应该在可能的转换之后发送。
类似地,事件管道定义看起来像下面这样: --- sources: - name: 'source name' events: - 'event filter' sinks: - 'sink name' sinks: - name: 'sink name' publishers: - 'list of publishers'
事件过滤器使用与meter管道相同的过滤逻辑。
Transformers
备注:Transformers在内存中保存数据,因此不能保证在某些场景下的持久性。 使用像Gnocchi这样的解决方案可以实现更持久、更有效的解决方案。
转换器的定义可以包含以下字段: name 转换器的名称 parameters 转换器的参数
参数部分可以包含transformer特定字段, 在变化速率的案例中,像source和target字段包含有不同的子字段,这依赖于 transformer 的实现。
下面是支持的 transformers:
Rate of change transformer
此种转换器是计算两个数据点之间的时间变化值。下面的transformer例子定义了 cpu_util meter: transformers: - name: "rate_of_change" parameters: target: name: "cpu_util" unit: "%" type: "gauge" scale: "100.0 / (10**9 * (resource_metadata.cpu_number or 1))"
变化率的transformer从cpu计数器的样本值生成 cpu_util meter, 它代表了纳秒的累计CPU时间。 上面的transformer定义定义了一个比例因子(用于纳秒和多cpu), 在转换之前应用于从cpu表的顺序值派生出一个带有%单位的度量样本序列。
磁盘I/O速率的定义,也由变化率的转换器生成 : transformers: - name: "rate_of_change" parameters: source: map_from: name: "disk\\.(read|write)\\.(bytes|requests)" unit: "(B|request)" target: map_to: name: "disk.\\1.\\2.rate" unit: "\\1/s" type: "gauge"
Unit conversion transformer
此种转换器应用于单位转换。 它接收meter的volume,并将它乘以给定的尺度表达式。 也支持如 transformer变化率一样带有 map_from 和 map_to 字段。
样本配置: transformers: - name: "unit_conversion" parameters: target: name: "disk.kilobytes" unit: "KB" scale: "volume * 1.0 / 1024.0"
使用 map_from 和 map_to : transformers: - name: "unit_conversion" parameters: source: map_from: name: "disk\\.(read|write)\\.bytes" target: map_to: name: "disk.\\1.kilobytes" scale: "volume * 1.0 / 1024.0" unit: "KB"
Aggregator transformer
在到达足够的样本或超时之前, 此种转换器会对输入的样本进行汇总。
可以使用 retention_time 选项指定超时。 如果您想要刷新aggregation,在聚合了一定数量的samples之后,请指定参数大小。
所创建的样本容量是输入到l转换器的样本容量的总和。 样本可以通过 project_id , user_id 和 resource_metadata 属性聚合。 根据所选择的属性进行聚合,在配置中指定它们,并设置该属性的值以获取新样本( 首先使用第一个样本属性,最后取最后一个样本属性,然后删除该属性)。
通过 resource_metadata 汇总60秒的样本值,并保存最新收到的样本的 resource_metadata : transformers: - name: "aggregator" parameters: retention_time: 60 resource_metadata: last
通过 user_id 和 resource_metadata 聚合每个15个样本, 并保留第一个接收到的sample的 user_id ,并删除 resource_metadata : transformers: - name: "aggregator" parameters: size: 15 user_id: first resource_metadata: drop
Accumulator transformer
这种转换器只是简单地缓存样本,直到达到足够的样本,然后立即将它们全部冲下管道: transformers: - name: "accumulator" parameters: size: 15
Multi meter arithmetic transformer
此种转换器使我们能够在一个或多个meters上进行算术运算,进行 and/or元数据。例如: memory_util = 100 * memory.usage / memory
根据 transformer 配置的 target 部分里的属性描述会创建一个新的sample。 样本容量是根据提供的表达式计算的结果。 对同一资源的样本进行计算。
备注: 计算的范围仅限于同一区间内的 meter。
例子配置文件: transformers: - name: "arithmetic" parameters: target: name: "memory_util" unit: "%" type: "gauge" expr: "100 * $(memory.usage) / $(memory)"
为了演示元数据的使用,以下一种新型测量器的实现显示了每个核心的平均CPU时间: transformers: - name: "arithmetic" parameters: target: name: "avg_cpu_per_core" unit: "ns" type: "cumulative" expr: "$(cpu) / ($(cpu).resource_metadata.cpu_number or 1)"
备注: Expression evaluation gracefully handles NaNs and exceptions. 在这种情况下,它不会创建一个新的sample,而是只记录一个警告。
Delta transformer
这种转换器计算一个资源的两个样本数据点之间的变化。 它可以配置为只捕获正增长的增量(deltas)。
实例配置: transformers: - name: "delta" parameters: target: name: "cpu.delta" growth_only: True
Publishers
遥测服务提供几种传输方法,将收集到的数据传输到外部系统。 这些数据的消费者有很大的不同,就像监视系统一样,数据丢失是可以接受的但计费系统需要可靠的数据传输。遥测技术提供了满足两种系统要求的方法。
发布者组件可以通过消息总线将数据保存到持久存储中,或将其发送给一个或多个外部消费者。一个chain可以包含多个发布者。
为了解决这个问题,可以为遥测服务中的每个数据点配置多发布者,允许将相同的技术meter或事件多次发布到多个目的地,每个目的地都可能使用不同的传输。
支持下面的发布者类型:
gnocchi (默认)
在启用gnocchi发布者时,会将度量和资源信息推送到gnocchi进行时间序列优化存储。 Gnocchi必须在 Identity服务中注册,因为Ceilometer通过Identity服务来发现确切的路径。
关于如何启用和配置gnocchi的更多细节可以在其 官方文档页面 找到。
panko
云计算中的事件数据可以存储在panko中,它提供了一个HTTP REST接口来查询OpenStack中的系统事件。 把数据推给panko, 设置 publisher 为 panko:// 。
notifier
notifier publisher 可以以 notifier://?option1=value1&option2=value2 的形式指定。 它使用oslo.messaging来发出AMQP的数据。 然后,任何消费者都可以订阅已发布的主题进行额外的处理。
以下是可用的定制选项:
per_meter_topic
这个参数的值是1。 它用于在额外的 metering_topic.sample_name 主题队列,除了默认的 metering_topic 队列,发布samples。
policy
用于配置案例的行为,当发布者无法发送样品时,可能的预定义值是:
default : 用于等待和阻塞,直到samples被发送。
drop: 用于丢弃未能发送的samples。
queue: 用于创建内存中的队列,并在下一次样本发布期间重新尝试将样品发送到队列中(队列长度可以用 max_queue_length 属性来配置,默认值是 1024 )。
topic
要发布到的队列的主题名称。 设置这个选项将会覆盖由 metering_topic 和 event_topic 默认设定的主题。 这个选项可以用来支持多个消费者。
udp
此publisher 可以用 udp://:/ 的形式指定。 它通过UDP发出计量数据。
file
此publisher 可以用 file://path?option1=value1&option2=value2 的形式指定。 此种发布者将测量数据记录到一个文件中。
备注: 如果没有指定文件名和位置, file 发布者不会记录任何meters,而是为Telemetry在配置的日志文件中记录一条警告消息。
以下选项可供 file publisher 使用:
max_bytes 当这个选项大于零时,它将导致翻转。 当指定的大小即将溢出时,文件将被关闭,一个新的文件将被静默打开以输出。 如果它的值为零,那么翻转就不会发生。
backup_count 如果该值是非零的,则扩展将被追加到旧日志的文件名,如.1、.2等等,直到达到指定的值为止。 编写状态和包含最新数据的文件始终是没有任何指定扩展的。
http
遥测服务支持将samples发送到外部HTTP目标。samples没有任何修改地发出。 要将此选项设置为通知代理目标,请将 http:// 设置为管道定义文件中的发布者端点。 HTTP目标应该与发布者声明一起设置。 例如,可以通过 http://localhost:80/?option1=value1&option2=value2 来传递额外的配置选项。
下面的选项是可用的:
timeout HTTP请求超时前的秒数。
max_retries 在失败之前重试请求的次数。
batch 如果为 false, 发布者将分别发送每个sample和event,无论通知代理是否被配置成批量处理。
verify_ssl 如果为 false,则禁用ssl证书验证。
默认发布者是gnocchi,没有指定其他选项。 /etc/ceilometer/pipeline.yaml 配置文件里的 sample publisher部分类似下面: publishers: - gnocchi:// - panko:// - udp://10.0.0.2:1234 - notifier://?policy=drop&max_queue_length=512&topic=custom_target
管道分割
备注: Partitioning只有当管道包含有transformations时才是必须的。在某些publishers的支持下, 它有次要的好处。 在大的工作负载下,可以部署多个通知代理来处理来自监视服务的传入消息的泛滥。 如果在管道中启用了转换,则必须协调通知代理,以确保将相关消息路由到同一代理。 要启用协调,请在 notification 部分设置 workload_partitioning 值。
要跨代理分发消息,应该设置 pipeline_processing_queues 选项。 这个值定义了要创建多少个管道队列,然后将其分发给活动的通知代理。 建议处理队列的数量至少与代理的数量匹配。
增加处理队列的数量将改进消息在代理之间的分布。 它还有助于将请求最小化到Gnocchi存储后端。 它还将增加对消息队列的加载,因为它将使用队列到碎片数据。
警告: 减少处理队列的数量可能会导致数据丢失,因为以前创建的队列可能不再被分配给活动代理。 只建议您增加处理队列。
转载: http://luozn.top/2018/04/11/223/

云计算
2018-04-09 11:51:00
yum源概述
  yum需要一个yum库,也就是yum源。默认情况下,CentOS就有一个yum源。在/etc/yum.repos.d/目录下有一些默认的配置文件(可以将这些文件移到/opt下,或者直接在yum.repos.d/下重命名)。
  首先要找一个yum库(源),然后确保本地有一个客户端(yum这个命令就是客户端),由yum程序去连接服务器。连接的方式是由配置文件决定的。通过编辑/etc/yum.repos.d/CentOS-Base.repo文件,可以修改设置。
打开CentOS-Base.repo文件,可以看到url路径是CentOS的官网自身的yum源, http://mirrorlist.centos.org/?release=releasever&arch=releasever&arch=basearch&repo=os 。可以将这个mirrorlist注释掉,然后将baseurl设置成国内的阿里云源 http://mirrors.aliyun.com/repo/Centos-6.repo ,也可以在用于大量的rpm包的前提下设置成自己的本地文件系统(挂载目录),需要移除CentOS-Base.repo文件,并编辑CentOS-Media.repo文件。
name=Description#一个描述,随意。 baseurl=#设置资源库的地址,可以写阿里云也可以是自己的yum ftp:// http:// file:/// enabled={1|0}#enabled=1开启本地更新模式 gpgcheck={1|0}# gpgcheck=1表示检查;可以不检查gpgcheck=0 gpgkey=#检查的key;如果上面不检查这一行可以不写。
[centos] yum软件仓库唯一标识符,避免与其他仓库冲突
name=centos yum软件仓库的名称描述,易于识别仓库用处
baseurl=file:///mnt 提供的方式包括FTP(ftp://..)、HTTP(http://...)、本地(file:///...)。
gpgcheck=0 设置此源是否校验证文件;1为校验,0为不校验。
enabled 设置此源是否可用;1为可用,0为禁用。

centos 多个yum源,系统怎么选择
yum配置文件:
/etc/yum.conf
pkgpolicy:包的策略。一共有两个选项,newest和last,这个作用是如果你设置了多个repository,而同一软件在不同的repository中同时存在,yum应该安装哪一个,如果是newest,则yum会安装最新的那个版本。如果是last,则yum会将服务器id以字母表排序,并选择最后的那个服务器上的软件安装。一般都是选newest。
如果包在两个yum源中都有,会在下面的文件中按顺序:
/var/cache/yum/x86_64/6/timedhosts.txt

yum源配置的两种方法 :
配置方法一 : (本地挂载目录) 本地挂载
配置方法二(远程挂载目录) 网络挂载 (常见的 阿里云源 )

1、 yum更换国内源
cd /etc/yum.repos.d/ #切换到/etc/yum.repos.d/
rm -f dvd.repos #删除dvd.repos
wget http://mirrors.163.com/.help/CentOS7-Base-163.repo
或者
curl -O http://mirrors.163.com/.helpo/CentOS7-Base-163.repo #
yum list #安装CentOS7-Base-163.repo的源
实例:
使用cp ../yum.repos.d.bak/* . ,把之前的拷贝回来,CentOS-Base.repo是yum源。
安装下载国内源
使用vim查看安装的源,使用yum list 查看
安装zlib

yum安装失败,重新生成缓存,执行完图形中的命令后,使用yum clean all 和yum install zsh命令。

清理所有的缓存。
查看有哪些仓库

下载wget
常见问题:报错的原因,可能是因为没有把dev.repo删除
2、 yum下载rpm包
yum install -y 包名 --downloaonly    #仅仅下载不安装
ls /var/cache/yum/x86-64/7/        #查看下载的位置
yum list -y 包名 --downloaonly --downloaddir=路径 #
yum reinstall -y 包名 --downloaonly --downloaddir=路径  #重新安装到指定下载的目录
先使用yum list查看有没有安装,然后使用yum install安装。
指定下载的rpm包

指定下载的目录为/tmp/,使用ls /tmp/查看下。
注意:你如果用的是本地的yum源的话,它确实不支持下载。要用网络的源才行。
3、源码包安装
安装扩展源epel
yum install -y epel-release #安装源epel-release,安装完成后,使用yum list 查看下
yum list |grep epel #查看源epel
源码包安装
1.cd /usr/local/src/ #切换到/usr/local/src/目录,把源码包放在/usr/local/src/目录下
2.wget http://mirrors.cnnic.cn/apache/httpd/httpd-2.2.32.tar.gz #下载压缩包
3.tar zxvf httpd-2.2.32.tar.gz #解压缩httpd-2.2.32.tar.gz
4.cd httpd-2.2.32 #切换到httpd-2.2.32 然后使用ls命令下有一个叫INSTALL的文件,使用more INSTALL查看
5、 (1) ./configure --prefix=/usr/local/apache2 #指定安装路径
(2)make #
(3)make install #
卸载就是删除安装的文件
源码包下载地址:r.aminglinux.com
下载 httpd-2.2.32.tar.gz 包,
5、 ./configure --prefix=/usr/local/apache2 #指定安装路径
如果后面结果是No,说明没有安装。使用命令
解决办法:你下载一个包,编译安装:yum -y install pcre-devel ,,只是编译,,接着make,,make && make install
安装apr-util报的错。 安装一个依赖包就好了 ,命令:
yum install expat-devel
编译成功 再安装应该没多大问题
这是编译的显示(参数),接着make&&make install

安装完成了

apr \apr-util编译的两个版本:1、./configure --prefix=/usr/local/apache --with-included-apr

2、./configure --prefix=/usr/local/apache2 --with-apr=/usr/local/apr --with-apr-util=/usr/local/apr-util
如果还是不行,把你下载的apr和apr-util源码包解压到httpd下面的srclib目录里面,重命名为apr和apr-util,,,解压apr和apr-util包到这个目录下
查找资料包里面的httpd目录下的srclib目录,,重新编译,要在源码包里面。

Make提示错误。是依赖的目录不对。
安装的目录,解压到当前的目录下。安装就指定目录了。Src目录


编译的时候禁用 proxy 就可以了 ,命令: ./configure --prefix=/usr/local/apache2 --disable-proxy

安装2.4.33的httpd安装不了,试着安装2.4.29的httpd

httpd 2.4.33版本报错,编译安装完apr和apr-util之后,在编译的时候指定路径也可以解决。 # ./configure --prefix=/usr/local/apache4 --with-apr=/usr/local/apr --with-apr-util=/usr/local/apr

语法错误。使用vi编辑查看,第三十行。


解决办法/原因:版本底,改用python或者把yum的首行该成/usr/bin/python2

还是语法错误。

修复CentOS7升级Python到3.6版本后yum不能正确使用的解决方法

http://www.jb51.net/article/133730.htm?utm_source=debugrun&utm_medium=referral

显示404,,,写错地址了。

使用命令echo $?查看是上一个命令是否错误。如果结果非零,那么就是错的。
使用yum install gcc安装没有安装的包,再运行命令 ./configure --prefix=/usr/local/apache2 查看
再使用命令echo $?查看上一个命令是否正确。
(2).执行make命令
再使用echo $?命令检测下,结果为0,说明没错。
(3). make install 把编译完成的二进制文件目录放到指定的files目录下,在使用下echo $?命令检测下
使用命令ls /usr/local/apache2/查看下
常见问题,执行yum install glibc-static命令。
安装参考链接:http://blog.51cto.com/13658403/2105586

另一个版本的说明:http://blog.51cto.com/11751505/2105637
HOSTORY命令:http://blog.lishiming.net/?p=484

资源链接 :
yum源配置的三种方法 : https://www.cnblogs.com/yangp/p/8506264.html
企业实际应用之同步远程yum源到本地 荐 : http://blog.51cto.com/dl528888/1342653




云计算
2018-04-09 11:36:00
当 PV 不再需要时,可通过删除 PVC 回收。
当 PVC mypvc1 被删除后,我们发现 Kubernetes 启动了一个新 Pod recycler-for-mypv1 ,这个 Pod 的作用就是清除 PV mypv1 的数据。此时 mypv1 的状态为 Released ,表示已经解除了与 mypvc1 的 Bound,正在清除数据,不过此时还不可用。
当数据清除完毕, mypv1 的状态重新变为 Available ,此时则可以被新的 PVC 申请。
/nfsdata/pv1 中的 hello 文件已经被删除了。
因为 PV 的回收策略设置为 Recycle ,所以数据会被清除,但这可能不是我们想要的结果。如果我们希望保留数据,可以将策略设置为 Retain 。
通过 kubectl apply 更新 PV:
回收策略已经变为 Retain ,通过下面步骤验证其效果:
① 重新创建 mypvc1 。
② 在 mypv1 中创建文件 hello 。
③ mypv1 状态变为 Released 。
④ Kubernetes 并没有启动 Pod recycler-for-mypv1 。
⑤ PV 中的数据被完整保留。
虽然 mypv1 中的数据得到了保留,但其 PV 状态会一直处于 Released ,不能被其他 PVC 申请。为了重新使用存储资源,可以删除并重新创建 mypv1 。删除操作只是删除了 PV 对象,存储空间中的数据并不会被删除。
新建的 mypv1 状态为 Available ,已经可以被 PVC 申请。
PV 还支持 Delete 的回收策略,会删除 PV 在 Storage Provider 上对应存储空间。NFS 的 PV 不支持 Delete ,支持 Delete 的 Provider 有 AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume 等。
下一节我们学习 PV 的动态供给功能。
书籍:
1.《每天5分钟玩转Kubernetes》
https://item.jd.com/26225745440.html
2.《每天5分钟玩转Docker容器技术》
https://item.jd.com/16936307278.html
3.《每天5分钟玩转OpenStack》
https://item.jd.com/12086376.html
云计算
2018-04-09 06:16:00
CDN是将源站内容分发至全国所有的节点,从而缩短用户查看对象的延迟,提高用户访问网站的响应速度与网站的可用性的技术。它能够有效解决网络带宽小、用户访问量大、网点分布不均等问题。

为了让大家更全面的了解CDN的原理、调度、缓存和安全等关键技术点,阿里云高级技术专家白金将自己从事 CDN 相关领域工作 8 年来的一些经验、收获和个人认知撰写成《CDN之我见》系列文章,分享给大家。
《CDN 之我见》共分成多个部分,分为原理篇、详解篇和陨坑篇,因为篇幅问题这里先讲第一部分。本篇章适合那些从未接触过、或仅了解一些 CDN 专业术语,想深入了解和感受 CDN 究竟是什么的同学。下面我们进入分享正文:

这个篇章,主要分成 4 个小部分来和大家做一下简单的介绍和分享。

CDN的起源

CDN 诞生于二十多年前,随着骨干网压力的逐渐增大,以及长传需求的逐渐增多,使得骨干网的压力越来越大,长传效果越来越差。于是在 1995 年,MIT 的应用数学教授 Tom Leighton 带领着研究生 Danny Lewin 和其他几位顶级研究人员一起尝试用数学问题解决网络拥堵问题。

他们使用数学算法,处理内容的动态路由安排,并最终解决了困扰 Internet 使用者的难题。后来,史隆管理学院的 MBA 学生 Jonathan Seelig 加入了 Leighton 的队伍中,从那以后他们开始实施自己的商业计划,最终于 1998 年 8 月 20 日正式成立公司,命名为 Akamai。
同年 1998 年,中国第一家 CDN 公司 ChinaCache 成立。

在接下来的20年中,CDN行业历经变革和持续发展,行业也涌现出很多云CDN厂商。阿里云CDN是2008年从淘宝CDN起家,在2014年正式发展成为阿里云CDN的,它不仅为阿里巴巴集团所有子公司提供服务,同时也将自身的资源、技术以云计算的方式输出。

那什么是 CDN 呢?

CDN 其实是 Content Delivery Network 的缩写,即“内容分发网络”。
上图是一个做过 CDN 之后的拓扑图,里面有几个概念需要明确一下: Origin Server:源站,也就是做 CDN 之前的客户真正的服务器。 User:访问者,也就是问网站的网民。 Edge Server:CDN 的服务器,不单指“边缘服务器”,这个之后细说。
在 CDN 中,还有 3 个”一英里“的概念,即 First Mile、Middle Mile 和 Last Mile。 First Mile:和 CDN 客户的服务器越近越好的 CDN 设备,即第一英里。 Last Mile:访问者(网民)到离他最近的 CDN 服务器,即最后一英里。 Middle Mile:数据从进入 CDN 网络,到出 CDN 网络之前的所有环节,即中间一英里。

为什么要用 CDN 呢?

从上图可以看到,左图是未做 CDN 之前跨洋跨国的长传业务,用户从西班牙访问到美国纽约要经过北大西洋,直线距离6,000km 左右,按照光速300,000km/s 的传输速度,一束光从西班牙到纽约也至少需要 20ms 时间,一个往返就需要 40ms。如果是光纤传输数据,加上传输损耗、传输设备延时引入等,可能上百毫秒就出去了,即使用浏览器访问一个再小不过的图片,也会等个上百毫秒,积少成多,访问一个美国购物网站会让用户无法接受。

右侧这张图是做过 CDN 之后的示意图。从图上可以看出,网民实际访问到的服务器不是位于美国的真实服务器,而是位于英国的 CDN 服务器。而 CDN 本身有缓存功能,把那些网页里一成不变的内容,例如图片、音乐、视频等,都分发并缓存到了各个 CDN 服务节点上,这样网民就不必从西班牙访问到纽约,而是访问距离自己较近的英国节点即可,从而节省了 80% 以上的时间。

当然,这是一个西班牙访问英国 CDN 节点的例子,如果 CDN 节点也位于西班牙本地,则效果会更加明显,具体细节后续会有更详细的说明。

接下来说一下调度。调度是 CDN 中的重中之重,流量接入、流量牵引、选择合适的 CDN 节点服务器等工作,都是在调度环节完成的。

要理解调度策略和原理,必须先了解 DNS 协议及其工作原理。
我们平时所工作的电脑里,都会配置(人为或自动)一个 DNS 服务器地址,我们称之为”本地 DNS“,也叫 Local DNS,简称 LDNS。在解析一个域名的时候,实际访问的不是”域名“而是 IP 地址,则 LDNS 服务器的用途就是负责将域名翻译成 Internet 可以识别的 IP 地址。
在请求某个域名时,LDNS 一般有两个情况:一种是域名在 LDNS 上有记录,另一种情况是没有记录,两种情况的处理流程不一样。 假设当访问 163 这个域名时,如果 LDNS 上有缓存记录,那它会直接将 IP 地址吐出来。 如果没有缓存记录,它将会一步步向后面的服务器做请求,然后将所有数据进行汇总后交给最终的客户,这个环节术语叫”递归“。
在完全不命中情况,LDNS 首先会向全球13个根域服务器发起请求,询问 .com 域名在哪里,然后根域服务器作出回答,然后去向 .com 的服务器询问 .163.com 在哪里,一步步往下,最后拿到 www.163.com 这个域名所对应的 IP 地址。这个过程较复杂,如果大家感兴趣可去查相关资料,在这就不一一赘述。
肯定很多人好奇是如何进行调度和进行定位的?其实也是通过 LDNS 的具体地址来进行的,如上图所示。
假设网民是一个北京客户,那他所使用的 DNS 服务器去做递归的时会访问到CDN厂商的 GLB(Global Load Balance),它可以看到所访问的域名请求是来自于哪个 LDNS,根据一般人的使用习惯,网民所在位置和 LDNS 所在位置是一样的,因此 GLB 可以间接知道网民来自什么位置。
假如网民是一个北京联通的用户,它使用的 LDNS 地址也是北京联通的,而 LDNS 访问 GLB 也是北京联通的,则 GLB 则认为网民的位置在北京联通,那么会分配一个北京联通的 CDN 服务器地址给 LDNS,LDNS 将 http:www.a.com 解析出的 IP 地址返回给最终网民,那么在以后网民浏览器发起请求的时候,都会直接与北京联通的 CDN 节点进行流量通信,从而达到了加速的目的。
从这个调度理论上看,我们可以不难发现一个问题,就是重点标注出的“根据一般人的使用习惯”。假设网民所使用的 LDNS 地址和他自己在同一个区域,调度才有可能是准确的(后续篇章会重点描述为什么是“有可能”)。
但是举个例子来说,如果网民是北京联通的用户,但他却偏要使用深圳电信的 LDNS,LDNS 出口也同样是深圳电信的 IP 地址,那么 GLB 会误判网民位于深圳电信,分配给网民的 CDN 服务器也都是深圳电信的,后续网民会从北京联通访问到深圳电信,不但没加速,可能反而降速了。

如前文所述,由于用户使用习惯或一些其他原因,通过 LDNS 调度有可能是不准确的,因此又出现了另一种调度方式,HTTP 302 调度。
原理很简单,无论网民最初拿到的 IP 地址是否是正确的,但最终都是要和这个 IP 地址的 CDN 服务器通信的,因此 CDN 服务器可以在这时知道网民的真实地址(DNS 调度时只能间接知道网民地址,虽然 EDNS-Client-Subnet 技术可以解决问题,但尚未大规模使用)。
HTTP 协议中有一个特殊的返回状态:302。在 HTTP 服务器返回 302 状态码时,可以携带一个新的 URL(使用的是正确 IP),浏览器在拿到 302 返回状态码时,会提取其中新的 URL 地址发起请求,这样就可以做到重新调度了。

除了 DNS 调度、HTTP 302 调度,还有一种使用 HTTP 进行的 DNS 调度策略。
随着网络日新月异的发展和演进,也逐渐出现了很多鲜为人知的技术和设备,例如劫持(具体在后面的篇章里会单独阐述)。劫持后,网民所访问的目标有可能不再是真实服务器,即使是真实服务器,内容也有可能是虚假的、被替换过的,这对业务安全来说是十分危险的,这种劫持现象多出现在移动互联网(手机上网)。
为了规避这种问题,出现了一种 HTTP DNS 的调度方式,原理是通过 HTTP 报文传输 DNS 请求和应答信息。但这种方式没有任何 RFC 的支持,所以没有任何现成的操作系统直接支持,必须有自己的 HTTP DNS 客户端,来与 HTTP DNS 服务端进行通信,需要双端支持。这种做法在 APP 中使用较多。
那 CDN 是如何将用户的流量引入到 CDN 网络中的呢?
在未做 CDN 时,我们访问某个域名,直接拿到的是一个真实的服务器 IP 地址,这个显示 IP 地址的 DNS 记录信息叫 A 记录,一般是下图这个样子。

当业务需要接入到 CDN 时,用户只需调整自己的 DNS 配置信息,将 A 记录改为 CNAME 记录,将内容改为 CDN 厂商所提供的接入域名即可。
原文链接
阅读更多干货好文,请关注扫描以下二维码:
云计算
2018-04-08 17:23:00
当我试图部署一个应用到SAP云平台的neo环境时: 指定Compute Unit Size为Lite: 点击Deploy按钮,遇到如下错误消息:there is no compute unit quota for subaccount:
解决方案
使用命令行neo set-quota --account wc4e460ce --user i042416 --host int.sap.hana.ondemand.com --amount lite:1 给subaccount分配一个计算单元:
分配之后,使用如下命令查看subaccount状态,确保分配成功: neo account:list-accounts --account wc4e460ce --user i042416 --host int.sap.hana.ondemand.com
之后即可成功部署:
neo的console客户端命令参考 SAP help
要获取更多Jerry的原创技术文章,请关注公众号"汪子熙"或者扫描下面二维码:
云计算
2018-06-23 19:41:00
摘要: 最为常见的【弹窗】反而是最“捉摸不定”的东西。各种类型的弹窗傻傻分不清楚,不知道在什么场景下应该用哪种弹窗。尤其是遇到“二次确认”等场景…… 因此,打算从头整理移动弹窗的基础知识,以iOS弹窗体系为切入点,从定义出发,对移动弹窗进行分类,然后分别分析每一类弹窗的应用场景,以及在使用过程中需要注意的点。
云小妹导读:作为设计童鞋的经常打交道的移动组件,反而是最捉摸不定的东西,各种类型的弹窗傻傻分不清楚,不知道在什么场景下应该用哪种弹窗。尤其是遇到“二次确认”等场景
今天的Work Like Alibaba实践分享,我们邀请 阿里巴巴TXD体验中心 的交互设计师夏天 为我们带来IOS弹窗体系分享。
1 前言
前段时间整理移动组件,发现最为常见的【弹窗】反而是最“捉摸不定”的东西。各种类型的弹窗傻傻分不清楚,不知道在什么场景下应该用哪种弹窗。尤其是遇到“二次确认”等场景……
因此,打算从头整理移动弹窗的基础知识,从定义出发,对移动弹窗进行分类,然后分别分析每一类弹窗的应用场景,以及在使用过程中需要注意的点。
本想一次性全部整理完,但是发现iOS和Material Design两大体系下的弹窗类目繁多,相互之间又有千丝万缕的关联,因此决定拆分成四篇来仔细整理: 移动弹窗基础知识浅析系列一:iPhone弹窗体系 移动弹窗基础知识浅析系列二:安卓手机弹窗体系(Material Design) 移动弹窗基础知识浅析系列三:iPhone与安卓两大手机弹窗体系之间的关系与差异 移动弹窗基础知识浅析系列四:手机、平板、手表端的弹窗体系之间的关系与差异
2 名词解释 弹窗:
弹框是人机交互中常见的方式,常常出现于询问、警示以及完成某个插入任务,常见于网页端及移动端。弹框能使用户有效聚焦于当前最紧急的信息,也可以在不用离开当前页面的前提下,完成一些轻量的任务。 移动弹窗:
运用在移动端的弹窗,包括了手机、平板、手表等移动端设备。本文整理学习对象的是【iPhone】的弹窗体系。 模态:
模态(Modality) 是一种视图,在当前的iOS 10的人机交互指南(Human Interface Guidelines)中有如下定义: 模态视图突出焦点,因为用户只有在完成当前的任务或关闭一个信息或视图之后才能去做其它事情。
当屏幕上出现一个模态视图时,用户必须采取一个决定(点击按钮或是其它)才能退出模态化体验。一个模态视图可以占据整个屏幕、整个父视图(比如浮出层)或者屏幕的一部分。一个模态视图一般都含有“完成”和“取消”按钮来退出视图。
Modality creates focus by preventing people from doing other things until they complete a task or dismiss a message or view. When a modal view appears onscreen, the user must make a choice by tapping a button or otherwise exiting the modal experience. A modal view can occupy the entire screen, an entire parent view, such as a popover, or a portion of the screen. A modal view typically includes completion and cancel buttons that exit the view.
早在iOS 7的HIG中,模态是归属于【Temporary View】类目下,且在定义上更加直白地指出: 模态视图是完成一系列任务的有效视图。他出现在所有元素的顶部,且会阻塞所有底部元素的操作。
Modals are a useful view for tasks that require multiple commands or inputs by the user. They appear on top of everything else, and, while open, block interaction with any other interactive elements underneath.
简单理解起来,模态视图,就是在原始视图上,叠加一层蒙版,用以隔离原始视图中的所有操作,然后在蒙版上展示一层新视图,让用户更专注于完成新视图中的任务。
模态弹窗:
运用模态视图的弹窗。 非模态弹窗
运用非模态视图的弹窗。
3 移动弹窗的分类
根据是否运用模态视图,我把收集到的所有iOS的弹窗类型进行如下分类:
4 模态弹窗
4.1 对话框(Alerts,System Rating and Review Prompts)
4.1.1 定义
对话框,是我们最为常见的【弹窗】类型。
对话框 - Alerts : 对话框承载与当前状态有关的重要信息,常需要用户进行响应。对话框由标题、信息内容(可选)、一个或多个按钮、文本输入框(可选)四部分组成。除了上述可选元素以外,对话框的外观是固定的不可修改的。
Alerts convey important information related to the state of your app or the device, and often request feedback. An alert consists of a title, an optional message, one or more buttons, and optional text fields for gathering input. Aside from these configurable elements, the visual appearance of an alert is static and can’t be customized.
4.1.2 常见的使用方式
常用于信息提示、操作二次确认、邀请评分、授权等场景。
——百度网盘,微信,蜗牛睡眠,Worktile

除了定义中提到的【文本输入框】之外,iOS还提供了默认打分的组件【System Rating and Review Prompts】:

4.1.3 使用过程中需要注意的点
标题:简短能说明问题的标题。 信息内容:根据需要可不填写。 按钮: 一般数量控制在3个以内,若需要更多的按钮,建议使用【操作列表】。 可使用加粗、颜色等方式,引导用户作出选择。 文案要具体精准,让用户明白选择之后会发生什么。而不要使用“是”“否”等语意不明的词。 符合用户预期的按钮放在右侧,【取消】按钮固定在左侧。 当有破坏性的操作的时候,一方面要突出显示具有潜在破坏性的操作按钮,另一方面要确保有【取消】按钮,保证用户能够安全地取消破坏性操作。(例如删除等。) 支持Home键关闭弹窗。 扩展组件:特殊情况下,可使用定义的扩展组件。例如文本输入框、打分组件等。 操作方式:由于必须要获取用户明确的响应,因此只有选择按钮才能关闭弹窗。(点击蒙版无法关闭弹窗)
4.2 操作列表(Action Sheets,Action Views)
4.2.1 定义
操作列表 - Action Sheet 操作列表是一种特殊的对话框,是对操作动作的响应,显示当前操作场景下相关联的多个选项。用于让用户开始任务,或者在执行潜在的破坏性操作前,进行二次确认。
An action sheet is a specific style of alert that appears in response to a control or action, and presents a set of two or more choices related to the current context. Use an action sheet to let people initiate tasks, or to request confirmation before performing a potentially destructive operation.
操作视图 - Activity View 操作视图是app快捷任务的展示面板。用户点击面板上的任务,可以直接执行相应的任务。
An activity is a task, such as Copy, Favorite, or Find, that’s useful in the current context. Once initiated, an activity can perform a task immediately, or ask for more information before proceeding. Activities are managed by an activity view, which appears as a sheet or popover, depending on the device and orientation.
4.2.2 常见的使用方式
操作列表常被用于单选操作,以及 删除操作的二次确认。 (单一操作)
——哔哩哔哩,teambition,照片,微信(未使用原生弹窗)
操作视图常被用于分享操作。
——Safari,钉钉,微信,UC
4.2.3 使用过程中需要注意的点 确保有一个【取消】的按钮。 突出显示具有潜在破坏性的操作按钮。 尽量避免列表的滚动,如选项过多,则需要留出视觉线索。 对于【操作视图】,需要明确的应用图标和操作名称,用于清晰地描述任务。
4.3 浮出层(Popover,Edit Menus,Home Screen Quick Action Menus)
4.3.1 定义
浮出层 - Popovers 浮出层是一种暂时性的视图,他出现在用户点击区域的顶层。典型的浮出层包括一个箭头,指向浮出层出现的位置。浮出层可以是模态的,也可以是非模态的。
A popover is a transient view that appears above other content onscreen when you tap a control or in an area. Typically, a popover includes an arrow pointing to the location from which it emerged. Popovers can be nonmodal or modal.
编辑菜单 - Edit Menus 用户可以在文本、网页、图片等地方,使用长按、双击的手势唤起【编辑菜单】。他包含了一些相关联的编辑操作,比如复制、粘贴等。
People can touch and hold or double-tap an element in a text field, a text view, a web view, or an image view to select content and reveal edit options, such as Copy and Paste.
主屏快捷操作菜单 - Home Screen Quick Action Menus 快捷主屏操作菜单,是通过3D Touch唤起的快捷菜单。
Home screen quick actions are a convenient way to perform useful, app-specific actions right from the Home screen, using 3D Touch.
4.3.2 常见的使用方式
严格意义上的浮出层,能够包含【导航栏、工具栏、标签栏、表格、收藏、图片、地图】等各种元素,所以由于展示空间的问题,只能使用在iPad端,在手机端对应的是【全屏模态视图(Full-Screen Modal Views)】。
但是,浮出层的明确指向性和便捷性,依旧非常适合用于手机端的菜单选择,因此很多app都自己设计了小型的Popovers:
——微信,钉钉,手机淘宝,支付宝
编辑菜单,常用于对文本和聊天记录的编辑。
——微信,钉钉,备忘录,UC
主屏快捷操作菜单,是iOS独有的交互形式,只在主屏中使用,用于快速执行应用的常用任务。
——iOS主屏

4.3.3 使用过程中需要注意的点
显示符合上下文情景的操作选项,并用通用的文案描述。 尽可能地减少选项数量,只显示最有意义的操作。 使用标准手势唤起菜单。 根据唤起的位置,自动调整菜单的位置。 对于【编辑菜单】: 自动选择相关联的词组。 不要加入【编辑】按钮。 支持【撤销/重做】操作。
4.4 模态视图(Modal View)
4.4.1 定义 一个模态视图可以占据整个屏幕、整个父视图(比如浮出层)或者屏幕的一部分。
A modal view can occupy the entire screen, an entire parent view, or a portion of the screen.
这里分析的【模态视图】,区别于【对话框】,占据了更大范围的屏幕,内部包含更多的操作。
4.4.2 常见的使用方式
根据占据屏幕的方式及范围,可以分为【全屏、半屏、中央】三种类型,其中【全屏、半屏】常包含复杂表单:
全屏,常见于“新建后发送、选择后下载”等场景。
——网易邮箱-写邮件,钉钉-DING,微信-转发消息,腾讯视频-缓存
半屏,常见于“侧边导航、选择器”等场景。
——滴滴出行,大众点评,手机淘宝,支付宝
中央,常见于“宣传、引导用户”等场景。
——百度糯米,滴滴出行,美团,teambition
4.4.3 使用过程中需要注意的点 确保模态视图中的任务是简练严谨的,让用户能够聚焦高效地完成任务。 提供明显且安全的退出模态视图的方式。 对于【全屏/半屏】: 未点击【保存/确认/完成】等明确的按钮之前,所有的修改都不会生效。 模态视图多从边缘进入。 点击蒙版即可关闭模态视图。
5 非模态弹窗
5.1 透明指示层(UIProgressHUD)
具体的定义没有找到,对应的是安卓独有的的Toast,据说iOS称之为 HUD(head up display) 。目前未开放接口,只应用在原生系统的音量键。
但是在很多APP中,大家已经习惯将广义上的Toast用于状态的提示:
——iOS音量键,手机淘宝,大众点评,腾讯视频
5.2 通知(Notifications)
5.2.1 定义 无论手机是锁屏状态还是使用状态,app应用都能通过通知,第一时间传递给用户重要信息。
Apps can use notifications to provide timely and important information anytime, whether the device is locked or in use.
5.2.2 常见的使用方式
运行中的顶部banner,重按之后,会展开并呼出【操作列表 Action Sheet】。
5.2.3 使用过程中需要注意的点 提供精炼有价值的信息。 注意通知发送的频率和时机。 考虑3D Touch重按之后的展示细节内容,以及相关的操作按钮。
6 参考文献 认识移动端弹框, https://mp.weixin.qq.com/s/9XyiKTiXYaIHcFHDbpvLEg Human Interface Guidelines(iOS 10,2017.06), https://developer.apple.com/ios/human-interface-guidelines/overview/design-principles/ The iOS Design Guidelines(iOS 7,2015.9.28), http://ivomynttinen.com/blog/ios-design-guidelines 几种弹窗设计模式(iOS端), http://www.jianshu.com/p/63eb8fad9329 实用干货!UI设计师需要了解的 APP弹窗体系, http://www.uisdc.com/app-popup-ui-system

注1:本文是基于iOS 11的人机交互指南(Human Interface Guidelines)、网上大神们的文章、个人经验总结梳理而成,还望大家不吝赐教,提出宝贵的意见或建议。
注2:若内容涉及侵权,请联系管理员,我们将第一时间删除相关内容。
原文链接
本文为云栖社区原创内容,未经允许不得转载。
云计算
2018-06-22 18:15:00
摘要: 东方明珠新媒体如何基于阿里云,搭建了面向第三方的视频SaaS服务?6月8日,上海云栖大会视频专场中,东方明珠新媒体股份有限公司云计算中心的副总周少毅带来了《东方明珠视频云》为题的精彩演讲,介绍了东方明珠视频云的搭建过程。
东方明珠新媒体如何基于阿里云,搭建了面向第三方的视频SaaS服务?6月8日,上海云栖大会视频专场中,东方明珠新媒体股份有限公司云计算中心的副总周少毅带来了《东方明珠视频云》为题的精彩演讲,介绍了东方明珠视频云的搭建过程。
东方明珠新媒体股份有限公司拥有国内最大的多渠道视频集成与分发平台及文化娱乐消费资源,为用户提供丰富多元、特色鲜明的视频内容服务及一流的视频购物、文旅消费、影视剧及游戏等文娱产品,是上海广播电视台、上海文化广播影视集团有限公司(SMG)旗下统一的产业平台和资本平台,在2017年中国互联网企业100强中排名16位。
在分享中,周少毅表示:起初,各行业、各企业都想建立自己的网站,而现在,各行业、各企业都希望在网站中加入视频,因为视频在传播中最有震撼力,这是一个市场需求。但是并不是所有企业都可以投入如此多的人力和时间,所以东方明珠基于阿里云视频服务,建立了一套完整的OTT平台SaaS服务,让非专业公司拥有视频服务像搭建一个网站一样简单。
整体的视频流处理通常分为五大流程:素材上传、审核、视频剪辑、转码发布、展现播放,基于东方明珠这套视频SaaS服务,全部工作都可以直接通过网页完成,功能可以非常轻便快捷的实现。视频的SaaS服务可以应用于门户网站、新零售、医疗、新媒体等众多行业场景中,任何需要视频为媒介来宣传,或者以视频为载体进行培训的企业都可以接入,东方明珠新媒体内部客户已经开始使用了。
周少毅也提到,在使用阿里云视频服务的过程中,有几点对他比较有吸引力。第一是视频云的云端剪辑能力,它让视频内容编辑可以很轻量的完成;第二是内容安全,HLS标准加密解决方案能够支持加密传输,配合存储中的安全、攻击防护、劫持抵御等,提高整个视频传输链路中的安全性;第三是云服务无需硬件采购,没有使用边界,在任何时间、地点都可以轻松登录云端;第四是弹性投资,按照实际用量付费。
东方明珠视频SaaS服务采用的阿里云产品图
对于视频云的HLS标准加密方案,周少毅评价整体流程既简单又高效、既安全又方便,对方案非常满意。在本次分论坛现场,他也分享了一些实践流程及细节。
HLS标准加密视频加密流程相对比较简单,从KMS拿到密钥,告诉VOD,VOD把这个视频加密,并且把加密密钥写在RDS中就好了,整个加密在转码过程很高效地就完成了。
但是加密播放是比较复杂的,因为涉及到不同种类的终端。HLS标准加密最大的好处就是加密的工作都在服务端完成,播放器端几乎不用改,播放明文和播放非加密的流程是一样的,省去了复杂的适配调整。同时,关于KEY的发放、加密内容的传输的安全级别也是很高的。
周少毅表示作为客户,整个使用的过程非常简单,客户端发起请求加密视频之后,对于EPG或者AAA来说,只要去请求服务,拿到Token,放到URL中,播放URL返回给客户端,就结束了。
除了VOD HLS标准加密解决方案之外,东方明珠视频SaaS平台也采用阿里云标准大数据解决方案,整个过程如下图。
在分享的最后,周少毅为现场的开发者和企业提出了一些建议:我们做事情还是不能从轱辘做起,最好基于现有的平台,如果能采用SaaS,你的人力投入可能是基本是零;如果能用PaaS,投入可能是几个人。如此才能快速地具备能力,应对当今迅速变化的市场环境。
原文链接
云计算
2018-06-22 17:02:00