关于集群:CNStack-多集群服务基于-OCM-打造完善的集群管理能力

概述随着 Kubernetes 在企业业务中的利用和倒退,单集群内的治理能力曾经趋于欠缺,越来越多的客户冀望在多云、多集群场景部署其业务,因而须要提供相应的多云、多集群治理能力。 CNStack 多集群服务是 CNStack 面向多集群、多云场景提供的云原生服务,可能对立治理 CNStack 平台创立的、阿里云上的、客户自建的和其余云上的 Kubernetes 集群。 在 CNStack 2.0 中,CNStack 多集群服务是以云服务(cnstack-multicluster)的模式存在,这样一方面在单集群模式下用户能够齐全聚焦集群内治理,另一方面也便于多集群服务能力独立演进,更加麻利高效。该服务在 CNStack2.0 中次要提供以下性能,并会逐渐在后续版本上线更多能力(如多集群资源散发、利用跨集群故障迁徙、多集群Service等)。• 扩大 OCM[1] 的集群注册能力,提供更加欠缺的注册相干的集群治理能力• 提供多种散发资源的模式: • 基于 OCM ManifestWork API 的 Pull 模式• 基于 Cluster Gateway 的 Push 模式• 反对实现多集群多租户治理,多集群对立认证和鉴权• 为平台和云服务/云组件提供管控集群(Hub Cluster)和被治理集群(Managed Cluster)之间的跨集群高可用互访能力 残缺内容请点击下方链接查看: https://developer.aliyun.com/article/1173337?utm_content=g_10... 版权申明:本文内容由阿里云实名注册用户自发奉献,版权归原作者所有,阿里云开发者社区不领有其著作权,亦不承当相应法律责任。具体规定请查看《阿里云开发者社区用户服务协定》和《阿里云开发者社区知识产权爱护指引》。如果您发现本社区中有涉嫌剽窃的内容,填写侵权投诉表单进行举报,一经查实,本社区将立即删除涉嫌侵权内容。

May 26, 2023 · 1 min · jiezi

关于集群:网易易盾流量多发反外挂落地实践

背景及目标环境迁徙反外挂服务建德机房线上迁徙,采取的计划是:建德机房独立部署一套残缺的集群,对立经由残缺的性能测试、故障演练、性能回归后,通过线上分阶段切换流量的形式来切服务。QA 须要比对验证 2 个不同环境下外围接口返回值,保证数据上报检测性能稳固,确保迁徙前后性能的一致性。 策略验证智能风控新产品上线前,为了保障策略成果,建设上线信念,须要对现有的策略进行验证。验证的伎俩是通过客户端 QA 在功能测试阶段收集的真机样本,同时也对这些蕴含了多种外挂危险、环境危险等信息的样本进行准确标记,在性能回归阶段将样本重放,查看策略是否满足预期成果。 日常回归在反外挂服务的日常测试中,服务端的测试数据是通过脚本结构的,对于简单的场景的测试,更好的抉择是利用线上实在的玩家数据——其中蕴含丰盛的设施信息、外挂信息等数据,能够更好地笼罩反外挂策略。在此基础上建设样本回归的常态化,利用实在样本,更全面地笼罩外围场景。 反外挂接入流程反外挂的接入次要分为 8 个步骤(如下图所示)其中步骤 1 在 GoAPI 平台实现,步骤 2、3、5、6、8 在流量比对平台实现,步骤 4、7 在代码中稍微革新。 GoAPI 平台建设接口/场景等信息在 GoAPI 平台上创立被测接口或场景信息,将步骤蕴含在“数据循环”中,能够是单接口也能够是存在依赖关系的多个接口。 “数据”设置“参数 key”和“值”。“参数 key”为须要替换的数据(样本中的 key),“值”为样本的具体数值。 流量比对平台创立接口信息在流量比对平台上创立被测接口信息,设置好子服务和业务类型,配置须要测试的 2 个环境的域名,输出场景 id,关联刚刚在 GoAPI 平台上创立的场景,这样流量比对平台上后续的工作就能触发 GoAPI 平台上的场景进行执行。 建设反外挂样本库接下来是要在流量比对平台上创立反外挂的样本库,通过样本库的治理进行样本的存储和更新。创立的样本库设置子服务和业务类型、样本下限等信息,后续采集的样本归属于以后样本库。 定制化反外挂样本采集机制反外挂的样本采集起源有 2 个:一是线上 ES 存储的实在玩家上报数据,依照肯定的要求提取数据,而后荡涤、字段映射、加密等操作后输入为反外挂样本数据;另一个是客户端 QA 应用真机在测试过程收集的数据,而后进行手动标注,取得准确标注各种外挂信息的样本。 线上 ES 采集反外挂样本在 ES 中依照设定的要求(平台或者外挂信息等)提取数据,而后依照反外挂接口须要的信息以及格局进行解决:包含依据 Protobuf 协定,从新映射字段;依据客户端与服务端通信加密算法从新加密数据,而后将最终数据存入对应的样本库。目前已采集线上真机样本数据: 真机测试数据转化反外挂样本客户端 QA 在测试过程中,应用真机装置了各类辅助工具或者外挂工具测试零碎策略,并将这些上报的信息存储在数据库中,再对这些真机样本进行准确的标注,这些样本就能够转化为流量比对平台可用的样本。目前已采集标注客户端真机样本:105 条。 样本采集配置在流量比对平台上创立样本采集的配置,前文中形容的 ES 提取数据所依照的要求就是在此处设置实现的。 导入配置:ES 中提取的数据荡涤和过滤的要求,以及提取的比例。 提取字段:ES 中数据提取的字段,能够提取结构化的数据的局部字段。 保护反外挂场景信息咱们在测试反外挂的过程中,心愿能把握测试的场景笼罩状况,所以梳理出各种场景以及场景分类。在流量比对平台上手动增加场景信息。在样本的管理处能够将已知的样本与对应的场景进行关联,将样本与场景分割起来,通过不同的样本执行实现不同的场景笼罩,并能在执行后果中对场景的笼罩进行观测。 ...

May 23, 2023 · 1 min · jiezi

关于集群:Sealer-09-帮助集群和分布式应用实现-Build-ShareRun

新春之际,很快乐在此时发表 Sealer[1] 0.9 版本的正式公布。Sealer 是一款致力于摸索面向分布式应用的疾速打包、交付和运行的解决方案。2021 年5月 Sealer 我的项目正式开源;短短一年工夫,Sealer 在 2022 年 4 月成为 CNCF Sandbox 我的项目。Sealer 0.9 版本中,其在外围定位上由专一 “集群维度的 Build,Share,Run” 降级为 “以集群为根底,以利用为核心,帮忙集群和分布式应用实现 Build, Share,Run”,并重点加强了对利用的反对能力。 版本详解加强对利用的反对利用与集群解耦Docker Image 很好的解决了单机利用的打包交付问题,而 Sealer Image[2] 尝试在集群维度,解决类 Kubernetes 集群以及分布式应用的打包交付问题。Sealer Image 基于蕴含内容将 Sealer Image 分为集群镜像和利用镜像。 残缺内容请点击下方链接查看: https://developer.aliyun.com/article/1143611?utm_content=g_10... 版权申明:本文内容由阿里云实名注册用户自发奉献,版权归原作者所有,阿里云开发者社区不领有其著作权,亦不承当相应法律责任。具体规定请查看《阿里云开发者社区用户服务协定》和《阿里云开发者社区知识产权爱护指引》。如果您发现本社区中有涉嫌剽窃的内容,填写侵权投诉表单进行举报,一经查实,本社区将立即删除涉嫌侵权内容。

May 22, 2023 · 1 min · jiezi

关于集群:yaml文件中在哪加命名空间

在集群治理页左侧导航栏中,抉择工作负载 > 无状态。 在无状态页面上方的命名空间下拉列表中抉择指标命名空间,而后在页面右上角单击应用YAML创立资源。 在集群列表页面中,单击指标集群名称,而后在左侧导航栏中,选择网络 > 服务。 在服务页面顶部,设置命名空间为istio-system,在右上角单击应用YAML创立资源。 残缺内容请点击下方链接查看: https://developer.aliyun.com/ask/501031?utm_content=g_1000371411 版权申明:本文内容由阿里云实名注册用户自发奉献,版权归原作者所有,阿里云开发者社区不领有其著作权,亦不承当相应法律责任。具体规定请查看《阿里云开发者社区用户服务协定》和《阿里云开发者社区知识产权爱护指引》。如果您发现本社区中有涉嫌剽窃的内容,填写侵权投诉表单进行举报,一经查实,本社区将立即删除涉嫌侵权内容。

May 9, 2023 · 1 min · jiezi

关于集群:集群部署看过来低代码AWS智能集群的架构与搭建方案

亚马逊AWS是葡萄城的生态合作伙伴。为了帮忙您充分利用AWS的托管服务疾速构建起一套集群环境,彻底去掉“繁多故障点”,实现最高的可用性,咱们筹备了《低代码智能集群@AWS的架构与搭建计划》看完本文,带你把握“基于nginx配置服务器集群”。 利用场景如果你须要解决如下的问题,能够思考搭建一套活字格@AWS智能集群: 保障系统高可用,全面升高停服危险在做好各项性能优化(参考系列教程)的前提下,须要进一步晋升性能,以满足大并发量申请的响应速度 集群能力本计划是官网与生态合作伙伴亚马逊AWS提供的一套高可用负载平衡解决方案,在活字格智能集群的根底上,通过引入ALB等托管服务,进一步晋升可用性。本计划提供的次要能力如下: 高可用负载平衡可用性监控特地提醒:活字格智能集群不兼容内建SQLite数据库,您须要在外联数据库上构建数据表和业务。 搭建计划活字格&亚马逊AWS集群须要用到亚马逊提供的EC2负载均衡器(ALB模式)、ElasticCache Redis集群、Elastic File Systems、RDS for MySQL、CloudWatch托管服务,还须要用到nginx实现应用服务器外部的端口转发。对上述技术的理解水平,很大水平上决定了您搭建出的集群的安全性、性能和可用性。 网络拓扑简图 为了实现高可用的指标,本计划的应用服务器设计为位于不同可用区的2台EC2,其余托管服务也抉择了多可用区的配置。 步骤1:配置EFS 在AWS控制台中抉择EFS服务,创立文件系统,点击“自定义”按钮后,依照上面的推荐值实现配置: 存储类:规范挂载指标:抉择至多2个可用区平安组:抉择的平安组中须要容许2049端口(你能够在EC2服务的管制台上找到“网络与平安→平安组”创立一个平安组) 创立实现后,等文件系统的文件系统状态变成“可用”,点击刚创立的文件系统,DNS名称就是用来拜访该EFS的地址,记录下来备用。 步骤2:配置RDS RDS的默认平安设置与活字格不兼容。所以,在创立数据库前,你须要创立参数组,具体做法如下:在AWS控制台中抉择RDS服务,在“资源”区域,点击“参数组”,创立新的参数组,抉择和创立RDS时统一的版本,示例中组名和形容都设置为“huozige-aws”。点击创立好的参数组,在搜寻框中输出“log\_bin\_trust\_function\_creators”,而后点击“编辑参数”按钮,将值批改为1。 而后回到控制台,点击“创立数据库”,点击“规范创立”后,依照上面的推荐值实现配置: 引擎类型:MySQL版本:MySQL 5.6.x、5.7.x、8.0.x都能够,示例抉择的是5.7.38模板:生产设置-主明码:你的登录明码,示例设置的是123456数据库实例类:依据并发用户数、业务数据量和估算抉择调配的存储空间:依据业务数据量抉择,须要留神的是活字格不会将用户上传的文件寄存的数据库,不占用该存储空间多可用区实例:创立备用实例连贯-公开拜访:是平安组:抉择的平安组中须要容许3306端口其余设置-参数组:刚创立的huozige-aws 创立实现后,等数据库的状态变成“可用”,点击刚创立的数据库实例,找到连贯和安全性选项卡下的“终端节点”,这个就是数据库服务的地址,记录下来备用。应用本地装置的MySQL Workbrench等工具登录到该地址,创立一个userservicedb数据库备用。 步骤3:配置EC Redis 在AWS控制台中抉择ElastiCache服务,点击右侧菜单中“资源→Redis集群”,点击“创立Redis集群”后,依照上面的推荐值实现配置: 集群模式:已启用地位-多可用区:已启用引擎版本:举荐6.2节点类型:依据用户数量和估算抉择,活字格会应用Redis存储用户会话,示例抉择的是cache.t3.medium(3.09GB)子网组设置:创立新的子网组,确保“已抉择 子网”蕴含不少于2个可用区平安组:抉择的平安组中须要容许6379端口创立实现后,等集群的状态变成“可用”,点击刚创立的集群,找到“主终端节点”,这个就是Redis的地址,记录下来备用。 步骤4:配置应用服务器 在AWS控制台中抉择EC2服务,点击右侧菜单中“实例→实例”,点击“创立新实例”后,依照上面的推荐值实现配置: 镜像:在【亚马逊云科技Marketplace】中搜寻“GrapeCity Huozige Lowcode Development Platform”,抉择官网提供的AMI镜像实例类型:依据利用复杂度、并发用户数和估算抉择,示例中应用的是t3.meduim,举荐用于简略的部门级利用子网:应用服务器须要放到不同的可用区,如cn-northwest-1a和cn-northwest-1b平安组:抉择的平安组中须要容许22端口(SSH)、22345端口(活字格利用公布)、8200(用于活字格应用服务器,能够在nginx.conf中批改)ssh证书:妥善保存浏览器下载的pem格局的证书,这是近程登录EC2的惟一凭据。举荐所有EC2共享同一个证书,这样在登录时更不便一些 创立实现后,等实例状态变成“正在运行”后,点击查看详情,公有IPv4地址即内网IP,用于配置负载均衡器;私有IPv4 DNS是外网地址,用于监控(EC2实例进行后重新启动时,私有IPv4地址会发生变化,所以,不能应用这个地址做监控),记录下这两个值备用。点击“连贯”按钮,进入SSH客户端选项卡,复制“示例”下的ssh命令,记录备用。 在Windows电脑上,将下载的pem证书拷贝到%homepath%(如C:\Users\Will)下,这里也是Windows终端的启动目录。启动终端,用EC2共的ssh命令就能够近程登录到该服务器,执行上面的装置和配置操作。 4.1 装置中文字体 受到版权限度,咱们无奈为您预置罕用的“微软雅黑”等中文字体,如果您须要导出PDF性能,须要手动装置字体,具体方法见 帮忙文档的第6节。 4.2 装置和配置ngnix nginx负责将各利用的端口对立成8200(可批改,须要和平安组的设置匹配)。 首先,咱们须要装置nginx。装置实现后,批改ngnix.conf文件 sudo apt-get updatesudo apt-get install nginx在http节点下,为治理控制台和每一个利用别离创立upstream # 内置服务指向本机22345固定端口upstream local-us{server localhost:22345;}# 针对每个利用创立上游,指向本机即可upstream local-e{server localhost:8005;}而后,在http→server节点下,设置侦听端口,过滤location并转发治理控制台和每一个利用 server {# 对外的端口号listen 8200;server\_name huozige-aws-app-server.com;proxy\_set\_header   Upgrade $http\_upgrade;proxy\_set\_header   Connection keep-alive;proxy\_set\_header   Host $host;proxy\_cache\_bypass $http\_upgrade;proxy\_set\_header   X-Forwarded-For $proxy\_add\_x\_forwarded\_for;proxy\_set\_header   X-Forwarded-Proto $scheme;proxy\_set\_header   X-Real-IP $remote\_addr;# 转发内置服务location ^~ /UserService/ {proxy\_pass http://local-us/UserService/;proxy\_redirect default;}# 针对每个利用做转发,去掉端口号location ^~ /app\_e/ {proxy\_pass http://local-e/app\_e/;proxy\_redirect default;}}配置文件批改结束,让nginx做热加载,不中断服务器的前提下,读取新的配置 ...

November 28, 2022 · 1 min · jiezi

关于集群:揭露sealer背后实现整个集群一键交付的奥秘-龙蜥技术

编者按:集群镜像把整个集群看成一台服务器,把 k8s 看成云操作系统,实现整个集群的镜像化打包和交付,为企业级软件提供一种“开箱即用”的利用封装技术。本文整顿自龙蜥大讲堂技术直播第11期,由龙蜥社区集群镜像 SIG 核心成员、sealer我的项目发起人方海涛分享——通过 sealer 实现整个集群 Build&Share&Run。 以下是本期龙蜥大讲堂直播回顾文: 什么是镜像集群顾名思义,和操作系统 .iso 镜像或 Docker 镜像相似,集群镜像是用肯定的技术手段把整个集群的所有文件以肯定格局打成的一个资源包。 比照单机和集群会发现一些的乏味景象: 单机有计算、存储、网络等驱动;集群有 CNI/CSI/CRI 实现像是集群的驱动。单机有 ubuntu centos 操作系统;集群中能够把 Kubernetes 看成云操作系统。单机上能够运行 docker 容器或虚拟机;相当于一个运行的实例,集群上也有运行着 K8s 的实例。单机上有虚拟机镜像,docker 镜像;随着云计算技术的倒退,集群上也会形象出相似的镜像技术。以基于 Kubernetes 的集群镜像为例,外面蕴含了除操作系统以外的所有文件: docker 依赖的二进制与 systemd 配置、dockerd 配置,以及一个公有的容器镜像仓库。Kubernetes 外围组件二进制、容器镜像、kubelet system 配置等。利用须要用到的 yaml 配置或 helm chart,以及利用的容器镜像。其它脚本、配置与二进制工具等利用运行须要的所有依赖。同样,集群镜像运行时必定不是起一个容器或者装在一台机器上,而是这个镜像能够间接装置到多台服务器上或者间接对接到私有云的基础设施上。 sealer 介绍sealer 是阿里巴巴开源的集群镜像的一个实现形式(开源我的项目地址见文末)。 Docker 解决了单个容器的镜像化问题,而 sealer 通过把整个集群打包,实现了分布式软件的 Build Share Run!!!试想咱们要去交付一个 SaaS 利用,它依赖了 MySQL/ES/Redis 这些数据库和中间件,所有货色都在 Kubernetes 上进行编排,如果没有集群镜像时,要做如下操作: 1)找个工具去装置 K8s 集群 2)helm install mysql es redis... 如果是离线环境可能还须要导入容器镜像 3)kubectl apply yoursaas ...

April 15, 2022 · 3 min · jiezi

关于集群:如何利用-集群流控-保障微服务的稳定性

作者:宿何 微服务的稳定性始终是开发者十分关注的话题。随着业务从单体架构向分布式架构演进以及部署形式的变动,服务之间的依赖关系变得越来越简单,业务零碎也面临着微小的高可用挑战。利用高可用服务 AHAS (Application High Availability Service) 是经阿里巴巴外部多年高可用体系积淀下来的云产品,以流量与容错为切入点,从流量管制、不稳固调用隔离、熔断降级、热点流量防护、零碎自适应爱护、集群流控等多个维度来帮忙保障服务的稳定性,同时提供秒级的流量监控剖析性能。AHAS 不仅在阿里外部淘宝、天猫等电商畛域有着宽泛的利用,在互联网金融、在线教育、游戏、直播行业和其余大型政央企行业也有着大量的实际。 流控是保障微服务稳定性最罕用也是最间接的一种管制伎俩。每个零碎、服务都有其能承载的容量下限,流控的思路非常简单,当某个接口的申请 QPS 超出肯定的下限后,回绝多余的申请,避免零碎被突发的流量打垮。市面上最常见的计划是单机维度的流控,比方通过 PTS 性能测试预估某个接口的容量下限是 100 QPS,服务有 10 个实例,则配置单机流控 10 QPS。但很多时候,因为流量散布的不确定性,单机维度的流量管制存在一些成果不佳的状况。 典型场景 1:准确管制对上游的调用总量 场景: 服务 A 须要频繁调用服务 B 的查问接口,但服务 A 和 B 的容量存在差别,服务 B 约定最多给服务 A 提供总共 600 QPS 的查问能力,通过流控等伎俩进行管制。 痛点: 若依照单机流控的策略配置,因为调用逻辑、负载平衡策略等起因,A 调用 B 达到每个实例的流量散布可能十分不均,局部流量较大的服务 B 实例触发单机流控,但总体限度量尚未达到,导致 SLA 未达标。这种不均的状况常常会产生在调用某个依赖服务或组件(如数据库拜访)的时候,这也是集群流控的一个典型场景:准确管制微服务集群对上游服务(或数据库、缓存)的调用总量。 典型场景 2:业务链路入口进行申请总量管制 场景: 在 Nginx/Ingress 网关、API Gateway (Spring Cloud Gateway, Zuul) 进行入口流量管制,心愿准确管制某个或某组 API 的流量来起到提前爱护作用,多余流量不会打到后端系统。 痛点: 如果依照单机维度配置,一方面不好感知网关机器数变动,另一方面网关流量不均可能导致限流成果不佳;而且从网关入口角度来讲,配置总体阈值是最天然的伎俩。 AHAS 集群流控AHAS 集群流控能够准确地管制某个服务接口在整个集群的实时调用总量,能够解决单机流控因流量不平均、机器数频繁变动、均摊阈值太小导致限流成果不佳的问题,联合单机流控兜底,更好地施展流量防护的成果。 对于下面的场景,通过 AHAS 集群流控,无论是 Dubbo 服务调用、Web API 拜访,还是自定义的业务逻辑,均反对准确管制调用总量,而无关调用逻辑、流量散布状况、实例散布。既能够撑持数十万 QPS 大流量管制,也反对分钟小时级业务维度小流量准确管制。防护触发后的行为可由用户自定义(如返回自定义的内容、对象)。 ...

November 28, 2021 · 1 min · jiezi

关于集群:集群-与-分布式微服务

简明扼要分布式:一个业务分拆多个子业务,部署在不同的服务器上集群:同一个业务,部署在多个服务器上解释: 集群每一台服务器实现的性能【没有什么差异】。分布式每一台实现的性能是【有差别】集群是同一个业务部署在多台机器上,进步零碎可用性。分布式是不同业务模块拆分到不同机器上,解决高并发的问题集群为程度拆分、分布式为垂直拆分分布式与微服务的关系是什么参考文章: https://zhuanlan.zhihu.com/p/... 分布式,将我的项目拆分成多个模块,并离开部署,即为分布式微服务,更细粒度的拆分(如 用户信息模块,结算模块等等)三者之间的个性集群将多台服务器集中到一起,它们都做雷同的事件,缓解单体架构下的单体故障和并发压力问题 伸缩性: 一组服务器组合在一起,每台能够独自解决工作,如果遇到压力问题能够减少集群数量,也能够缩小高可用性: 即如一台服务出问题,可应用其余服务,保障整体业务的高可用负载平衡: 平衡解决网络流量负载,将流量摊派到各服务器缩小单体压力高性能:在集群的多台服务状况下,能够使的程序运行解决并行计算下,进步计算速度分布式将不同业务进行拆分,缩小整体服务的压力,并通过某种形式对不同业务数据进行连贯,进步整体服务运行效率 微服务即十分渺小的业务拆分,独自部署,独自运行,独自保护 分布式也等同于微服务

July 4, 2021 · 1 min · jiezi

关于中间件:nsqlookupd高性能消息中间件-NSQ-解析

摘要:本篇将会联合源码介绍 nsqlookupd 的实现细节。本文分享自华为云社区《高性能消息中间件 NSQ 解析-nsqlookupd 实现细节介绍》,原文作者:aoho 。 本篇将会联合源码介绍 nsqlookupd 的实现细节。nsqlookupd 次要流程与nsqd 执行逻辑类似,区别在于具体运行的工作不同。 nsqlookupd是nsq治理集群拓扑信息以及用于注册和发现nsqd服务。所以,也能够把nsqlookupd了解为注册发现服务。当nsq集群中有多个nsqlookupd服务时,因为每个nsqd都会向所有的nsqlookupd上报本地信息,因而nsqlookupd具备最终一致性。 入口函数在 nsq/apps/nsqlookupd/main.go 能够找到执行入口文件。 // 位于apps/nsqlookupd/main.go:45func main() { prg := &program{} if err := svc.Run(prg, syscall.SIGINT, syscall.SIGTERM); err != nil { logFatal("%s", err) }}func (p *program) Init(env svc.Environment) error { if env.IsWindowsService() { dir := filepath.Dir(os.Args[0]) return os.Chdir(dir) } return nil}func (p *program) Start() error { opts := nsqlookupd.NewOptions() flagSet := nsqlookupdFlagSet(opts) ...}同样,通过第三方 svc 包进行优雅的后盾过程治理,svc.Run() -> svc.Init() -> svc.Start(),启动 nsqlookupd 实例。 ...

April 7, 2021 · 3 min · jiezi

关于集群:CODING-CD-Nginx-Ingress-实现蓝绿发布

本文作者:杨浩佳 - CODING 后端开发工程师 全文约 4000+ 字,预计浏览工夫 20 分钟前言本文将介绍如何通过 CODING CD 应用 Nginx Ingress 来实现蓝绿公布。 为什么要采纳蓝绿公布?随着业务的疾速倒退,对开发团队的要求越来越高,一方面要求为用户提供稳固的服务,一方面要求进行疾速业务迭代。因而基于零碎稳定性和疾速业务迭代的综合思考,须要采纳蓝绿公布上线新版本服务的形式,实现应用服务的安稳降级。 为什么要应用 CODING CD?传统的部署是批改 YAML 文件的镜像版本,而后通过命令行 kubectl apply 的形式更新应用服务的版本,这种公布形式过于依赖人工执行,对于 DevOps 团队来说是不可忍耐的。而通过 CODING CD 部署流程实现自动化流水线,流水线的所有阶段都能够供团队中的任何人查看、改良和验证,开发团队能够进步公布的速度和升高公布的危险和老本。 概述什么是 Nginx IngressNginx Ingress 是 Kubernetes Ingress 的一种实现,它通过 watch Kubernetes 集群的 Ingress 资源,将 Ingress 规定转换成 Nginx 的配置,而后让 Nginx 来进行 7 层的流量转发。 应用注解阐明咱们通过给 Ingress 资源指定 Nginx Ingress 所反对的一些 annotation 能够实现蓝绿公布,须要给服务创立两个 Ingress,一个失常的 Ingress(myapp-ingress),另一个是带 nginx.ingress.kubernetes.io/canary: "true" 这个固定的 annotation 的 Ingress,咱们权且称它为 Canary Ingress(myapp-blue-ingress),个别代表新版本的服务,联合另外针对流量切分策略的 annotation 一起配置即可实现多种场景的蓝绿公布,以下是对本次实际应用到的 annotation 的介绍: ...

April 1, 2021 · 4 min · jiezi

关于集群:通过AWS-EMR降低集群计算成本

本文首发于:行者AIAWS EMR是一个计算集群。能够通过ta创立自定义配置的虚拟机,并主动装置所需计算框架(Spark,Hadoop,Hive等),以便用来进行大数据计算。 1. 我的项目背景公司目前有一个我的项目,通过爬虫收集数据,离线计算失去用户画像,并将最终后果写入rds,通过api向外展现数据。 2. 架构演进2.1 技术栈计算框架 Spark调度框架 Airflow数据存储 Hadoop,Mysql数仓工具 Hive,Presto辅助工具 Zepplin脚本语言 Java,Scala,Python2.2 第一版环境 咱们在某云厂商开了6台虚构器(4核8G),spark on yarn模式运行,其中1台作为主节点,运行hadoop主节点和airflow调度程序,其余作为数据节点。 计算过程 通过Spark Streaming将数据落地到HadoopAirflow定时向主节点通过Spark-submit形式提交命令Spark计算后将最终后果写入Mysql平时开发人员能够在Zepplin进行查问成果 计算流程能够失常进行 思考 通过一段时间的察看剖析,咱们发现 大部分计算工作都能在较短时间内实现机器每天闲置工夫很长业务没有很高的实时性要求高配置虚构器老本很高论断 基于现状,咱们心愿能有个即开即用的零碎,就像电脑一样,要用就关上,用完就敞开。通过调研,最终抉择了AWS的EMR。 2.3 第二版环境 在将零碎迁徙到AWS EMR之后,在AWS上开了一台虚构器(1核2G)运行Airflow和Kinesis 这台虚构器须要始终运行,但Airflow自身不须要高配置 计算过程 通过Kinesis将数据落到S3Airflow定时发动工作 发动创立EMR申请可自定义机器配置,要装置的计算框架,也可笼罩框架配置。可通过Python脚本检测集群是否创立胜利 提交计算工作敞开集群成果 计算流程能够失常进行,但不须要长开机器了,只须要一台低配来触发定时工作即可 思考 通过一段时间的察看 EMR费用比起虚构器,的确便宜很多能够通过console台查看集群状态,管制集群开关不不便的中央,平时要查看Hadoop的数据,须要本人写脚本拉取,不能应用辅助工具了::: hljs-center Talk is cheap, show me the code::: 筹备工作 注册AWS账号,登录开明EMR,S3开明S3的目标是为了长久化数据,因为EMR集群自身不带额定硬盘,须要内部介质贮存 开明AWS内网可拜访的Mysql如果不必Hive,可跳过这一步,同理,须要内部介质贮存Hive的数据结构 筹备创立EMR集群的脚本这里有个坑,开始咱们应用的AWS SDK来做这件事,但无奈自定义计算框架配置(应该是BUG),最后咱们通过批改SDK源码解决了这个问题,但起初发现根本没用到SDK其余性能时,咱们将这部分代码提成了独自的文件,因为应用了Airflow进行调度,所以决定用了Python 编写Spark工作,打包上传至S3EMR LIB # coding: UTF-8import boto3, json, requests, requestsfrom datetime import datetimedef get_region(): # 这个地址不必改 r = requests.get("http://169.254.169.254/latest/dynamic/instance-identity/document") response_json = r.json() return response_json.get('region')def client(region_name): global emr emr = boto3.client('emr', region_name=region_name)# 创立EMRdef create_cluster(name): param = { # 批改须要的框架 "Applications":[{ "Name":"Hadoop" },{ "Name":"Hive" },{ "Name":"Spark" }], # 这里的名字会显示到控制台 "Name":name, "ServiceRole":"EMR_DefaultRole", "Tags":[], "ReleaseLabel":"emr-5.26.0", "Instances":{ "TerminationProtected":False, "EmrManagedMasterSecurityGroup":"sg-0085fba9c3a6818f5", "InstanceGroups":[{ "InstanceCount":1, "Name":"主实例组 - 1", "InstanceRole":"MASTER", "EbsConfiguration":{ "EbsBlockDeviceConfigs":[{ "VolumeSpecification":{ "SizeInGB":32, "VolumeType":"gp2" }, "VolumesPerInstance":1 }] }, # 批改须要的硬件配置 "InstanceType":"m4.large", "Market":"ON_DEMAND", "Configurations":[{ # 批改Hive的meta源 "Classification":"hive-site", "Properties":{ "javax.jdo.option.ConnectionURL":"jdbc:mysql://host:port/db?useUnicode=true&characterEncoding=UTF-8", "javax.jdo.option.ConnectionDriverName":"org.mariadb.jdbc.Driver", "javax.jdo.option.ConnectionUserName":"user", "javax.jdo.option.ConnectionPassword":"pwd" } },{ "Classification":"yarn-env", "Properties":{}, "Configurations":[{ "Classification":"export", "Properties":{ "AWS_REGION":"cn-northwest-1", "S3_ENDPOINT":"s3.cn-northwest-1.amazonaws.com.cn", "S3_USE_HTTPS":"0", "S3_VERIFY_SSL":"0" } }] }] },{ "InstanceRole":"CORE", "InstanceCount":1, "Name":"外围实例组 - 2", "Market":"ON_DEMAND", # 批改须要的硬件配置 "InstanceType":"r5d.2xlarge", "Configurations":[{ "Classification":"hive-site", "Properties":{ "javax.jdo.option.ConnectionURL":"jdbc:mysql://host:port/db?useUnicode=true&characterEncoding=UTF-8", "javax.jdo.option.ConnectionDriverName":"org.mariadb.jdbc.Driver", "javax.jdo.option.ConnectionUserName":"user", "javax.jdo.option.ConnectionPassword":"pwd" } },{ "Classification":"yarn-env", "Properties":{}, "Configurations":[{ "Classification":"export", "Properties":{ "AWS_REGION":"cn-northwest-1", "S3_ENDPOINT":"s3.cn-northwest-1.amazonaws.com.cn", "S3_USE_HTTPS":"0", "S3_VERIFY_SSL":"0" } }] }] },{ # 批改须要的工作节点数 "InstanceCount":4, "Name":"工作实例组 - 4", "InstanceRole":"TASK", "EbsConfiguration":{ "EbsBlockDeviceConfigs":[{ "VolumeSpecification":{ "SizeInGB":32, "VolumeType":"gp2" }, "VolumesPerInstance":4 }] }, # 批改须要的硬件配置 "InstanceType":"r5d.2xlarge", "Market":"ON_DEMAND", "Configurations":[{ "Classification":"hive-site", "Properties":{ "javax.jdo.option.ConnectionURL":"jdbc:mysql://host:port/db?useUnicode=true&characterEncoding=UTF-8", "javax.jdo.option.ConnectionDriverName":"org.mariadb.jdbc.Driver", "javax.jdo.option.ConnectionUserName":"user", "javax.jdo.option.ConnectionPassword":"pwd" } },{ "Classification":"yarn-env", "Properties":{}, "Configurations":[{ "Classification":"export", "Properties":{ "AWS_REGION":"cn-northwest-1", "S3_ENDPOINT":"s3.cn-northwest-1.amazonaws.com.cn", "S3_USE_HTTPS":"0", "S3_VERIFY_SSL":"0" } }] }] }], "KeepJobFlowAliveWhenNoSteps":True, "Ec2SubnetId":"subnet-027bff297ea95039b", "Ec2KeyName":"hifive.airflow", "EmrManagedSlaveSecurityGroup":"sg-05a0e076ee7babb9e" }, "JobFlowRole":"EMR_EC2_DefaultRole", "Steps":[{ "HadoopJarStep":{ "Args":["state-pusher-script"], "Jar":"command-runner.jar" }, "Name":"Setup Hadoop Debugging" }], "ScaleDownBehavior":"TERMINATE_AT_TASK_COMPLETION", "VisibleToAllUsers":True, "EbsRootVolumeSize":10, "LogUri":"s3n://aws-logs-550775287661-cn-northwest-1/elasticmapreduce/", "AutoScalingRole":"EMR_AutoScaling_DefaultRole" } cluster_response = emr.run_job_flow(**param) return cluster_response['JobFlowId']# 获取EMR拜访入口def get_cluster_dns(cluster_id): response = emr.describe_cluster(ClusterId=cluster_id) return response['Cluster']['MasterPublicDnsName']# 期待集群创立实现def wait_for_cluster_creation(cluster_id): emr.get_waiter('cluster_running').wait(ClusterId=cluster_id)# 敞开EMRdef terminate_cluster(cluster_id): emr.terminate_job_flows(JobFlowIds=[cluster_id])调用测试 ...

March 4, 2021 · 2 min · jiezi

关于集群:在-TKE-中使用-Velero-迁移复制集群资源

概述Velero(以前称为Heptio Ark)是一个开源工具,能够平安地备份和还原,执行劫难复原以及迁徙 Kubernetes 群集资源和长久卷,能够在 TKE 集群或自建 Kubernetes 集群中部署 Velero 用于: 备份集群并在失落的状况下进行还原。将集群资源迁徙到其余集群。将生产集群复制到开发和测试集群。更多对于 Velero 介绍,请参阅 Velero 官网,本文将介绍应用 Velero 实现 TKE 集群间的无缝迁徙复制集群资源的操作步骤。 迁徙原理在须要被迁徙的集群和指标集群上都装置 Velero 实例,并且两个集群的 Velero 实例指向雷同的腾讯云 COS 对象存储地位,应用 Velero 在须要被迁徙的集群执行备份操作生成备份数据存储到腾讯云 COS ,而后在指标集群上应用 Velero 执行数据的还原操作实现迁徙,迁徙原理如下: 前提条件已 注册腾讯云账户。已开明腾讯云 COS 服务。已有须要被迁徙的 TKE 集群(以下称作集群 A),已创立迁徙指标的 TKE 集群(以下称作集群 B),创立 TKE 集群请参阅 创立集群。集群 A 和 集群 B 都须要装置 Velero 实例(1.5版本以上),并且共用同一个腾讯云 COS 存储桶作为 Velero 后端存储,装置步骤请参阅 配置存储和装置 Velero 。注意事项从 1.5 版本开始,Velero 能够应用 Restic 备份所有pod卷,而不用独自正文每个 pod。默认状况下,此性能容许用户应用 restic 备份所有 pod 卷,但以下卷状况除外: ...

February 23, 2021 · 2 min · jiezi

关于集群:5步教你将MRS数据导入DWS

摘要:GaussDB(DWS)反对在雷同网络中,配置一个GaussDB(DWS)集群连贯到一个MRS集群,而后将数据从HDFS中的文件读取到GaussDB(DWS)。MapReduce服务(MapReduce Service,简称MRS)是一个基于开源Hadoop生态环境而运行的大数据集群,对外提供大容量数据的存储和剖析能力,可解决用户的数据存储和解决需要。用户能够将海量业务数据,存储在MRS的剖析集群,即应用Hive/Spark组件保留。Hive/Spark的数据文件则保留在HDFS中。GaussDB(DWS)反对在雷同网络中,配置一个GaussDB(DWS)集群连贯到一个MRS集群,而后将数据从HDFS中的文件读取到GaussDB(DWS)。从MRS导入数据到集群的流程,大抵能够分为5个步骤: 第一步: MRS集群上的数据筹备 第二步:手动创立内部服务器 第三步:创立表面 第四步:执行数据导入 第五步:革除资源 1 MRS集群上的数据筹备从MRS导入数据到GaussDB(DWS)集群之前,假如您曾经实现了以下筹备工作: (1)已创立MRS集群。 (2)在MRS集群上创立了Hive/Spark ORC表,且表数据曾经存储到该表对应的HDFS门路上。 如果您曾经实现上述筹备,则能够跳过本章节。 为不便起见,咱们将以在MRS集群上创立Hive ORC表作为示例,实现上述筹备工作。在MRS集群上创立Spark ORC表的大抵流程和SQL语法,同Hive相似,在本文中不再开展形容。 1.1 数据文件假如有数据文件product_info.txt,示例数据如下所示: 100,XHDK-A-1293-#fJ3,2017-09-01,A,2017 Autumn New Shirt Women,red,M,328,2017-09-04,715,good205,KDKE-B-9947-#kL5,2017-09-01,A,2017 Autumn New Knitwear Women,pink,L,584,2017-09-05,406,very good!300,JODL-X-1937-#pV7,2017-09-01,A,2017 autumn new T-shirt men,red,XL,1245,2017-09-03,502,Bad.310,QQPX-R-3956-#aD8,2017-09-02,B,2017 autumn new jacket women,red,L,411,2017-09-05,436,It's really super nice150,ABEF-C-1820-#mC6,2017-09-03,B,2017 Autumn New Jeans Women,blue,M,1223,2017-09-06,1200,The seller's packaging is exquisite200,BCQP-E-2365-#qE4,2017-09-04,B,2017 autumn new casual pants men,black,L,997,2017-09-10,301,The clothes are of good quality.250,EABE-D-1476-#oB1,2017-09-10,A,2017 autumn new dress women,black,S,841,2017-09-15,299,Follow the store for a long time.108,CDXK-F-1527-#pL2,2017-09-11,A,2017 autumn new dress women,red,M,85,2017-09-14,22,It's really amazing to buy450,MMCE-H-4728-#nP9,2017-09-11,A,2017 autumn new jacket women,white,M,114,2017-09-14,22,Open the package and the clothes have no odor260,OCDA-G-2817-#bD3,2017-09-12,B,2017 autumn new woolen coat women,red,L,2004,2017-09-15,826,Very favorite clothes980,ZKDS-J-5490-#cW4,2017-09-13,B,2017 Autumn New Women's Cotton Clothing,red,M,112,2017-09-16,219,The clothes are small98,FKQB-I-2564-#dA5,2017-09-15,B,2017 autumn new shoes men,green,M,4345,2017-09-18,5473,The clothes are thick and it's better this winter.150,DMQY-K-6579-#eS6,2017-09-21,A,2017 autumn new underwear men,yellow,37,2840,2017-09-25,5831,This price is very cost effective200,GKLW-l-2897-#wQ7,2017-09-22,A,2017 Autumn New Jeans Men,blue,39,5879,2017-09-25,7200,The clothes are very comfortable to wear300,HWEC-L-2531-#xP8,2017-09-23,A,2017 autumn new shoes women,brown,M,403,2017-09-26,607,good100,IQPD-M-3214-#yQ1,2017-09-24,B,2017 Autumn New Wide Leg Pants Women,black,M,3045,2017-09-27,5021,very good.350,LPEC-N-4572-#zX2,2017-09-25,B,2017 Autumn New Underwear Women,red,M,239,2017-09-28,407,The seller's service is very good110,NQAB-O-3768-#sM3,2017-09-26,B,2017 autumn new underwear women,red,S,6089,2017-09-29,7021,The color is very good 210,HWNB-P-7879-#tN4,2017-09-27,B,2017 autumn new underwear women,red,L,3201,2017-09-30,4059,I like it very much and the quality is good.230,JKHU-Q-8865-#uO5,2017-09-29,C,2017 Autumn New Clothes with Chiffon Shirt,black,M,2056,2017-10-02,3842,very good1.2 在MRS集群上创立Hive ORC表(1)创立了MRS集群。 ...

February 4, 2021 · 4 min · jiezi

关于集群:14天1000大集群滚动升级银行柜台尽然毫无感觉

摘要:中国工商银行联结华为实现了金融行业首家规模超千台的Hadoop集群大版本滚动降级,为期两周的降级过程冲破了传统的离线降级模式,真正实现了业务无感的平滑滚动降级。2020年8月27日,中国工商银行联结华为实现了金融行业首家规模超千台的Hadoop集群大版本滚动降级,为期两周的降级过程冲破了传统的离线降级模式,真正实现了业务无感的平滑滚动降级。全程集群作业无中断、性能无影响,为全行上百个利用、上千个场景、上万个作业保障了7*24小时不间断的数据服务。本次滚动降级对金融科技领域意义重大,中国工商银行为金融同业建立了大数据服务连续性上的建设标杆,响应了国家大数据和人工智能策略技术洼地的建设要求,为金融同业大数据平台的高可用建设提供了可参考的综合解决方案。 一、我的项目背景中国工商银行从2002年起继续优化数据架构,推动数据赋能业务,在实现数据大集中的同时,率先建设金融行业企业级数据仓库。以“凋谢、共享”为准则,工商银行于2016年启动大数据服务云体系的建设,实现了企业级全量数据集中和通用服务积淀,截至目前以牢靠、高效、易扩大的大数据和人工智能平台为根底,以数据中台为赋能外围,构建了集基础设施、大数据和人工智能技术、海量高时效全数据、规范智能共享服务、丰盛多样业务场景于一体的数据智能生态新模式(如图1),助力全行服务提质增效,向智能化、生态化时代的跃进。 图1 中国工商银行大数据服务云现有架构 工行大数据平台的Hadoop批量集群已超过一千个节点,日均解决作业数十万个,数据存储数十PB,赋能于180余总行利用和境内外41家分行及子公司,承载了全行重点批量作业,其中包含监管报送、反洗钱、反欺诈、损益剖析、减值测算等多个重要业务场景,服务连续性需要较高。为了在保障7*24小时不间断服务的前提下,维持技术引领,Hadoop集群应做到业务无感的平滑滚动降级,保障技术组件的先进性,升高技术危险,深入技术能力,助力新技术场景翻新和IT架构转型降级。 二、我的项目内容2.1 技术挑战工行本次滚动降级面向的Hadoop集群,部署了ZooKeeper、HDFS、YARN、MapReduce、Spark、Hive、HBase等各类组件,各组件的版本更新必然存在一些适用性、兼容性问题(组件版本变更如表1)。 表1. 组件版本变更表 此外,集群中每日上万作业的执行,也为无感知的滚动降级加大了难度。次要挑战有以下几点: 一是Hadoop 2.X到3.X的跨大版本升级中,社区仅提供了HDFS的滚动降级能力,YARN的社区原生指标版本因为与原版本协定不同,无奈反对滚动降级。 二是Hive 1.2到3.1的跨大版本升级中,因为元数据前后格局不兼容、API前后版本有变动、局部语法不兼容等问题,导致社区原生版本无奈反对滚动降级。 三是社区原生版本的HDFS在降级过程中,删除的文件并不会物理删除,而是挪动到trash目录,这一解决对大容量集群的滚动降级造成存储资源压力,妨碍了残余信息爱护。 四是降级前后因为版本变动,每日上万任务量,如何保障安稳运行,尤其是损益剖析、减值测算等外围场景。 五是上千台的物理节点的环境下,须要确保在降级过程中,疾速应答硬件(磁盘、内存等)故障,不影响降级。 六是降级过程较为简单,应答集群降级状态强化监控、告警等运维治理服务,增强关键技术、治理瓶颈的应急响应。 2.2 技术保障所谓滚动降级,就是借助于Hadoop外围组件的高可用机制,在不影响集群整体业务的状况下,一次降级/重启大量节点。循环滚动,直至集群所有节点降级到新版本。下图为已HDFS组件滚动降级示例: 为应答上述技术挑战我的项目组建了滚动降级小组,由社区PMC、社区Commiter、版本Developer形成,次要执行了以下技术保障: 一是依靠协定同步、元数据映射转换、API封装转换等形式,解决了社区协定不同、元数据格式不同、API变动等导致的兼容性问题,保障了滚动降级过程中低版本的组件客户端的失常应用,目前项目组已将发现的通用问题反馈开源社区。 二是针对HDFS社区新版本升级过程中的文件未删除问题,项目组额定实现了trash目录主动清理,将逻辑删除转换为物理删除,并增补了旧版本定期清理trash目录的工具。一方面确保了基础设施资源利用的有效性,升高存储老本;另一方面贯彻了国标、金标等保2.0中的残余信息爱护,确保要害信息存储空间的齐全开释。 三是具体评估了各组件降级过程及降级后版本的性能情况,实现了降级时长的预估,针对降级过程中和预先可能呈现的瓶颈点,做了相应架构调整及优化,助力实现滚动降级的全局可控、全程无感、全面无误。 为解决上千节点规模集群的调度性能,小组推出了自研Superior调度器,在旧版本的根底上深度优化了调度算法,将一维的调度转换为二维调度,实现调度速率晋升至每秒35万个Container。 为解决大规模存储的瓶颈问题,社区推出了联邦解决方案,但不同的命名空间的引入,导致下层业务在开发、数据管理、保护上复杂度晋升,为解决这一问题,社区又推出了Router Based Federation个性,但因为在NameNode之上加了一层Router进行交互,导致性能降落。小组提供了如下优化: l 通过在大集群生产环境中辨认要害瓶颈,咱们通过合并单次读写流程中的交互次数、应用改进的数据通信压缩算法等技术计划,将性能降落管制在4%以内。 l 为解决不同命名空间之间数据不平衡的问题,咱们利用DataMovementTool主动平衡不同命名空间之间的数据,大大降低了集群保护老本。 同时,小组发现Hive的元数据在面对海量表/分区的时候,也面临着十分大的瓶颈。尽管社区推出了Metastore Cache的解决方案,但仅实用于一个MetaStore的场景,多个MetaStore的缓存并不统一,导致此个性无奈在理论场景中应用。小组提出应用Redis作为代替计划,同时通过分布式锁、缓存黑白名单机制、缓存生命周期治理等技术手段加强了该个性的可用性。 为保障大规模集群在滚动降级期间的容错能力,小组提供了工作级“断点续传”能力,例如: Hive不中断业务能力:即当Hive beeline断连、Hive Server因故障重启、MapReduce JobHistory无响应等起因导致Hive工作失败时,工作可能持续重试运行,无需失败从头开始,大大降低了重试老本及工作时长。 AM的断点续传能力:尽管Yarn的Application Master故障后,可能立刻在其余节点上被拉起,但之前已执行的计算工作只能从头开始解决。小组提供了AM记录工作执行状态、辨别工作执行进度能力,待AM因故障被重启拉起后,能够装置之前的记录状态继续执行,晋升了执行效率。 四是运维治理方面,项目组针对性的研发了降级治理服务界面,能够端到端、分步骤地实现滚动降级,便于查看滚动降级状态,实现组件级管制。为了升高在降级过程中对要害工作服务连续性的影响,我的项目实现了按降级批次暂停的性能,有助于在要害作业或者作业顶峰时段,通过暂停降级进行危险躲避,确保业务无影响。此外,为疾速解决降级过程中可能呈现的硬件故障,降级治理服务提供了故障节点隔离能力,在故障产生时,能够跳过对应节点的降级动作,保障了故障解决和降级的同步进行。 2.3 组织保障本次降级确立了“危险可控、业务无感”的总体目标,因为指标集群规模大、波及利用广、相干部门多,除了上述技术保障伎俩,工行还采取了一系列伎俩,提供组织保障(见图2),具体形容如下: 图2 工行滚动降级我的项目组织保障 在项目管理方面,如何保障跨多部门高效协同地实现工作,是集群降级过程中一个微小的挑战。本次滚动降级我的项目,造成了大数据与人工智能实验室牵头、相干部门配合评审施行的组织模式。前者负责制订了整个我的项目具体计划和我的项目流程,通过外部多级评审机制,就总体方案与多部门疾速达成共识,同时依照不同的部门职责实现子任务分配,从而保障跨多部门的我的项目组织架构高效协同工作,安稳推动整体我的项目进度。 降级筹备方面,项目组一是实现了降级版本功能性、非功能性评估,重点验证了滚动降级的正确性、完整性、适用性;二是实现了对全行的利用场景的梳理,定制了分级验证机制,为每一个利用场景制订了相应适度的测试、验证计划,并实现了正式邮件的告知,用于百余利用的配合验证。对于分级验证机制中的数十个典型利用,通过行内“工作单”项目管理形式纳入了我的项目级配合流程,确保对降级过程进行重点验证。 灾备应急设计方面,工行制订了具体的保障计划,包含数据备份策略和回滚策略。对于备份策略,一是在降级之前全量备份集群元数据,排除因元数据失落而导致丢数的状况;二是对于重点批量数据采纳双园区备份,实现双加载以防止主集群降级中的故障危险影响业务。对于回滚策略,一是在技术维度保障了回滚原版本的可行性,保障业务的连续性,二是确立了“无奈疾速解决的生产故障”、“大规模批量作业中断”两项回滚断定条件。上述的“双加载”是重点业务双活运行计划的一部分,次要波及监管报送类损益剖析、减值测算等多个利用场景,该类作业在备集群同步运行,实现重点批量双园区双活,切实防止因单边园区故障影响业务连续性的状况呈现。 降级模仿方面,为了遵循危险可控、循序渐进的准则,工行先后进行了两套较小规模的集群滚动降级。一是2020年3月针对Hadoop批量备集群进行滚动降级,该集群负责同城双活运行的重要批量作业,经生产环境理论验证,降级过程中业务无感知,也未发现集群侧危险;二是2020年4月,工行搭建一套规模更大的Hadoop批量集群,一方面加强批量双活承载能力,另一方面再次验证了滚动降级。两次生产环境模拟之外,开发、测试环境共计10套不同的Hadoop集群陆续实现了滚动降级验证,实现了降级危险的演绎总结和研发订正,为最大规模的集群降级打下坚实基础。 三、总结与瞻望中国工商银行联结华为公司实现的本次金融业首家规模超千台的Hadoop集群大版本滚动降级,实现了客户无感知,切实保障了客户的外围利益,标记着工行向金融大数据蓝图迈出了重要的一步,借助于Hadoop外围组件的高可用机制,实现了端到端分步骤的滚动降级,实现了降级过程中的可视化管制和治理。 大数据的高速倒退带来的社会经济的“反动”,在广度、深度和速度上都将会是空前的,也将会远远超出工业社会的常识和认知,并且倒退所带来的的挑战和艰难也将是前所未有的。在此背景下,中国工商银行会持续建立健全企业级大数据平台,进一步晋升数据洞察能力和基于场景的数据挖掘能力,充沛开释大数据作为基础性策略资源的外围价值,为金融科技利用实际和大数据生态建设建设添砖加瓦。 本文分享自华为云社区《华为云FusionInsight MRS金融行业首个1000+大集群滚动降级胜利》,原文作者:Sailing27 。 点击关注,第一工夫理解华为云陈腐技术~

January 30, 2021 · 1 min · jiezi

关于集群:Rancher首席架构师解读Fleet它何以管理百万集群

作者简介Darren Shepherd,Rancher Labs联结创始人及首席架构师。在退出Rancher之前,Darren是Citrix的高级首席工程师,他在那里从事CloudStack、OpenStack、Docker的工作,并构建下一代基础设施编排技术。在退出Citrix之前,Darren曾在GoDaddy工作,他设计并领导一个团队施行私有和公有IaaS云。 本文转自Rancher Labs 2020年年初,Rancher开源了海量集群治理我的项目Fleet,为大量的Kubernetes集群提供集中的GitOps式治理。Fleet最重要的指标是可能治理100万个散布于不同地理位置的集群。当咱们设计Fleet架构时,咱们心愿应用规范的Kubernetes controller架构。这意味着咱们能够扩大Kubernetes的数量比之前要多很多。在本文中,我将介绍Fleet的架构、咱们用于测试扩大规模的办法和咱们的发现。 为什么是100万个集群?随着K3s用户量爆发式增长(目前Github Star曾经超过15,000),边缘Kubernetes也开始迅猛发展。一些企业曾经采纳了边缘部署模型,其中每个设施都是单节点集群。或者你可能会看到应用3个节点的集群来提供高可用性(HA)。关键点在于咱们须要解决的是大量小型集群,而不是一个有很多节点的大型集群。现如今,简直任何中央的工程师都在应用Linux,他们都心愿应用Kubernetes来管理工作负载。尽管大多数K3s的边缘部署少于10,000个节点,但达到100万个节点并非不可能。而Fleet将满足你的规模扩大要求。 Fleet架构Fleet架构的要害局部如下: Fleet应用两阶段pull办法Fleet是一组由规范K8S API交互驱动的K8S ControllerFleet agent不须要始终放弃连贯Fleet agent自身是另一组Kubernetes controller要从git中进行部署,Fleet Manager首先要复制并存储git中的内容,而后Fleet manager决定须要应用git中的内容更新哪个集群,并创立部署记录供agent读取。当agent能够读取时,agent将check in以读取部署集群,部署新的资源并报告状态。 扩大规模测试方法咱们应用两种办法来模仿100万个集群。首先,咱们部署了一组大型VM(m5ad.24xlarge - 384 GiB RAM)。每个VM应用k3d运行10个K3s集群。而后这10个集群每个都运行750个agent,每个agent都代表着一个上游的集群。总的来说,每个VM模仿7500个集群。均匀来看,部署一个VM、在Fleet注册所有集群并达到稳固状态大概须要破费40分钟。在两天的工夫里,咱们以这种形式启动虚拟机,直到达到10万个集群。在最后的10万个集群中,咱们发现了大部分的扩大问题。在解决了这些问题之后,扩大变得相当可预测。以这一速度,模仿剩下的90万个集群将会破费很长的工夫以及相当可观的资金。 而后,咱们采纳第二种办法:运行一个模拟器,它能够执行100万个集群会进行的所有API调用,而不须要上游的Kubernetes集群或部署Kubernetes资源。取而代之的是,模拟器进行API调用以注册新集群、发现新部署并报告它们的胜利状态。应用这种办法,咱们在一天内实现了从0到100万个模仿集群。 Fleet manager是一个运行在Kubernetes集群上的controller,运行在3个大型虚拟机(m5ad.24xlarge - 384 GiB RAM)和一个RDS(db.m5.24xlarge)实例上。实际上,咱们应用K3s来运行Fleet Manager集群。咱们这样做是因为Kine曾经在其中集成了。我将在前面解释什么是Kine以及为什么应用它。只管K3s针对的是小规模的集群,但它可能是最容易大规模运行的Kubernetes发行版,咱们应用它是因为其简略易用。值得注意的是,在EKS这样的托管提供商上,咱们无奈大规模运行Fleet,稍后我会解释这一点。 发现1:调整服务账户和费率限度咱们遇到的第一个问题齐全出其不意。当一个Fleet agent注册到Fleet Manager时,它会应用一个长期的集群注册令牌(token)。而后,该令牌被用来为该集群/agent创立新的身份和凭证。集群注册令牌和该agent的凭证都是服务账户。咱们注册集群的速度受到controller-manager为服务账户创立令牌的速度的限度。通过钻研,咱们发现咱们能够批改controller-manager的默认设置来进步咱们创立服务账户的速度(-concurrent-serviceaccount-token-syncs=100)和每秒API申请的总体数量(-kube-api-qps=10000)。 发现2:etcd不能在此规模下运行Fleet是作为Kubernetes Controller编写的。因而,将Fleet扩大到100万个集群意味着要在Kubernetes中治理数千万个对象。正如咱们所理解的,etcd并没有能力治理这么大的数据量。Etcd的次要空间有8GB的限度,默认设置为2GB。要害空间包含以后的值和它们之前尚未被垃圾收集的值。在Fleet中,一个简略的集群对象大概须要6KB。对于100万个集群,咱们至多须要6GB。然而一个集群个别蕴含10个左右的Kubernetes对象,加上每个部署一个对象。所以在实际操作中,咱们更有可能须要超过100万个集群10倍的内存空间。 为了绕过etcd的限度,咱们应用了Kine,这使得应用传统的RDBMS运行任何Kubernetes发行版成为可能。在这个规模测试中,咱们运行了RDS db.m5.24xlarge实例。咱们没有尝试对数据库进行适当的大小调整,而是从最大的m5实例开始。在测试完结时,咱们在Kine中领有大概2000万个对象。这意味着以这种规模运行Fleet不能在EKS这样的托管提供商上进行,因为它是基于etcd的,也不会为咱们的需要提供足够可扩大的数据存储。 这个测试仿佛并没有把数据库push得很厉害。诚然,咱们应用了一个十分大的数据库,但很显著咱们还有很多垂直扩大的空间。单条记录的插入和查找持续以可承受的速度进行。咱们留神到,随机列出大量对象(最多一万个)将会破费30秒到一分钟的工夫。但一般来说,这些查问会在不到1秒的工夫内实现,或者在十分粗犷的测试下5秒也能够实现。因为这些耗时很长的查问产生在缓存重载期间,所以对系统整体影响不大,咱们将在前面探讨。只管这些迟缓的查问并没有对Fleet造成显著的影响,但咱们还是须要进一步考察为什么会呈现这种状况。 发现3:减少监控缓存大小当controller加载缓存时,首先会列出所有对象,而后从列表的修订版开始监控。如果有十分高的变化率并且列出对象破费了很长的工夫,那么你很容易陷入这样的状况:你实现了列表但无奈启动监控,因为API Server的监控缓存中没有这个修订版,或者曾经在etcd中被压缩了。作为一个变通办法,咱们将监控缓存设置为一个十分高的值(–default-watch-cache-size=10000000)。实践上,咱们认为咱们会遇到Kine的压实问题(compact),但咱们没有,这须要进一步考察。一般来说,Kine在压实(compact)的频率上要低很多。但在这种状况下,咱们狐疑咱们增加记录的速度超过了Kine压实的速度。这并不蹩脚。咱们并不心愿保持要保持一致的变化率,这只是因为咱们正在疾速注册集群。 发现4:加载迟缓的缓存Kubernetes controller的规范实现是将你正在解决的所有对象缓存在内存中。对于Fleet,这意味着咱们须要加载数百万个对象来建设缓存。对象列表的默认分页大小为500。加载100万个对象须要2000个API申请。如果你假如咱们能够每秒钟进行一次列表调用、解决对象并开启下一页,这意味着加载缓存须要30分钟左右。可怜的是,如果这2000个API申请中的任何一个失败,这个过程就会从新开始。咱们尝试将页面大小减少到10,000个对象,但看到整体加载工夫并没有显著放慢。咱们开始一次列出1万个对象之后,咱们就遇到了一个问题,Kine会随机破费超过1分钟的工夫来返回所有对象。而后Kubernetes API Server会勾销申请,导致整个加载操作失败,不得不重新启动。咱们通过减少API申请超时(-request-timeout=30m)来解决这个问题,但这不是一个可承受的解决方案。放弃较小的页面大小能够确保申请的速度更快,但申请的数量减少了失败几率,并导致整个操作重启。 重启Fleet controller将须要破费45分钟的工夫。这一重启工夫同样实用于kube-apiserver和kube-controller-manager。这意味着你须要十分小心。这也是咱们发现运行K3s不如运行RKE等传统发行版的一点。K3s将api-server和controller-manager联合到同一个过程中,这使得重启api-server或controller-manager的速度比本来应有的速度慢,而且更容易出错。模仿一场灾难性的故障,须要齐全重启所有服务,包含Kubernetes,这所有花了几个小时才复原上线。 加载缓存所需的工夫和失败的几率是迄今为止咱们发现的扩大Fleet的最大问题。今后,这是咱们要解决的首要问题。 结 论通过测试,咱们证实了Fleet的架构能够扩大到100万个集群,更重要的是,Kubernetes能够作为一个平台来治理更多的数据。Fleet自身与容器没有任何间接的关系,能够看成只是一个简略的利用,在Kubernetes中治理数据。这些发现为咱们开启了一个可能性,即把Kubernetes更多的当作一个通用的编排平台来写代码。当思考到你能够很容易地将一套controller与K3s捆绑在一起,Kubernetes就变成了一个很好的自成一体的利用server。 在扩大规模方面,从新加载缓存所需的工夫令人担忧,但相对是可控的。咱们将持续在这方面进行改良,使运行100万个集群不仅是可行的,而且是简略的。因为在Rancher Labs,咱们喜爱简略。

January 14, 2021 · 1 min · jiezi

AI赋能DevOps数据驱动的全栈工程师实践

DevOps是什么? 对于传统的软件研发而言,开发,测试,运维,运营,有不同的岗位进行分工协作,以保证质量和专业度,同一件事情,依赖不同岗位的排期、沟通、协调,效率难免会有打折。而对于互联网业务来说,快速的迭代,对人力的需求非常强烈,不大可能有足够的人力支撑这么多岗位。同时跨部门的沟通,强烈影响了项目的进度,因此一些快速发展的团队,开始推行DevOps,自己做测试,保证代码质量,自己上线运维,监控告警。亚马逊很早就开始推行"you build it, you run it"的文化。由于自己对自己的做事情很清楚,因此效率也会很高。这就是DevOps。 DevOps的挑战 DevOps责任多,事情多且杂。一天的时间怎么分配?我作为研发,肯定是希望一天90%能够专心的写代码。但实际上只有20%的时间来写代码,其他的时间做什么?帮用户调查问题,处理工单。做线上的运维等等。用户提了一个工单,你要立马放下手中的工作去帮用户调查问题。结果就发现时间被碎片化了,一天中很难有大块的时间去专门做研发。 通过数据驱动和智能自动化应对DevOps的挑战 怎么解决研发过程中时间碎片化的问题?我们原来做了很多重复性的工作,这些工作可以总结和沉淀下来,通过工具帮我们去沉淀。我们原来需要调查问题的时候,才登录集群要抓日志;现在做一个采集日志的工具,把所有日志的实时采集到云端,当需要看日志的时候,我立马就可以在服务端看到所有的日志信息。原来需要到机器上搜索日志,现在在云端做倒排索引,直接就可以搜索到整个集群的日志。原来我可能要用excel做一些数据分析的工作,去分析我的运营效果怎么样。现在在服务端实现一套实时分析的计算引擎,再加上可视化功能,帮助做各种各样的报表。原来调查问题的时候要登录集群上,用vim打开集群上的日志,看文件上下文是什么样子的。现在在云端做一个上下文关联的功能,直接在云端就可以看到所有集群上的日志和上下文信息。原来调查问题可能依赖于人的经验。现在通过AI帮我们做自动化的事情。 所以总结下来我们希望通过数据中台帮我们实现数据驱动的运维,来代替原来的人工驱动。借助于AI帮我们实现自动化、智能化。通过这种数据驱动加上智能自动化的运维帮我们节省被碎片化的时间。 数据中台的挑战 如果我们要做这样一个数据中台会面临哪些挑战呢?首先就是数据太少,如果我们抓取的数据太少的话,那么我们的信息量就会太少,在分钟级别的监控里面可能很多信息就被平均掉了,我们只有抓秒级监控才可以看到我们所关心的数据。第二个是实时性的挑战,我们做线上故障恢复的时候,都希望是说可以尽快定位问题的答案,尽快去恢复,这就是一个实时性的需求。如果我们找到答案太慢,可能已经错过了一个最佳的自救的时间。第三,系统越来越复杂,我们的需求是越来越多的,我们每加一个需求要加一个模块,那么维护整个一套系统其实是一个非常大的挑战。最后是数据太多的问题,数据太少是问题,太多也是问题。太少的话信息量不足,太多的话很多重要的信息被淹没。关于数据规模的问题和数据速度的问题可以通过数据中台来解决,数据中台帮我们通过算力来换取一个数据的速度和规模;而数据太多信息爆炸的问题,我们用AI算法来换取对数据深入的洞察力。 数据中台的基础能力 数据中台具备的能力,第一个就是数据采集,数据采集帮我们从各个数据孤岛中,从各种环境中,把各种各样的格式的日志统一采集,然后以统一的格式被存储起来。原来数据可能在手机上,可能在网页上等等各种各样的环境,格式也不一样。统一采集之后, 我们就有统一的格式,以后分析就非常方便了。数据采集帮我们做的脏活累活,其实是帮我们节省了很多的时间。数据采集之后,中台要有二次加工的能力。为什么要二次加工?因为我们采集过来的数据可能包含着脏数据,垃圾数据,我们要过滤掉,做一些转换和富华。增强数据质量,数据质量增强以后,分析的时候才可以得心应手。接下来就是一个查询分析的能力,中台提供的进行交互式的查询分析,可以在秒级别分析上亿日志。通过这种查询分析能力你可以尽情的探索你数据里面包含了什么价值。查询分析依赖于人的经验探索数据,那么我们还可以借助AI自动探索数据,这就是AI的预测能力和异常检测能力以及根因分析的能力。通过数据中台将AI,帮助我们去获取对数据源的可观察性,进而通过数据可观察性,实现对运维系统的可观察性。 基于数据中台的问题调查路径 我们前面介绍了数据中台的,接下来我会以一系列的实践去分享我们怎么样利用这样一个数据中台帮我们解决我们DevOps所遇到的各种各样的问题。 我们说到数据驱动的运维,首先我们会面临大规模的数据,如何去找有效的信息,这就是一个发现的过程。原来我们通过grep搜索的关键字,通过awk做一些简单的计算;借助中台,我们可以通过交互式查询去不停探索答案,也可以通过异常检测帮助我们智能的检测数据里面到底有什么异常的信息。当我们发现一些有效信息以后,接下来怎么办?我们要从这些线索出发,然后去找更多的线索,去找关联关系,去找因果关系,这个就是上下文钻取,以及聚类。那么通过这种钻取我们可以找到一系列的更加关联的信息,我们最终找到了信息足够多之后,我们要确定最终的一个答案,这个就是根因分析,帮我们确定故障的根本原因是什么。 数据驱动和AI驱动的DevOps实践1:搜索和上下文 我们做数据分析最简单的形式是什么?我们上网的时候,用的最多的工具是什么?是搜索引擎,搜索可以帮我们尽情探索数据中的价值。原来我们到机器上搜索日志,数据在文件中是是有序的存储的。而在采集的过程中,为了性能的考虑,会以乱序的形式存储下来,当然我们搜索完之后,可能我们看到的是乱序的日志。如何从这些乱序的日志中找它的上下文信息呢?我们为每一条日志指定一个编码。当我们搜索到一条日志之后,去看它的编码值,再去计算它的下一条编码是什么,根据编号搜索下一条日志。通过这种方式去找,搜索,去定位下上文 我们看一个搜索和上下文的样例。我们把所有集群的日志都被统一的采集到一起,然后去搜索整个集群日志,这个时候如果我们对某一台机器感兴趣的话,我们可以把机器的hostname加入到搜索条件里面去。这个时候如果我们对某一些关键字不感兴趣的话,我们可以过滤掉。这个时候我们定位到9条日志,我们对这9条日志感兴趣。我们可以去看上下文的信息。在上下文里面,可以以上下文严格有序的一种形式去看这条日志前后发生的一些事情,通过这种方式找它的一个因果关系。 2:全局视野和局部视野 搜索针对的对象是什么?是日志;日志是什么?是一种事件类型的数据,里面包含的信息有事件的发生的时间、对象、操作,还有各种属性,关于事件的描述是非常详细的。除了这种事件日志,还有一种指标日志。指标日志有时间,有一个汇总的数值,例如用一个数值表示这一分钟有多少个浏览量。这两种数据有什么区别?事件日志描述的是一个非常详细的信息,所以它的体量和规模是非常大的。它代表的是我们从局部去观察问题的一种视角。而指标数据是一种汇总的信息,所有它的体量非常小。但是它代表的是一种全局视角,概括整个事件的信息。例如,我们一分钟有1万次的访问,我们用这种事件日志来表示可能就真的是1万条数据。用这种指标日志可能就是1万这一个数字,这就是两者之间的差别。这两种日志之中是不是割裂的?不是,我们可以通过计算把事件日志转化为指标日志,一个是代表大视野,一个代表小视野。我们可以充分利用计算在这两种视野之间切换去调查问题。 举个例子,我们面对一个事件日志,可能对某一些维度感兴趣,比方说时间维度,那么在时间维度中统计趋势指标;或者对IP维度感兴趣,可以统计出IP分布,他们这个时候我们就把一个事件日志转化成了指标日志,从局部视野跳到全部视野看待问题。当我们看到某一个数值比较特殊,我们对它进行下钻,增加维度,进行更多的统计。比方说我们按照不同的IP统计出它的趋势。假如统计出来的各个维度之间,我们对某一些维度感兴趣的话,我们把它单独拎出来,跳回我们原来的事件日志当中,帮我们搜索对应的事件。这样的话我们就形成了一个调查问题的闭环,我们从事件日志出发去统计它全局的信息,再回到原来的事件,这是一个闭环。 3:聚类解决数据爆炸 事件日志的体量是非常大的,现在对于我们的业务来说,每天的数据量都在上涨,每分钟能达到上亿条的日志,日志这么多,重要的信息被淹没了怎么办?即使我们只关心错误的日志,但是错误的信息可能都有上千条,什么时候看完?我们通常对于这很多大量日志的这种场景,首先想的是排除法,比方说我们先把一些不关心的日志排除掉,逐步排除掉一些关键字,逐步的缩小数据的体量,慢慢靠近我们关心的信息。对于数值类来说,我们怎么样排除?我们可能统计数值的百分位,去统计它的25分位在哪里,75分位在哪里?99分位在哪里?假如说说我们对99分位感兴趣,只需要过滤出来99分位以上的数据,通过这种方式减少数值类型数据的体量。 但是这种排除法不一定可以帮助我们找到所有我们所关心的问题,因为我们现在的业务实在是太复杂了,维度太多了。有一个真实的案例,就是有一次我们一个新版本发布,有一个边界的条件没有测试到,上线之后也没发现,直到用户跑过来问,为什么我之前可以用,现在不能用?现在开始报错了?我到这个时候才发现发现,真的是从升级那一刻开始出现一种新类型的日志,原来都没有这种日志。显然用排除法是没有办法帮我解决升级后的这种异常检测,怎么办呢?那我们引入了智能聚类。即使每分钟产生上亿条日志,可能里面不到100种类新的事件,只是说每一种类新的事件重复发生了很多次,所以造成整体数据的膨胀。 通过这种分析数据之间的关联性,把数据里面的干扰信息过滤掉,提取出里面一些公共的特征,这个就是聚类。在这个例子中我们有1300万条数据,人眼去看这1300万条可能一天一夜也看不到。但是我们可以通过聚类,最后只有35条聚类的结果,这个时候我们去看35种类型的事件,其实一眼就可以看到,那么在机器上到底发生了什么事情。比如说,我可以一眼看到这是有这样一个timeout关键字,是不是要特殊的关注它? 我们怎么样利用智能聚会帮助我们解决升级后故障发现的问题。我们可以通过对比升级后你的聚类结果和升级前了聚类结果,查看有没有什么差别,如果一个新的事件在升级之后出现了,而之前是没有的,这是特殊关注的。通过这种方式我们去做告警,及时发现问题,及时的处理,避免影响到用户。4:Metric数据异常检测 通过智能聚类实现对文本类的数据异常类检测。那么对于我们刚才说的Metric指标数据,怎么样寻求异常检测?最简单的指标什么?是一条平稳的直线,围绕这样一条直线,可能有一个很轻微的在正常范围之内的波动,对于这种数值我们设一个固定的阈值,可以很好的把一些大的抖动捕获出来。但是这是一种非常简单的场景,在现实的业务中其实没有这么简单的,现实的数据一定是有各种各样的波动。最常见波动是什么?是周期性。一般我们工作日它的流量比较高,到了周末流量又跌下去了,那就是一个周期新的波动,所以对于波动性的信息我们怎么样做异常的检测?我可以通过同比、环比,拿当前时间点的数据和上一个周期同一个时间点的数据进行对比,看看有没有发生比较大的偏差,这就是同环比算法。 还有一种情况就是趋势性,对于互联网业务来说,增长是一种常态,没有增长的业务是没有前途的。在增长的趋势中,可能还有周期性的波动,以及扰动。我们所关心的那种异常的点可能被掩藏在这样一个增长的趋势中,对于人眼来说,其实一眼就可以看出来哪一个点是异常点。但是对于算法来说检测出来这样一个异常点是一个很大的挑战。我们的解决方案是通过机器学习,通过学习历史上的数据它的一个趋势性信息,周期性信息,然后去预测未来的点是什么样子的。那么把预测的点和真实出现的这个数据进行一个对比,那么当这样一个差值发生比较大的偏差的时候,就认为这是一个异常的点。通过这种方式去检测趋势性数据里面的一个异常点。 不管是周期性信息还是趋势性的信息,它其实都是一种很规律的一种波动。那么还有一种数据波动称为断层。比方说原来我们一个机器,它的CPU很低。突然有一天你把流量切到机器上,它的CPU立马暴涨到另外一个水平,但是它的波动又没有什么变化,这就是断层。对于断层的数据,其实统计的时候是非常难的,因为在这样一个点里面它的导数是没有的。那么我们可以用专门的断层检测算法去检测出来。最后一个就是变点,变点是什么?就是在某一个点,它的波动形态、统计特征发生了变化。原来可能是一条平稳的直线,但是在某一个时间点假如说发生了异常,你的流量抖动开始发生了非常大的一个抖动,这就是一个变点。通过变点算法,统计所有数据里面的波动信息,然后对比不同点上的波动信息进行检测这种变点。这就是我们针对Metric指标数据,利用机器学习、统计算法进行异常检测的方法。 5:异常根因分析 当我们检测到异常之后,下一步要做什么事情?要找这个异常它发生的原因是什么?并且及时的去修复它。假如我们网站流量下跌了7%,下跌是什么原因引起的?通常人工是怎么检测这个问题的?我们可能按照我们的经验逐步去排查,比方说我们先到服务端看一下,有没有错过日志;服务端没有,再看网络上有没有抖动。OK,那网络端没有抖动,接下来怎么办,再去看用户的统计上有没有异常的一些抖动,结果发现,用户的统计上有抖动的话怎么办?我们再去下钻,去看什么类型的用户发生了抖动。比方说不同的城市有没有抖动,不同的接入点有没有抖动?不同的客户端有没有抖动?结果发现在客户端这样一个维度,有数据是抖动的。那么我们再深入的下钻去找哪一种类型的客户端发生了问题。通过这种逐层的下钻,逐层去找,最终定位到版本因素造成了流量下跌。 这是我们人工调查问题的一个方法,这一套流程走下来其实是非常耗费时间的。我们怎么样借助算法帮助我们做这种异常检测呢?这就是关联规则算法,大家都听说过啤酒和尿布这个故事:在一大堆物品当中,啤酒和尿布同时出现的频率非常高,所以我们认为它两个之间是有关联关系的,然后进行关联推荐。我们可以把这种关联推荐给映射到根因分析算法。比方说我拿了一个访问日志,访问日志里面有很多的错误信息,然后我们再把网络日志拿过来。结果发现在网络日志里面某个交换机经常会和这个错误日志同时出现,是不是可以认为这个交换机上出现了错误? 如何找两个关联的项目,就是我们通过频繁集算法。我们把一份错误的日志拿出来,找这个日志里面它高频出现的一些数据集合。比方说我们在这样一个错误日志里面定位到IP等于1002这样一个用户,他出现的频率是68%,那么是不是认为这样一个用户他就是造成我们错误的一个原因?不一定。为什么?因为这个用户可能在错误的日志中出现的频率比较高,但是在正确的日志中出现的频率也是非常高的,所以你不能简单认为他就是一个错误的原因。那怎么办呢?要通过差异集合算法进行统计,我们把一份完整的数据,按照是否有错误,分成正负两份样本,然后比较两个样本里面的频繁集有什么差别,如果某一个集合它在一个错误的集合中出现的频率比较高,而在正确的集合里面出现的频率比较低,就可以认为这个集合是造成错误的根本原因。 如果我们再引入到时序维度,针对我们刚才说的网站浏览量下跌的问题,我们怎么样做这种根因分析呢?我们首先面对一个汇总的流量下跌的曲线,然后可以把我们所关心的维度都引入进来,例如地区维度,运营商维度,客户端维度全部引入进来,把各种维度自由组合各种各样的集合,那么我们算出来每一个集合它的一个流量曲线,计算算每一个集合它下跌的一个趋势,和整体流量下跌趋势之间的关联度,并且打分,按照分数的高低寻找根因集合。通过这种打分找出来一个集合,它对整个流量下跌的贡献是最大的。比方说我们最终统计出来上海这个地区所有的运营商流量下跌都非常的严重,打分非常高,那我们认为上海这个集合就是根因。 6:DevOps成本控制 对于我们DevOps而言,我们不仅要关心我们所做的成果,还要关心我们的成本,因为拿堆资源做出来的成果不代表一个人的能力,用最少的资源做最大的事情才可以代表一个人的能力。我们通常做采购机器,然后等待机器到货、上架,最终部署这个软件,交付。这是一个原来传统的上线机器的流程。这个流程是很长的,一般过几个月才能拿到机器。现在有云服务,一键可以创建机器,当你需要的时候可以立马拿到资源,这样一个流程实在太方便了。但是就是方便背后其实也有一些其他的困扰。比方说我一次测试的时候买了一台机器,用完之后忘了释放,结果这机器在那里跑着一直产生费用,或者我在储存里面放了一大堆的数据,测试完全之后忘记了删除,过了很久,谁都不知道这个数据是干嘛的,谁也不敢删,谁都不知道这个数据删掉以后会不会影响其他的业务。但是这些资源一直产生的费用。直到财务人员发现你的消费比较高的时候,一般都会来踢你的屁股,说你部门成本怎么这么高?你要优化一下了。这个时候其实就已经是很被动了,为什么?因为这个时候我们去统计所有的资源,统计谁在用这些资源,这个流程是非常长的。我们可以通过主动的成本控制,去统计我们的资源使用量,实时去统计资源使用量,实时去优化。 我们看一个成本控制的样例。我们把实时的把账单数据导入数据中台,然后可以统计出来,我这个月到底花费了多少钱,预测这个月大概花多少钱,以及每一个云产品花钱的数量。还可以去看,过去三个月的趋势是怎么样的,以及每一个产品的趋势。或者根据我们过去的趋势信息预测我未来三个月大概要花多少钱,利用这个数字及时的去申请预算。 同时我们还可以在我们账单数据里面,根据统计信息看一下有没有一些异常的账单。比方说我在近三个月的消费曲线中,发现10月1号这一天账单发生了暴涨。我要抓出来到底是哪一个云产品产生了这么多消费?于是深入下钻到日志里面去分析,用刚才提到的根因分析的算法去找哪一个产品对一个消费的上涨贡献归最大,所以我们发现SLS这样一个产品,它的异常打分是最高的。那么我们就认为,这个产品出现的消费异常,及时的发出告警即可。 Summary 我们做一个总结,我们介绍了调查问题的一系列案例,通过这些样例展示我们如何借助于数据中台,帮助我们做数据驱动,以及借助AI做一些智能化、自动化的运维。通过这种数据驱动和智能、自动化的运维,整体提升我们的效率,减少我们被碎片化的时间。 阿里云双11领亿元补贴,拼手气抽iPhone 11 Pro、卫衣等好礼,点此参与:http://t.cn/Ai1hLLJT 本文作者:云雷 阅读原文 本文为云栖社区原创内容,未经允许不得转载。

November 5, 2019 · 1 min · jiezi

阿里巴巴-Kubernetes-应用管理实践中的经验与教训

导读:云原生时代,Kubernetes 的重要性日益凸显。然而,大多数互联网公司在 Kubernetes 上的探索并非想象中顺利,Kubernetes 自带的复杂性足以让一批开发者望而却步。本文中,阿里巴巴技术专家孙健波在接受采访时基于阿里巴巴 Kubernetes 应用管理实践过程提供了一些经验与建议,以期对开发者有所帮助。在互联网时代,开发者更多是通过顶层架构设计,比如多集群部署和分布式架构的方式来实现出现资源相关问题时的快速切换,做了很多事情来让弹性变得更加简单,并通过混部计算任务来提高资源利用率,云计算的出现则解决了从 CAPEX 到 OPEX 的转变问题。 云计算时代让开发可以聚焦在应用价值本身,相较于以前开发者除了业务模块还要投入大量精力在存储、网络等基础设施,如今这些基础设施都已经像水电煤一样便捷易用。云计算的基础设施具有稳定、高可用、弹性伸缩等一系列能力,除此之外还配套解决了一系列应用开发“最佳实践”的问题,比如监控、审计、日志分析、灰度发布等。原来,一个工程师需要非常全面才能做好一个高可靠的应用,现在只要了解足够多的基础设施产品,这些最佳实践就可以信手拈来了。但是,在面对天然复杂的 Kubernetes 时,很多开发者都无能为力。 作为 Jira 和代码库 Bitbucket 背后的公司,Atlassian 的 Kubernetes 团队首席工程师 Nick Young 在采访中表示: 虽然当初选择 Kubernetes 的战略是正确的(至少到现在也没有发现其他可能的选择),解决了现阶段遇到的许多问题,但部署过程异常艰辛。那么,有好的解决办法吗? 太过复杂的 Kubernetes“如果让我说 Kubernetes 存在的问题,当然是‘太复杂了’”,孙健波在采访中说道,“不过,这其实是由于 Kubernetes 本身的定位导致的。” 孙健波补充道,Kubernetes 的定位是“platform for platform”。它的直接用户,既不是应用开发者,也不是应用运维,而是“platform builder”,也就是基础设施或者平台级工程师。但是,长期以来,我们对 Kubernetes 项目很多时候都在错位使用,大量的应用运维人员、甚至应用研发都在直接围绕 Kubernetes 很底层的 API 进行协作,这是导致很多人抱怨 “Kubernetes 实在是太复杂了”的根本原因之一。 这就好比一名 Java Web 工程师必须直接使用 Linux Kernel 系统调用来部署和管理业务代码,自然会觉得 Linux “太反人类了”。所以,目前 Kubernetes 项目实际上欠缺一层更高层次的封装,来使得这个项目能够对上层的软件研发和运维人员更加友好。 如果可以理解上述的定位,那么 Kubernetes 将 API 对象设计成 all-in-one 是合理的,这就好比 Linux Kernel 的 API,也不需要区分使用者是谁。但是,当开发者真正要基于 K8s 管理应用、并对接研发、运维工程师时,就必然要考虑这个问题,也必然要考虑如何做到像另一层 Linux Kernel API 那样以标准、统一的方式解决这个问题,这也是阿里云和微软联合开放云原生应用模型 Open Application Model (OAM)的原因。 ...

November 5, 2019 · 2 min · jiezi

今日头条在消息服务平台和容灾体系建设方面的实践与思考

本篇文章整理自今日头条的沈辉在 RocketMQ 开发者沙龙中的演讲,主要和大家分享一下,RocketMQ 在微服务架构下的实践和容灾体系建设。沈辉是今日头条的架构师,主要负责 RocketMQ 在头条的落地以及架构设计,参与消息系统的时间大概一年左右。 以下是本次分享的议题: 头条的业务背景为什么选择 RocketMQRocketMQ 在头条的落地实践头条的容灾系统建设业务背景今日头条的服务大量使用微服务,容器数目巨大,业务线繁多, Topic 的数量也非常多。另外,使用的语言比较繁杂,包括 Python,Go, C++, Java, JS 等,对于基础组件的接入,维护 SDK 的成本很高。 引入 RocketMQ 之前采用的消息队列是 NSQ 和 kafka , NSQ 是纯内存的消息队列,缺少消息的持久性,不落盘直接写到 Golang 的 channel 里,在并发量高的时候 CPU 利用率非常高,其优点是可以无限水平扩展,另外,由于不需要保证消息的有序性,集群单点故障对可用性基本没有影响,所以具有非常高的可用性。我们也用到了 Kafka ,它的主要问题是在业务线和 Topic 繁多,其写入性能会出现明显的下降,拆分集群又会增加额外的运维负担。并且在高负载下,其故障恢复时间比较长。所以,针对当时的状况和业务场景的需求,我们进行了一些调研,期望选择一款新的 MQ 来比较好的解决目前的困境,最终选择了 RocketMQ 。 为什么选择 RocketMQ这是一个经过阿里巴巴多年双11验证过的、可以支持亿级并发的开源消息队列,是值得信任的。其次关注一下他的特性。 RocketMQ 具有高可靠性、数据持久性,和 Kafka 一样是先写 PageCache ,再落盘,并且数据有多副本;并且它的存储模型是所有的 Topic 都写到同一个 Commitlog 里,是一个append only 操作,在海量 Topic 下也能将磁盘的性能发挥到极致,并且保持稳定的写入时延。然后就是他的性能,经过我们的 benchmark ,采用一主两从的结构,单机 qps 可以达到 14w , latency 保持在 2ms 以内。对比之前的 NSQ 和 Kafka , Kafka 的吞吐非常高,但是在多 Topic 下, Kafka 的 PCT99 毛刺会非常多,而且平均值非常长,不适合在线业务场景。另外 NSQ 的消息首先经过 Golang 的 channel ,这是非常消耗 CPU 的,在单机 5~6w 的时候 CPU 利用率达到 50~60% ,高负载下的写延迟不稳定。另外 RocketMQ 对在线业务特性支持是非常丰富的,支持 retry , 支持并发消费,死信队列,延时消息,基于时间戳的消息回溯,另外消息体支持消息头,这个是非常有用的,可以直接支持实现消息链路追踪,不然就需要把追踪信息写到 message 的 body 里;还支持事务的消息。综合以上特性最终选择了 RocketMQ 。 ...

November 5, 2019 · 3 min · jiezi

阿里巴巴开源-Dragonwell-JDK-最新版本-811GA-发布

导读:新版本主要有三大变化:同步了 OpenJDK 上游社区 jdk8u222-ga 的最新更新;带来了正式的 feature:G1ElasticHeap;发布了用户期待的 Windows 实验版本 Experimental Windows version。距离 Dragonwell JDK 第一个正式版本 8.0.0-GA 发布已经过去 3 个月了,项目在 Github 上的 stars 继续攀升达到了 1900。今天我们带来了最新版本 8.1.1-GA 的发布,包含了全新的特性和更新。详情见下文。 龙井 8.1.1-GA 的新变化新版本里我们同步了 OpenJDK 上游社区 jdk8u222-ga 的最新更新,带来了上游稳定版本的最新安全更新和补丁。 在 8.0.0-GA 发布的时候,我们介绍了 Dragonwell 第三个新特性 ElasticHeap 的一些情况,很多用户已经跃跃欲试了,这次发布我们带来了正式的 feature:G1ElasticHeap。能够在不影响 Java 业务运行的前提下,动态节约 Java 进程物理内存。 另外,我们还发布了用户期待的 Windows 实验版本 Experimental Windows version,使用 Windows 开发的小伙伴们可以更加方便的使用 Dragonwell JDK 进行相应的开发工作。 G1ElasticHeap从 feature 的名字上我们可以看到 ElasticHeap 是基于 G1 GC 开发的,所以想要使用这个功能的小伙伴,需要开启 G1 GC(-XX:+UseG1GC)。在 8.0.0-GA 正式版介绍时,我们介绍了部分技术背景,由于 Java 自动管理内存的特性,整个 Java Heap 的地址空间和物理内存将被 Java 进程占用,即使使用率不高,回收后也并不会归还给操作系统,导致 Java 进程会有较高的常驻内存。 ...

October 17, 2019 · 2 min · jiezi

为什么-K8s-集群达万级规模阿里购物体验还能如丝顺滑

阿里妹导读:本文主要介绍阿里巴巴和蚂蚁金服在大规模生产环境中落地 Kubernetes 的过程中,在集群规模上遇到的典型问题以及对应的解决方案,内容包含对 etcd、kube-apiserver、kube-controller 的若干性能及稳定性增强,这些关键的增强是阿里巴巴和蚂蚁金服内部上万节点的 Kubernetes 集群能够平稳支撑 2019 年天猫 618 大促的关键所在。文内藏福利,向下滑滑滑,免费课程立刻领取~背景从阿里巴巴最早期的 AI 系统(2013)开始,集群管理系统经历了多轮的架构演进,到 2018 年全面的应用 Kubernetes ,这期间的故事是非常精彩的。这里忽略系统演进的过程,不去讨论为什么 Kubernetes 能够在社区和公司内部全面的胜出,而是将焦点关注到应用 Kubernetes 中会遇到什么样的问题,以及我们做了哪些关键的优化。 在阿里巴巴和蚂蚁金服的生产环境中,容器化的应用超过了 10k 个,全网的容器在百万的级别,运行在十几万台宿主机上。支撑阿里巴巴核心电商业务的集群有十几个,最大的集群有几万的节点。在落地 Kubernetes 的过程中,在规模上面临了很大的挑战,比如如何将 Kubernetes 应用到超大规模的生产级别。 罗马不是一天就建成的,为了了解 Kubernetes 的性能瓶颈,我们结合阿里和蚂蚁的生产集群现状,估算了在 10k 个节点的集群中,预计会达到的规模: 20w pods100w objects 我们基于 Kubemark 搭建了大规模集群模拟的平台,通过一个容器启动多个(50个)Kubemark 进程的方式,使用了 200 个 4c 的容器模拟了 10k 节点的 kubelet。在模拟集群中运行常见的负载时,我们发现一些基本的操作比如 Pod 调度延迟非常高,达到了惊人的 10s 这一级别,并且集群处在非常不稳定的状态。 当 Kubernetes 集群规模达到 10k 节点时,系统的各个组件均出现相应的性能问题,比如: etcd 中出现了大量的读写延迟,并且产生了拒绝服务的情形,同时因其空间的限制也无法承载 Kubernetes 存储大量的对象;API Server 查询 pods/nodes 延迟非常的高,并发查询请求可能地址后端 etcd oom;Controller 不能及时从 API Server 感知到在最新的变化,处理的延时较高;当发生异常重启时,服务的恢复时间需要几分钟;Scheduler 延迟高、吞吐低,无法适应阿里业务日常运维的需求,更无法支持大促态的极端场景。etcd improvements为了解决这些问题,阿里云容器平台在各方面都做了很大的努力,改进 Kubernetes 在大规模场景下的性能。 ...

October 17, 2019 · 5 min · jiezi

使用datax迁移cassandra数据

DataX 是阿里巴巴集团内被广泛使用的离线数据同步工具/平台,实现各种异构数据源之间高效的数据同步功能。最近,阿里云cassandra团队为datax提供了cassandra读写插件,进一步丰富了datax支持的数据源,可以很方便实现cassandra之间以及cassandra与其他数据源之间的数据同步。本文简单介绍如何使用datax同步cassandra的数据,针对几种常见的场景给出配置文件示例,还提供了提升同步性能的建议和实测的性能数据。 datax快速入门使用datax同步数据的方法很简单,一共只需要三步: 部署datax。编写同步作业配置文件。运行datax,等待同步作业完成。datax的部署和运行都很简单,可以通过datax官方提供的下载地址下载DataX工具包,下载后解压至本地某个目录,进入bin目录,即可运行同步作业: $ cd {YOUR_DATAX_HOME}/bin$ python datax.py {YOUR_JOB.json}同步作业的配置格式可以参考datax文档。 一个典型的配置文件如下: { "job": { "content": [ { "reader": { "name": "streamreader", "parameter": { "sliceRecordCount": 10, "column": [ { "type": "long", "value": "10" }, { "type": "string", "value": "hello,你好,世界-DataX" } ] } }, "writer": { "name": "streamwriter", "parameter": { "encoding": "UTF-8", "print": true } } } ], "setting": { "speed": { "channel": 5 } } }}一个同步作业的配置文件主要包括两部分,setting包括任务调度的一些配置,content描述同步任务的内容,里面包含reader插件的配置和writer插件的配置。例如我们需要从mysql同步数据到cassandra,那么我们只需要把reader配置为mysqlreader,writer配置为cassandrawriter,并提供相应的插件配置信息即可。在datax项目页面上面可以看到datax支持的插件列表,点击对应的链接就可以查看相关插件的文档了解插件需要的配置内容和格式要求。例如,cassandra插件的文档可点击如下链接:读插件 写插件。 以下列举几种常见的场景。 ...

October 15, 2019 · 2 min · jiezi

阿里巴巴的云原生与开发者

摘要:利用云原生技术构建应用简便快捷,部署应用轻松自如,运行应用按需伸缩。如今,云原生已经成为下一代技术发展的趋势。在 2019 杭州云栖大会开发者峰会上,阿里巴巴资深技术专家李响就为大家分享了阿里巴巴的云原生技术与开发者的那些故事。为什么选择云原生?云原生的本质目标就是充分释放云计算带来的红利,阿里巴巴希望开发者能够使用云上极致弹性的资源交付能力,也能够使用云上极为便捷的产品和服务。阿里巴巴实践云原生也已经走过了几年时间,并在去年启动了全站上云。阿里巴巴希望业务可以更好地拥抱云,更加全面地推进云原生。 云原生既带来了技术红利,同时也带来了业务红利。 在资源效率方面,云原生为资源效率带来了极大提升。使用容器、调度等技术不仅提高了单机维度的部署密度和资源效率,还提高了集群维度资源配置的合理性和使用率。除此之外,将业务搬到云上,还可以使用云的极致弹性的资源交付能力,既能够应对流量洪峰,也降低了资源的使用成本。在开发效率方面,使用 Kubernetes 这样的平台增强了运维自动化的能力,也增强了对应用和资源进行编排的能力,并降低了运维负担,提高了开发效率。同时,阿里云也在推动 CI/CD 系统的演进,希望加速应用从完成到上线的过程,并提高这一过程的稳定性和确定性,提高开发人员迭代的信心。此外,阿里云也希望将通用框架下沉到基础设施中,使得开发者能够在多语言的环境下更容易地接入和使用平台的能力,其中具有代表性的就是对服务网格的探索。在标准与开放方面,通过云原生可以帮助阿里巴巴实现基础设施和生态标准的完全融合。这不仅可以将开源生态中的新技术、新理念引入到阿里巴巴的基础设施中,利用阿里内部的大规模场景和复杂业务进行打磨、锤炼,并将经过打磨的结果回馈给社区,让它带给广大开发者更多的技术红利。还可以将打造的技术引入阿里云,打造出一套完整的云原生产品技术家族,帮助云上的开发者。从 Kubernetes 开始谈到实践云原生,其实可以从 Kubernetes 这个云原生的基石开始。从 Kubernetes 开始实践云原生的原因主要有两点: 一是 Kubernetes 向下可以对接各种不同的资源层,既可以对接像阿里云这样的公有云,也可以对接专有云,因此可以利用 Kubernetes 构建混合云平台。二是 Kubernetes 向上提供了强大的自动化运维能力、编排能力以及强大的拓展性,因此可以在 Kubernetes 上层构建一些垂直性的平台能力,比如可观测性、服务治理以及无服务化。基于这些垂直能力,可以进一步构建更贴近业务的平台,这也正是 Kubernetes 本身“Platform for Platform”的定位。 阿里巴巴的规模阿里巴巴的规模非常庞大,内部有超过 10 个集群,超过 10 万个节点,以及超过百万级别的容器。那么,开源技术和开源项目是否能够承受阿里巴巴的体量?能够抗住双11峰值规模的考验呢? 阿里巴巴坚信一定要和上游共建生态,阿里不希望只是去 ForkKubernetes,而希望去锤炼和打造 Kubernetes,因此有三个策略: 第一个策略是对自身业务进行负载的追踪和模拟,并将追踪和模拟的结果应用到 Kubernetes 云原生体系中进行测试。第二个策略是对于测试过程中发现的规模性问题,会持续优化,并反馈到上游,使得整个社区受益,进而推动云原生领域的发展。第三个策略是持续推动社区去接受这些可扩展的能力,阿里巴巴也定制了自己的调度器和控制器,来满足自身的业务场景。Kubernetes 1.16 和 etcd 3.4在最近发布的 Kubernetes 1.16 和 etcd 3.4 版本中,阿里巴巴和蚂蚁金服也一同作出了大量贡献,单机的数据存储规模提升了 50 倍,单集群节点规模也提升了 3 倍,完全可以满足阿里巴巴这样体量的公司在双 11 这种场景下的需求。今年的 618,蚂蚁金服已经对 Kubernetes 集群进行了验证,在即将到来的双 11,阿里会对 Kubernetes 集群进行再次验证。如果阿里巴巴可以使用 Kubernetes 作为云原生的基石,相信 99.9% 的企业都可以信任 Kubernetes 以及云原生技术。 应用运维与交付除了云原生的基石 Kubernetes 以外,阿里巴巴还希望推动整体基础设施的全面升级,希望把云原生技术的红利传导到更上层。 基础设施中一个重要的应用就是交付和运维,以前面向虚拟机的交付和运维非常复杂,并且不同企业有自己不同的运维模式和方法,可能是手动也可能是半自动,甚至在同一家企业内,运维手段也不尽相同。云原生倡导的是统一的平台和统一的理念,希望能够实现自动化运维,因此构建统一的应用模型和统一的应用架构分层就非常重要。 因此,阿里巴巴也同社区一起在推进云原生领域中应用交付与运维分层模型。并且将这一理念在阿里内部进行了规模化落地,目前已经推动了阿里内部的 4 个应用管理产品线面向云原生全面升级,构建了 100 多个应用。阿里认为这套应用结构非常有意义和价值,因此也与 CNCF 成立了应用交付领域小组,并由阿里的张磊担任小组联系主席 ,希望与社区一起推进这个项目。 服务网格在云原生领域中,位于更上层的系统就是服务网格。服务网格的好处在于具有强大的多语言支持能力,能够降低业务对接服务治理的难度,更易于实现统一的基础设施升级。在真正的实践中,Service Mesh 也会面临一些挑战,比如如何支持更多的协议,能否在大规模场景下得以较好运用,数据链路、服务面是否足够稳定等。 为了解决 Service Mesh 面临的上述挑战,阿里巴巴和蚂蚁金服率先决定选用一套与社区兼容的体系,并在阿里巴巴和蚂蚁金服内部的云原生系统当中进行打磨。今年 618 蚂蚁金服已经完成核心系统上到 SOFAMosn 的验证工作,在马上来临的今年的双 11,阿里巴巴和蚂蚁金服将会在核心系统大规模上线 Service Mesh,同时会把自身技术演进的结果及时反馈到上游去,和社区一起把 Service Mesh 从一个非常先进的技术变成一个非常稳定和可靠的技术,并且会在阿里云推出 Service Mesh 服务,让阿里云上的开发者能够便捷地使用服务网格技术。 FaaSFaaS 是开发人员非常喜欢的技术和概念,它可以极大地提升开发效率,使得开发者无需关注脚手架,可以直接以响应式模式来填充代码。同时,FaaS 可以帮助大家实现自动的扩容和缩容,当遇到问题时也可以帮助大家自动恢复,免去了运维的困扰。 但 FaaS 本身也存在几个问题: 第一个问题是如何找到一个既能够适应不同业务,也能够适应复杂业务逻辑的编程模型。第二个问题是如何在提供运维和弹性的自动化能力的同时,不增加额外的开销。阿里巴巴希望在今年的双 11 考验 FaaS 服务的极致弹性和极致的启动时间,阿里也会把 FaaS 的研究结果及时反馈到上游和阿里云中去,为广大开发者提供更大的便利和红利。 开源社区贡献阿里巴巴与蚂蚁金服对于核心开源社区的云原生领域都做出了巨大的贡献,并且在 etcd、Kata Containers、Containerd 以及 Dragonfly 等项目中都有核心 Maintainer。除这些项目外,我们也会持续向 Kubernetes 等云原生其他领域提供贡献,希望通过我们的努力,可以让云原生成为一个稳定、可靠的技术,成为企业未来的 IT 基石。 引领开发者走向云原生阿里巴巴在中国的开源社区以及开发者社区中有深厚的积累,之前就一直在运作很多开源项目。阿里巴巴希望用自身构建的土壤引领中国开发者走向云原生模式。 DubboDubbo 是国内最受开发者欢迎的微服务引擎之一,最近阿里把 Dubbo 捐献给了 Apache 基金会,希望它可以成为更加开放、更加标准的微服务引擎,希望能够与社区和开发者共建这个引擎。 现在,阿里巴巴对 Apache Dubbo 有了新的期望,希望 Apache Dubbo 能够成为更云原生的微服务框架。因此,在 Apache Dubbo 未来的演进道路中,有三个具体目标: 第一个目标是希望 Apache Dubbo 作为 RPC 框架可以更好地结合 Service Mesh,并对 Apache Dubbo 进行一定程度的瘦身,将一些能力下沉到 Service Mesh 上去。第二个目标是希望 Apache Dubbo 可以变得更加标准,能够和其他生态体系互融互通,能够支持 HTTP/2,能够融入 gRPC、Spring Cloud、Kubernetes 体系,为开发者提供更多选择。第三个目标是希望提升 Dubbo 本身的可观测性,支持 OpenTracing 等,使得基于 Apache Dubbo 构建的分布式系统能够具备更高的可运维能力。Nacos Nacos 是阿里巴巴去年开源的一个项目,开源之后很快就收到了广泛的好评。目前在 GitHub 上有超过 8000 个 Star,也有数十家企业已经将 Nacos 应用到了生产环境中。Nacos 本身在阿里巴巴内部也支撑了巨大体量微服务的注册。Nacos 的研发目标是简单且易用,其提供了一组非常简单的 API,方便开发者使用 HTTP 或 DNS 进行服务发现。阿里巴巴希望 Nacos 能够成为联动传统微服务框架和云原生微服务框架的桥梁,因此也希望 Nacos 既可以注册传统服务,又能注册云原生服务,让两边的服务实现互融互通。这样才能帮助阿里巴巴以及广大开发者平滑、稳定地从传统服务治理模式演进到云原生的服务治理模式。 ...

October 15, 2019 · 1 min · jiezi

K8s-从懵圈到熟练-–-集群网络详解

导读:阿里云 K8S 集群网络目前有两种方案:一种是 flannel 方案;另外一种是基于 calico 和弹性网卡 eni 的 terway 方案。Terway 和 flannel 类似,不同的地方在于 terway 支持 Pod 弹性网卡,以及 NetworkPolicy 功能。本文中,作者基于当前的 1.12.6 版本,以 flannel 为例,深入分析阿里云 K8S 集群网络的实现方法。鸟瞰总体上来说,阿里云 K8S 集群网络配置完成之后,如下图所示:包括集群 CIDR、VPC 路由表、节点网络、节点的 podCIDR、节点上的虚拟网桥 cni0、连接 Pod 和网桥的 veth 等部分。 类似的图大家可能在很多文章中都看过,但因为其中相关配置过于复杂,比较难理解。这里我们可以看下这些配置背后的逻辑。 基本上我们可以把这些配置分三种情况来理解:集群配置,节点配置以及 Pod 配置。与这三种情况对应的,其实是对集群网络 IP 段的三次划分:首先是集群 CIDR,接着是为每个节点分配 podCIDR(即集群 CIDR 的子网段),最后在 podCIDR 里为每个 Pod 分配自己的 IP。 集群网络搭建初始阶段集群的创建,基于云资源 VPC 和 ECS,在创建完 VPC 和 ECS 之后,我们基本上可以得到如下图的资源配置。我们得到一个 VPC,这个 VPC 的网段是 192.168.0.0/16,我们得到若干 ECS,他们从 VPC 网段里分配到 IP 地址。 ...

October 9, 2019 · 2 min · jiezi

MongoDB-sharding-集合不分片性能更高

最近云上用户用户遇到一个 sharding 集群性能问题的疑惑,比较有代表性,简单分享一下 测试配置mongos x 2、shard x 3测试1:集合不开启分片,批量 insert 导入数据,每个 batch 100 个文档测试2:集合开启分片,随机生成 shardKey,chunk 已提前 split 好,能确保写入均分到3个shard测试结果测试1:单个 shard cpu 跑满,insert qps 在 6w 左右测试2:3个 shard cpu 跑满,insert qps 在 7w 左右(平均每个分片2.4w左右)注:两个测试里,mongos 都不是瓶颈,能力足够 从测试结果看,每个shard都承担 1/3 的负载,的确达到横向扩张的目的,但为啥分片之后,单个shard的能力就下降了呢?如果是这样,sharding的扩展能力如何体现? 结果分析这里核心的问题在于 batch insert 在 mongos 和 mongod 上处理行为的差别 导入数据时,一次 insert 一条数据,和一次 insert 100 条数据,性能差距是很大的;首先减少了client、server 端之间的网络交互;同时 server 可以将 batch insert 放到一个事务里,降低开销;mongos 在收到 batch insert 时,因为一个 batch 里的数据需要根据 shardKey 分布到不同的shard,所以一个 batch 实际上需要被拆开的;这里 mongos 也做了优化,会尽量将连续的分布在一个shard上的文档做 batch 发到后端 shard。在集合不开启分片的情况,mongos 收到的 batch 肯定是转发给 primary shard,所以转发过去还是一整个 batch 操作; 而在集合开启分片的情况下,因为用户测试时,shardKey 是随机生成的,基本上整个 batch 被打散成单条操作,逐个往后端 shard 上发送,请求到后端 shard 基本已经完全没有合并了。所以在上述测试中,不分片的单个 shard 6w qps、与分片后每个 shard 2.4w qps,实际上就是请求是否 batch 执行的差别。 ...

July 11, 2019 · 1 min · jiezi

千亿级的数据难题优酷工程师怎么解决

阿里妹导读:优酷一天的日志量会达到千亿级别,面对如此大的数据样本,2017年5月,优酷完成了从Hadoop迁移到阿里云MaxCompute,实现计算消耗和储存的消耗呈下降趋势,得到了非常大的收益。今天,阿里数据技术专家门德亮给大家做个分享,从为什么要用MaxCompute,到优酷的业务场景下典型的方案及应用分析,聊聊迁移后对业务及平台的具体价值。本文内容根据演讲视频以及PPT整理而成,希望对你有所助益。 大家好,我是门德亮,很荣幸,我正好见证了优酷从没有MaxCompute到有的,这样一个历程,我们正好是在快到5年的时候,做了从Hadoop到MaxCompute的这样一个升级。 2016年5月到2019年5月优酷的发展历程。整个用户数,还有表的数据,实际上是呈指数式增长的。但是在2017年5月,当优酷完成了整个Hadoop迁移MaxCompute后,优酷的计算消耗,还有储存的消耗实际上是呈下降趋势的,整个迁移得到了非常大的收益。 下面说一下优酷的业务特点。 第一个特点是大数据平台整个的用户复杂度,不止是数据的同学和技术的同学在使用,还会包括一些BI同学,测试同学,甚至产品运营都可能去使用这个大数据的平台。 第二个特点就是业务复杂,优酷是一个视频网站,它有非常复杂的业务场景,从日志分类上,除了像页面浏览,还会有一些播放相关的数据、性能相关的数据。从整个的业务模式上,有直播、有会员、有广告、有大屏等这样一些非常不一样的场景。 第三个特点,就是数据量非常巨大,一天的日志量会达到千亿级别,这是一个非常庞大的数据量,而且会做非常复杂的计算。 第四个比较有意思,不管是小公司、大公司,对成本的意识是非常高的。优酷也是有非常严格的预算,包括在阿里集团内是有非常严格的预算系统的,但是我们也经常会去做一些重要的战役,像双十一战役,像我们暑期的世界杯战役,还有春节也会搞各种战役。这其实对计算资源的弹性要求是非常高的。 基于上面的优酷的业务特点,我整理了MaxCompute可以完美的支持我们业务的几个特点。 简单易用。完善的生态。性能非常强悍。资源使用非常弹性。第一个特点,简单易用。MaxCompute有一个非常完整的链路,不管是从数据开发,还是数据运维,包括数据集成,数据质量的管控,还有整个数据地图,数据安全。当年优酷从Hadoop迁到MaxCompute之后,我们最大的体会是不用经常自己半夜起来去维护集群了,不用去跑任务了,之前别人提一个需求过来,我可能要排几周,现在我可以告诉他,我给你马上跑一下,就可以出来了。包括之前像分析师BI还要登录客户端,写脚本,自己写调度,经常会说我的数据今天为什么没出来?包括高层看的数据,可能要到12点钟才能出来。而现在基本上所有重要的数据都会在7点钟产出,包括一些基本的业务需求,其实分析师或者产品,他们自己都可以实现了,不需要所有需求都提到数据这边。 第二个特点,完整的生态。优酷在2017年之前是完全基于Hadoop的生态,迁到MaxCompute之后,是基于阿里云提供的Serverless大数据服务的生态。大家可以在开源上看到的组件,在整个的MaxCompute上都是有的,而且比开源的要更好用、更简单。从架构图上可以看到,我们中间是MaxCompute,左侧依赖的Mysql、Hbase、ES、Redis这些都是由同步中心去做一个双向的同步。右侧会有资源管理、资源监控、数据监控,包括数据资产,还有一些数据规范。我们下层的数据输入,包括一些集团的采集工具,再往上边,有提供给开发人员用的DataWorks,包括一些命令行的工具,有提供给BI人员用的QuickBI及数据服务。 第三个特点,强悍的性能,MaxCompute支撑了优酷EB级的数据存储,千亿级的数据样本分析,包括千亿级的数据报表,10W级实例的并发、任务。这些在之前维护Hadoop的时候,是想都不敢想的。 第四个特点,资源使用的弹性。我们在2016年迁移之前,其实优酷的Hadoop集群规模已经达到了一千多台,这个当时还是一个比较大的规模。当时我们遇到了很多问题,包括像NameNode 这种内存的问题,机房没有办法再扩容的问题,当时是非常痛苦的,包括一些运维管理上面的问题。我们不断地去问运维要资源,运维说你们已经花了资源,多少钱。我们面临的问题是计算资源如何按需使用,夜里的作业很多,到了午后,整个集群都空下来了,没有人用,造成了浪费。其实MaxCompute完美地解决了这个问题。 第一个,它是按用量计费的,不是说给你多少台机器,就收你多少钱,是你用了多少资源收多少钱的,在成本上来说,比自己去维护集群,可能是一个砍半(降50%)的收益。 第二个,实际上MaxCompue计算资源是可以分时的,比如说生产队列,凌晨的时候会调高一些,保证报表能够尽快出来。到白天时候,让开发的计算资源高一些,可以让分析师、开发去临时跑一些数据,会更顺畅一些。 第三个,MaxCompute快速的扩容能力,比如说突然有一个比较强的业务需求,发现数据跑不动了,计算资源不够,所有的队列都堵死了,这个时候其实可以直接跟运维说一声,帮忙一键扩容,两秒钟敲一个命令就搞定了。这样,所有的资源可以迅速地消化下去。 这张图实际上是优酷,包括可能现在阿里集团内部一些非常典型的技术架构图。中间可以看到,MaxCompute在中间核心的位置,左侧主要是一个输入,右侧是一个输出的趋向,绿色的线是一个实时的链路,包括现在我们从整个的数据源上,比如DB也好或者服务器的本地日志Log也好,我们通过TT&Datahub存储到MaxCompute上面做分析。当然现在非常火的Flink实时计算,其实是作为一个实时处理的链路。 包括DB的同步,除了实时的链路,DB也会去通过按天/按小时,把数据同步到MaxCompute,数据计算结果也可以同步到Hbase、Mysql这种DB上面。再通过统一的服务层对应用提供服务。下面这个是机器学习Pai做的一些算法训练,再把训练的结果通过OSS传到一个算法的应用上面去。 这张图可能也是业界比较流行的一个数仓分层的图,因为我们这边是数据中台,所有的数据都是统一从ods层cdm层,然后ads层,去一层一层地往上去做精细,再到最上面,通过接口服务、文件服务、SQL服务,去提供多样化的服务。再往上面,提供对内的一些数据产品,对高管、对小二,可能还有一些对外的,比如说像优酷的播放数,包括热度这些对应用的数据。 这张图其实就是我们从Hadoop迁到MaxCompute平台上以来,两个非常经典的案例。我们通过数据中台对不同场景的用户打通,来去赋能到两个不同的场景,提升业务价值。 第二个,可能是内部的,我们通过优酷,还有集团内部的一些BU去做换量,我们通过统一的标签去做样本放大,把优酷的量导给其它的BU,把其它BU的量导给优酷,这样去达到一个共赢的效果。 这张图是大部分互联网公司不太会涉及到的,就是关于反作弊的问题。这个是我们在MaxCompute做的一个反作弊的架构,通过原始的数据去提取它的特征,然后再通过算法模型,包括机器学习、深度学习、图模型去支持流量反作弊、渠道反作弊等等。再通过业务场景上反作弊的监控工具,把监控到的作弊信息去打一个黑白样本,再把这个黑白样本跟特征一起来不断地迭代优化算法模型。同时针对算法模型,做一个模型的评价,不断来完善反作弊体系。 最后一点,其实还是跟成本相关,在日常使用中,一定是有小白用户或者一些新来的用户去错误地使用或者不在乎地使用一些资源,比如经常会有一些实习生或者是非技术的同学,如分析师,一个SQL消费比较高,这个其实是非常浪费资源,而且可能他一个任务,让其他所有人的任务都在这儿等着排队,实际上我们会去对整个的资源做一个治理。 从节点的粒度上,通过大数据来治理大数据,我们可以算出哪些表产出来之后,多少天没有被读取的,包括它的访问跨度可能没有那么大的,我们会去做下线或者去做治理,有一些业务场景可能并不是非常的重要或者它的时间要求没有那么高,比如一些算法训练,可以去做一些错峰的调度,保证水位不要太高。从MaxCompute任务的角度,可以算出哪些任务有数据倾斜、哪些数据可能会有相似计算,哪些任务需要去做MapJoin,哪些任务需要去做一些裁剪,然后来节省它的IO。还有哪些任务会去做暴力扫描,扫一个月、扫一年的数据,哪些数据可能会有这样一个数据膨胀,比如说它做了CUBE之类的这种复杂计算,一些算法模型的迭代;我们通过数据计算出来的这些迹象,去反推用户,来去提高它的这样一个数据的质量分,来去达到我们降低整个计算资源的目的。 在计算平台的角度,我们也持续地在使用MaxCompute推出的一些非常高级的用法,比如我们这边的HBO、Hash Cluster、Aliorc; 第一个,HBO就是我们基于一个历史的优化,这样避免了用户不知道怎么调参,我可能为了自己任务快一点,就调一个特别大的参数,这样的话,对集成的资源是非常浪费的。通过这个功能,用户就不用去调参数,集群自动调好,用户就写好自己业务逻辑就好了。 第二个,可能就是最近两年推出的Hash Cluster,当时在使用Hadoop的时候经常会出现,两个大表Join的时候计算不出来,这个Hash Cluster其实是一个优化的利器。大表跟小表Join,可以做一些分发,做一些优化。大表跟大表就涉及到一个排序的问题。这个Hash Cluster,实际上就是提前把数据排好,中间省掉很多计算环节,来达到效率提升的目的。 第三个,Aliorc,在一些固定的场景上面,可以稳定的提升20%的计算效率。 第四个,Session。对一些比较小的数据,直接就放到SSD或缓存里面,一个节点下游有100个叶子场景,是非常友好的,因为低延迟秒出结果。同时,优酷也在使用Lightning解决计算加速,这个是在一个计算架构方案上的优化,它是一个MPP的架构。 最后一页是存储的优化,因为像一些关键的原始数据或者是需要审计的数据是不能删的,永久不能删的。实际上就会造成我们数据存储的趋势是一直往上不减的,计算会在某一个时间点达到一个平衡。当前用这么多的计算资源,再往后,其实应该也不会再大涨了,比如说旧的业务逻辑下掉了,会换新的业务逻辑,这样会保持在一个相对平稳的波动上面。 但是储存,因为它有一些历史的数据是永远不能删的,可能会出现一直在增长,而且是指数级的。所以我们也会持续关注存储的情况,还是通过大数据来治大数据,去看哪些表的访问跨度比较小,来去做生命周期的优化,来去控制它的增速。还有刚才提到的Aliorc,实际上也是做压缩的。我们会去做一些大字段的拆分,来提高压缩的比例。 共建大数据生态,企业级大数据平台开发者版已正式发布,点击文末“阿里技术”阅读原文立即申请。 本文作者:阿里技术阅读原文 本文来自云栖社区合作伙伴“阿里技术”,如需转载请联系原作者。

July 10, 2019 · 1 min · jiezi

云原生应用-Kubernetes-监控与弹性实践

前言   云原生应用的设计理念已经被越来越多的开发者接受与认可,而Kubernetes做为云原生的标准接口实现,已经成为了整个stack的中心,云服务的能力可以通过Cloud Provider、CRD Controller、Operator等等的方式从Kubernetes的标准接口向业务层透出。开发者可以基于Kubernetes来构建自己的云原生应用与平台,Kubernetes成为了构建平台的平台。今天我们会向大家介绍一个云原生应用该如何在Kubernetes中无缝集成监控和弹性能力。 本文整理自由阿里云容器平台技术专家 刘中巍(莫源)在 KubeCon 分享的《Cloud Native Application monitoring and autoscaling in kubernetes》演讲。获取 KubeCon 全部阿里演讲PPT,关注阿里巴巴云原生公众号,微信菜单栏点击 PPT下的“获取PPT” 阿里云容器服务Kubernetes的监控总览 云服务集成  阿里云容器服务Kubernetes目前已经和四款监控云服务进行了打通,分别是SLS(日志服务)、ARMS(应用性能监控)、AHAS(架构感知监控服务)、Cloud Monitor(云监控)。 SLS主要负责日志的采集、分析。在阿里云容器服务Kubernetes中,SLS可以采集三种不同类型的日志 APIServer等核心组件的日志Service Mesh/Ingress等接入层的日志应用的标准日志  除了采集日志的标准链路外,SLS还提供了上层的日志分析能力,默认提供了基于APIServer的审计分析能力、接入层的可观测性展现、应用层的日志分析。在阿里云容器服务Kubernetes中,日志组件已经默认安装,开发者只需要通过在集群创建时勾选即可。 ARMS主要负责采集、分析、展现应用的性能指标。目前主要支持Java与PHP两种语言的集成,可以采集虚拟机(JVM)层的指标,例如GC的次数、应用的慢SQL、调用栈等等。对于后期性能调优可以起到非常重要的作用。 AHAS是架构感知监控,通常在Kubernetes集群中负载的类型大部分为微服务,微服务的调用拓扑也会比较复杂,因此当集群的网络链路出现问题时,如何快速定位问题、发现问题、诊断问题则成为了最大的难题。AHAS通过网络的流量和走向,将集群的拓扑进行展现,提供更高层次的问题诊断方式。 开源方案集成开源方案的兼容和集成也是阿里云容器服务Kubernetes监控能力的一部分。主要包含如下两个部分: Kubernetes内置监控组件的增强与集成  在kubernetes社区中,heapster/metrics-server是内置的监控方案,而且例如Dashboard、HPA等核心组件会依赖于这些内置监控能力提供的metrics。由于Kubernetes生态中组件的发布周期和Kubernetes的release不一定保证完整的同步,这就造成了部分监控能力的消费者在Kubernetes中存在监控问题。因此阿里云就这个问题做了metrics-server的增强,实现版本的兼容。此外针对节点的诊断能力,阿里云容器服务增强了NPD的覆盖场景,支持了FD文件句柄的监测、NTP时间同步的校验、出入网能力的校验等等,并开源了eventer,支持离线Kubernetes的事件数据到SLS、kafka以及钉钉,实现ChatOps。 Prometheus生态的增强与集成   Promethes作为Kubernetes生态中三方监控的标准,阿里云容器服务也提供了集成的Chart供开发者一键集成。此外,我们还在如下三个层次作了增强: 存储、性能增强:支持了产品级的存储能力支持(TSDB、InfluxDB),提供更持久、更高效的监控存储与查询。采集指标的增强:修复了部分由于Prometheus自身设计缺欠造成的监控不准的问题,提供了GPU单卡、多卡、共享分片的exporter。提供上层可观测性的增强:支持场景化的CRD监控指标集成,例如argo、spark、tensorflow等云原生的监控能力,支持多租可观测性。阿里云容器服务Kubernetes的弹性总览   阿里云容器服务Kubernetes主要包含如下两大类弹性组件:调度层弹性组件与资源层弹性组件。 调度层弹性组件  调度层弹性组件是指所有的弹性动作都是和Pod相关的,并不关心具体的资源情况。 HPAHPA是Pod水平伸缩的组件,除了社区支持的Resource Metrics和Custom Metrics,阿里云容器服务Kubernetes还提供了external-metrics-adapter,支持云服务的指标作为弹性伸缩的判断条件。目前已经支持例如:Ingress的QPS、RT,ARMS中应用的GC次数、慢SQL次数等等多个产品不同维度的监控指标。 VPA VPA是Pod的纵向伸缩的组件,主要面向有状态服务的扩容和升级场景。    cronHPA cronHPA是定时伸缩组件,主要面向的是周期性负载,通过资源画像可以预测有规律的负载周期,并通过周期性伸缩,实现资源成本的节约。 ResizerResizer是集群核心组件的伸缩控制器,可以根据集群的CPU核数、节点的个数,实现线性和梯度两种不同的伸缩,目前主要面对的场景是核心组件的伸缩,例如:CoreDNS。 资源层弹性组件资源层弹性组件是指弹性的操作都是针对于Pod和具体资源关系的。 Cluster-Autoscaler Cluster-Autoscaler是目前比较成熟的节点伸缩组件,主要面向的场景是当Pod资源不足时,进行节点的伸缩,并将无法调度的Pod调度到新弹出的节点上。 virtual-kubelet-autoscaler virtual-kubelet-autoscaler是阿里云容器服务Kubernetes开源的组件,和Cluster-Autoscaler的原理类似,当Pod由于资源问题无法调度时,此时弹出的不是节点,而是将Pod绑定到虚拟节点上,并通过ECI的方式将Pod进行启动。 Demo Show Case  最后给大家进行一个简单的Demo演示:应用主体是apiservice,apiservice会通sub-apiservice调用database,接入层通过ingress进行管理。我们通过PTS模拟上层产生的流量,并通过SLS采集接入层的日志,ARMS采集应用的性能指标,并通过alibaba-cloud-metrics-adapster暴露external metrics触发HPA重新计算工作负载的副本,当伸缩的Pod占满集群资源时,触发virtual-kubelet-autoscaler生成ECI承载超过集群容量规划的负载。 总结  在阿里云容器服务Kubernetes上使用监控和弹性的能力是非常简单的,开发者只需一键安装相应的组件Chart即可完成接入,通过多维度的监控、弹性能力,可以让云原生应用在最低的成本下获得更高的稳定性和鲁棒性。 本文作者:jessie筱姜阅读原文 本文为云栖社区原创内容,未经允许不得转载。

July 4, 2019 · 1 min · jiezi

K8S环境中NAS卷添加noresvport方法

通过K8S使用NAS卷,请区分以下场景: 静态存储卷: 使用阿里云ACK,PV、PVC方式,nfs驱动;使用阿里云ACK,PV、PVC方式,Flexvolume驱动;使用阿里云ACK,Volume方式,nfs驱动;使用阿里云ACK,Volume方式,Flexvolume驱动;自建K8S,PV、PVC方式,nfs驱动;自建K8S,Volume方式,nfs驱动;动态存储卷: 使用阿里云ACK使用自建K8S静态卷-使用阿里云Kubernetes(ACK)时1. 使用PV、PVC方式(nfs驱动)首先确认当前的挂载是否配置了noresvport参数,参考NAS团队提供的方式; 例如当前的pv如下面yaml: apiVersion: v1kind: PersistentVolumemetadata: name: pv-nasspec: accessModes: - ReadWriteOnce capacity: storage: 2Gi mountOptions: - vers=3 nfs: path: /default server: 2564f49129-ggu23.cn-shenzhen.nas.aliyuncs.com persistentVolumeReclaimPolicy: Retain编辑PV: kubectl edit pv pv-nas更新mountOptions:mountOptions: - vers=4.0 - noresvport或者: mountOptions: - vers=3 - nolock,tcp,noresvport重启使用这个pv的pod; 需要注意: 由于一个节点上,如果已经有某个挂载点挂载在一个目录下了,其他的挂载(相同挂载点)即使配置了noresvport参数,还是会follow以前的挂载参数。即noresvport不生效;解决方法:方法1:修改pv参数后,把所有使用这个挂载点的pod掉离这个节点,然后再调回来。方法2:使用新的挂载点创建新的pv使用(一个nas文件系统可以有2个挂载点); 示例方法1: 集群中有2个worker节点,部署一个deploy包含3个Pod;# kubectl get node | grep -v masterNAME STATUS ROLES AGE VERSIONcn-shenzhen.i-wz9c9m0m4oldr6mt89rd Ready <none> 55d v1.12.6-aliyun.1cn-shenzhen.i-wz9gvy73m4qyk03xzg1y Ready <none> 60d v1.12.6-aliyun.1# kubectl get podNAME READY STATUS RESTARTS AGEnas-static-784496fbb9-cqr97 1/1 Running 0 63mnas-static-784496fbb9-gljbq 1/1 Running 0 63mnas-static-784496fbb9-ngzkq 1/1 Running 0 63m编辑pv,添加- nolock,tcp,noresvport Options;编辑deploy,把这个deploy的pod都调度到节点:cn-shenzhen.i-wz9c9m0m4oldr6mt89rd上;> 在deploy中添加 nodeName: cn-shenzhen.i-wz9c9m0m4oldr6mt89rd> 如果您的集群节点较多,可以给一批节点添加label,然后通过nodeSelector把pod调度到这写节点;> 参考:https://kubernetes.io/zh/docs/tasks/configure-pod-container/assign-pods-nodes/注意:如果您用的时候statefulset的应用,需要把updateStrategy.type配置为RollingUpdate;然后再把pod调度到其他节点:cn-shenzhen.i-wz9gvy73m4qyk03xzg1y到节点cn-shenzhen.i-wz9gvy73m4qyk03xzg1y 上验证noresport,已经生效。2564f49129-ggu23.cn-shenzhen.nas.aliyuncs.com:/default on /var/lib/kubelet/pods/aa79e380-9bdb-11e9-a545-00163e0eff42/volumes/kubernetes.io~nfs/pv-nas type nfs (rw,relatime,vers=3,rsize=1048576,wsize=1048576,namlen=255,hard,nolock,noresvport,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=192.168.0.11,mountvers=3,mountport=4002,mountproto=tcp,local_lock=all,addr=192.168.0.11)最后,由于当前使用nas的pod是有nodeName标签的,可以编辑deploy,把nodeName(nodeSelector)去掉。2. 使用PV、PVC方式(Flexvolume驱动)首先确认当前的挂载是否配置了noresvport参数,参考NAS团队提供的方式; ...

July 3, 2019 · 2 min · jiezi

Kafka集群部署指南

一、前言1、Kafka简介Kafka是一个开源的分布式消息引擎/消息中间件,同时Kafka也是一个流处理平台。Kakfa支持以发布/订阅的方式在应用间传递消息,同时并基于消息功能添加了Kafka Connect、Kafka Streams以支持连接其他系统的数据(Elasticsearch、Hadoop等) Kafka最核心的最成熟的还是他的消息引擎,所以Kafka大部分应用场景还是用来作为消息队列削峰平谷。另外,Kafka也是目前性能最好的消息中间件。 2、Kafka架构 在Kafka集群(Cluster)中,一个Kafka节点就是一个Broker,消息由Topic来承载,可以存储在1个或多个Partition中。发布消息的应用为Producer、消费消息的应用为Consumer,多个Consumer可以促成Consumer Group共同消费一个Topic中的消息。 概念/对象简单说明BrokerKafka节点Topic主题,用来承载消息Partition分区,用于主题分片存储Producer生产者,向主题发布消息的应用Consumer消费者,从主题订阅消息的应用Consumer Group消费者组,由多个消费者组成3、准备工作1、Kafka服务器准备3台CentOS服务器,并配置好静态IP、主机名 服务器名IP说明kafka01192.168.88.51Kafka节点1kafka02192.168.88.52Kafka节点2kafka03192.168.88.53Kafka节点3软件版本说明 项说明Linux ServerCentOS 7Kafka2.3.02、ZooKeeper集群Kakfa集群需要依赖ZooKeeper存储Broker、Topic等信息,这里我们部署三台ZK 服务器名IP说明zk01192.168.88.21ZooKeeper节点zk02192.168.88.22ZooKeeper节点zk03192.168.88.23ZooKeeper节点部署过程参考:https://ken.io/note/zookeeper... 二、部署过程1、应用&数据目录#创建应用目录mkdir /usr/kafka#创建Kafka数据目录mkdir /kafkamkdir /kafka/logschmod 777 -R /kafka2、下载&解压Kafka官方下载地址:https://kafka.apache.org/down...这次我下载的是2.3.0版本 #创建并进入下载目录mkdir /home/downloadscd /home/downloads#下载安装包wget http://mirrors.tuna.tsinghua.edu.cn/apache/kafka/2.3.0/kafka_2.12-2.3.0.tgz #解压到应用目录tar -zvxf kafka_2.12-2.3.0.tgz -C /usr/kafkakafka_2.12-2.3.0.tgz 其中2.12是Scala编译器的版本,2.3.0才是Kafka的版本3、Kafka节点配置#进入应用目录cd /usr/kafka/kafka_2.12-2.3.0/#修改配置文件vi config/server.properties通用配置配置日志目录、指定ZooKeeper服务器 # A comma separated list of directories under which to store log fileslog.dirs=/kafka/logs# root directory for all kafka znodes.zookeeper.connect=192.168.88.21:2181,192.168.88.22:2181,192.168.88.23:2181分节点配置Kafka01broker.id=0#listeners=PLAINTEXT://:9092listeners=PLAINTEXT://192.168.88.51:9092Kafka02broker.id=1#listeners=PLAINTEXT://:9092listeners=PLAINTEXT://192.168.88.52:9092Kafka03broker.id=2#listeners=PLAINTEXT://:9092listeners=PLAINTEXT://192.168.88.53:90924、防火墙配置#开放端口firewall-cmd --add-port=9092/tcp --permanent#重新加载防火墙配置firewall-cmd --reload5、启动Kafka#进入kafka根目录cd /usr/kafka/kafka_2.12-2.3.0/#启动/bin/kafka-server-start.sh config/server.properties &#启动成功输出示例(最后几行)[2019-06-26 21:48:57,183] INFO Kafka commitId: fc1aaa116b661c8a (org.apache.kafka.common.utils.AppInfoParser)[2019-06-26 21:48:57,183] INFO Kafka startTimeMs: 1561531737175 (org.apache.kafka.common.utils.AppInfoParser)[2019-06-26 21:48:57,185] INFO [KafkaServer id=0] started (kafka.server.KafkaServer)三、Kafka测试1、创建Topic在kafka01(Broker)上创建测试Tpoic:test-ken-io,这里我们指定了3个副本、1个分区 ...

July 3, 2019 · 1 min · jiezi

坚持探索与落地并重阿里巴巴云原生之路全景揭秘

阿里妹导读:阿里云已经成功地规模化落地云原生,26日的 KubeCon 大会上,CNCF TOC 和阿里云资深技术专家李响发表主题演讲,分享了阿里巴巴在规模扩展、可靠性、开发效率、迁移策略等方面的经验,并探讨云原生的落地及应对若干技术挑战。为什么要做云原生?云原生究竟能带来什么价值?从最初的独自摸索到如今拥抱开源回馈社区,阿里巴巴走过了怎样的云原生旅程?又有哪些技术心得?今天,将全部分享出来。 多年沉淀,坚持探索与落地并重阿里巴巴从2011年开始通过容器实践云原生技术体系,在整个业界都还没有任何范例可供参考的大背境下,逐渐摸索出了一套比肩全球一线技术公司并且服务于整个阿里集团的容器化基础设施架构。这个探索历程虽然孤独,但却被始终如一的坚持至今。这正是在这个孤注一掷的技术探索与奋进的过程中,阿里巴巴的技术团队完整的经历了云原生技术浪潮里的所有关键节点,不仅成为了这次技术革命的重要见证者,也逐渐成为中国云原生技术体系当之无愧的推动者与引领者之一。 阿里的体量大、业务复杂,推动云原生要找到合适的切入点。在双十一成本压力的推动下,资源成本与效率优化成了阿里云原生的起点。 阿里从容器入手,研究低成本虚拟化与调度技术:提供灵活、标准的部署单元;将静态资源分配更换为动态按需调度,进一步提升部署效率,解决资源碎片化问题,提高部署密度;通过存储网络虚拟化和存储计算分离等技术,增强任务的可迁移性,进一步提高了资源的可靠性,降低了资源成本。 在资源成本的推动下,阿里完成了全面容器化,资源分配也被高效调度平台接管。阿里的云原生并未止步于此。提高研发效率与加快迭代周期是推动阿里业务增强的秘密武器。阿里希望通过云原生让开发者效率更高。 为了降低应用部署难度,提高部署自动化程度,阿里开始采用 Kubernetes 作为容器编排平台,并且持续推动 Kubernetes 的性能与可扩展性。具体 Kubernetes,阿里持续对研发、部署流程进行改进。为了构建更云原生化的 CI/CD,进一步做到标准化和自动化,从研发到上线流程,阿里引入了诸如 Helm 的应用标准化管理,也尝试了 GitOps 这样的部署流程,还推动了 PaaS 层的面向终态自动化改造。于此同时,阿里也开始探索服务网格,致力于进一步提高服务治理的普适性与标准性,降低开发者采用门槛,进一步推动微服务在多语言和多环境下的普及。 今年,阿里也展开了全站上云。经过云原生的探索与改造,阿里基础架构体系是现代化和标准化的。利用容器技术,应用与宿主机运行时完成了解耦;利用 Kubernetes 对 Pod 与 Volume 等的抽象,完成了对多种资源实现的统一化;通过智能调度与 PaaS 平台,让自动迁移应用,修复不稳定因素成为了可能,阿里通过云原生技术大大降低了上云的难度。 在这个提高资源和人员效率的过程中,阿里巴巴的整个基础设施也变得更加开放,连通开源生态,在交流互动中不断吸收和贡献好的理念、技术、思想。如今,阿里云不仅支撑着中国最大的云原生应用双11,而且拥有国内最大的公共云集群和镜像仓库。作为唯一入选 Gartner 的公有云容器服务竞争格局的厂商,阿里云也积累了最为丰富和宝贵的客户实践。 追求极致,优化扩展性和规模性弹性和规模性,这是支撑阿里巴巴各种类型的复杂场景以及流量高峰的关键因素。 经过不断打磨,阿里巴巴在 Kubernetes 规模与性能上取得了显著的成果:将存储object 的数量提升25倍,支持的节点数从5000提升到上万,在端到端调度延迟从5s变为100ms等等。其中有不少工作在阿里巴巴和社区中共同开展,而这些研发成果都已经贡献给社区,我们期望其他企业及开发者也可以享受阿里巴巴规模所带来的技术红利。 阿里巴巴持续优化性能,可以分为以下四个维度:工作负载追踪、性能分析、定制化调度、大规模镜像分发。首先对工作负载调度有完整的追踪、重放机制,其次将所有性能问题的进行细致分析,逐一攻克技术瓶颈。Kubernetes 本身的可定制性很强,阿里巴巴针对自身业务场景沉淀了定制化的调度能力和镜像分发系统。开源Dragonfly 项目脱胎于双十一,具备极强的镜像分发能力。数十个超级集群,每个超级集群具有数万节点,数百万的容器。 阿里巴巴落地 Kubernetes 可以分为三个阶段:首先通过 Kubernetes 提供资源供给,但是不过多干扰运维流程,这系统容器是富容器,将镜像标准化与轻量级虚拟化能力带给了上面的 PaaS 平台。第二步,通过 Kubernetes controller 的形式改造PaaS 平台的运维流程,给 PaaS 带来更强的面向终态的自动化能力。最后把运行环境等传统重模式改成原生容器与 pod 的轻量模式,同时将 PaaS 能力完全移交给Kubernetes controller,从而形成一个完全云原生的架构体系。 如何解决云原生的关键难点阿里巴巴云原生的探索,起步于自研容器和调度系统,到如今拥抱开源的标准化技术。对于当下开发者的建议是:如果想构建云原生架构,建议直接从 Kubernetes 入手即可。一方面,Kubernetes 为平台建设者而生,已经成为云原生生态的中流砥柱,它不仅向下屏蔽了底层细节,而且向上支撑各种周边业务生态;另一方面,更重要的是社区中有着越来越多围绕 Kubernetes 构建的开源项目,比如Service Mesh、Kubeflow。 ...

June 28, 2019 · 1 min · jiezi

Linus-本尊来了为什么-KubeCon-越来越火

阿里妹导读: 从200人的小会议到3500 多位云原生和开源领域工程师齐聚一堂的大会,KubeCon 只用了四年,昨天,在KubeCon China 2019 上阿里巴巴宣布开源 OpenKruise,今天,Linus 本尊竟然现身会场!现在,我们继续连线会场,探索阿里云为开发者带来的多份重磅献礼。 2015年11月,第一届 KubeCon 在美国旧金山开始的时候,还只是个200人的小会议,2019年的7月,KubeCon 第二次在中国举办,就有 3500 多位云原生和开源领域工程师齐聚一堂。 连 Linux 及 Git 创始人 Linus Torvalds 本人都来到 KubeCon China 上海现场。Linux 基金会执行董事 Jim Zemlin 说道:“我见证了开源圈子的两大事件:一个是 Linux 的成功,一个就是 Kubernetes 和云原生的大爆发。开源是历史上最成功的全球创新推动者之一,Linux 已经成长为世界上最重要的软件平台,而云原生正以势如破竹之态爆发。” 中国在整个云原生运动中贡献巨大,中国的 K8s contributors 已经在全球所有贡献者中排名第二,超过 10% 的 CNCF 会员来自中国,26%的 Kubernetes 的认证供应商来自中国。 阿里云作为最早成为 CNCF member 的中国公司之一,一直在云原生技术领域不停地实践和探索。在阿里云已经是铂金会员的基础上,蚂蚁金服也最新加入 CNCF 成为黄金会员。 本次 KubeCon China,阿里云又发布了什么黑科技呢?一起来感受下。 拥抱社区,服务最广泛开发者:云原生应用管理与交付体系发布 整个云原生应用管理与交付体系包含五大项目,本次 KubeCon 两大项目率先亮相:国内首个开放云原生应用中心—— Cloud Native App Hub 和云原生应用自动化引擎—— OpenKruise。 ...

June 27, 2019 · 2 min · jiezi

容器服务Windows-Kubernetes使用阿里云日志服务来收集容器日志

目前,容器服务Windows Kubernetes支持将业务容器产生的stdout输出、日志文件同步到阿里云日志服务(SLS)进行统一管理。 支撑组件安装在Windows Kubernetes集群安装界面勾选使用日志服务,集群会安装支持日志收集的必要组件logtail。 集群安装完毕后,可以在日志服务控制台 查看到按k8s-sls-{Kubernetes 集群 ID}形式命名的工程。收集到的业务容器日志都会放在该工程下。 使用YAML模版部署业务容器YAML 模板的语法同 Kubernetes 语法,但是为了给容器指定采集配置,需要使用 env 来为 container 增加采集配置和自定义 Tag,并根据采集配置,创建对应的 volumeMounts 和 volumns。以下是一个简单的 Deployment 示例: apiVersion: extensions/v1beta1kind: Deploymentmetadata: labels: app: logtail-test name: logtail-testspec: replicas: 1 template: metadata: labels: app: logtail-test name: logtail-test spec: containers: - name: logtail image: registry-vpc.cn-hangzhou.aliyuncs.com/acs/windows-logtail:1809-1.0.0.4 command: ["powershell.exe"] args: [cmd /k "ping -t 127.0.0.1 -w 10000 > C:\log\data.log"] env: ######### 配置 环境变量 ########### - name: aliyun_logs_log-stdout value: stdout - name: aliyun_logs_log-varlog value: C:\log\*.log - name: aliyun_logs_log_tags value: tag1=v1 ################################# ######### 配置vulume mount ####### volumeMounts: - name: volumn-sls-win mountPath: c:\log volumes: - name: volumn-sls-win emptyDir: {} ############################### nodeSelector: beta.kubernetes.io/os: windows其中有三部分需要根据您的需求进行配置,一般按照顺序进行配置。 ...

June 20, 2019 · 1 min · jiezi

OceanBase数据库实践入门性能测试建议

概述本文主要分享针对想压测OceanBase时需要了解的一些技术原理。这些建议可以帮助用户对OceanBase做一些调优,再结合测试程序快速找到适合业务的最佳性能。由于OceanBase自身参数很多、部署形态也比较灵活,这里并没有给出具体步骤。 数据库读写特点压测的本质就是对一个会话的逻辑设计很高的并发。首先需要了解单个会话在数据库内部的读写逻辑。比如说,业务会话1对数据库发起一个DML SQL,第一次修改某笔记录,数据库会怎么做呢? 为了便于理解OB的行为,我们先看看ORACLE是怎么做的。后面有对比才可以加深理解。 ORACLE 读写特点ORACLE会话第一次修改一行记录,如果该记录所在块(8K大小)不在内存(Buffer Cache)里时会先从磁盘文件里读入到内存里。这个称为一次物理读,为了性能考虑,ORACLE一次会连续读取相邻的多个块。然后就直接在该块上修改,修改之前会先记录REDO和UNDO(包括UNDO的REDO)。然后这个数据块就是脏块(Dirty Block)。假设事务没有提交,其他会话又来读取这个记录,由于隔离级别是读已提交(READ COMMITTED),ORACLE会在内存里克隆当前数据块到新的位置,新块包含了最新的未提交数据。然后ORACLE在新块上逆向应用UNDO链表中的记录,将数据块回滚到读需要的那个版本(SCN),然后才能读。这个也称为一次一致性读(Consistency Read),这个新块也称为CR块。 即使是修改一条记录一个字段的几个字节,整个块(8K大小)都会是脏块。随着业务持续写入,大量脏块会消耗数据库内存。所以ORACLE会有多重机制刷脏块到磁盘数据文件上。在事务日志切换的时候也会触发刷脏块操作。如果业务压力测试ORACLE,大量的写导致事务日志切换很频繁,对应的刷脏操作可能相对慢了,就会阻塞日志切换,也就阻塞了业务写入。这就是ORACLE的特点。解决办法就是加大事务日志文件,增加事务日志成员或者用更快的磁盘存放事务日志和数据文件。 ORACLE里一个表就是一个Segment(如果有大对象列还会有独立的Segment,这个先忽略),Segment由多个不一定连续的extent组成,extent由连续的Block(每个大小默认8K)组成,extent缺点是可能会在后期由于频繁删除和插入产生空间碎片。 OceanBase 读写特点OceanBase会话第一次修改一行记录,如果该记录所在块(64K大小)不在内存(Block Cache)里时也会先从磁盘文件里读入到内存里。这个称为一次物理读。然后要修改时跟ORACLE做法不同的是,OceanBase会新申请一小块内存用于存放修改的内容,并且链接到前面Block Cache里该行记录所在块的那笔记录下。如果修改多次,每次修改都跟前面修改以链表形式关联。同样在修改之前也要先在内存里记录REDO。每次修改都会记录一个内部版本号,记录的每个版本就是一个增量。其他会话读取的时候会先从Block Cache中该记录最早读入的那个版本(称为基线版本)开始读,然后叠加应用后面的增量版本直到合适的版本(类似ORACLE中SCN概念)。(随着版本演进,这里细节逻辑可能会有变化。) OB的这个读方式简单说就是从最早的版本读起,逐步应用增量(类似REDO,但跟REDO日志无关)。而ORACLE一致性读是从最新的版本读起,逐步回滚(应用UNDO)。在OB里,没有UNDO。当版本链路很长时,OB的读性能会略下降,所以OB也有个checkpoint线程定时将记录的多个版本合并为少数几个版本。这个合并称为小合并(minor compaction)。此外,OB在内存里针对行记录还有缓存, 从上面过程还可以看出,每次修改几个字节,在内存里的变脏的块只有增量版本所在的块(默认写满才会重新申请内存),基线数据块是一直不变化。所以OB里脏块产生的速度非常小,脏块就可以在内存里保存更久的时间。实际上OB的设计就是脏块默认不刷盘。那如果机器挂了,会不会丢数据呢? OB跟ORACLE一样,修改数据块之前会先记录REDO,在事务提交的时候,REDO要先写到磁盘上(REDO同时还会发送往其他两个副本节点,这个先忽略)。有REDO在,就不怕丢数据。此外,增量部分每天还是会落盘一次。在落盘之前,内存中的基线数据和相关的增量数据会在内存里进行一次合并(称Merge),最终以SSTable的格式写回到磁盘。如果说内存里块内部产生碎片,在合并的那一刻,这个碎片空间基本被消弭掉了。所以说OB的数据文件空间碎片很小,不需要做碎片整理。同时OB的这个设计也极大降低了LSM的写放大问题。 当业务压测写OB时,脏块的量也会增长,最终达到增量内存限制,这时候业务就无法写入,需要OB做合并释放内存。OB的合并比较耗IO、CPU(有参数可以控制合并力度),并且也不会等到内存用尽才合并,实际会设置一个阈值。同时为了规避合并,设计了一个转储机制。当增量内存使用率超过阈值后,就开启转储。转储就是直接把增量内存写到磁盘上(不合并)。转储对性能的影响很小,可以高峰期发生,并且可以转储多次(参数配置)。 OB增量内存就类似一个水池,业务写是进水管在放水, 转储和大合并是出水管。水位就是当前增量内存使用率。当进水的速度快于出水,池子可能就会满。这时候业务写入就会报内存不足的错误。这就是OB读写的特点,解决方法就是加大OB内存、或者允许OB自动对业务写入速度限流。 OceanBase部署建议OB 在commit的时候redo落盘会写磁盘。读数据的时候内存未命中的时候会有物理读,转储和大合并的时候落盘会有密集型写IO。这些都依赖磁盘读写性能。所以建议磁盘都是SSD盘,并且建议日志盘和数据盘使用独立的文件系统。如果是NVME接口的闪存卡或者大容量SSD盘,那日志盘和数据盘放在一起也可以。不要使用LVM对NVME接口的大容量SSD做划分,那样瓶颈可能会在LVM自身。 OB的增量通常都在内存里,内存不足的时候会有转储,可以转储多次。尽管如此,建议测试机器的内存不要太小,防止频繁的增量转储。通常建议192G内存以上。 OB集群的节点数至少要有三个。如果是功能了解,在单机上起3个OB进程模拟三节点是可以的,但是如果是性能测试,那建议还是使用三台同等规格的物理机比较合适。机器规格不一致时,最小能力的机器可能会制约整个集群的性能。 OceanBase集群的手动部署请参考《OceanBase数据库实践入门——手动搭建OceanBase集群》。在部署好OceanBase之后,建议先简单了解一下OceanBase的使用方法,详情请参考文章《OceanBase数据库实践入门——常用操作SQL》。 如果要验证OB的弹性缩容、水平扩展能力,建议至少要6节点(部署形态2-2-2)。并且测试租户(实例)的每个Zone里的资源单元数量至少也要为2个,才可以发挥多机能力。这是因为OB是多租户设计,对资源的管理比较类似云数据库思想,所以里面设计有点精妙,详情请参见《揭秘OceanBase的弹性伸缩和负载均衡原理》。 下面是一个租户的测试租户资源初始化建议 登录sys租户create resource unit S1, max_cpu=2, max_memory='10G', min_memory='10G', max_iops=10000, min_iops=1000, max_session_num=1000000, max_disk_size=536870912;create resource unit S2, max_cpu=4, max_memory='20G', min_memory='20G', max_iops=20000, min_iops=5000, max_session_num=1000000, max_disk_size=1073741824;create resource unit S3, max_cpu=8, max_memory='40G', min_memory='40G', max_iops=50000, min_iops=10000, max_session_num=1000000, max_disk_size=2147483648;select * from __all_unit_config;create resource pool pool_demo unit = 'S2', unit_num = 2;select * from __all_resource_pool order by resource_pool_id desc ;create tenant t_obdemo resource_pool_list=('pool_demo');alter tenant t_obdemo set variables ob_tcp_invited_nodes='%';请注意上面的unit_num=2这个很关键。如果unit_num=1,OB会认为这个租户是个小租户,后面负载均衡处理时会有个默认规则。 ...

June 19, 2019 · 2 min · jiezi

云上快速搭建Serverless-AI实验室

Serverless Kubernetes和ACK虚拟节点都已基于ECI提供GPU容器实例功能,让用户在云上低成本快速搭建serverless AI实验室,用户无需维护服务器和GPU基础运行环境,极大降低AI平台运维的负担,显著提升整体计算效率。 如何使用GPU容器实例在pod的annotation中指定所需GPU的类型(P4/P100/V100等),同时在resource.limits中指定GPU的个数即可创建GPU容器实例。每个pod独占GPU,暂不支持vGPU,GPU实例的收费与ECS GPU类型收费一致,不产生额外费用,目前ECI提供多种规格的GPU类型。(请参考https://help.aliyun.com/document_detail/114581.html) 示例1. 创建Serverless Kubernetes集群选择深圳区域,可用区D。 2. 创建GPU容器实例我们使用tensorflow模型对如下图片进行识别: 使用模版创建pod,其中选择P100 GPU规格。在pod中的脚本会下载上述图片文件,并根据模型进行识别计算。 apiVersion: v1kind: Podmetadata: name: tensorflow annotations: k8s.aliyun.com/eci-gpu-type : "P100"spec: containers: - image: registry-vpc.cn-shenzhen.aliyuncs.com/ack-serverless/tensorflow name: tensorflow command: - "sh" - "-c" - "python models/tutorials/image/imagenet/classify_image.py" resources: limits: nvidia.com/gpu: "1" restartPolicy: OnFailure部署后pod会处于pending状态: 等待几十秒后pod状态变成Running,待计算完成后会变成Terminated状态。 从pod的日志我们可以看到pod能够识别P100 GPU硬件,而且可以正确识别图片为Panda。 总结通过以上示例可以看出,从环境搭建到计算结束,整个过程用户无需购买和管理服务器,无需安装GPU运行环境,serverless的方式可以让用户更加关注在AI模型构建,而不是底层基础设施的管理和维护。 本文作者:贤维原文链接 本文为云栖社区原创内容,未经允许不得转载。

June 18, 2019 · 1 min · jiezi

规模化落地云原生阿里云即将重磅亮相-KubeCon-China

2019 年 6 月 24 日至 26 日, 由 Cloud Native Computing Foundation (CNCF) 主办的云原生技术大会 KubeCon + CloudNativeCon + Open Source Summit(上海 )即将在中国上海盛装启幕。 继 2018 年 KubeCon 首次成功登陆中国,本届 KubeCon 将吸引来自全世界数千名技术人员将会参加此次盛会,参与CNCF 全部项目和话题的深度探讨和案例分析,聆听 CNCF 项目的运维者和最终用户的分享。本届 KubeCon + CloudNativeCon + Open Source Summit 大会项目委员会由 75 名专家组成,审阅 KubeCon + CloudNativeCon 的 618 项提案,在本次 KubeCon China 2019 上,阿里巴巴共有 26 个技术演讲入选。 在本次 KubeCon 上,阿里云智能容器平台负责人丁宇(叔同)、 CNCF TOC、etcd 项目作者、阿里云容器平台资深技术专家李响,CNCF 大使、Kubernetes 项目维护者、阿里云高级技术专家张磊等众多云原生技术大咖都会悉数到场并做技术分享,同时会为您带来包括开源 Virtual Cluster 强多租户设计、 OpenKruise 开源项目、开放云原生应用中心(Cloud Native App Hub)等众多云原生先进技术的最新动态与进展。我们非常期待您能够在 KubeCon China 上与阿里容器平台团队见面、进行交流或者开展技术合作。 ...

June 18, 2019 · 2 min · jiezi

基于Knative开发应用

目录安装 Istio安装 Knative玩转 helloworld-goWordPress 实战创建 Kubernetes 集群确保 Kubernetes 集群创建的时候已经选择了启用日志服务确保 Kubernetes 集群和 OSS 在一个 regionKubernetes 集群创建的时候需要开启 kube-apiserver 公网访问提前帮用户配置好 kubeconfig 命令行安装 Istio安装 Istio 时注意以下几点: 默认要安装 gateway日志服务和 Xtrace 要提前开通,Istio 需要使用 ZipKin v1 向 Xtrace 汇报监控数据在容器服务集群管理页面可以直接在目标集群上部署 Istio 安装 Knative选择好目标集群使用一键部署功能直接安装即可, 安装文档 玩转 helloworld-go配置日志采集策略部署 Helloworld监控告警调用链压测数据展示日志管理日志服务控制台: https://sls.console.aliyun.com本示例以容器标准输出采集为例进行展示,详细设置步骤可以参考日志服务文档根据 Kubernetes 集群 ID 找到对应的日志服务 Project创建一个新的 Logstore设置数据导入方式 选择 Docker标准输出 配置容器标准输出日志采集策略{ "inputs": [ { "detail": { "IncludeEnv": { "K_SERVICE": "helloworld-go" }, "IncludeLabel": {}, "ExcludeLabel": {} }, "type": "service_docker_stdout" } ], "processors": [ { "detail": { "KeepSource": false, "NoMatchError": true, "Keys": [ "time", "level", "msg" ], "NoKeyError": true, "Regex": "(\\d+-\\d+-\\d+ \\d+:\\d+:\\d+)\\s+(\\w+)\\s+(*)", "SourceKey": "content" }, "type": "processor_regex" } ]}分别为相应的键值 time、level 和 msg 设置数据类型 ...

June 17, 2019 · 2 min · jiezi

基于ExternalDNS的多集群Service-DNS实践

概述External-DNS提供了编程方式管理Kubernetes Service资源的DNS的功能,类似于容器服务kubernetes federation v2实践一:基于External-DNS的多集群Ingress DNS实践,External-DNS会监听LoadBalancer类型的Service,然后与云厂商打通,按照可用区、region和全局三个维度生成独自的域名解析记录,便于服务间调用引导流量。本文简单介绍如何在阿里云容器平台上使用External-DNS管理多集群Service DNS。 环境准备参考容器服务kubernetes federation v2实践一:基于External-DNS的多集群Ingress DNS实践完成【联邦集群准备】、【配置RAM信息】和【部署External-DNS】部分,并配置好kubeConfig,如下所示: kubectl config get-contextsCURRENT NAME CLUSTER AUTHINFO NAMESPACE* cluster1 cluster1 kubernetes-admin1 cluster2 cluster2 kubernetes-admin2资源部署创建FederatedDeployment和FederatedServiceyaml如下,注意FederatedService类型为LoadBalancer apiVersion: v1kind: Namespacemetadata: name: test-namespace---apiVersion: types.federation.k8s.io/v1alpha1kind: FederatedNamespacemetadata: name: test-namespace namespace: test-namespacespec: placement: clusterNames: - cluster1 - cluster2---apiVersion: types.federation.k8s.io/v1alpha1kind: FederatedDeploymentmetadata: name: test-deployment namespace: test-namespacespec: template: metadata: labels: app: nginx spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - image: nginx name: nginx placement: clusterNames: - cluster1 - cluster2---apiVersion: types.federation.k8s.io/v1alpha1kind: FederatedServicemetadata: name: test-service namespace: test-namespacespec: template: spec: selector: app: nginx type: LoadBalancer ports: - name: http port: 80 placement: clusterNames: - cluster2 - cluster1查看各个集群Service详情: ...

June 14, 2019 · 2 min · jiezi

优酷背后的大数据秘密

在本文中优酷数据中台的数据技术专家门德亮分享了优酷从Hadoop迁移到阿里云MaxCompute后对业务及平台的价值。 本文内容根据演讲视频以及PPT整理而成。 大家好,我是门德亮,现在在优酷数据中台做数据相关的事情。很荣幸,我正好见证了优酷从没有MaxCompute到有的这样一个历程,因为刚刚好我就是入职优酷差不多5年的时间,我们正好是在快到5年的时候,去做了从Hadoop到MaxCompute的这样一个升级。这个是2016年5月到2019年现在的5月优酷的发展历程,上面是计算资源,下面是储存资源。大家可以看到整个用户数,还有表的数据,实际上是在呈一个指数式增长的。但是在2017年5月,当优酷完成了整个Hadoop迁移MaxCompute后,优酷的计算消耗,还有储存的消耗实际上是呈下降趋势的,整个迁移得到了一个非常大的收益。 下面说一下优酷的业务特点。 第一个特点从大数据平台整个的用户复杂度上面,不止是数据的同学和技术的同学在使用,还会包括一些BI同学,测试同学,甚至产品运营都可能去使用这个大数据的平台。 第二个特点就是业务复杂,优酷是一个视频网站,它有非常复杂的业务场景,从日志分类上,除了像页面浏览,还会有一些播放相关的数据、性能相关的数据。从整个的业务模式上,有直播、有会员、有广告、有大屏等这样一些非常不一样的场景。 第三个特点,就是数据量是非常巨大的,一天的日志量会达到千亿级别,这是一个非常旁大的数据量,而且会做非常复杂的计算。 第四个是比较有意思的,不管是小公司、大公司,对成本的意识是非常高的。优酷也是有非常严格的预算,包括在阿里集团内是有非常严格的预算系统的,但是我们也经常会去做一些重要的战役,像双十一战役,像我们暑期的世界杯战役,还有春节也会搞各种战役。这样的话,其实对计算资源的弹性要求是非常高的。 基于上面的优酷的业务特点,我整理了MaxCompute可以完美的支持我们业务的几个特点。 第一个,简单易用。第二个,完善的生态。第三个,性能非常强悍。第四个,资源使用非常弹性。 第一个特点,简单易用。MaxCompute有一个非常完整的链路,不管是从数据开发,还是数据运维,包括数据集成,数据质量的管控,还有整个数据地图,数据安全。当年优酷从Hadoop迁到MaxCompute之后,我们最大的体会是自己不用半夜经常起来去维护集群了,不用去跑任务了,写一个任务,别人之前提一个需求过来,我可能要给他排几周,而现在我可以告诉他,我给你马上跑一下,就可以出来了。包括之前像分析师BI还要登录客户端,写脚本,自己写调度,经常会说我的数今天为什么没出来?包括高层看的数,可能要到12点钟才能出来。而现在基本上所有重要的数据都会在7点钟产出,包括一些基本的业务需求,其实分析师或者产品,他们自己都可以实现了,不需要所有需求都提到数据这边。 第二个特点,完整的生态。优酷在2017年之前是完全基于Hadoop的生态,迁到MaxCompute之后,是基于阿里云提供的Serverless大数据服务的生态。大家可以在开源上看到的组件,在整个的MaxCompute上都是有的,而且比开源的要更好用、更简单。从架构图上可以看到,我们中间是MaxCompute,左侧依赖的Mysql、Hbase、ES、Redis这些都是由同步中心去做一个双向的同步。右侧会有资源管理、资源监控、数据监控,包括数据资产,还有一些数据规范。我们下层的数据输入,包括一些集团的采集工具,再往上边,有提供给开发人员用的DataWorks,包括一些命令行的工具;有提供给BI人员用的QuickBI及数据服务。 第三个特点,强悍的性能,MaxCompute支撑了优酷EB级的数据存储,千亿级的数据样本分析,包括千亿级的数据报表,10W级实例的并发、任务。这些在之前维护Hadoop的时候,是想都不敢想的。 第四个特点,资源使用的弹性。我们在2016年迁移之前,其实优酷的Hadoop集群规模已经达到了一千多台,这个当时还是一个比较大的规模。当时我们遇到了很多问题,包括像NameNode 这种内存的问题,机房没有办法再扩容的问题,当时是非常痛苦的,包括一些运维管理上面的问题。我们不断的去问运维要资源,运维告诉说,说你们已经花了多少多少资源,花了多少多少钱。我们面临的问题是计算资源如何按需使用,夜里的时候作业很多,到了下午之后,我的整个集群都空下来了,没有人用,造成了浪费。其实MaxCompute完美的解决了这个问题。 第一个,它是按用量计费的,不是说给你多少台机器,然后就收你多少钱的,真的是你用了多少资源收多少钱的,这个在成本上来说,比自己去维护集群,可能是一个砍半(降50%)这样的收益。 第二个,实际上MaxCompue计算资源是可以分时的,比如说生产队列,凌晨的时候会调高一些,保证报表能够尽快出来。到白天时候,让开发的计算资源高一些,可以让分析师、开发去临时跑一些数据,会更顺畅一些。 第三个,MaxCompute快速的扩容能力,比如说突然有一个比较强的业务需求,发现数据跑不动了,计算资源不够,所有的队列都堵死了,这个时候其实可以直接跟运维说一声,帮忙一键扩容,他两秒钟敲一个命令就搞定了。这样的话,所有的资源可以迅速的消化下去。 上面是优酷为什么采用MaxCompute,下面是在优酷的业务场景下,我们一些典型的方案、应用。这张图实际上是优酷,包括可能现在阿里集团内部一些非常典型的技术架构图。中间可以看到,MaxCompute在中间核心的位置,左侧主要是一个输入,右侧是一个输出的趋向,绿色的线是一个实时的链路,包括现在我们从整个的数据源上,比如DB也好或者服务器的本地日志Log也好,我们通过TT&Datahub存储到MaxCompute上面做分析。当然现在非常火的Flink实时计算,其实是作为一个实时处理的链路。 包括DB的同步,除了实时的链路,DB也会去通过按天/按小时,把数据同步到MaxCompute,数据计算结果也可以同步到Hbase、Mysql这种DB上面。再通过统一的服务层对应用提供服务。下面这个是机器学习Pai做的一些算法训练,再把训练的结果通过OSS传到一个算法的应用上面去。 这张图可能也是业界比较流行的一个数仓分层的图,因为我们这边是数据中台,所有的数据都是统一从ods层cdm层,然后ads层,去一层一层的往上去做精细,再到最上面,通过接口服务、文件服务、SQL服务,去提供多样化的服务。再往上面,提供对内的一些数据产品,对高管、对小二,可能还有一些对外的,比如说像优酷的播放数,包括热度这些对应用的数据。 这张图其实就是我们从Hadoop迁到MaxCompute平台上以来,两个非常经典的案例。我们通过数据中台对不同场景的用户打通,来去赋能到两个不同的场景,提升业务价值。 第二个,可能是内部的,我们通过优酷,还有集团内部的一些BU去做换量,我们通过统一的标签去做样本放大,把优酷的量导给其它的BU,把其它BU的量导给优酷,这样去达到一个共赢的效果。 这张图大部分互联网公司不太会涉及到,就是关于反作弊的问题。这个是我们在MaxCompute做的一个反作弊的架构,通过原始的数据去提取它的特征,然后再通过算法模型,包括机器学习、深度学习、图模型去支持流量反作弊、渠道反作弊等等。再通过业务场景上反作弊的监控工具,把监控到的作弊信息去打一个黑白样本,再把这个黑白样本跟特征一起来不断的迭代优化算法模型。同时针对算法模型,做一个模型的评价,不断来完善反作弊体系。 最后一点,其实还是跟成本相关,在日常使用中,一定是有小白用户或者一些新来的用户去错误的使用或者不在乎的使用一些资源,比如经常会有一些实习生或者是非技术的同学,如分析师,一个SQL消费比较高,这个其实是非常浪费资源,而且可能他一个任务,让其他所有人的任务都在这儿等着排队,实际上我们会去对整个的资源做一个治理。 从节点的粒度上,通过大数据来治理大数据,我们可以算出哪些表产出来之后,多少天没有被读取的,包括它的访问跨度可能没有那么大的,我们会去做下线或者去做治理,有一些业务场景可能并不是非常的重要或者它的时间要求没有那么高,比如一些算法训练,可以去做一些错峰的调度,保证水位不要太高。从MaxCompute任务的角度,可以算出哪些任务有数据倾斜、哪些数据可能会有相似计算,哪些任务需要去做MapJoin,哪些任务需要去做一些裁剪,然后来节省它的IO。还有哪些任务会去做暴力扫描,扫一个月、扫一年的数据,哪些数据可能会有这样一个数据膨胀,比如说它做了CUBE之类的这种复杂计算,一些算法模型的迭代;我们通过数据计算出来的这些迹象,去反推用户,来去提高它的这样一个数据的质量分,来去达到我们降低整个计算资源的目的。 在计算平台的角度,我们也持续的在使用MaxCompute推出的一些非常高级的用法,比如我们这边的HBO、Hash Cluster、Aliorc,HBO就是我们基于一个历史的优化,这样避免了用户不知道怎么调参,我可能为了自己任务快一点,就调一个特别大的参数,这样的话,对集成的资源是非常浪费的。通过这个功能,用户就不用去调参数,集群自动调好,用户就写好自己业务逻辑就好了。 第二块,可能就是最近两年推出的Hash Cluster,当时在使用Hadoop的时候经常会出现,两个大表Join的时候计算不出来,这个Hash Cluster其实是一个优化的利器。大表跟小表Join,可以做一些分发,做一些优化。大表跟大表就涉及到一个排序的问题。这个Hash Cluster,实际上就是提前把数据排好,中间省掉很多计算环节,来达到效率提升的目的。 第三个,Aliorc,在一些固定的场景上面,可以稳定的提升20%的计算效率。 第四个,Session。对一些比较小的数据,直接就放到SSD或缓存里面,一个节点下游有100个叶子场景,是非常友好的,因为低延迟秒出结果。同时,优酷也在使用Lightning解决计算加速,这个是在一个计算架构方案上的优化,它是一个MPP的架构。 最后一页是存储的优化,因为像一些关键的原始数据或者是需要审计的数据是不能删的,永久不能删的。实际上就会造成我们数据存储的趋势是一直往上不减的,计算会在某一个时间点达到一个平衡。当前用这么多的计算资源,再往后,其实应该也不会再大涨了,比如说旧的业务逻辑下掉了,会换新的业务逻辑,这样会保持在一个相对平稳的波动上面。但是储存,因为它有一些历史的数据是永远不能删的,可能会出现一直在增长,而且是指数级的。所以我们也会持续关注存储的情况,我们主要有四个手段。 第一个,还是通过大数据来治大数据,去看哪些表它的访问不够或者它的访问跨度不够。就是对一些生命周期的优化,来去控制它的增速。包括下面的,刚才提到的Aliorc,实际上是做压缩的,我们会去做一些大字段的拆分,来提高压缩的比例。 OK,这个是优酷在MaxCompute中的一些应用场景,感谢大家的聆听。 本文作者:隐林原文链接 本文为云栖社区原创内容,未经允许不得转载。

June 13, 2019 · 1 min · jiezi

关于分布式集群负载均衡微服务的关系说明

https://www.cnblogs.com/wmqia...

June 13, 2019 · 1 min · jiezi

规模化落地云原生阿里云即将重磅亮相-KubeCon-China

2019 年 6 月 24 日至 26 日, 由 Cloud Native Computing Foundation (CNCF) 主办的云原生技术大会 KubeCon + CloudNativeCon + Open Source Summit(上海 )即将在中国上海盛装启幕。 继 2018 年 KubeCon 首次成功登陆中国,本届 KubeCon 将吸引来自全世界数千名技术人员将会参加此次盛会,参与CNCF 全部项目和话题的深度探讨和案例分析,聆听 CNCF 项目的运维者和最终用户的分享。本届 KubeCon + CloudNativeCon + Open Source Summit 大会项目委员会由 75 名专家组成,审阅 KubeCon + CloudNativeCon 的 618 项提案,在本次 KubeCon China 2019 上,阿里巴巴共有 26 个技术演讲入选。  在本次 KubeCon 上,阿里云智能容器平台负责人丁宇(叔同)、 CNCF TOC、etcd 项目作者、阿里云容器平台资深技术专家李响,CNCF 大使、Kubernetes 项目维护者、阿里云高级技术专家张磊等众多云原生技术大咖都会悉数到场并做技术分享,同时会为您带来包括开源 Virtual Cluster 强多租户设计、 OpenKruise 开源项目、开放云原生应用中心(Cloud Native App Hub)等众多云原生先进技术的最新动态与进展。我们非常期待您能够在 KubeCon China 上与阿里容器平台团队见面、进行交流或者开展技术合作。 ...

June 12, 2019 · 2 min · jiezi

Knative-初体验Serving-Hello-World

通过前面两章的学习你已经掌握了很多 Knative 的理论知识,基于这些知识你应该对 Knative 是谁、它来自哪里以及它要做什么有了一定的认识。可是即便如此你可能还是会有一种犹抱琵琶半遮面,看不清真容的感觉,这就好比红娘拿姑娘的 100 张生活照给你看也不如你亲自去见一面。按常理出牌,一般到这个阶段就该 Hello World 出场了。本篇文章就通过一个 Hello World 和 Knative 来一个“约会”,让你一睹 Knative 这位白富美的真容。 安装 KnativeKnative 社区提供的安装步骤见这里,整个流程大概包含如下三个部分: 准备 kubernetes 环境(你可以在阿里云容器服务中快速创建一个 kubernetes 集群 )安装istio安装 Knative组件虽然看起来只有三步,但是每一步其实都需要手动做大量的工作,执行一堆命令。另外社区文档提供的 yaml 文件默认使用了大量的 gcr.io 镜像,目前国内无法拉取 gcr.io 镜像。所以这些 yaml 文件在国内不能直接使用,至少需要手动同步 30 多个镜像才行。 不过别着急,阿里云容器服务的应用目录已经有 Knative 的安装包,现在只需要在阿里云容器服务上面点击几下鼠标就能轻轻松松搭建一个 Knative 集群 O ^ ~ ^ O O ^ ~ ^ O O ^ ~ ^ O 创建 Kubernetes 集群阿里云容器服务可以通过管理控制台非常方便地创建 Kubernetes 集群。具体过程可以参考创建Kubernetes集群。容器服务提供了专有集群和托管集群两种类型,如果不知道该怎么选择建议你直接选择托管版的 Kubernetes 集群。托管版无需你自己承担 Kubernetes Master 组件的管理和运维,你只需要提供 Node 节点即可。 ...

June 11, 2019 · 6 min · jiezi

CICD联动阿里云容器服务Kubernetes实践之Bamboo篇

本文档以构建一个 Java 软件项目并部署到 阿里云容器服务的Kubernetes集群 为例说明如何使用 Bamboo在阿里云Kubernetes服务上运行Remote Agents并在agents上运行Build Plans。 1. 源码项目本示例中创建的GitHub源码项目地址为: https://github.com/AliyunContainerService/jenkins-demo.git 分支为: bamboo2. 在Kubernetes中部署Remote Agent2.1 创建kaniko-docker-cfg secret kaniko-docker-cfg secret用于Remote Agent上构建任务使用kaniko推送容器镜像时的权限配置 kubectl -n bamboo create secret generic kaniko-docker-cfg --from-file=/root/.docker/config.json上面命令中的/root/.docker/config.json,是在linux服务器上使用root用户通过以下命令生成的: docker login registry.cn-hangzhou.aliyuncs.com2.2 创建serviceaccount bamboo以及clusterrolebinding用于kubectl部署应用到kubernetes集群的权限设置,创建bamboo-agent deployment 注意: 本示例中的clusterrolebinding为admin权限, 具体使用中可以根据自己的需要创建最小权限的serviceaccount bamboo-agent.yaml: ---apiVersion: v1kind: ServiceAccountmetadata: namespace: bamboo name: bamboo---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata: name: bamboo-cluster-adminsubjects: - kind: ServiceAccount name: bamboo namespace: bambooroleRef: kind: ClusterRole name: cluster-admin apiGroup: rbac.authorization.k8s.io---apiVersion: apps/v1beta2kind: Deploymentmetadata: name: bamboo-agentspec: replicas: 1 selector: matchLabels: app: bamboo-agent template: metadata: labels: app: bamboo-agent spec: serviceAccountName: bamboo containers: - name: bamboo-agent env: - name: BAMBOO_SERVER_URL value: http://xx.xx.xx.xx:8085 image: registry.cn-hangzhou.aliyuncs.com/haoshuwei/docker-bamboo-agent:v1 imagePullPolicy: Always volumeMounts: - mountPath: /root/.docker/ name: kaniko-docker-cfg volumes: - name: kaniko-docker-cfg secret: secretName: kaniko-docker-cfgkubectl -n bamboo apply -f bamboo-agent.yaml上述kubernetes资源创建完毕后等待remote agent完成初始化配置, 可以使用如下命令查看日志: ...

June 10, 2019 · 1 min · jiezi

基于ExternalDNS的多集群Ingress-DNS实践

概要External-DNS提供了编程方式管理Kubernetes Ingress资源的DNS的功能,方便用户从Ingress管理DNS解析记录。而在kubernetes federation v2环境中,使用External-DNS可以快速的管理多个联邦集群的Ingress DNS解析,降低用户的操作成本。下面将简单介绍在阿里云容器服务环境中,如何使用External-DNS管理联邦集群的Ingress DNS解析。 联邦集群准备参考阿里云Kubernetes容器服务上体验Federation v2 搭建两个集群组成的联邦集群(配置好kubeconfig,并完成两个集群的join)。 配置RAM信息选择Kubernetes集群节点列表内任意一个Worker节点,打开对应的节点列表信息页面。 找到对应的 RAM 角色,打开RAM控制台,找到对应的角色名称,添加【AliyunDNSFullAccess】权限。 注意:每个集群都需要配置RAM信息。 部署External-DNS配置RBAC 执行下面yaml: apiVersion: v1kind: ServiceAccountmetadata: name: external-dns---apiVersion: rbac.authorization.k8s.io/v1beta1kind: ClusterRolemetadata: name: external-dnsrules:- apiGroups: [""] resources: ["services"] verbs: ["get","watch","list"]- apiGroups: [""] resources: ["pods"] verbs: ["get","watch","list"]- apiGroups: ["extensions"] resources: ["ingresses"] verbs: ["get","watch","list"]- apiGroups: [""] resources: ["nodes"] verbs: ["list"]- apiGroups: ["multiclusterdns.federation.k8s.io"] resources: ["dnsendpoints"] verbs: ["get", "watch", "list"]---apiVersion: rbac.authorization.k8s.io/v1beta1kind: ClusterRoleBindingmetadata: name: external-dns-viewerroleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: external-dnssubjects:- kind: ServiceAccount name: external-dns namespace: default部署External-DNS服务 ...

June 6, 2019 · 2 min · jiezi

使用EMR-Spark-Relational-Cache跨集群同步数据

背景Relational Cache是EMR Spark支持的一个重要特性,主要通过对数据进行预组织和预计算加速数据分析,提供了类似传统数据仓库物化视图的功能。除了用于提升数据处理速度,Relational Cache还可以应用于其他很多场景,本文主要介绍如何使用Relational Cache跨集群同步数据表。通过统一的Data Lake管理所有数据是许多公司追求的目标,但是在现实中,由于多个数据中心,不同网络Region,甚至不同部门的存在,不可避免的会存在多个不同的大数据集群,不同集群的数据同步需求普遍存在,此外,集群迁移,搬站涉及到的新老数据同步也是一个常见的问题。数据同步的工作通常是一个比较痛苦的过程,迁移工具的开发,增量数据处理,读写的同步,后续的数据比对等等,需要很多的定制开发和人工介入。基于Relational Cache,用户可以简化这部分的工作,以较小的代价实现跨集群的数据同步。下面我们以具体示例展示如何通过EMR Spark Relational Cache实现跨集群的数据同步。 使用Relational Cache同步数据假设我们有A,B两个集群,需要把activity_log表的数据从集群A同步到集群B中,且在整个过程中,会持续有新的数据插入到activity_log表中,A集群中activity_log的建表语句如下: CREATE TABLE activity_log ( user_id STRING, act_type STRING, module_id INT, d_year INT)USING JSONPARTITIONED BY (d_year)插入两条信息代表历史信息: INSERT INTO TABLE activity_log PARTITION (d_year = 2017) VALUES("user_001", "NOTIFICATION", 10), ("user_101", "SCAN", 2)为activity_log表建一个Relational Cache: CACHE TABLE activity_log_syncREFRESH ON COMMITDISABLE REWRITEUSING JSONPARTITIONED BY (d_year)LOCATION "hdfs://192.168.1.36:9000/user/hive/data/activity_log"AS SELECT user_id, act_type, module_id, d_year FROM activity_logREFRESH ON COMMIT表示当源表数据发生更新时,自动更新cache数据。通过LOCATION可以指定cache的数据的存储地址,我们把cache的地址指向B集群的HDFS从而实现数据从集群A到集群B的同步。此外Cache的字段和Partition信息均与源表保持一致。 在集群B中,我们也创建一个activity_log表,创建语句如下: CREATE TABLE activity_log ( user_id STRING, act_type STRING, module_id INT, d_year INT)USING JSONPARTITIONED BY (d_year)LOCATION "hdfs:///user/hive/data/activity_log"执行MSCK REPAIR TABLE activity_log自动修复相关meta信息,然后执行查询语句,可以看到在集群B中,已经能够查到之前集群A的表中插入的两条数据。 ...

June 6, 2019 · 1 min · jiezi

蚂蚁金服终端实验室演进之路

摘要: 本文将从支付宝业务特性出发,深度解析无线实验集群在支付宝的演进与发展,并探讨 IoT 与人机如何交互并提供真正落地的时间方案。作者:周力(问瑾),蚂蚁金服技术专家。本文将从支付宝业务特性出发,深度解析无线实验集群在支付宝的演进与发展,并探讨 IoT 与人机如何交互并提供真正落地的时间方案。 现场视频(复制地址到浏览器中打开):http://t.cn/AiKDZg5G 0. 背景作为国民级 App,支付宝客户端需要为亿级用户提供多元化的服务,因此应用的稳定性与可靠性面临巨大的挑战,需要不断地完善和优化。 今天,让我们站在服务质量的全方位监控与优化的角度,从蚂蚁终端实验室的演进之路展开探讨,从借助使用开源的自动化方案,到自研并逐步完善无线实验集群技术体系,支付宝内部经历了怎样的业务场景演练,以及相应的技术架构如何借助移动开发平台 mPaaS 对外输出。 1. 发展历程 总的来说, 蚂蚁终端实验室从诞生到现在,一共经历过三个阶段(工具化、服务化以及中台化),其每个阶段都有特点和意义: 工具化阶段:该阶段主要以使用市面上主流开源软件为主,如客户端开源软件 Appium, 其覆盖的端为 Android 和 iOS;通过这种开源工具和 App 测试流程结合的方式,快速满足业务方的提测需求,从而帮助业务方完成一般意义上的自动化测试工作(如基本的功能测试、兼容性测试等)。 服务化阶段:服务化阶段存在一个重要的背景:支付宝着手前后端研发流程分离,并逐步沉淀出独立的 App 端研发流程系统(研发协作流程与 App 构建流程)。在独立的 App 研发流程和系统的基础上,终端实验室以一种服务化的形式支撑 App 的研发和协作, 处理满足日常用户自动化工作外,同时还担当着持续集成、日常发布前自动验包工作等; 另外在日常发布发布提供质量数据支持,如客户端代码覆盖率统计等。 中台化阶段:伴随着终端实验室的能力不断提升优化以及测试规模的逐步扩大,服务上不仅需要满足蚂蚁金服体系 App(支付宝、口碑、网商银行等)日常测试需求,而且还需要将能力扩散覆盖到整个阿里巴巴集团的业务。 随之而来的是实验室需要面临多样化的业务方需求和定制化功能,如何在多元复杂的业务环境中,与业务方或者说上游系统完成能力共建?带着这个问题,终端实验室逐步沉淀并着手建设中台化平台:一方面让通用服务不断下沉,另一方面抽象出标准 SDK 的方式,让业务方根据自身业务特点建设特定的能力。 此外,在建设平台化的同时,终端实验室贴合支付宝业务场景的发展,构建如网络实验室、扫码实验室等一系列真实实验室的能力。 经历了几年的不断发展,终端实验室逐步完成了中台化的转变,其端上覆盖了 Android、iOS 以及 IoT 设备,服务上覆盖了通用能力、小程序准入、研发流程建设、真机租用以及用例管控等。 2. 技术生态在了解完终端实验室的历程之后,我们能够对其提供的服务有一个全面的认识。当我们去总结和分析这些服务时,可以把这些具体能力分为三大块:平台服务能力、客户端SDK 以及 实验室能力。 平台服务能力平台服务能力的目标是聚焦“如何把蚂蚁实验室构建成一个更为开放的平台”,因此我们需要考虑到如何让更多的业务方和上游系统一起参与能力共建,从而将平台的建设思路分为 2 大部分:设备实验集群和开放SDK。 1. 设备集群 蚂蚁实验室不仅包含数以千计的公用终端设备,覆盖市面绝大多数手机终端,帮助业务同学完成日常自动化测试工作,而且提供了用户自建实验室的方式:用户只需要根据自身业务场景特性进行设备采购、实验室部署,便具备在自有平台上运行自有设备的能力。 从平台的开放性与部署动态化角度看,目前设备集群能保证设备归属和业务场景做到充分隔离,保证各业务在平台使用上能相互独立。另外,面对阿里巴巴集团众多研发中心,设备集群在部署上也支持多地部署、相互隔离。 2. 开放SDK 为了给上游系统和用户提供更为开放的能力,帮助业务方根据自身需求完成能力建设。终端实验室提供开放的 SDK 能力:上游系统只需在自己服务上接入 SDK,就能够完成任务构建链路,从用例管理、设备选择、任务执行,到执行结果回调,在此基础上用户就能够根据自身业务特点将业务数据进行多维度组合,形成自己的能力输出。 ...

June 5, 2019 · 1 min · jiezi

阿里PB级Kubernetes日志平台建设实践

摘要: 将在QCon上分享的《阿里PB级Kubernetes日志平台建设实践》整理出来,分享给大家。阿里PB级Kubernetes日志平台建设实践QCon是由InfoQ主办的综合性技术盛会,每年在伦敦、北京、纽约、圣保罗、上海、旧金山召开。有幸参加这次QCon10周年大会,作为分享嘉宾在刘宇老师的运维专场发表了《阿里PB级Kubernetes日志平台建设实践》,现将PPT和文字稿整理下来,希望和更多的爱好者分享。 计算形态的发展与日志系统的演进 在阿里的十多年中,日志系统伴随着计算形态的发展在不断演进,大致分为3个主要阶段: 在单机时代,几乎所有的应用都是单机部署,当服务压力增大时,只能切换更高规格的IBM小型机。日志作为应用系统的一部分,主要用作程序Debug,通常结合grep等Linux常见的文本命令进行分析。随着单机系统成为制约阿里业务发展的瓶颈,为了真正的Scale out,飞天项目启动:2009年开始了飞天的第一行代码,2013年飞天5K项目正式上线。在这个阶段各个业务开始了分布式改造,服务之间的调用也从本地变为分布式,为了更好的管理、调试、分析分布式应用,我们开发了Trace(分布式链路追踪)系统、各式各样的监控系统,这些系统的统一特点是将所有的日志(包括Metric等)进行集中化的存储。为了支持更快的开发、迭代效率,近年来我们开始了容器化改造,并开始了拥抱Kubernetes生态、业务全量上云、Serverless等工作。要实现这些改造,一个非常重要的部分是可观察性的工作,而日志是作为分析系统运行过程的最佳方式。在这阶段,日志无论从规模、种类都呈现爆炸式的增长,对日志进行数字化、智能化分析的需求也越来越高,因此统一的日志平台应运而生。日志平台的重要性与建设目标 日志不仅仅是服务器、容器、应用的Debug日志,也包括各类访问日志、中间件日志、用户点击、IoT/移动端日志、数据库Binlog等等。这些日志随着时效性的不同而应用在不同的场景: 准实时级别:这类日志主要用于准实时(秒级延迟)的线上监控、日志查看、运维数据支撑、问题诊断等场景,最近两年也出现了准实时的业务洞察,也是基于这类准实时的日志实现。小时/天级别:当数据积累到小时/天级别的时候,这时一些T+1的分析工作就可以开始了,例如用户留存分析、广告投放效果分析、反欺诈、运营监测、用户行为分析等。季度/年级别:在阿里,数据是我们最重要的资产,因此非常多的日志都是保存一年以上或永久保存,这类日志主要用于归档、审计、攻击溯源、业务走势分析、数据挖掘等。在阿里,几乎所有的业务角色都会涉及到各式各样的日志数据,为了支撑各类应用场景,我们开发了非常多的工具和功能:日志实时分析、链路追踪、监控、数据清洗、流计算、离线计算、BI系统、审计系统等等。其中很多系统都非常成熟,日志平台主要专注于智能分析、监控等实时的场景,其他功能通常打通的形式支持。 阿里日志平台现状 目前阿里的日志平台覆盖几乎所有的产品线和产品,同时我们的产品也在云上对外提供服务,已经服务了上万家的企业。每天写入流量16PB以上,对应日志行数40万亿+条,采集客户端200万,服务数千Kubernetes集群,是国内最大的日志平台之一。    为何选择自建                       日志系统存在了十多年,目前也有非常多的开源的方案,例如最典型的ELK(Elastic Search、Logstash、Kibana),通常一个日志系统具备以下功能:日志收集/解析、查询与检索、日志分析、可视化/告警等,这些功能通过开源软件的组合都可以实现,但最终我们选择自建,主要有几下几点考虑: 数据规模:这些开源日志系统可以很好的支持小规模的场景,但很难支持阿里这种超大规模(PB级)的场景。资源消耗:我们拥有百万规模的服务器/容器,同时日志平台的集群规模也很大,我们需要减少对于采集以及平台自身的资源消耗。多租户隔离:开源软件搭建的系统大部分都不是为了多租户而设计的,当非常多的业务 / 系统使用日志平台时,很容易因为部分用户的大流量 / 不恰当使用而导致打爆整个集群。运维复杂度:在阿里内部有一套非常完整的服务部署和管理系统,基于内部组件实现会具备非常好的运维复杂度。高级分析需求:日志系统的功能几乎全部来源与对应的场景需求,有很多特殊场景的高级分析需求开源软件没办法很好的支持,例如:上下文、智能分析、日志类特殊分析函数等等。 Kubernetes日志平台建设难点围绕着Kubernetes场景的需求,日志平台建设的难点主要有以下几点: 日志采集:采集在Kubernetes中极其关键和复杂,主要因为Kubernetes是一个高度复杂的场景,K8s中有各式各样的子系统,上层业务支持各种语言和框架,同时日志采集需要尽可能的和Kubernetes系统打通,用K8的形式来完成数据采集。资源消耗:在K8s中,服务通常都会拆的很小,因此数据采集对于服务自身的资源消耗要尽可能的少。这里我们简单的做一个计算,假设有100W个服务实例,没个采集Agent减少1M的内存、1%的CPU开销,那整体会减少1TB的内存和10000个CPU核心。运维代价:运维一套日志平台的代价相当之大,因此我们不希望每个用户搭建一个Kubernetes集群时还需再运维一个独立的日志平台系统。因此日志平台一定是要SaaS化的,应用方/用户只需要简单的操作Web页面就能完成数据采集、分析的一整套流程。便捷使用:日志系统最核心的功能是问题排查,问题排查的速度直接决定了工作效率、损失大小,在K8s场景中,更需要一套高性能、智能分析的功能来帮助用户快速定位问题,同时提供一系列简单有效的可视化手段进行辅助。阿里PB级Kubernetes日志平台建设实践Kubernetes日志数据采集 无论是在ITOM还是在未来的AIOps场景中,日志获取都是其中必不可少的一个部分,数据源直接决定了后续应用的形态和功能。在十多年中,我们积累了一套物理机、虚拟机的日志采集经验,但在Kubernetes中不能完全适用,这里我们以问题的形式展开: 问题1:DaemonSet or Sidecar 日志最主要的采集工具是Agent,在Kubernetes场景下,通常会分为两种采集方式: DaemonSet方式:在K8S的每个node上部署日志agent,由agent采集所有容器的日志到服务端。Sidecar方式:一个POD中运行一个sidecar的日志agent容器,用于采集该POD主容器产生的日志。每种采集方式都有其对应的优缺点,这里简单总结如下: DaemonSet方式Sidecar方式采集日志类型标准输出+部分文件文件部署运维一般,需维护DaemonSet较高,每个需要采集日志的POD都需要部署sidecar容器日志分类存储一般,可通过容器/路径等映射每个POD可单独配置,灵活性高多租户隔离一般,只能通过配置间隔离强,通过容器进行隔离,可单独分配资源支持集群规模中小型规模,业务数最多支持百级别无限制资源占用较低,每个节点运行一个容器较高,每个POD运行一个容器查询便捷性较高,可进行自定义的查询、统计高,可根据业务特点进行定制可定制性低高,每个POD单独配置适用场景功能单一型的集群大型、混合型、PAAS型集群在阿里内部,对于大型的PAAS集群,主要使用Sidecar方式采集数据,相对隔离性、灵活性最好;而对与功能比较单一(部门内部/产品自建)的集群,基本都采用DaemonSet的方式,资源占用最低。 问题2:如何降低资源消耗 我们数据采集Agent使用的是自研的Logtail,Logtail用C++/Go编写,相对开源Agent在资源消耗上具有非常大的优势,但我们还一直在压榨数据采集的资源消耗,尤其在容器场景。通常,为了提高打日志和采集的性能,我们都使用本地SSD盘作为日志盘。这里我们可以做个简答的计算:假设每个容器挂载1GB的SSD盘,1个物理机运行40个容器,那每台物理机需要40GB的SSD作为日志存储,那5W物理机则会占用2PB的SSD盘。为了降低这部分资源消耗,我们和蚂蚁金服团队的同学们一起开发了FUSE的日志采集方式,使用FUSE(Filesystem in Userspace,用户态文件系统)虚拟化出日志盘,应用直接将日志写入到虚拟的日志盘中,最终数据将直接从内存中被Logtail采集到服务端。这种采集的好处有: 物理机无需为容器提供日志盘,真正实现日志无盘化。应用程序视角看到的还是普通的文件系统,无需做任何额外改造。数据采集绕过磁盘,直接从内存中将数据采集到服务端。所有的数据都存在服务端,服务端支持横向扩展,对于应用来说他们看到的日志盘具有无线存储空间。问题3:如何与Kubernetes无缝集成 Kubernetes一个非常大的突破是使用声明式的API来完成服务部署、集群管理等工作。但在K8s集群环境下,业务应用/服务/组件的持续集成和自动发布已经成为常态,使用控制台或SDK操作采集配置的方式很难与各类CI、编排框架集成,导致业务应用发布后用户只能通过控制台手动配置的方式部署与之对应的日志采集配置。因此我们基于Kubernetes的CRD(CustomResourceDefinition)扩展实现了采集配置的Operator,用户可以直接使用K8s API、Yaml、kubectl、Helm等方式直接配置采集方式,真正把日志采集融入到Kubernetes系统中,实现无缝集成。 问题4:如何管理百万级Logtail 对于人才管理有个经典的原则:10个人要用心良苦,100个人要杀伐果断,1000个人要甩手掌柜。而同样对于Logtail这款日志采集Agent的管理也是如此,这里我们分为3个主要过程: 百规模:在好几年前,Logtail刚开始部署时,也就在几百台物理机上运行,这个时期的Logtail和其他主流的Agent一样,主要完成数据采集的功能,主要流程为数据输入、处理、聚合、发送,这个时期的管理基本靠手,采集出现问题的时候人工登录机器去看问题。万规模:当越来越多的应用方接入,每台机器上可能会有多个应用方采集不同类型的数据,手动配置的接入过程也越来越难以维护。因此我们重点在多租户隔离以及中心化的配置管理,同时增加了很多控制相关的手段,比如限流、降级等。百万规模:当部署量打到百万级别的时候,异常发生已经成为常态,我们更需要的是靠一系列的监控、可靠性保证机制、自动化的运维管理工具,让这些机制、工具来自动完成Agent安装、监控、自恢复等一系列工作,真正做到甩手掌柜。Kubernetes日志平台架构 上图是阿里Kubernetes日志平台的整体架构,从底到上分为日志接入层、平台核心层以及方案整合层: 平台提供了非常多的手段用来接入各种类型的日志数据。不仅仅只有Kubernetes中的日志,同时还包括和Kubernetes业务相关的所有日志,例如移动端日志、Web端应用点击日志、IoT日志等等。所有数据支持主动Push、被动Agent采集,Agent不仅支持我们自研的Logtail,也支持使用开源Agent(Logstash、Fluentd、Filebeats等)。日志首先会到达平台提供的实时队列中,类似于Kafka的consumer group,我们提供实时数据订阅的功能,用户可以基于该功能实现ETL的相关需求。平台最核心的功能包括: 实时搜索:类似于搜索引擎的方式,支持从所有日志中根据关键词查找,支持超大规模(PB级)。实时分析:基于SQL92语法提供交互式的日志分析方法。机器学习:提供时序预测、时序聚类、根因分析、日志聚合等智能分析方法。流计算:对接各类流计算引擎,例如:Flink、Spark Stream、Storm等。离线分析:对接离线分析引擎,例如Hadoop、Max Compute等。基于全方位的数据源以及平台提供的核心功能,并结合Kubernetes日志特点以及应用场景,向上构建Kubernetes日志的通用解决方案,例如:审计日志、Ingress日志分析、ServiceMesh日志等等。同时对于有特定需求的应用方/用户,可直接基于平台提供的OpenAPI构建上层方案,例如Trace系统、性能分析系统等。下面我们从问题排查的角度来具体展开平台提供的核心功能。 PB级日志查询 排查问题的最佳手段是查日志,大部分人脑海中最先想到的是用 grep 命令查找日志中的一些关键错误信息, grep 是Linux程序员最受欢迎的命令之一,对于简单的问题排查场景也非常实用。如果应用部署在多台机器,那还会配合使用pgm、pssh等命令。然而这些命令对于Kubernetes这种动态、大规模的场景并不适用,主要问题有: 查询不够灵活,grep命令很难实现各种逻辑条件的组合。grep是针对纯文本的分析手段,很难将日志格式化成对应的类型,例如Long、Double甚至JSON类型。grep命令的前提条件是日志存储在磁盘上。而在Kubernetes中,应用的本地日志空间都很小,并且服务也会动态的迁移、伸缩,本地的数据源很可能会不存在。grep是典型的全量扫描方式,如果数据量在1GB以内,查询时间还可以接受,但当数据量上升到TB甚至PB时,必须依赖搜索引擎的技术才能工作。我们在2009年开始在飞天平台研发过程中,为够解决大规模(例如5000台)下的研发效率、问题诊断等问题,开始研支持超大规模的日志查询平台,其中最主要的目标是“快”,对于几十亿的数据也能够轻松在秒级完成。 日志上下文 当我们通过查询的方式定位到关键的日志后,需要分析当时系统的行为,并还原出当时的现场情况。而现场其实就是当时的日志上下文,例如: 一个错误,同一个日志文件中的前后数据一行LogAppender中输出,同一个进程顺序输出到日志模块前后顺序一次请求,同一个Session组合一次跨服务请求,同一个TraceId组合在Kubernetes的场景中,每个容器的标准输出(stdout)、文件都有对应的组合方式构成一个上下文分区,例如Namesapce+Pod+ContainerID+FileName/Stdout。为支持上下文,我们在采集协议中对每个最小区分单元会带上一个全局唯一并且单调递增的游标,这个游标对单机日志、Docker、K8S以及移动端SDK、Log4J/LogBack等输出中有不一样的形式。 为日志而生的分析引擎 ...

May 30, 2019 · 1 min · jiezi

把握数据库发展趋势-DBA应如何避免踩坑

摘要:在DTCC 2019大会上,阿里云智能数据库产品事业部高级产品专家萧少聪做了题为《如何构建云时代DBA的知识体系》的演讲,进行云时代以后,IT行业各工种的职责都在发生变化,云数据库使得日常DBA管理实现更多的自动化,大大提高日常管理效率,同时也对于企业整体投资产出可以更快获得成效。面对云数据库的发展趋势,DBA应如何避免“踩坑”呢?本文就为大家揭晓答案。 专家简介:萧少聪(花名:铁庵),阿里云智能数据库产品事业部高级产品专家,PostgreSQL中国社区常委。 直播回放链接:https://yq.aliyun.com/live/1046 议题PPT下载,戳这里!https://yq.aliyun.com/download/3562 本文将主要围绕以下四个方面进行分享: 管理模式的变化云数据库VS.自建数据库云DBA知识体系构成如何成为优秀的云DBA一、管理模式的变化对于数据库技术而言,“云”已经成为大家无法忽视的技术趋势。在Gartner 2018年的数据库魔力四象限里面,云计算数据库厂商已经占LEADERS及VISIONARIES领域的绝对比例,这也代表了业界对于云的认可。 那么,云和传统架构有什么不同呢?对于传统数据库系统而言,需要搭建很多的硬件,连接很多的网线,在自己搭建的私有云里面可能会有一些虚拟化或者容器化的架构,再往上对于DBA而言其实需要的就是一个数据库,需要能够连接进去进行操作。当然了,在传统架构下,DBA能够对数据库有更多的操作和配置,但是在云上可能只会提供一部分数据库配置文件的修改权限,并不会允许修改全部配置,这是因为云为DBA提供的是SLA,也就是说云数据库提供的是服务。针对于服务而言,不太可能允许DBA去对操作系统进行改变,因为这样可能会破坏HA,因此会有一些限制,但是对于数据库操作而言,依旧是通过一个端口就连接进去的。 除了数据库架构设计之外,传统架构和云架构在做安装配置的时候也会有所不同。在传统架构下,DBA需要去规划数据库所有的一切,包括操作系统、硬件以及各种安装准备以及验收、切换等一系列演练。在云架构之下,整体的配置、安装以及部署是不需要DBA敲各种命令或者安装各种业务系统的,操作系统、参数优化以及整体的HA只需要在云控制台上点击几下就可以配置完成,无论使用阿里的公共云还是私有云都是这样的状态。这些就是在管理模式方面或者在系统创建过程中已经能够看到的变化。 二、云数据库VS.自建数据库有很多人存在这样一个疑问。那就是“云数据库和自建数据库有哪些区别?”。这里首先澄清一个概念,在阿里巴巴看来,真正云托管的数据库才是云数据库,而如果只是使用ECS云服务器来自行搭建的数据库并不算是真正的云数据库。 实际上,云数据库最终提供的是一个服务,其包括了系统的可靠性、可用性、安全、备份等一系列的东西,当建立完云数据库这些都是配置完成的,无需DBA进行二次配置。当然,如果DBA有自己配置的需求,阿里云所提供的云数据库服务也会提供API接口进行调配,或者也可以通过阿里云的管理平台进行操作,而不像传统情况下需要非常高的数据库初始建设费用。 成本模式的变迁 对于成本而言,传统情况下自己建设数据中心需要规划好未来3到5年到底需要多少资源,所以成本是一次性提供的。此外,对于DBA而言,一般将其分为业务DBA和运维DBA,前者为数据库业务解决问题,发挥功用,后者纯粹地负责运维工作,比如安装、部署、定期进行各种类型的巡检。未来,运维DBA会因为云架构的体现慢慢地减少,而业务DBA却不会消亡,因此DBA应该更加关注于企业在做什么业务,数据架构应该如何优化,帮助企业改变本身的运营状态。 以往成本的开支,一下子就是一台服务器,但是如今在云上或者互联网上有很多的创业公司,所谓的“独角兽”就是从很小规模开始起步,突然之间变成很大。当这些创业公司小的时候或许并不需要购买一台服务器,通过云架构,就可以从很小开始,逐渐弹性上去,这样的弹性能力使得IT实现资源的释放。如果今天还在使用传统的数据库服务器购买方式,而竞争对手或许就能够将节省下来的资金用于技术人员或者业务上去,因为没有了固定资产初期的开销,对于创业公司而言,其运行的资金链也会更加健康,发展的速度也会更快。 三、云DBA知识体系构成随着数据库技术的发展,企业对于DBA的需求也不断提高。从对于OLTP这样的SQL数据库和NoSQL数据的掌握,进一步演进,为了解决性能问题可能需要Key-Value缓存数据库,之后建立OLAP数据仓库,再之后实现大数据离线分析。 而对于初创公司而言,就会发现在最开始可能三两台机器就搞定了,只需要一个兼职的DBA。 进一步当开始使用Key-Value缓存数据库之后,业务越来越重,单台服务器无法搞定,需要实现HA。此时就比较困难了,因此需要一个比较神奇的DBA,需要DBA什么都懂。 当企业进一步发展到更大的时候,可能不仅仅需要解决一套系统的问题,可能需要解决多套系统的问题。此时可能需要一个DBA团队,分工会变得更为细致,不仅有专业的DBA,还应该有顶尖的架构级别DBA来解决整体问题。 更进一步,可能需要做数据仓库和大数据,那么整个DBA团队的分工就会更加明细。 在企业的实际运行过程中,DBA需要做大量的工作,有的时候甚至是操作系统的各种细节都需要了解清楚才能将数据库调优好。 云数据库的理论基础 而当进入云数据库时代,需要看到的是另外一种景象。这里有一些云计算的新名词,比如Region地域、AZ可用区、VPC以及VSwith等,这些都是云DBA需要了解和掌握的。从数据库的角度来看,云数据库的确出现了很多新名词,但是数据库基础理论依然是不变的,依然会有实例、高可用、分布式、SQL、ACID和CAP等理论。 运维简化:自动化部署 以往都会说需要部署一个主备集群,而今天如果想要部署主备集群也会在一个IDC中心进行部署。如果想要部署跨IDC的主备集群,在传统架构下往往需要购买光纤、光缆,并且需要确定光纤、光缆的延迟情况,判断其所造成的延迟是否能够接受。而在云数据库架构之下,这些信息都不需要进行管理,所需要管理的就是在购买云数据库时进行选择,比如选择跨中心的主备就可以直接建立起来,因此这种复杂架构的构建并不需要自己来规划,可以节省DBA去做传统底层业务处理的时间。 运维简化:跨地域部署及切换 除了对于传统架构比较容易的同一个城市跨AZ之外,其实如果想要实现跨省就会变得非常复杂了。然而,在云上就会变得非常容易,如果想要实现跨Region的搭建就可以利用阿里云上的DTS工具将数据拉过去,需要进行数据复制的时候才会收费,平时不用的时候甚至可以直接将其关闭掉。 当搭建了跨Region的数据中心之后,后面就会有更多的事情。比如到底敢不敢进行主备切换,以往做主备切换的时候都需要配置一大堆的DNS,自己写很多脚本做确认,而在云架构底下,只需要通过一个按钮就可以实现。因此,大家一定要清楚,作为云DBA应该去学习哪些东西,同时需要放弃哪些东西的学习。因此当有云架构之后,DBA可以将重心放到学习如何优化SQL以及各种不同的数据库特性以及它们之间的组合架构如何解决业务上的问题,而底层的业务架构可以交给云去做。 运维简化:定期全/增量备份 在云上面,如果需要做定期增量备份也仅仅需要点击几个按钮进行构建即可。 运维简化:恢复到时间点 无论针对于哪个数据库,阿里云的服务都可以做到任意时间点的秒级恢复。这一功能并不只是为了帮助用户找回数据,很多用户的DBA和开发的互动越来越频繁,如果开发收到某个时间段系统运行较慢的反馈,就可以直接克隆一个那个时间段的新实例出来,并且只需要按需购买即可,克隆出来实例调试完程序之后直接将其关闭掉即可,一切的成本都在DBA的掌握之中。 运维简化:按需横向扩展 DBA对于数据库的横向扩展也会做很多动作,传统的方式通过只读实例可以做相应的扩展,同时还有像阿里云的DRDS分布式数据库分片的运行方案,也能够比较容易地搭建出来,进一步地还可以走向PolarDB,通过分布式的一写多读来简化业务规则。未来,DBA需要重点关注的点在于什么时候使用什么样的架构。举例而言,如果需要解决某个大促时间段大量的读请求问题,应该通过只读实例来实现。而如果老旧业务完全可以基于互联网改写,就可以选择直接通过DRDS做整个系统的分库分表操作。如果需要非常强的与关系型数据库一致性的业务,并且与此同时数据量非常大,可能需要选择PolarDB的架构,因此DBA需要对于不同的数据库架构以及其背后原理有自己的理解。 运维简化:自动读写分离阿里云数据库帮助用户实现了读写分离,DBA不需要再进行应用程序上的业务改写,比如对于读写分离的设置都可以实现自动化。通过对于请求的分析来判断应该分发到读实例还是写实例。 以上这些都是云数据库能够提供的能力,大家会发现以往的管理模型已经都覆盖到了。未来运维方面的DBA工作可能减轻,因此DBA应该跳到业务方向上进行发展。 四、如何成为优秀的云DBA在云数据库的背景下,DBA是否还需要学习每一部分的数据库管理知识呢?因为人的时间是有限的,未来除非真的要做类似于阿里云的整体管控系统时需要深入底层进行分析,而如果不是,那么这些数据库管理就可以交给云管控平台来实现。但是数据库优化却需要DBA知道和掌握,这里并不是指修改哪些参数能够优化成什么样子,因为这些在云平台上就已经配置好了,但是DBA需要知道的是针对于某个数据库,什么样的索引对它更加有效,表与表之间的关系应该如何建立才能使得数据库性能更好。 云数据库提供了很多的集群架构,也并不一定需要全部学习。无论是单节点、双节点还是三节点,通过阿里云都可以实现一键式部署。因此作为DBA更加需要了解不同的数据库实例之间应该如何进行互动,从而产生对业务有效的架构方案和规划方案,这正是DBA需要深入思考的,而不是每天都在备份服务器,部署数据库,检修各种硬件。 云服务支持边界 基于云的运行环境,云数据库服务和DBA的边界会发生改变。资源调度、基础优化、平台能力以及准确输出都是由云来提供的,而企业的DBA需要做这样几件事情:对于表结构需要花费更多的时间来规划,定义自己企业的SQL标准来规范开发模型,对于SQL以及结构进行优化来提升业务性能。此外,DBA不仅应该关注于数据库,实际上也应该做企业成本的控制,通过不同的数据模型组合来解决不同的业务问题,也需要了解云数据库日志的不同,并通过故障检测自查或者发起服务需求。 性能问题甄别 对于云DBA而言,如果出现了数据库性能问题应该怎么做呢?其实任何的云厂商都会有自己成熟的一整套监控以及性能分析方案,比如阿里云的方案就源自于阿里巴巴内部的经验,能够帮助DBA发现故障并提供解决方案,使用起来非常方便。 云服务支持边界 此外,阿里云也提供了一种能力,就是阿里云后端的DBA会帮助用户解决数据库相关的问题。以往情况下,如果数据库出现了问题,需要打电话给服务商来约时间解决,存在一定的延迟。而今天在阿里云上面,DBA随时可以进入。并且阿里云还提供了安全保障,具有完善的授权机制,只有用户授权阿里云的DBA访问用户数据库或者进行服务的时候,阿里云的DBA才有权限为用户提供服务,而如果没有得到授权,阿里云的DBA是不能够进入的。 高危SQL预防 阿里巴巴具有自己的一整套数据库开发规范,而用户的DBA也可以自己定义一套数据库开发规范,比如可以定义某一个字段是否可以以某种方式编写,这样就从系统设计和规范的层面避免烂SQL进入系统,进而造成系统故障。 跨云管理 今天,阿里云本身在运营云,而其实阿里云也会提供跨云的管理工具。无论用户使用的是哪里的云,只要管理的是MySQL、MongoDB、Redis数据库都会提供HDM工具来协助用户管理跨云数据库。 总结一下,云数据库带来了标准化部署、自动化运维、按需扩容以及工具化调优等优势。对于企业而言,不要再让DBA为部署和备份等琐碎的运维工作所缠绕了,他们应该将精力投入到优化架构、写好SQL以及做好数据库的整体构造上,进而为企业输出核心技术生产力。 本文作者:七幕 阅读原文 ...

May 29, 2019 · 1 min · jiezi

Nacos-Namespace-和-Endpoint-在生产环境下的最佳实践

随着使用 Nacos 的企业越来越多,遇到的最频繁的两个问题就是:如何在我的生产环境正确的来使用 namespace 以及 endpoint。这篇文章主要就是针对这两个问题来聊聊使用 nacos 过程中关于这两个参数配置的最佳实践方式。 namespce关于 namespace ,以下主要从 namespace 的设计背景 和 namespace 的最佳实践 两个方面来讨论。 namespace 的设计背景namespace 的设计是 nacos 基于此做多环境以及多租户数据(配置和服务)隔离的。即: 从一个租户(用户)的角度来看,如果有多套不同的环境,那么这个时候可以根据指定的环境来创建不同的 namespce,以此来实现多环境的隔离。例如,你可能有日常,预发和生产三个不同的环境,那么使用一套 nacos 集群可以分别建以下三个不同的 namespace。如下图所示: 从多个租户(用户)的角度来看,每个租户(用户)可能会有自己的 namespace,每个租户(用户)的配置数据以及注册的服务数据都会归属到自己的 namespace 下,以此来实现多租户间的数据隔离。例如超级管理员分配了三个租户,分别为张三、李四和王五。分配好了之后,各租户用自己的账户名和密码登录后,创建自己的命名空间。如下图所示。 注意: 该功能还在规划中。 namespace 的最佳实践关于 namespace 的最佳实践 ,这部分主要包含有两个 Action: 如何来获取 namespace 的值namespace 参数初始化方式如何来获取 namespace 的值无论您是基于 Spring Cloud 或者 Dubbo 来使用 nacos,都会涉及到 namespace 的参数输入,那么这个时候 namespace 的值从哪里可以获取呢? 如果您在使用过程中没有感知到这个参数的输入,那么 nacos 统一会使用一个默认的 namespace 作为输入,nacos naming 会使用 public 作为默认的参数来初始化,nacos config 会使用一个空字符串作为默认的参数来初始化。。如果您需要自定义自己的 namespace,那么这个值该怎么来产生?可以在 nacos 的控制台左边功能侧看到有一个 命名空间 的功能,点击就可以看到 新建命名空间 的按钮,那么这个时候就可以创建自己的命名空间了。创建成功之后,会生成一个命名空间ID,主要是用来避免命名空间名称有可能会出现重名的情况。因此当您在应用中需要配置指定的 namespace 时,填入的是命名空间ID。重要的事情说三遍, 当您在应用中需要配置指定的 namespace 时,填入的是命名空间 ID当您在应用中需要配置指定的 namespace 时,填入的是命名空间 ID当您在应用中需要配置指定的 namespace 时,填入的是命名空间 ID说明: namesace 为 public 是 nacos 的一个保留控件,如果您需要创建自己的 namespace,最好不要和 public 重名,以一个实际业务场景有具体语义的名字来命名,以免带来字面上不容易区分自己是哪一个 namespace。 ...

May 28, 2019 · 1 min · jiezi

5分钟了解阿里时序时空数据库

简介时序时空数据库(Time Series & Spatial Temporal Database,简称 TSDB)是一种高性能、低成本、稳定可靠的在线时序时空数据库服务,提供高效读写、高压缩比存储、时序数据插值及聚合计算等服务,广泛应用于物联网(IoT)设备监控系统、企业能源管理系统(EMS)、生产安全监控系统和电力检测系统等行业场景;除此以外,还提供时空场景的查询和分析的能力。 三个数据库时序时空数据库文档最近经过几次大的变动,有点乱,看的时候注意一下。 时序数据库TSDB版 经过阿里集团大规模验证的时序数据库,支持分布式集群架构水平扩展,支持千万物联网设备接入,基于自研压缩算法,具备高效压缩比。 - 针对时序数据优化,包括存储模型,多值数据模型,时序数据压缩、聚合、采样,高效压缩算法,列存,边缘一体化;- 具备高性能,内存优先数据处理,分布式MPP SQL并行计算,动态schema,实时流式数据计算引擎,海量时间线自适应索引;- 高可扩展,数据动态分区,水平扩展,动态弹性扩容,动态升降配规格;高可靠性,自动集群控制,线程级读写分离,多层数据备份,分级存储;- 瞄准的是大规模指标数据,事件数据场景协议兼容OpenTSDB,但后面内核实现是阿里自研的。但还是完全可以把它当作OpenTSDB的阿里云版,参见 相比OpenTSDB优势 InfluxDB® 不仅仅是一个数据库,更是一个监控系统,围绕采集,可视化,分析服务,事件和指标存储和计算系统;走的是tick生态,瞄准指标,事件,trace,日志,实时分析场景。 InfluxDB®刚上线不久,现在还处在公测阶段。写入速度经测试,每次500条数据,每秒可以执行26次左右,平均速度达到1万/s,增加每次写入数据条数应该还能提高速度。另外,请求地址是外网,如果使用vpc网络速度应该还会加快不少。 注意:InfluxDB在阿里云上有时间线限制(数据库级别最高1万),时间线的定义参见后面简介。 时空数据库 时空数据库能够存储、管理包括时间序列以及空间地理位置相关的数据。时空数据是一种高维数据,具有时空数据模型、时空索引和时空算子,完全兼容SQL及SQL/MM标准,支持时空数据同业务数据一体化存储、无缝衔接,易于集成使用。 时空数据库主要是空间相关的场景,比如热力图,店铺选址等等。 时序数据库简介(主要是InfluxDB)时序数据库英文全称为 Time Series Database,提供高效存取时序数据和统计分析功能的数据管理系统。主要的时序数据库包括OpenTSDB、Druid、InfluxDB以及Beringei这四个。本人主要了解一点OpenTSDB和InfluxDB,不过时序数据库有很多共性。 基本名词 measurement: tag,field和time列的容器对InfluxDB: measurement在概念上类似于传统DB的table(表格) 从原理上讲更像SQL中表的概念,这和其他很多时序数据库有些不同对其他时序DB: Measurement与Metric等同field(数值列): TSDB For InfluxDB®中不能没有field。注意:field是没有索引的在某种程度上,可以把field理解为k/v表的valuetag(维度列): tag不是必须要有的字段tag是被索引的,这意味着以tag作为过滤条件的查询会更快在某种程度上,可以把field理解为k/v表的keytimestamp(时间戳): 默认使用服务器的本地时间戳时间戳是UNIX时间戳,单位:纳秒最小的有效时间戳是-9223372036854775806或1677-09-21T00:12:43.145224194Z最大的有效时间戳是9223372036854775806或2262-04-11T23:47:16.854775806Zpoint(数据点): 由时间线(series)中包含的field组成。每个数据点由它的时间线和时间戳(timestamp)唯一标识您不能在同一时间线存储多个有相同时间戳的数据点Series(时间线) Series是InfluxDB中最重要的概念,时序数据的时间线就是:一个数据源采集的一个指标随着时间的流逝而源源不断地吐出数据这样形成的一条数据线称之为时间线。 下图中有两个数据源,每个数据源会采集两种指标: Series由Measurement和Tags组合而成,Tags组合用来唯一标识Measurement就是说:1\. Measurement不同,就是不同的时间线2\. Measurement相同,Tags不同也是不同的时间线retention policy(保留策略,简称RP) 一个保留策略描述了: 1.InfluxDB保存数据的时间(DURATION) 2.以及存储在集群中数据的副本数量(REPLICATION) 3.指定ShardGroup Duration注:复本系数(replication factors)不适用于单节点实例。autogen:无限的存储时间并且复制系数设为1RP创建语句如下: CREATE RETENTION POLICY ON <retention_policy_name> ON <database_name>DURATION <duration> REPLICATION <n> [SHARD DURATION <duration> ] [DEFAULT]实例:CREATE RETENTION POLICY "one_day_only" ON "water_database"DURATION 1d REPLICATION 1 SHARD DURATION 1h DEFAULT写入时指定rp进行写入: ...

May 27, 2019 · 2 min · jiezi

虎牙在全球-DNS-秒级生效上的实践

本文整理自虎牙中间件团队在 Nacos Meetup 的现场分享,阿里巴巴中间件受权发布。 这次分享的是全球 DNS 秒级生效在虎牙的实践,以及由此产生的一些思考,整体上,分为以下5各部分: 背景介绍;方案设计和对比;高可用;具体实践和落地;规划;背景介绍虎牙用到的基础技术很多,DNS 是其中比较重要的一个环节。 DNS 的解析过程很关键,例如上图中的 DNS 解析器通过一个定位解析追踪到我们的 DNS,再到本地域名服务器迭代解析,经过根域再到.com名,最后到huya.com的根域名,获取最终的解析结果。 在这个过程中, DNS解析是天然的分布式架构,每一层都会有缓存,上一层出现问题挂掉,下一层都会有缓存进行容灾。另外,整个 DNS 协议支持面广,包括手机和 PC,我们用的编程框架里也有 DNS 解析器,服务器也会配 DNS 解析引擎,因此,DNS 在虎牙的基础设施中是很重要的部分。 虎牙的 DNS 的应用现状虎牙当前主要是依赖于公共的 DNS,相信在座的小伙伴们或多或少都会遇到过下面这些问题: 依赖公共 localDNS,解析不稳定,延迟大。记录变更生效时间长,无法及时屏蔽线路和节点异常对业务的影响。例如,权威 DNS 全球各节点数据同步时间不可控,全局生效时间超过10分钟;localDNS 缓存过期时间不可控,部分 localDNS 不遵循TTL时间,缓存时间超过48小时。内部 DNS 功能缺失,无法解决内部服务调用面临挑战。例如,时延大、解析不准、支持多种调度策略。无法满足国外业务的快速发展,虽然一些海外云厂商提供了基于 DNS 的快速扩容方案,以及基于 DNS 的数据库切换方案。方案设计和对比基于以上的问题,我们开始重新规划 DNS 的设计。 名字服务架构 整个规划会分三个方面,核心是我们做了「名字服务」的中心点,基于此,可以满足我们的需求。 一方面通过 Nacos Sync,将现有多个注册中心的服务, 同步到「名字服务」中, 通过 DNS 实现不同框架之间的 Rest 服务方式的调用, 实现例如 Eureka,Consul,Taf等框架之间的服务调用。 另一方面,在全球负载均衡的场景下,由于虎牙是以音视频业务为主,而音视频业务对节点的延迟是非常敏感的,所以我们希望一旦出现节点延迟的情况,能立马做切换。 第三个是传统 DNS 的场景, 可以满足容器和物理机的 DNS 需求, 提供本机 Agent 和集群两种方案, 通过缓存和 prefect 大大提高 DNS 解析的可用性和加快生效时间。 ...

May 27, 2019 · 3 min · jiezi

阿里开发者招聘节-2019阿里巴巴技术面试题分享20位专家28道题

摘要: 阿里巴巴资深技术专家们结合多年的工作、面试经验总结提炼而成的笔试真题这一次将陆续放出(面试题答案将在专辑分享结束后统一汇总分享)。并通过这些笔试真题开放阿里巴巴工作机会,让更多的开发者加入到阿里这个大平台。为帮助开发者们提升面试技能、有机会入职阿里,云栖社区特别制作了这个专辑——阿里巴巴资深技术专家们结合多年的工作、面试经验总结提炼而成的面试真题这一次将陆续放出(面试题官方参考答案将在专辑结束后统一汇总分享,点此进入答题并围观他人答案)。并通过这些笔试真题开放阿里巴巴工作机会,让更多的开发者加入到阿里这个大平台。 这一次,不仅是知识的收获,还将间接地与技术大牛们做了直观的沟通,了解他们的出题思路与考察要点,并加以消化吸收,这对自己技术能力本身就是一种极大的提升。走上编程之路,不断丰富自己方能与世接轨,努力做最优秀的自己。5月21日,我们给开发者的第28道面试题。 28.请评估一下程序的执行结果?public class SynchronousQueueQuiz { public static void main(String[] args) throws Exception { BlockingQueue<Integer> queue = new SynchronousQueue<>(); System.out.print(queue.offer(1) + " "); System.out.print(queue.offer(2) + " "); System.out.print(queue.offer(3) + " "); System.out.print(queue.take() + " "); System.out.println(queue.size()); }}• A. true true true 1 3• B. true true true (阻塞)• C. false false false null 0• D. false false false (阻塞) 阿里巴巴出题专家:桃谷 阿里云中间件技术专家, Apache Dubbo PMC ,Spring Cloud Alibaba Architect,具有多年分布式以及中间件架构设计及研发经验,目前负责Apache Dubbo的研发及社区生态。  ...

May 27, 2019 · 1 min · jiezi

TalkingData的Spark-On-Kubernetes实践

摘要: 本文整理自talkingdata云架构师徐蓓的分享,介绍了Spark On Kubernetes在TalkingData的实践。众所周知,Spark是一个快速、通用的大规模数据处理平台,和Hadoop的MapReduce计算框架类似。但是相对于MapReduce,Spark凭借其可伸缩、基于内存计算等特点,以及可以直接读写Hadoop上任何格式数据的优势,使批处理更加高效,并有更低的延迟。实际上,Spark已经成为轻量级大数据快速处理的统一平台。Spark作为一个数据计算平台和框架,更多的是关注Spark Application的管理,而底层实际的资源调度和管理更多的是依靠外部平台的支持: Spark官方支持四种Cluster Manager:Spark standalone cluster manager、Mesos、YARN和Kubernetes。由于我们TalkingData是使用Kubernetes作为资源的调度和管理平台,所以Spark On Kubernetes对于我们是最好的解决方案。 如何搭建生产可用的Kubernetes集群部署 目前市面上有很多搭建Kubernetes的方法,比如Scratch、Kubeadm、Minikube或者各种托管方案。因为我们需要简单快速地搭建功能验证集群,所以选择了Kubeadm作为集群的部署工具。部署步骤很简单,在master上执行: kubeadm init在node上执行: kubeadm join --token : --discovery-token-ca-cert-hash sha256:具体配置可见官方文档:https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/。需要注意的是由于国内网络限制,很多镜像无法从k8s.gcr.io获取,我们需要将之替换为第三方提供的镜像,比如:https://hub.docker.com/u/mirrorgooglecontainers/。 网络 Kubernetes网络默认是通过CNI实现,主流的CNI plugin有:Linux Bridge、MACVLAN、Flannel、Calico、Kube-router、Weave Net等。Flannel主要是使用VXLAN tunnel来解决pod间的网络通信,Calico和Kube-router则是使用BGP。由于软VXLAN对宿主机的性能和网络有不小的损耗,BGP则对硬件交换机有一定的要求,且我们的基础网络是VXLAN实现的大二层,所以我们最终选择了MACVLAN。CNI MACVLAN的配置示例如下: { "name": "mynet", "type": "macvlan", "master": "eth0", "ipam": { "type": "host-local", "subnet": "10.0.0.0/17", "rangeStart": "10.0.64.1", "rangeEnd": "10.0.64.126", "gateway": "10.0.127.254", "routes": [ { "dst": "0.0.0.0/0" }, { "dst": "10.0.80.0/24", "gw": "10.0.0.61" } ] }}Pod subnet是10.0.0.0/17,实际pod ip pool是10.0.64.0/20。cluster cidr是10.0.80.0/24。我们使用的IPAM是host-local,规则是在每个Kubernetes node上建立/25的子网,可以提供126个IP。我们还配置了一条到cluster cidr的静态路由10.0.80.0/24,网关是宿主机。这是因为容器在macvlan配置下egress并不会通过宿主机的iptables,这点和Linux Bridge有较大区别。在Linux Bridge模式下,只要指定内核参数net.bridge.bridge-nf-call-iptables = 1,所有进入bridge的流量都会通过宿主机的iptables。经过分析kube-proxy,我们发现可以使用KUBE-FORWARD这个chain来进行pod到service的网络转发: ...

May 23, 2019 · 2 min · jiezi

利用Packer自定义镜像创建容器集群

阿里云容器服务Kubernetes集群支持CentOS操作系统,在绝大多数情况下可以满足客户的要求。但是有些客户由于业务系统对操作系统依赖比较高,希望定制化一些操作系统参数,则可以用自定义镜像来创建Kubernetes集群。 创建自定义操作系统镜像有两种方式,一是在控制台上通过为一台ECS创建快照的方式创建镜像,注意一定要基于阿里云CentOS作为基础镜像,把对操作系统的定制化更新完打成镜像即可。但这种方式的不便之处在于,如果每次对操作系统镜像有更新,则都要手动操作一遍,很难自动化。而且如果是从已有的Kubernetes节点制作镜像,还需要把Docker,Kubelet等清理干净才能制作镜像,步骤繁琐且容易遗漏。 另外一种方式就是本文介绍的用Packer构建镜像。相关的参考文档:使用Packer创建自定义镜像。采用Packer构建镜像的好处是可以把构建方式自动化,构建所需的参数文件中包含了对干净的基础镜像所做的修改,一目了然,并且可以把配置进行版本化管理。后期需要构建新的镜像,只需改变配置重新执行一下Packer构建即可,非常方便,是在生产环境中使用自定义镜像的推荐方式。 那么有没有一个针对容器服务集群的Packer配置模版呢?容器服务团队开源的ack-image-builder就是一个这样的示例项目。下面我们就来一起动手实践一下。 安装Packer可以根据官方文档安装Packer https://www.packer.io/intro/getting-started/install.html 。 创建自定义镜像克隆ack-image-builder项目到本地,可以看到config和scripts目录下是一些示例定制化脚本,读者可以根据自己的需求更新改。 $ git clone https://github.com/AliyunContainerService/ack-image-builder.git$ cd ack-image-builderack-image-builder $ tree.├── LICENSE.txt├── README.md├── ack-centos.json├── config│   └── default.sh└── scripts ├── cleanUpKerneles.sh ├── reboot.sh ├── updateKernel.sh └── verify.sh2 directories, 8 files在ack-centos.json 可以配置在把生成好的自定义镜像存在哪个区(示例中为cn-hangzhou)。 { "variables": { "region": "cn-hangzhou", "image_name": "ack_test_image{{timestamp}}", "source_image": "centos_7_06_64_20G_alibase_20190218.vhd", ... },配置好阿里云账号的AK,然后执行构建命令。 export ALICLOUD_ACCESS_KEY=XXXexport ALICLOUD_SECRET_KEY=XXXpacker build ack-centos.json大约7-8分钟一个新的自定义镜像就构建成功了。可以进入ECS控制台查看新生成的镜像。 利用自定义镜像创建容器集群开通自定义镜像白名单 读者如果需要尝试自定义镜像能力,需要先开工单,申请在容器服务控制台上开通自定义镜像的白名单。 创建容器集群 白名单开通后进入容器服务控制台 https://cs.console.aliyun.com/#/k8s/cluster/list,创建Kubernetes集群。选择自定义镜像所在的区,在示例中是cn-hangzhou。 在创建集群的页面中点击"显示高级选项",会出现"自定义镜像"的选择界面: 如果在选择中找不到刚创建的镜像,请检查一下集群和自定义镜像是否在同一个Region。 选择了自定义镜像后点击创建集群即可完成一个自定义镜像集群的创建。 集群扩容与自动伸缩 使用自定义镜像创建集群后,集群的扩容与自动伸缩中所用的都是自定义镜像。 Terraform 中自定义镜像支持利用Terraform创建容器集群也可以使用自定义镜像,具体参数是: image_id - The ID of node image.相关链接如下: ...

May 16, 2019 · 1 min · jiezi

如何统一管理谷歌GKEAWS-EKS和Oracle-OKE

在Rancher出现之前,管理在不同云提供商中运行的kubernetes集群从来都不是一件容易的事。Rancher是什么?它是一个开源的Kubernetes管理平台,用户可以在Rancher上创建对接不同云的Kubernetes集群,或直接向导入已有的Kubernetes集群进行统一纳管。 在这篇文章中,我将演示如何在Google云、AWS Cloud中启动Kubernetes集群以及如何从Oracle Cloud导入集群。所有这三个集群,最终都将在Rancher Dashboard上拥有直观的视图,并能进行统一管理。本文将逐步展示如何从Rancher创建Kubernetes集群,以及如何通过Rancher Dashboard轻松完成监控和部署。 除了Rancher Kubernetes管理平台之外,Rancher Labs也发布过自己的RKE(Rancher Kubernetes Engine)供用户选择使用。RKE这是一个非常简单、闪电般快速的Kubernetes安装程序,可以在任何地方使用。因此,它消除了在裸机服务器或VM上安装Kubernetes集群的痛苦,并且它还提供了很多自定义的灵活性。 RKE安装 在这一章里我将演示如何在3个VM上安装Rancher Kubernetes集群。首先你需要三台机器来启动RKE集群。我使用的是3个EC2实例与ubuntu18.04,作为启动镜像。所以现在我已经有了一个单独的VM,我将执行这三个节点的所有安装,其中一个将是主节点,另外两个将是工作节点。我已经按照官方文档(https://rancher.com/docs/rke/...)进行了安装,为了让整个工作更简单,我稍微调整了一些步骤。 步骤1:下载RKE二进制文件 wget https://github.com/rancher/rk... 步骤2:mv rke_linux-amd64 rke 步骤3:导出PATH = / home / cloud_user / rke:$ PATH 步骤4:到目前为止,我已经安装了三台安装了docker的ubuntu EC2机器(一定要运行“usermod -aG docker ubuntu”,这样才能让docker可以被ubuntu用户访问)、以及在创建这些实例时我使用的私钥文件。你需要做的是在当前的VM中创建文件,复制密钥的内容,更改密钥权限并尝试登录到你的EC2实例之一。 然后运行以下命令: rke config --name cluster.yml(如果你还没有设置路径,此处则可以使用./rke)。 一旦你按下Enter键,它将开始询问你一些不同的参数值,因为它会根据这些参数值来创建cluster.yml文件。这些参数基本上是你定义的节点特征,rke会自动为你创建cluster.yml。你也可以按照Rancher的文档自行创建。 以上是我传递的参数,并基于它生成了cluster.yml文件。基本上它就是三个节点配置和我默认选择的其他一些与集群相关的配置。 以上是Node基于我们传递的参数在cluster.yml文件中的样子。 现在你已准备好了cluster.yml文件,就可以继续下一步了。 步骤5:运行“rke up”以启动集群(如果你在同一位置有cluster.yml文件的话),或者如果你拥有cluster.yml以外的文件,则可以运行:rke up --config abc.yml 就这样简单!!! 然后你将可以看到集群启动了,并开始显示各种INFO日志,以执行各种工作来启动集群并将节点连接在一起。这也让你可以看到幕后发生的事情,以便你可以感受到集群创建的所有步骤。如果不需要这些,你只需看看我们“成功建立Kubernetes集群”即可。 部分日志 在此之后,rke还会创建一个kubeconfig文件,你可以使用该文件与集群进行交互(在此之前需安装kubectl),名称为“kube_config_cluster_yml”。如果你使用的yml文件用了其他名称,那么它将是'kube_config_test_yml',然后就可以使用这个config文件与集群进行交互了。 设置完成 Rancher安装 现在我将向你展示如何安装Rancher并从Rancher Dashboard创建/导入集群。 我将使用我用于RKE安装的相同VM。 我将在端口80上运行Rancher作为docker容器。 命令:docker run -d --restart=unless-stopped -p 80:80 -p 443:443 rancher/rancher ...

May 16, 2019 · 1 min · jiezi

etcd-在超大规模数据场景下的性能优化

作者 | 阿里云智能事业部高级开发工程师 陈星宇(宇慕)概述etcd是一个开源的分布式的kv存储系统, 最近刚被cncf列为沙箱孵化项目。etcd的应用场景很广,很多地方都用到了它,例如kubernetes就用它作为集群内部存储元信息的账本。本篇文章首先介绍我们优化的背景,为什么我们要进行优化, 之后介绍etcd内部存储系统的工作方式,之后介绍本次具体的实现方式及最后的优化效果。 优化背景由于阿里巴巴内部集群规模大,所以对etcd的数据存储容量有特殊需求,之前的etcd支持的存储大小无法满足要求, 因此我们开发了基于etcd proxy的解决方案,将数据转储到了tair中(可类比redis))。这种方案虽然解决了数据存储容量的问题,但是弊端也是比较明显的,由于proxy需要将数据进行搬移,因此操作的延时比原生存储大了很多。除此之外,由于多了tair这个组件,运维和管理成本较高。因此我们就想到底是什么原因限制了etcd的存储容量,我们是否可以通过技术手段优化解决呢? 提出了如上问题后我们首先进行了压力测试不停地像etcd中注入数据,当etcd存储数据量超过40GB后,经过一次compact(compact是etcd将不需要的历史版本数据删除的操作)后发现put操作的延时激增,很多操作还出现了超时。监控发现boltdb内部spill操作(具体定义见下文)耗时显著增加(从一般的1ms左右激增到了8s)。之后经过反复多次压测都是如此,每次发生compact后,就像世界发生了停止,所有etcd读写操作延时比正常值高了几百倍,根本无法使用。 etcd内部存储工作原理etcd存储层可以看成由两部分组成,一层在内存中的基于btree的索引层,一层基于boltdb的磁盘存储层。这里我们重点介绍底层boltdb层,因为和本次优化相关,其他可参考上文。 etcd中使用boltdb作为最底层持久化kv数据库,boltdb的介绍如下: Bolt was originally a port of LMDB so it is architecturally similar. Both use a B+tree, have ACID semantics with fully serializable transactions, and support lock-free MVCC using a single writer and multiple readers.Bolt is a relatively small code base (<3KLOC) for an embedded, serializable, transactional key/value database so it can be a good starting point for people interested in how databases work。如上介绍,它短小精悍,可以内嵌到其他软件内部,作为数据库使用,例如etcd就内嵌了boltdb作为内部存储k/v数据的引擎。boltdb的内部使用B+ tree作为存储数据的数据结构,叶子节点存放具体的真实存储键值。它将所有数据存放在单个文件中,使用mmap将其映射到内存,进行读取,对数据的修改利用write写入文件。数据存放的基本单位是一个page, 大小默认为4K. 当发生数据删除时,boltdb不直接将删掉的磁盘空间还给系统,而是内部将他先暂时保存,构成一个已经释放的page池,供后续使用,这个所谓的池在boltdb内叫freelist。例子如下: ...

May 15, 2019 · 2 min · jiezi

Nacos-Committer-张龙Nacos-Sync-的设计原理和规划

与你同行,抬头便是星空。 本文整理自Nacos Committer 张龙的现场分享,阿里巴巴中间件受权发布。 随着 Nacos 1.0.0 稳定版的发布,越来越多的企业开始在测试/预演/生产环境中逐步部署 Nacos。目前,除了部分企业已处于转型分布式架构的过程中,会考虑直接使用 Nacos 上生产,但仍有不少企业会考虑一些比较现实的问题: 存量用户如何迁移注册中心到 Nacos?多区域注册中心之间如何同步?已有注册中心与 Nacos 如何并存使用?这里,我将通过对 Nacos Sync 的介绍,来回答这三个问题。 Nacos Sync 是什么?Nacos Sync 是一个支持多种注册中心的同步组件,基于 SpringBoot 开发框架,数据层采用 Spring Data JPA,遵循了标准的 JPA 访问规范,支持多种数据源存储,默认使用 Hibernate 实现,更加方便的支持表的自动创建更新。 下图是 Nacos Sync 系统的概念图,Nacos Sync 通过从各个注册中心拉取注册的服务实例数据同步到 Nacos,左右两边是不同的注册中心,绿色代表目前是可以进行双向同步的,蓝色代表暂时只能进行单向同步。 Nacos Sync 使用了高效的事件异步驱动模型,支持多种自定义事件,使得同步任务处理的延时控制在3s,8C16G的单机能够支持6K的同步任务。 除了单机部署,Nacos Sync 也提供了高可用的集群部署模式,作为无状态设计,支持将任务等状态数据迁移到了数据库,使得集群扩展非常方便。 系统模块架构下图是 Nacos Sync 目前的系统架构图,画的比较简单,只是把一些比较重要的模块做了描述。 Web Console: 提供给用户进行注册中心和同步任务进行相关界面操作 Processor Frame: 注册中心和任务的业务处理逻辑 Timer Manager: 定时轮询数据库获取同步任务进行处理 Event Frame: 异步事件来进行同步任务的同步以及删除 Extension: 对接各种注册中心客户端的扩展实现 整体调用流程我们来看一下 Nacos Sync 一次完整的调用流程: ...

May 13, 2019 · 1 min · jiezi

阿里开发者招聘节-面试题15如何看待异构计算在整个云计算中的位置和作用

摘要: 阿里巴巴资深技术专家们结合多年的工作、面试经验总结提炼而成的笔试真题这一次将陆续放出(面试题答案将在专辑分享结束后统一汇总分享)。并通过这些笔试真题开放阿里巴巴工作机会,让更多的开发者加入到阿里这个大平台。为帮助开发者们提升面试技能、有机会入职阿里,云栖社区特别制作了这个专辑——阿里巴巴资深技术专家们结合多年的工作、面试经验总结提炼而成的面试真题这一次将陆续放出(面试题官方参考答案将在专辑结束后统一汇总分享,点此进入答题并围观他人答案)。并通过这些笔试真题开放阿里巴巴工作机会,让更多的开发者加入到阿里这个大平台。 这一次,不仅是知识的收获,还将间接地与技术大牛们做了直观的沟通,了解他们的出题思路与考察要点,并加以消化吸收,这对自己技术能力本身就是一种极大的提升。走上编程之路,不断丰富自己方能与世接轨,努力做最优秀的自己。 5月10,我们给开发者的第15道面试题。 15.如何看待异构计算在整个云计算中的位置和作用?阿里巴巴出题专家:隐达 FPGA异构计算资深专家,2007年即作为芯片架构师,成功开发两款规模分别超过3500万门的ASIC芯片,达到了当时最先进的45nm工艺的极限。在FPGA/ASIC以及硬件设计领域有超过20年的工作经验,对于超大规模FPGA设计开发、ASIC开发与原型验证以及FPGA在数据中心中的加速价值有着深刻的理解和丰富的经验。 招聘职位:阿里云-GPU虚拟化研发高级专家 本文作者:山哥在这里阅读原文 本文为云栖社区原创内容,未经允许不得转载。

May 13, 2019 · 1 min · jiezi

阿里云Kubernetes服务上从零搭建GitLabJenkinsGitOps应用发布模型的实践全纪录

关于GitOps的介绍,可以参考 GitOps:Kubernetes多集群环境下的高效CICD实践 1. 在 容器服务控制台 创建kubernetes集群1.1 新建Kubernetes集群: 1.2 新建命名空间gitops 我们将会把gitlab和jenkins全部部署到此命名空间下 2. 创建GitLab应用 (可选项,可以对接已有GitLab环境)容器服务控制台上依次点击 市场 -> 应用目录 -> gitlab-ce : 在 参数 中设置externalUrl和gitlabRootPassword后选择gitops命名空间并创建应用,本次实践中 externalUrl 设置为 http://ls-gitlab.example.com/, 如果没有dns解析的话,可以在创建成功后直接使用ip 容器服务控制台上依次点击 路由与负载均衡 -> 服务 查看gitlab应用的访问地址,大约2分钟后可访问gitlab并登陆: 3. 设置GitLab并上传示例源码项目3.1 新建private group application 创建private group application: 3.2 新建并上传private project application-demo 创建private project application-demo, 示例源码地址: https://code.aliyun.com/haoshuwei/application-demo.git 从master新建一个分支latest: 设置master和latest分支只有管理员才能merge和push代码的操作: 3.3 新建private group builds 3.4 新建并上传private project preview-pipeline staging-pipeline production-pipeline preview-pipeline示例源码地址为: https://code.aliyun.com/haoshuwei/preview-pipeline.gitstaging-pipeline示例源码地址为: https://code.aliyun.com/haoshuwei/staging-pipeline.gitproduction-pipeline示例源码地址为: https://code.aliyun.com/haoshuwei/production-pipeline.git上传3个构建项目之前需要替换以下字段:IMAGE_REPO:  应用容器镜像要上传到哪个镜像仓库,镜像仓库地址dingTalkToken: 钉钉通知所使用的钉钉机器人accessTokenFetch Git Repo -> credentialsId : 用于Jenkins拉取git项目的证书名称,需要在Jenkins中创建名为gitlab的证书Fetch Git Repo -> url : Jenkins拉取git repo的url ...

May 9, 2019 · 2 min · jiezi

XPack-Spark归档POLARDB数据做分析

简介POLARDB数据库是阿里云自研的下一代关系型云数据库,100%兼容MySQL,性能最高是MySQL的6倍,但是随着数据量不断增大,面临着单条SQL无法分析出结果的现状。X-Pack Spark为数据库提供分析引擎,旨在打造数据库闭环,借助X-Pack Spark可以将POLARDB数据归档至列式存储Parquet文件,一条SQL完成复杂数据分析,并将分析结果回流到业务库提供查询。本文主要介绍如何使用X-Pack Spark数据工作台对POLARDB数据归档。 业务架构业务需要对多张表出不同纬度,按天、按月的报表并对外提供查询服务;最大表当前500G,数据量还在不断的增加。尝试过spark直接通过jdbc去分析POLARDB,一方面比较慢,另外一方面每次扫全量的POLARDB数据,对在线业务有影响。基于以下几点考虑选择POLARDB+Spark的架构: 选择POLARDB按天增量归档到spark列存,每天增量数据量比较少,选择业务低峰期归档,对在线查询无影响选择Spark作为报表分析引擎,因为Spark很适合做ETL,且内置支持数据回流到POLARDB、MongoDB等多种在线库选择Spark离线数仓作为数据的中转站,对于分析的结果数据回流到在线库提供查询,能够一条Spark SQL完成分析,不需要按维度值拆分多条分析SQL 前置条件1. 设置Spark访问POLARDB白名单 Spark集群和POLARDB需在同一个VPC下才能访问,目前X-Pack Spark上还不支持一键关联POLARDB数据库,需要将Spark集群的IP加到POLARDB白名单中。后续将会开放一键关联POLARDB的功能。在“HBase控制台”->“集群列表”中找到分析Spark实例,在“数据库连接”栏中找到“VSwitch ID”交换机ID,如下图: 然后在“专有网络VPC控制台”->"交换机"搜索交换机实例ID,查询到IPV4网段。 将Spark集群网络加入到POLARDB白名单,进入“控制台”->“集群列表”找到所要关联的POLARDB实例,然后在“基本信息”->“访问信息”->“白名单”加入Spark集群所属网段。 2. 创建测试表 POLARDB中已经存在测试表,如果没有可登录POLARDB数据库创建测试表,下文也以该测试表为例。 CREATE TABLE IF NOT EXISTS test.us_population ( state CHAR(2) NOT NULL PRIMARY KEY, city VARCHAR(10), population INTEGER, dt TIMESTAMP );INSERT INTO test.us_population VALUES('NY','New York',8143197, CURRENT_DATE );INSERT INTO test.us_population VALUES('CA','Los Angeles',3844829, CURRENT_DATE);INSERT INTO test.us_population VALUES('IL','Chicago',2842518, '2019-04-13');INSERT INTO test.us_population VALUES('TX','Houston',2016582, '2019-04-14');INSERT INTO test.us_population VALUES('PA','Philadelphia',1463281, '2019-04-13');INSERT INTO test.us_population VALUES('AZ','Phoenix',1461575, '2019-04-15');INSERT INTO test.us_population VALUES('SA','San Antonio',1256509, CURRENT_DATE);INSERT INTO test.us_population VALUES('SD','San Diego',1255540, CURRENT_DATE);INSERT INTO test.us_population VALUES('DL','Dallas',1213825, '2019-04-15');INSERT INTO test.us_population VALUES('SJ','San Jose',912332,'2019-04-15');一、使用交互式工作台归档数据(调试、测试)创建Spark运行会话 ...

May 7, 2019 · 1 min · jiezi

Redis-radix-tree源码解析

Redis实现了不定长压缩前缀的radix tree,用在集群模式下存储slot对应的的所有key信息。本文将详述在Redis中如何实现radix tree。 核心数据结构raxNode是radix tree的核心数据结构,其结构体如下代码所示: typedef struct raxNode { uint32_t iskey:1; uint32_t isnull:1; uint32_t iscompr:1; uint32_t size:29; unsigned char data[];} raxNode;iskey:表示这个节点是否包含key 0:没有key1:表示从头部到其父节点的路径完整的存储了key,查找的时候按子节点iskey=1来判断key是否存在isnull:是否有存储value值,比如存储元数据就只有key,没有value值。value值也是存储在data中iscompr:是否有前缀压缩,决定了data存储的数据结构size:该节点存储的字符个数data:存储子节点的信息iscompr=0:非压缩模式下,数据格式是:[header strlen=0][abc][a-ptr][b-ptr][c-ptr](value-ptr?),有size个字符,紧跟着是size个指针,指向每个字符对应的下一个节点。size个字符之间互相没有路径联系。iscompr=1:压缩模式下,数据格式是:[header strlen=3][xyz][z-ptr](value-ptr?),只有一个指针,指向下一个节点。size个字符是压缩字符片段Rax Insert以下用几个示例来详解rax tree插入的流程。假设j是遍历已有节点的游标,i是遍历新增节点的游标。 场景一:只插入abcd z-ptr指向的叶子节点iskey=1,使用了压缩前缀。 场景二:在abcd之后插入abcdef 从abcd父节点的每个压缩前缀字符比较,遍历完所有abcd节点后指向了其空子节点,j = 0, i < len(abcded)。查找到abcd的空子节点,直接将ef赋值到子节点上,成为abcd的子节点。ef节点被标记为iskey=1,用来标识abcd这个key。ef节点下再创建一个空子节点,iskey=1来表示abcdef这个key。 场景三:在abcd之后插入ab ab在abcd能找到前两位的前缀,也就是i=len(ab),j < len(abcd)。将abcd分割成ab和cd两个子节点,cd也是一个压缩前缀节点,cd同时被标记为iskey=1,来表示ab这个key。cd下挂着一个空子节点,来标记abcd这个key。 场景四:在abcd之后插入abABC abcABC在abcd中只找到了ab这个前缀,即i < len(abcABC),j < len(abcd)。这个步骤有点复杂,分解一下: step 1:将abcd从ab之后拆分,拆分成ab、c、d 三个节点。step 2:c节点是一个非压缩的节点,c挂在ab子节点上。step 3:d节点只有一个字符,所以也是一个非压缩节点,挂在c子节点上。step 4:将ABC 拆分成了A和BC, A挂在ab子节点上,和c节点属于同一个节点,这样A就和c同属于父节点ab。step 5:将BC作为一个压缩前缀的节点,挂在A子节点下。step 6:d节点和BC节点都挂一个空子节点分别标识abcd和abcABC这两个key。 场景五:在abcd之后插入Aabc abcd和Aabc没有前缀匹配,i = 0,j = 0。将abcd拆分成a、bcd两个节点,a节点是一个非压缩前缀节点。将Aabc拆分成A、abc两个节点,A节点也是一个非压缩前缀节点。将A节点挂在和a相同的父节点上。同上,在bcd和abc这两个节点下挂空子节点来分别表示两个key。 Rax Remove删除 ...

April 30, 2019 · 1 min · jiezi

Sentinel-成为-Spring-Cloud-官方推荐的主流熔断降级方案

近日,Sentinel 贡献的 spring-cloud-circuitbreaker-sentinel  模块正式被Spring Cloud社区合并至 Spring Cloud Circuit Breaker,由此,Sentinel 加入了 Spring Cloud Circuit Breaker 俱乐部,成为 Spring Cloud 官方的主流推荐选择之一。这意味着,Spring Cloud 微服务的开发者在熔断降级领域有了更多的选择,可以更方便地利用 Sentinel 来保障微服务的稳定性。 一、什么是 Spring Cloud Circuit Breaker?Spring Cloud Circuit Breaker是 Spring Cloud 官方的熔断器组件库,提供了一套统一的熔断器抽象API接口,允许开发者自由选择合适的熔断器实现。这个官方的熔断器组件库,截至目前,官方推荐的熔断器组件有: HystrixResilience4JSentinelSpring Retry当前,Spring Cloud Circuit Breaker 处于孵化阶段中,未来将合并到 Spring Cloud 主干版本正式发布。 Spring Cloud Circuit Breaker https://github.com/spring-cloud-incubator/spring-cloud-circuitbreaker 二、Sentinel 发展历程2012 年,Sentinel 诞生于阿里巴巴集团内部,主要功能为入口流量控制; 2013 - 2018 年,Sentinel 在阿里巴巴集团内部迅速发展,成为基础技术模块,覆盖了所有的核心场景。Sentinel 也因此积累了大量的流量控制场景以及生产实践; 2018年7月,阿里巴巴宣布限流降级框架组件 Sentinel 正式开源,在此之前,Sentinel 作为阿里巴巴“大中台、小前台”架构中的基础模块,已经覆盖了阿里的所有核心场景,因此积累了大量的流量归整场景以及生产实践; 2018年9月,Sentinel 发布 v0.2.0版本,释放异步调用支持、热点参数限流等多个重要特性; 2018年10月,Sentinel 发布首个 GA 版本 v1.3.0,该版本包括 Sentinel 控制台功能的完善和一些 bug 修复,以及其它的产品改进; ...

April 29, 2019 · 1 min · jiezi

阿里开发者招聘节-面试题05-关于epoll和select的区别哪些说法是正确的

摘要: 阿里巴巴资深技术专家们结合多年的工作、面试经验总结提炼而成的笔试真题这一次将陆续放出(面试题答案将在专辑分享结束后统一汇总分享)。并通过这些笔试真题开放阿里巴巴工作机会,让更多的开发者加入到阿里这个大平台。为帮助开发者们提升面试技能、有机会入职阿里,云栖社区特别制作了这个专辑——阿里巴巴资深技术专家们结合多年的工作、面试经验总结提炼而成的面试真题这一次将陆续放出(面试题官方参考答案将在专辑结束后统一汇总分享,点此进入答题并围观他人答案)。并通过这些笔试真题开放阿里巴巴工作机会,让更多的开发者加入到阿里这个大平台。 这一次,不仅是知识的收获,还将间接地与技术大牛们做了直观的沟通,了解他们的出题思路与考察要点,并加以消化吸收,这对自己技术能力本身就是一种极大的提升。走上编程之路,不断丰富自己方能与世接轨,努力做最优秀的自己。 4月26日,我们给开发者的第5道面试题。 关于epoll和select的区别,哪些说法是正确的?(多选)A. epoll和select都是I/O多路复用的技术,都可以实现同时监听多个I/O事件的状态
B. epoll相比select效率更高,主要是基于其操作系统支持的I/O事件通知机制,而select是基于轮询机制
C. epoll支持水平触发和边沿触发两种模式
D. select能并行支持I/O比较小,且无法修改 阿里巴巴出题专家:寈峰 阿里技术专家,阿里巴巴百年技术大学讲师,Apache RocketMQ Committer,Linux OpenMessaging Advisory Board Member,具有多年分布式消息系统等中间件架构设计及研发经验,对云计算及分布式系统架构有深刻理解。目前负责Apache RocketMQ的研发及社区生态。 招聘职位:阿里云中间件技术专家 本文作者:山哥在这里阅读原文 本文为云栖社区原创内容,未经允许不得转载。

April 28, 2019 · 1 min · jiezi

阿里开发者招聘节-面试题01如何实现一个高效的单向链表逆序输出

摘要: 阿里巴巴资深技术专家们结合多年的工作、面试经验总结提炼而成的笔试真题这一次将陆续放出(面试题答案将在专辑分享结束后统一汇总分享)。并通过这些笔试真题开放阿里巴巴工作机会,让更多的开发者加入到阿里这个大平台。面试,如同玩一场饥饿游戏:既要对环境了然于胸,又要对自身心知肚明。发现一个好工作不容易,但成功应聘又会面临一系列的挑战。 为帮助开发者们提升面试技能、有机会入职阿里,云栖社区特别制作了这个专辑——阿里巴巴资深技术专家们结合多年的工作、面试经验总结提炼而成的面试真题这一次将陆续放出(面试题官方参考答案将在专辑结束后统一汇总分享,点此进入答题并围观他人答案)。并通过这些笔试真题开放阿里巴巴工作机会,让更多的开发者加入到阿里这个大平台。 这一次,不仅是知识的收获,还将间接地与技术大牛们做了直观的沟通,了解他们的出题思路与考察要点,并加以消化吸收,这对自己技术能力本身就是一种极大的提升。走上编程之路,不断丰富自己方能与世接轨,努力做最优秀的自己。 4月24日,我们给开发者的第1道面试题。 如何实现一个高效的单向链表逆序输出?阿里巴巴出题专家:游亮 阿里云弹性人工智能负责人
,带领团队研发了同时支持Tensorflow、MXNET、PyTorch、Caffe的Perseus加速框架,曾获得Dawnbench推理世界竞赛的性能第一和成本最低双料冠军。曾任阿里云弹性高性能计算、超级计算集群技术架构师,获得过多项专利,拥有10年以上AI技术研发和高性能优化经验。精通针对CPU、GPU、MIC等微架构的计算性能优化以及网络、存储等系统性能优化。曾在英特尔SSG部门工作,并获得过英特尔中国最高成就奖(ICA)。
当人工智能遇上云计算,未来不可限量,欢迎加入阿里云弹性人工智能团队。 招聘职位:阿里云-GPU虚拟化研发高级专家 点击进入聚能聊答题,并围观大家的回答! 更多面试真题陆续放出,敬请期待! 本文作者:山哥在这里阅读原文 本文为云栖社区原创内容,未经允许不得转载。

April 25, 2019 · 1 min · jiezi

选择阿里云数据库HBase版十大理由

根据Gartner的预计,全球非关系型数据库(NoSQL)在2020~2022预计保持在30%左右高速增长,远高于数据库整体市场。 阿里云数据库HBase版也是踏着技术发展的节奏,伴随着NoSQL和大数据技术的兴起和发展,从2010年开始研究和发展。时光荏苒,日月如梭,转眼九年时间,在阿里云上直接开放提供服务也有1年多时间,并在去年的12月份全新发布X-Pack,将单一的HBase演进到一个完整的数据处理平台的能力。我们注意到还有很多同学和客户不清楚HBase X-Pack是什么,什么场景下合适选择HBase X-Pack。 首先我们先来看下HBase X-Pack的定位: HBase X-Pack是基于HBase及HBase生态构建的 低成本一站式数据处理平台。HBase X-Pack支持:HBase API(包括RestServerThriftServer)、关系Phoenix SQL、时序OpenTSDB、全文Solr、时空GeoMesa、图HGraph、分析Spark on HBase,是阿里云首个支持多模式的分布式数据库,且协议100%兼容开源协议。HBase X-Pack实现数据从处理、存储到分析全流程闭环,让客户用最低成本实现一站式数据处理。接下来一起来梳理一下阿里云HBase X-Pack关键能力,一起看看选择阿里云HBase X-Pack的十个理由。 理由一:一体化数据处理平台,提供一站式能力企业数字化转型时代,业务越来越复杂,需要一个平台可以提供一站式处理能力。传统大数据各个组件非常多,各个组件分层发展,给扩展性带来非常大的便利,但同时也引入了非常高的技术门槛,云HBase X-Pack通过集成Spark,Solr,HBase,时序,时空,图等组件,打通各个组件之间的数据同步,通过数据工作台提供统一一体化交互式的操作体验,实现计算、存储、分析、检索、机器学习五位一体的一站式能力,极大的降低了使用门槛,轻松上手,同时提供全托管的服务,避免各种复杂的运维和技术坑。 云HBase X-Pack详细的能力可以访问云HBase的帮助,里面有各个能力详细的介绍: 理由二:深厚的技术积累企业决策选择云服务,最核心的一个因素就是降低TCO,最看重的核心因素就是背后的技术力量,服务能力。阿里云HBase X-Pack经过9年的发展,积累强大的专家团队,目前拥有国际认证7个committer,4个PMC,拥有国内独一无二的技术实力。我们拥有集团超过万台的服务经验,对各种异常场景,数据可靠性,可用性,性能,数据迁移各个方面有全套的服务和工具。 理由三:独家企业版本,以及最新2.0版本阿里云HBase提供的版本是经过、千锤百炼的企业版本,在稳定性和性能上远胜于开源的版本,并且全球首家提供最新2.0版本。关于阿里云HBase发展历程,可以看这里详细介绍:https://yq.aliyun.com/articles/601531。阿里云HBase和开源版本的关键区别,可以查看:https://help.aliyun.com/document_detail/49502.html。 理由四:开发效率最高的数据库Gartner在2017年数据库厂商推荐报告中就明确指出多模是发展趋势阿里云新发布X-Pack更是将多模推上新高度,KV的基础上,同时支持时序、时空、图、文档等多种数据模型。我们知道,大数据时代,业务多样性是大数据的本质之一,强制使用单一模型只会降低生产效率,HBase X-Pack提供KV、SQL、时序、时空、图丰富的多模多模能力,帮助客户可以根据不同的业务选择不同的数据处理模型,支持业务灵活选择,从而实现最高效率的开发和生产。 理由五:做成本最低的数据库HBase诞生于Google的bigtable论文,天然是为了存储海量互联网数据而诞生,低成本能力是其天然的属性。云HBase X-Pack在继承HBase自身能力的同时,为了给客户节省成本做了很多努力。体现在内核,整体方案各个方面,主要有: 云HBase版本的内核是经过优化的,性能平均高出自建版本30%~300%:如果对性能有要求的场景,就可以节省更少的CPU资源,获取更大的效果,具体可以参考https://yq.aliyun.com/articles/198654。齐全的产品形态,满足各种业务场景,提供最高性价比:HBase X-Pack支持单节点,集群版本,跨可用区/跨地域双集群版本,满足用户从测试,生产环境,高可用各种使用环境,平衡能力和成本,提供高性价比的选择,具体可以参考https://help.aliyun.com/document_detail/71538.html。提供数据全生命周期管理功能,数据冷热分离,存储成本下降3.5倍:很多场景里面,数据有冷热的需求,我们提供不同的存储介质,包括OSS,本地盘,云盘,高性能云盘,帮助客户实现最佳的存储成本,详细的可以看下https://yq.aliyun.com/articles/646983。客户基于ECS自建,存储选择云盘,hdfs副本数天然是3副本:HBase服务通过和云盘深度集成2副本就可以同样的性能和可靠性。在存储上天然节省1/3,详细的可以访问https://yq.aliyun.com/articles/646983。全托管服务,提供代维,99.9%的SLA:运维在日常数据库工作中占了很大的比重,而且数据库的稳定性关系到整个系统,牵一发和动全身,云HBase X-Pack提供全托管的服务,给客户节省运维费用,以及极大的避免故障带来的损失。提供一体化的方案节省成本:云HBase X-Pack通过把各个组件深度集成和融合,通过组合各个产品之间的能力,给很多场景带来增效,解决了性能瓶颈的同时,带来成本的下降。这里举2个典型的例子:很多人工智能,多媒体场景,在线教育里面,大量图片、小视频文件。传统的使用方法都是存在OSS里面,OSS天然并发和时延处理能力有限,同时读写都是要收费的,读写次数越多,费用越高,使用HBase X-Pack没有这部分的费用,可以解决性能的瓶颈的同时,带来综合成本的降低。 碰到非结构化数据查询的诉求时,大家一般会想起ES。ES适合文本查询,入库会比较差(一般就几百条/S),查询函数也有限。HBase X-Pack通过支持Solr完全补齐了文本查询的能力。同时Phoneix+solr组合结合了HBase和搜索的两者的优势,在吞吐和并发上有优势。对SQL的易用性也有优势。尤其是在新零售等场景,一张表中混杂结构化字段和非结构化字段,可以根据需求,自动创建索引,融合两者的优势。倒排膨胀率很高,入库会极速下降。大部分客户只是部分字段有模糊查询的需求,ES强制所有的用单一技术。Phoneix非常适合并发高的查询,条件不多。搜索技术补充了索引技术,适合各种条件。通过结合phoneix+solr成功平滑查询和存储性能,提高性能的同时,存储成本也下降几倍,非常适合结构化+非结构化混合的场景。 理由六:力争做最好用的数据处理平台HBase主要提供在线查询能力,沉淀下来的数据需要使用Spark来做复杂分析,HBase X-Pack中的Spark为了让用户更便捷的做数据处理,产品上面提供了以下能力: 1)数据工作台:支持交互式、作业管理、工作流、资源管理、元数据管理,从测试、开发、上线一站式开发体验2)spark内置connector:一键关联hbase、mongo、redis、rds等集群,免去调试的烦恼,更加便捷的分析其他数据库的数据3)支持多语言:可以选择习惯的语言进行编程4)可维护性:支持小版本升级、监控、报警,免去Spark集群维护5)离线数仓能力:一键归档在线库rds、polardb、mongo、hbase、cassandra数据到Spark数仓6)成本:集群默认存储为集群版本HDFS,同时支持数据存储在oss降成本 使用HBase X-Pack Spark能够构建业界成熟的一体化数据处理平台,支撑推荐、风控、离线数仓、实时处理及计算、大数据运营、日志分析、去oracle复杂分析等业务场景: 理由七:数据可靠性作为重中之重对大多数公司来说数据的安全性以及可靠性是非常重要的,如何保障数据的安全以及数据的可靠是大多数数据库必须考虑的。2016 IDC的报告表示数据的备份(data-protection)和数据恢复(retention)是NoSQL的最基础的需求之一,阿里云NoSQL数据库也一直把怎么保障客户的数据安全放在首位。以云HBase为例,传统数据库备份恢复的能力都是TB级别,在交易等场景下面是足够的,但面向大数据场景就捉襟见肘了。云HBase通过垂直整合高压缩、内核级优化等能力,将备份恢复的量级成功推高百倍以上,做到 百TB级别甚至更高 ,让客户在大数据量场景下也无后顾之忧。云HBase支持全量(备份集)备份、全量(备份集)恢复、增量(实时)备份、增量(时间点)恢复完整备份恢复能力。 理由八:单集群3个9高可用,双集群4个9高可用HBase通过内核加固,一系列自动运维修复工具,单集群可以提供3个9的可用性,为了满足很多场景下面更高可用性的要求,云HBase支持跨可用区或者跨地域双集群主备同步,可以让多个HBase集群保持同步关系。在一个集群出现故障的时候,迅速地将业务切换至另外一个集群从而避免故障。HBase主备之间数据的同步基于异步链路实现,遵循最终一致性协议,典型的主备同步延迟在200ms左右。 理由九:大量场景验证,久经考验阿里云HBase从10年上线以来,在阿里集团内部久经考验,超过12000台服务器,单集群超过2000台的规模应用。云HBase自发布以来,通过丰富的能力,优秀的全托管能力,全面超越同类产品的技术能力得到金融、社交、多媒体、新零售、车联网网、制作业、政企等等多个行业,多上千个客户的信赖,积累了大量的使用经验。欢迎我们的新老客户访问首页获取更多的信息: 理由十:提供不停机迁移服务,让自建迁移无忧客户已经使用ECS自建服务,想使用云HBase服务,最担心的应该还是迁移过程中对业务的影响,技术团队充分考虑这一点,提供免费的不停机迁移服务,对在线业务0影响,数据迁移一行不丢。当前业界有能力提供不提供不停机迁移HBase服务的仅此一家。 本文简单梳理了阿里云HBase X-Pack十大理由,希望能对大家理解云HBase有一个帮助,另外也给您选型做一个充分的参考。当能我们还有很多改进的空间,我们还在成长的路上持续努力,也欢迎大家联系我们提出宝贵的意见,最后福利,欢迎使用云HBase X-Pack版本,针对首次购买的用户推出了云数据库HBase单节点独享规格,欢迎大家申请试用:https://promotion.aliyun.com/ntms/act/hbasefree.html 本文作者:所在jason阅读原文 本文为云栖社区原创内容,未经允许不得转载。

April 24, 2019 · 1 min · jiezi

GitOpsKubernetes多集群环境下的高效CICD实践

为了解决传统应用升级缓慢、架构臃肿、不能快速迭代、故障不能快速定位、问题无法快速解决等问题,云原生这一概念横空出世。云原生可以改进应用开发的效率,改变企业的组织结构,甚至会在文化层面上直接影响一个公司的决策,可以说,云时代的云原生应用大势已来。在容器领域内,Kubernetes已经成为了容器编排和管理的社区标准。它通过把应用服务抽象成多种资源类型,比如Deployment、Service等,提供了一个云原生应用通用的可移植模型。在这样的背景下,我们如何在云原生的环境下实践更高效的DevOps来达到更有生产力的表现就成为了一个新的课题和诉求。 与GitOps这个概念相比,大家可能对DevOps的概念已经耳熟能详了。起初DevOps是为了打破开发测试、运营这些部门之间的壁垒,通过自动化的构建、程式化的脚本,最低限度减少人工误差,一定程度上提高应用版本的迭代效率;容器技术出现以后,轻量、标准化的能力使得DevOps技术才有了突飞猛进的发展。不管技术怎样更新迭代,DevOps最主要的核心诉求是不变的,那就是提高应用迭代的频率和降低成本。GitOps就是DevOps的逻辑扩展,它的核心目标是为了更加高效和安全的应用发布。 首先我们提取出一些用户在做devops的过程中遇到的痛点进行分析。第一个问题是如何自动化推进应用在环境栈中的无差别发布.这里我列举了三种环境,测试环境、生产环境和预发环境,对于一个应用来说,我们通常的设定都是把不同分支部署到对应环境,比如master分支的源码对应的是线上环境,latest分支对应的是预发环境,其他开发分支对应地部署到测试环境;目前大多数的做法是创建不同的job,拉取不同的源码分支、部署到不同的环境,或者同一个job,通过添加不同的构建参数来决定进行怎样的构建和发布动作。 非常容易产生混乱和不便于管理。 第二个问题就是,生产环境的发布权限一般都是需要严格控制的,通常只有应用管理员或者运维管理员才有生产发布权限。我们在跟一些客户的交流中发现,一种方式是在同一套cicd环境中创建不同的job,然后通过基于角色访问控制策略来做job的隔离,只有管理员权限的人员才能看到用于发布生产的job; 更直接的一种做法就是再建一套cicd环境专门做生产环境的发布, 但这样既浪费资源又降低了应用迭代的频率。 第三个问题是说我们想要提高应用迭代的频率进而降低人力成本、时间成本、把精力放在新业务或创新业务的拓展上,但目前我们的开发测试人员在应用运行状态或测试结果的同步与反馈上有一定的隔阂,另外一个是线上业务出现问题的时候,如何快速定位、复现和回滚,这是一个我们可以重点思考的地方。以上三点只是我列举出来的我们用户在实际使用cicd的过程中的一些痛点的子集,那接下来我们就带着这些问题来看一下gitops模型的设计思路是怎样的 我们在设计gitosp发布模型的时候是有以下这些核心诉求的:第一个是版本管理,我们希望每一个发布的应用的版本号都能跟git commit id关联,这样的好处就是每一个变更都有历史记录查询、可以更快进行故障定位和修复,第二个是基线管理,这里我们一会儿会讲到分两种类型的基线,第三个是怎么做安全发布,包括发布权限管理以及安全审批的内容;最后一个是如何让开发测试人员快速获取反馈 首先gitops的核心思想就是将应用系统的声明性基础架构和应用程序存放在Git版本库中,所有对应用的操作变更都来源于Git仓库的更新,这也是gitops这个名称的由来。另外一个问题是,按照以往通用的做法,我们可能会把应用如何构建如何部署的脚本以及配置文件跟应用源码本身存放在同一个仓库里,这样带来的问题有两个,一是开发人员可能还需要维护这个部署脚本或配置文件,不能把精力集中到产品开发上,另外一个问题是部署脚本有时候会涉及环境敏感信息,安全性不够,所以我们这里一定要把应用源码仓库与构建仓库分开管理。 接下来就是基线管理,基线管理分两种,一种是环境栈基线,如图所示,我们的设定是,生产环境只能部署master分支的代码,预发环境只能部署latest分支的代码,预览环境用来部署其他开发分支,这里有个名词叫预览环境,其实也就是测试环境,但我们会在开发分支通过测试、通过验证成功合并到latest分支以后动态销毁这个测试环境,当然这在kubernetes容器集群下是非常容器做到的,在其他具体的场景下可以用不同的策略。这个基线我们可以把它称为小基线,它是用来明确管理应用在预览、预发、生产环境中的推进的。大基线是针对线上发布版本的管理的,这能保证我们在线上出现故障的时候能快速回滚到上一个稳定的版本。这在生产发布管理中是必不可少的,在gitops中我们还能快速定位故障精确到某个git commit。 然后是应用发布的权限管理和安全审批,gitops中的权限管理是通过代码合并的控制来做的,在这个模型中,普通的开发人员没有cicd环境比如jenkins的访问权限,更精确地说的话是只有日志查看的权限,在git这一端,普通开发者只有向开发测试分支推送代码的权限,并可以申请向latest分支合并代码,即提交MR/PR的权限,当普通开发者新建MR/PR后,就会触发构建把应用部署到预览环境,管理员通过查看这个新分支的构建部署是否通过一系列测试和验证来决定是否接受这个MR/PR, 只有管理员接受MR/PR的合并后,latest分支代码才会重新构建和部署到预发环境,这样就通过MR/PR的接受和拒绝来达到应用发布安全审批的目的。 最后是如何进行快速反馈和团队成员间的互动,这包括两部分内容:一个是普通开发测试人员在推送源码后,能通过邮件、钉钉、slack等工具实时地获取构建结果,对自己的应用进行高效开发测试,;另一方面是能在MR/PR的页面上查看自动化测试的反馈结果、应用预览链接、其他团队成员的comment等。 下面是使用GitOps管理应用发布到不同kubernetes集群的架构图和时序图。首先是应用源码与构建源码分离。最上面有一条虚线,虚线上面是普通开发者能看到的,或者说是有权限进行操作的部分,剩下其他的部分都是管理员才有权限做的,绿色区域是Jenkins的流水线任务。普通开发者没有Jenkins环境的创建Job和构建Job的权限,他有的只是构建Job的日志查看权限。这个普通应用是在Git仓库里,它有不同的分支,有一定设定的关系,每次有构建的时候会从另外一个Git仓库里做,比如preview-plpeline、prod-plpeline,在这里面可以存放一些信息,只有应用管理员才能看到,普通开发者没有权限看到信息。 然后我们需要设置应用发布环境栈,这在个示例中我们有预览环境、预发环境、生产环境的设置,应用在预发环境和生产环境中的发布是需要经过管理员安全审批的。 最后是一个时序图,开发人员提交新的feature,创建指向latest分支的MR,创建MR的动作会触发preview-plpeline的构建,构建会拉取preview-plpeline的构建仓库,构建仓库存放的是构建脚本以及要部署的环境信息。然后就是自动化的构建流程,首先会从应用源码仓库把应用源码拉取下来做构建,静态代码测试、单元测试,测试结果会反馈到MR上,然后打包容器镜像并把镜像推送到镜像仓库,最后会把应用通过文件部署到Kubernetes的集群里并进行功能测试,测试结果反馈到MR上,部署之后会收集应用相关信息,通过钉钉通知发送到开发群里。开发人员收到钉钉通知,可以直接点击链接查看应用状态,如果有问题,可以返回来自己重新开发,再重新进行提交,把前面的流程再走一遍,没问题就可以请求管理员进行审批,把代码合并到latest分支。latest分支和master分支有更新时,就会触发与前面的构建类似的流程把应用推进到预发环境和生产环境。 本文作者:流生阅读原文 本文为云栖社区原创内容,未经允许不得转载。

April 24, 2019 · 1 min · jiezi

阿里云首次在ASPLOS19发布重磅论文揭秘帮助ECS快速迭代的热升级技术

摘要: 阿里云首次在ASPLOS上发表论文,第24届ACM编程语言和操作系统(ASPLOS'19),于2019年4月13日至17日,在普罗维登斯召开,阿里云高级技术专家郑晓代表团队在会上发表了技术报告。第24届ACM编程语言和操作系统(ASPLOS'19),于2019年4月13日至17日,在普罗维登斯召开,阿里云高级技术专家郑晓代表团队在会上发表了技术报告。 论文主题为《Fast and Scalable VMM Live Upgrade in Large Cloud Infrastructure》,作者是张献涛,郑晓,沈益斌等。这篇论文被计算机系统结构的顶级会议ASPLOS'19接受,是业界对于VMM热升级这项突破性技术的认可。 论文ACM下载地址:https://dl.acm.org/citation.cfm?id=3304034PDF下载地址:https://yq.aliyun.com/download/3532 该论文系统的阐述了当前云计算领域面临的基础架构带业务热升级问题。提出了一种新型的,比热迁移更行之有效的方法,特别适合超大规模集群范围的使用,解决了困扰云计算行业多年的问题。该方案在阿里云大规模采用,服务百万级别的客户虚拟机数量。论文解决了在客户业务不中断的情况下以毫秒级的速度更换底层虚拟化组件。 阿里云热升级技术特点决定了可以同时热升级任意数量任意规格的虚拟机,并且升级时间恒定。更难得的是,在业界尚未有异构计算设备热迁移方案的情况下,阿里云热升级技术同时支持异构计算等以设备直通方式工作的虚拟机。帮助ECS在过去五年进行了快速的升级迭代,保障了产品和业务的快速奔跑。 ASPLOS(编程语言和操作系统的体系结构支持会议)会议全称为ACM International Conference on Architectural Support for Programming Languages and Operating Systems,是综合体系结构、编程语言和操作系统三个方向的计算机系统领域顶级会议,为CCF A类会议。从1982年创办至今的三十多年里,ASPLOS推动了多项计算机系统技术的发展,包括(但不限于)RISC、RAID、大规模多处理器、Cluster架构和网络存储等。 本文作者:阿里云头条阅读原文 本文为云栖社区原创内容,未经允许不得转载。

April 23, 2019 · 1 min · jiezi

主流微服务注册中心浅析和对比

开源产品受开发者热捧,是因为其代码透明、可以参与共建、有社区进行交流和学习,当然更重要的是开源产品的接入成本低。个人开发者或者中小型公司往往会将开源产品作为选型首选。 开发者通过阅读源代码,理解产品的功能设计和架构设计,同时也可以通过本地部署来测试性能,随之而来的是对各类开源产品的对比,用以选型。不过当前关于微服务注册中心的对比,大多聚焦在功能上的对比,对架构或者性能的深入探讨,比较少见。 另一方面,作为默默支持的产品,服务注册中心往往隐藏在服务框架背后。优秀的服务框架往往会支持多种配置中心,但是注册中心的选择依然与服务框架强关联,普遍的情况是一种服务框架会带一个默认的服务注册中心。这样虽然免去了用户在选型上的烦恼,但是单个注册中心的局限性,导致用户使用多个服务框架时,必须部署多套完全不同的注册中心,这些注册中心之间的数据协同是一个问题。 本文来自Nacos社区,作者是 Nacos PMC 朱鹏飞,作者力求公正和客观的去看待主流微服务注册中心的各个维度。本文不仅仅包含常见服务注册中心产品的对比,也试图从Nacos的经验和调研中总结并阐述服务注册中心产品设计上应该去遵循和考虑的要点,文章篇幅较长,若您有不同的看法,欢迎在文末留言,或到Nacos @GitHub 提issue。 前言服务发现是一个古老的话题,当应用开始脱离单机运行和访问时,服务发现就诞生了。目前的网络架构是每个主机都有一个独立的IP地址,那么服务发现基本上都是通过某种方式获取到服务所部署的IP地址。DNS协议是最早将一个网络名称翻译为网络IP的协议,在最初的架构选型中,DNS+LVS+Nginx基本可以满足所有的RESTful服务的发现,此时服务的IP列表通常配置在Nginx或者LVS。后来出现了RPC服务,服务的上下线更加频繁,人们开始寻求一种能够支持动态上下线并且推送IP列表变化的注册中心产品。 ZooKeeper是一款经典的服务注册中心产品(虽然它最初的定位并不在于此),在很长一段时间里,它是国人在提起RPC服务注册中心时心里想到的唯一选择,这很大程度上与Dubbo在中国的普及程度有关。Consul和Eureka都出现于2014年,Consul在设计上把很多分布式服务治理上要用到的功能都包含在内,可以支持服务注册、健康检查、配置管理、Service Mesh等。而Eureka则借着微服务概念的流行,与SpringCloud生态的深度结合,也获取了大量的用户。去年开源的Nacos,则携带着阿里巴巴大规模服务生产经验,试图在服务注册和配置管理这个市场上,提供给用户一个新的选择。 当市面上有多种相似功能的产品出现时,人们往往希望知道这些产品相比较的优劣。产品本身的定位会决定它包含了哪些功能,而产品架构的设计,则会影响产品的性能和可用性等。开源产品的一个优势是开发人员可以去阅读源代码,理解产品的功能设计和架构设计,同时也可以通过本地部署来测试性能,随之而来的是各种产品的对比文章。不过当前关于注册中心的对比,往往停留在表面的功能对比上,对架构或者性能并没有非常深入的探讨。 另一个现象是服务注册中心往往隐藏在服务框架背后,作为默默支持的产品。优秀的服务框架往往会支持多种配置中心,但是注册中心的选择依然强关联与服务框架,一种普遍的情况是一种服务框架会带一个默认的服务注册中心。这样虽然免去了用户在选型上的烦恼,但是单个注册中心的局限性,导致用户使用多个服务框架时,必须部署多套完全不同的注册中心,这些注册中心之间的数据协同也是一个问题。 本文是一篇来自Nacos项目组的文章,虽然是来自Nacos,我们依然力求公正和客观的去看待服务发现所有产品的各个维度。本文不仅仅包含常见服务注册中心产品的对比,还试图从我们的经验和调研中总结和阐述服务注册中心产品设计上应该去遵循和考虑的要点。 数据模型注册中心的核心数据是服务的名字和它对应的网络地址,当服务注册了多个实例时,我们需要对不健康的实例进行过滤或者针对实例的一些特征进行流量的分配,那么就需要在实例上存储一些例如健康状态、权重等属性。随着服务规模的扩大,渐渐的又需要在整个服务级别设定一些权限规则、以及对所有实例都生效的一些开关,于是在服务级别又会设立一些属性。再往后,我们又发现单个服务的实例又会有划分为多个子集的需求,例如一个服务是多机房部署的,那么可能需要对每个机房的实例做不同的配置,这样又需要在服务和实例之间再设定一个数据级别。 Zookeeper没有针对服务发现设计数据模型,它的数据是以一种更加抽象的树形K-V组织的,因此理论上可以存储任何语义的数据。而Eureka或者Consul都是做到了实例级别的数据扩展,这可以满足大部分的场景,不过无法满足大规模和多环境的服务数据存储。Nacos在经过内部多年生产经验后提炼出的数据模型,则是一种服务-集群-实例的三层模型。如上文所说,这样基本可以满足服务在所有场景下的数据存储和管理。 Nacos的数据模型虽然相对复杂,但是它并不强制你使用它里面的所有数据,在大多数场景下,你可以选择忽略这些数据属性,此时可以降维成和Eureka和Consul一样的数据模型。 另外一个需要考虑的是数据的隔离模型,作为一个共享服务型的组件,需要能够在多个用户或者业务方使用的情况下,保证数据的隔离和安全,这在稍微大一点的业务场景中非常常见。另一方面服务注册中心往往会支持云上部署,此时就要求服务注册中心的数据模型能够适配云上的通用模型。Zookeeper、Consul和Eureka在开源层面都没有很明确的针对服务隔离的模型,Nacos则在一开始就考虑到如何让用户能够以多种维度进行数据隔离,同时能够平滑的迁移到阿里云上对应的商业化产品。 Nacos提供了四层的数据逻辑隔离模型,用户账号对应的可能是一个企业或者独立的个体,这个数据一般情况下不会透传到服务注册中心。一个用户账号可以新建多个命名空间,每个命名空间对应一个客户端实例,这个命名空间对应的注册中心物理集群是可以根据规则进行路由的,这样可以让注册中心内部的升级和迁移对用户是无感知的,同时可以根据用户的级别,为用户提供不同服务级别的物理集群。再往下是服务分组和服务名组成的二维服务标识,可以满足接口级别的服务隔离。 Nacos 1.0.0介绍的另外一个新特性是:临时实例和持久化实例。在定义上区分临时实例和持久化实例的关键是健康检查的方式。临时实例使用客户端上报模式,而持久化实例使用服务端反向探测模式。临时实例需要能够自动摘除不健康实例,而且无需持久化存储实例,那么这种实例就适用于类Gossip的协议。右边的持久化实例使用服务端探测的健康检查方式,因为客户端不会上报心跳,那么自然就不能去自动摘除下线的实例。 在大中型的公司里,这两种类型的服务往往都有。一些基础的组件例如数据库、缓存等,这些往往不能上报心跳,这种类型的服务在注册时,就需要作为持久化实例注册。而上层的业务服务,例如微服务或者Dubbo服务,服务的Provider端支持添加汇报心跳的逻辑,此时就可以使用动态服务的注册方式。 数据一致性数据一致性是分布式系统永恒的话题,Paxos协议的艰深更让数据一致性成为程序员大牛们吹水的常见话题。不过从协议层面上看,一致性的选型已经很长时间没有新的成员加入了。目前来看基本可以归为两家:一种是基于Leader的非对等部署的单点写一致性,一种是对等部署的多写一致性。当我们选用服务注册中心的时候,并没有一种协议能够覆盖所有场景,例如当注册的服务节点不会定时发送心跳到注册中心时,强一致协议看起来是唯一的选择,因为无法通过心跳来进行数据的补偿注册,第一次注册就必须保证数据不会丢失。而当客户端会定时发送心跳来汇报健康状态时,第一次的注册的成功率并不是非常关键(当然也很关键,只是相对来说我们容忍数据的少量写失败),因为后续还可以通过心跳再把数据补偿上来,此时Paxos协议的单点瓶颈就会不太划算了,这也是Eureka为什么不采用Paxos协议而采用自定义的Renew机制的原因。 这两种数据一致性协议有各自的使用场景,对服务注册的需求不同,就会导致使用不同的协议。在这里可以发现,Zookeeper在Dubbo体系下表现出的行为,其实采用Eureka的Renew机制更加合适,因为Dubbo服务往Zookeeper注册的就是临时节点,需要定时发心跳到Zookeeper来续约节点,并允许服务下线时,将Zookeeper上相应的节点摘除。Zookeeper使用ZAB协议虽然保证了数据的强一致,但是它的机房容灾能力的缺乏,无法适应一些大型场景。 Nacos因为要支持多种服务类型的注册,并能够具有机房容灾、集群扩展等必不可少的能力,在1.0.0正式支持AP和CP两种一致性协议并存。1.0.0重构了数据的读写和同步逻辑,将与业务相关的CRUD与底层的一致性同步逻辑进行了分层隔离。然后将业务的读写(主要是写,因为读会直接使用业务层的缓存)抽象为Nacos定义的数据类型,调用一致性服务进行数据同步。在决定使用CP还是AP一致性时,使用一个代理,通过可控制的规则进行转发。 目前的一致性协议实现,一个是基于简化的Raft的CP一致性,一个是基于自研协议Distro的AP一致性。Raft协议不必多言,基于Leader进行写入,其CP也并不是严格的,只是能保证一半所见一致,以及数据的丢失概率较小。Distro协议则是参考了内部ConfigServer和开源Eureka,在不借助第三方存储的情况下,实现基本大同小异。Distro重点是做了一些逻辑的优化和性能的调优。 负载均衡负载均衡严格的来说,并不算是传统注册中心的功能。一般来说服务发现的完整流程应该是先从注册中心获取到服务的实例列表,然后再根据自身的需求,来选择其中的部分实例或者按照一定的流量分配机制来访问不同的服务提供者,因此注册中心本身一般不限定服务消费者的访问策略。Eureka、Zookeeper包括Consul,本身都没有去实现可配置及可扩展的负载均衡机制,Eureka的负载均衡是由ribbon来完成的,而Consul则是由Fabio做负载均衡。 在阿里巴巴集团内部,却是使用的相反的思路。服务消费者往往并不关心所访问的服务提供者的负载均衡,它们只关心以最高效和正确的访问服务提供者的服务。而服务提供者,则非常关注自身被访问的流量的调配,这其中的第一个原因是,阿里巴巴集团内部服务访问流量巨大,稍有不慎就会导致流量异常压垮服务提供者的服务。因此服务提供者需要能够完全掌控服务的流量调配,并可以动态调整。 服务端的负载均衡,给服务提供者更强的流量控制权,但是无法满足不同的消费者希望使用不同负载均衡策略的需求。而不同负载均衡策略的场景,确实是存在的。而客户端的负载均衡则提供了这种灵活性,并对用户扩展提供更加友好的支持。但是客户端负载均衡策略如果配置不当,可能会导致服务提供者出现热点,或者压根就拿不到任何服务提供者。 抛开负载均衡到底是在服务提供者实现还是在服务消费者实现,我们看到目前的负载均衡有基于权重、服务提供者负载、响应时间、标签等策略。其中Ribbon设计的客户端负载均衡机制,主要是选择合适现有的IRule、ServerListFilter等接口实现,或者自己继承这些接口,实现自己的过滤逻辑。这里Ribbon采用的是两步负载均衡,第一步是先过滤掉不会采用的服务提供者实例,第二步是在过滤后的服务提供者实例里,实施负载均衡策略。Ribbon内置的几种负载均衡策略功能还是比较强大的,同时又因为允许用户去扩展,这可以说是一种比较好的设计。 基于标签的负载均衡策略可以做到非常灵活,Kubernetes和Fabio都已经将标签运用到了对资源的过滤中,使用标签几乎可以实现任意比例和权重的服务流量调配。但是标签本身需要单独的存储以及读写功能,不管是放在注册中心本身或者对接第三方的CMDB。 在Nacos 0.7.0版本中,我们除了提供基于健康检查和权重的负载均衡方式外,还新提供了基于第三方CMDB的标签负载均衡器,具体可以参考CMDB功能介绍文章。使用基于标签的负载均衡器,目前可以实现同标签优先访问的流量调度策略,实际的应用场景中,可以用来实现服务的就近访问,当您的服务部署在多个地域时,这非常有用。使用这个标签负载均衡器,可以支持非常多的场景,这不是本文要详细介绍的。虽然目前Nacos里支持的标签表达式并不丰富,不过我们会逐步扩展它支持的语法。除此以外,Nacos定义了Selector,作为负载均衡的统一抽象。关于Selector,由于篇幅关系,我们会有单独的文章进行介绍。 理想的负载均衡实现应该是什么样的呢?不同的人会有不同的答案。Nacos试图做的是将服务端负载均衡与客户端负载均衡通过某种机制结合起来,提供用户扩展性,并给予用户充分的自主选择权和轻便的使用方式。负载均衡是一个很大的话题,当我们在关注注册中心提供的负载均衡策略时,需要注意该注册中心是否有我需要的负载均衡方式,使用方式是否复杂。如果没有,那么是否允许我方便的扩展来实现我需求的负载均衡策略。 健康检查Zookeeper和Eureka都实现了一种TTL的机制,就是如果客户端在一定时间内没有向注册中心发送心跳,则会将这个客户端摘除。Eureka做的更好的一点在于它允许在注册服务的时候,自定义检查自身状态的健康检查方法。这在服务实例能够保持心跳上报的场景下,是一种比较好的体验,在Dubbo和SpringCloud这两大体系内,也被培养成用户心智上的默认行为。Nacos也支持这种TTL机制,不过这与ConfigServer在阿里巴巴内部的机制又有一些区别。Nacos目前支持临时实例使用心跳上报方式维持活性,发送心跳的周期默认是5秒,Nacos服务端会在15秒没收到心跳后将实例设置为不健康,在30秒没收到心跳时将这个临时实例摘除。 不过正如前文所说,有一些服务无法上报心跳,但是可以提供一个检测接口,由外部去探测。这样的服务也是广泛存在的,而且以我们的经验,这些服务对服务发现和负载均衡的需求同样强烈。服务端健康检查最常见的方式是TCP端口探测和HTTP接口返回码探测,这两种探测方式因为其协议的通用性可以支持绝大多数的健康检查场景。在其他一些特殊的场景中,可能还需要执行特殊的接口才能判断服务是否可用。例如部署了数据库的主备,数据库的主备可能会在某些情况下切换,需要通过服务名对外提供访问,保证当前访问的库是主库。此时的健康检查接口,可能就是一个检查数据库是否是主库的MYSQL命令了。 客户端健康检查和服务端健康检查有一些不同的关注点。客户端健康检查主要关注客户端上报心跳的方式、服务端摘除不健康客户端的机制。而服务端健康检查,则关注探测客户端的方式、灵敏度及设置客户端健康状态的机制。从实现复杂性来说,服务端探测肯定是要更加复杂的,因为需要服务端根据注册服务配置的健康检查方式,去执行相应的接口,判断相应的返回结果,并做好重试机制和线程池的管理。这与客户端探测,只需要等待心跳,然后刷新TTL是不一样的。同时服务端健康检查无法摘除不健康实例,这意味着只要注册过的服务实例,如果不调用接口主动注销,这些服务实例都需要去维持健康检查的探测任务,而客户端则可以随时摘除不健康实例,减轻服务端的压力。 Nacos既支持客户端的健康检查,也支持服务端的健康检查,同一个服务可以切换健康检查模式。我们认为这种健康检查方式的多样性非常重要,这样可以支持各种类型的服务,让这些服务都可以使用到Nacos的负载均衡能力。Nacos下一步要做的是实现健康检查方式的用户扩展机制,不管是服务端探测还是客户端探测。这样可以支持用户传入一条业务语义的请求,然后由Nacos去执行,做到健康检查的定制。 性能与容量虽然大部分用户用到的性能不高,但是他们仍然希望选用的产品的性能越高越好。影响读写性能的因素很多:一致性协议、机器的配置、集群的规模、存量数据的规模、数据结构及读写逻辑的设计等等。在服务发现的场景中,我们认为读写性能都是非常关键的,但是并非性能越高就越好,因为追求性能往往需要其他方面做出牺牲。Zookeeper在写性能上似乎能达到上万的TPS,这得益于Zookeeper精巧的设计,不过这显然是因为有一系列的前提存在。首先Zookeeper的写逻辑就是进行K-V的写入,内部没有聚合;其次Zookeeper舍弃了服务发现的基本功能如健康检查、友好的查询接口,它在支持这些功能的时候,显然需要增加一些逻辑,甚至弃用现有的数据结构;最后,Paxos协议本身就限制了Zookeeper集群的规模,3、5个节点是不能应对大规模的服务订阅和查询的。 在对容量的评估时,不仅要针对企业现有的服务规模进行评估,也要对未来3到5年的扩展规模进行预测。阿里巴巴的中间件在内部支撑着集团百万级别服务实例,在容量上遇到的挑战可以说不会小于任何互联网公司。这个容量不仅仅意味着整体注册的实例数,也同时包含单个服务的实例数、整体的订阅者的数目以及查询的QPS等。Nacos在内部淘汰Zookeeper和Eureka的过程中,容量是一个非常重要的因素。 Zookeeper的容量,从存储节点数来说,可以达到百万级别。不过如上面所说,这并不代表容量的全部,当大量的实例上下线时,Zookeeper的表现并不稳定,同时在推送机制上的缺陷,会引起客户端的资源占用上升,从而性能急剧下降。 Eureka在服务实例规模在5000左右的时候,就已经出现服务不可用的问题,甚至在压测的过程中,如果并发的线程数过高,就会造成Eureka crash。不过如果服务规模在1000上下,几乎目前所有的注册中心都可以满足。毕竟我们看到Eureka作为SpringCloud的注册中心,在国内也没有看到很广泛的对于容量或者性能的问题报告。 Nacos在开源版本中,服务实例注册的支撑量约为100万,服务的数量可以达到10万以上。在实际的部署环境中,这个数字还会因为机器、网络的配置与JVM参数的不同,可能会有所差别。图9展示了Nacos在使用1.0.0版本进行压力测试后的结果总结,针对容量、并发、扩展性和延时等进行了测试和统计。 完整的测试报告可以参考Nacos官网:https://nacos.io/en-us/docs/nacos-naming-benchmark.htmlhttps://nacos.io/en-us/docs/nacos-config-benchmark.html 易用性易用性也是用户比较关注的一块内容。产品虽然可以在功能特性或者性能上做到非常先进,但是如果用户的使用成本极高,也会让用户望而却步。易用性包括多方面的工作,例如API和客户端的接入是否简单,文档是否齐全易懂,控制台界面是否完善等。对于开源产品来说,还有一块是社区是否活跃。在比较Nacos、Eureka和Zookeeper在易用性上的表现时,我们诚邀社区的用户进行全方位的反馈,因为毕竟在阿里巴巴集团内部,我们对Eureka、Zookeeper的使用场景是有限的。从我们使用的经验和调研来看,Zookeeper的易用性是比较差的,Zookeeper的客户端使用比较复杂,没有针对服务发现的模型设计以及相应的API封装,需要依赖方自己处理。对多语言的支持也不太好,同时没有比较好用的控制台进行运维管理。 Eureka和Nacos相比较Zookeeper而言,已经改善很多,这两个产品有针对服务注册与发现的客户端,也有基于SpringCloud体系的starter,帮助用户以非常低的成本无感知的做到服务注册与发现。同时还暴露标准的HTTP接口,支持多语言和跨平台访问。Eureka和Nacos都提供官方的控制台来查询服务注册情况。不过随着Eureka 2.0宣布停止开发,Eureka在针对用户使用上的优化后续应该不会再有比较大的投入,而Nacos目前依然在建设中,除了目前支持的易用性特性以外,后续还会继续增强控制台的能力,增加控制台登录和权限的管控,监控体系和Metrics的暴露,持续通过官网等渠道完善使用文档,多语言SDK的开发等。 从社区活跃度的角度来看,目前由于Zookeeper和Eureka的存量用户较多,很多教程以及问题排查都可以在社区搜索到,这方面新开源的Nacos还需要随着时间继续沉淀。 集群扩展性集群扩展性和集群容量以及读写性能关系紧密。当使用一个比较小的集群规模就可以支撑远高于现有数量的服务注册及访问时,集群的扩展能力暂时就不会那么重要。从协议的层面上来说,Zookeeper使用的ZAB协议,由于是单点写,在集群扩展性上不具备优势。Eureka在协议上来说理论上可以扩展到很大规模,因为都是点对点的数据同步,但是从我们对Eureka的运维经验来看,Eureka集群在扩容之后,性能上有很大问题。 集群扩展性的另一个方面是多地域部署和容灾的支持。当讲究集群的高可用和稳定性以及网络上的跨地域延迟要求能够在每个地域都部署集群的时候,我们现有的方案有多机房容灾、异地多活、多数据中心等。 首先是双机房容灾,基于Leader写的协议不做改造是无法支持的,这意味着Zookeeper不能在没有人工干预的情况下做到双机房容灾。在单机房断网情况下,使机房内服务可用并不难,难的是如何在断网恢复后做数据聚合,Zookeeper的单点写模式就会有断网恢复后的数据对账问题。Eureka的部署模式天然支持多机房容灾,因为Eureka采用的是纯临时实例的注册模式:不持久化、所有数据都可以通过客户端心跳上报进行补偿。上面说到,临时实例和持久化实例都有它的应用场景,为了能够兼容这两种场景,Nacos支持两种模式的部署,一种是和Eureka一样的AP协议的部署,这种模式只支持临时实例,可以完美替代当前的Zookeeper、Eureka,并支持机房容灾。另一种是支持持久化实例的CP模式,这种情况下不支持双机房容灾。 在谈到异地多活时,很巧的是,很多业务组件的异地多活正是依靠服务注册中心和配置中心来实现的,这其中包含流量的调度和集群的访问规则的修改等。机房容灾是异地多活的一部分,但是要让业务能够在访问服务注册中心时,动态调整访问的集群节点,这需要第三方的组件来做路由。异地多活往往是一个包含所有产品线的总体方案,很难说单个产品是否支持异地多活。 多数据中心其实也算是异地多活的一部分。从单个产品的维度上,Zookeeper和Eureka没有给出官方的多数据中心方案。Nacos基于阿里巴巴内部的使用经验,提供的解决方案是才有Nacos-Sync组件来做数据中心之间的数据同步,这意味着每个数据中心的Nacos集群都会有多个数据中心的全量数据。Nacos-Sync是Nacos生态组件里的重要一环,不仅会承担Nacos集群与Nacos集群之间的数据同步,也会承担Nacos集群与Eureka、Zookeeper、Kubernetes及Consul之间的数据同步。 ...

April 22, 2019 · 1 min · jiezi

你应该知道的 HBase 基础,都在这儿了

阿里妹导读:2006 年10 月Google 发布三架马车之一的《Bigtable:A Distributed Storage System for Strctured Data》论文之后,Powerset 公司就宣布 HBase 在 Hadoop 项目中成立,作为子项目存在。后来,在2010 年左右逐渐成为 Apache 旗下的一个顶级项目。可能是实际应用中包装得太好,很多人对于 HBase 的认识止步于 NoSQL 。今天,蚂蚁金服的南俊从基础开始讲起,希望有助于增强大家在实际业务中对 HBase 的理解。一、 HBase 简介 HBase 名称的由来是由于其作为 Hadoop Database 存在的,用来存储非结构化、半结构化数据。 要想知道 HBase 的用途,就需要看一看其在 Apache 的 Hadoop 生态系统中的位置,可以看到 HBase 是构建在 HDFS 之上的,这是由于 HBase 内部管理的文件全部都是存储在 HDFS 当中的。同时,MapReduce 这个计算框架在 HBase 之上又提供了高性能的计算能力来处理海量数据。此外还有一些像 Pig、Hive 用来提供高层语言的支持。还有 Sqoop 用来完成传统数据库到 HBase 之间的数据迁移。类似衍生出来的新技术还有很多,有兴趣的同学可以自己去了解一下。 Google 的三架马车 BigTable、GFS、MapReduce 现在在开源社区中都能找到对应的实现。HBase 就是 Bigtable 的开源实现,当然这句话不是完全正确,因为两者之间还是有些差异的。但是主要还是基于 BigTable 这个数据模型开发的,因此也是具有 Key-Value 特征的,同时也就具有 Bigtable 稀疏的、面向列的这些特性。 ...

April 22, 2019 · 1 min · jiezi

我眼中的 Redis

引言打开Microsoft To-Do,发现Redis的学习计划还躺在那里。其实我对Redis的理解,仅仅停留在我认识这个单词的层面上。学习简介本来对这个Redis没什么兴趣的,不就是一个缓存的数据库而已吗?直到上次配置spring-redis的时候,发现这个东西没有用户名。spring: redis: host: 127.0.0.1 port: 6379 password:配置如上所示,只有主机、端口和密码,和普通的MySQL或其他数据库不同。Redis是一个使用ANSI C编写的开源、支持网络、基于内存、可选持久性的键值对存储数据库。我们熟知的就是Redis的缓存,Redis采用C编写,运行异常的快。是有磁盘存储支持的内存数据库!适用于数据变化快且数据库大小可遇见(适合内存容量)的应用程序。使用场景:股票价格、数据分析、实时数据搜集、实时通讯。NoSQLRedis属于NoSQL,NoSQL = Not Only SQL。如今数据量越来越大,传统的关系型数据库已经无法应付如此大数据的需求了。举个例子:假设我们使用关系型数据库存储朋友圈,那一天会产生多少数据?再查询的时候数据库不就死了吗?这让我想起了我之前关注的一个帖子:腾讯微信的后台数据库到底是怎么设计的?无知的人相谈甚欢,最后好像是官方的哥们是在看不下去了,回复:谁告诉你们微信用的是关系型数据库?普通关系型数据库,如果只查询的话效率很高?如果算上读写的话?那可能传统的数据库都承受不住高并发。重要的是关系型数据库没法扩展,大家想一想,因为数据之间是有关系的,所以数据库扩展绝对不像扩展后台服务规模一样再拎个服务器出来那么简单。由此可见,在数据量日渐增长的今天,为了解决大数据量与高并发的难题,NoSQL应运而生。NoSQL产品主要有四类:类型特点代表适用场景键值对存储能实现快速查询,但存储的数据缺少结构化Redis内容缓存,主要用于处理大数据的高访问负载列存储数据库查找速度快,可扩展性强,更容易进行分布式扩展,但功能相对局限HBase分布式的文件系统文档数据库数据结构要求不严格,查询性能不高,而且缺乏统一的查询语法MongoDBWeb应用(相较于普通的Key-Value,其Value是结构化的)图形数据库利用图结构相关算法,但需要对整个图做计算才能得出结果,不容易分布式Neo4j社交网络,推荐系统,专注于构建关系图谱这些数据库的名称大家或多或少应该听说过吧?今天才真正知道它们的作用,各有其特长,我们需根据业务场景动态选择。Facebook的消息存储采用的就是HBase数据库,支持大数据进行随机、实时访问。NoSQL因为数据之间都是没有关系的,所以易扩展,同时具有很高的读写性能,很适合高并发场景。历史2008年,意大利的一家创业公司Merzia推出了一款基于MySQL的网站实时统计系统LLOOGG。没过多久,创始人Salvatore Sanfilippo对MySQL的性能大失所望,于是他决定自己写一个数据库。牛人就是牛人,我们就算质疑MySQL的性能,想写也写不出来啊?!2009年,Salvatore Sanfilippo完成了数据库的编写,这就是Redis。Salvatore Sanfilippo将Redis开源,并一直进行着Redis的开发,直到今天。我们熟知的Github、StackOverflow、新浪微博等公司都是Redis的用户。缓存传统的缓存代码需要这样写,很冗长,都是重复的代码。ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();logger.info(“判断Redis中是否有Key”);if (redisTemplate.hasKey(url)) { logger.info(“Redis命中,从Redis中获取”); return valueOperations.get(url);}logger.info(“发起Get请求”);ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);logger.info(“存入缓存”);valueOperations.set(url, response.getBody(), TIME_OUT, TimeUnit.MINUTES);感谢Spring AOP,我们可以使用注解实现缓存功能。@Cacheable(“cacheName”)public List<Student> findAll() { return studentRepository.findAll();}使用注解实现缓存很简单,同时@Cacheable还有许多的高级用法,以后与大家详述。操作Redis有三种动作:GET:根据键查找值。SET:给定键存储值。DEL:删除键中的值。然后就是Redis的数据结构,这个觉得暂时还不需要知道,毕竟现在使用的是现成的@Cacheable注解,还不需要我们手动去操作Redis。一如代码深似海,软件之路很广很远。生命有限的我们不能把所有东西都精通,我们要在学习成本与能力提升之间进行权衡。总结故不积跬步,无以至千里;不积小流,无以成江海。骐骥一跃,不能十步,驽马十驾,功在不舍。

April 20, 2019 · 1 min · jiezi

十年磨一剑,王坚自研的MaxCompute如何解决世界级算力难题

摘要: 2009年这项关于大数据的技术长征开始。王坚带队,目标是自研大数据计算平台MaxCompute统一阿里巴巴内部的数据和大数据计算体系。大数据时代,随着企业数据规模的急剧增长,传统软件已无法承载,这也推动了大数据技术的发展,Google、AWS、微软等硅谷巨头纷纷投入大数据技术的研发;而在国内,王坚也在十年前带领阿里云团队研发MaxCompute,率先在国内开启大数据计算平台的自研之路。十年后,MaxCompute已经可以承载EB级别的数据存储能力、百PB级的单日计算能力,在公共云上已经覆盖了国内外的十几个国家和地区,电商、工业、医疗、农业、气象、教育等诸多行业企业开始采用这项技术,轻松处理海量数据,为社会和消费者提供服务。MaxCompute的自研之路事实上,阿里大数据的发展历程映射出整个大数据行业的发展史。十年前,阿里巴巴比其它公司更早地遇到互联网规模化带来的挑战。当时全球企业的数据库基本都是Oracle,而阿里巴巴拥有亚洲最大的Oracle集群,计算规模达百TB级别。按照当时淘宝用户量的增长速度,Oracle集群很快将无法支撑业务发展,而最核心的问题就是算力不足。尽管当时阿里已开始把数据迁移到更大规模的Greenplum,但后者在百台机器规模时就遇到瓶颈,给业务增长造成极大阻碍。此外,Hadoop之类的开源技术在可靠性、安全性上也遭遇了天花板。2008年,王坚带着解决大规模算力瓶颈的任务加入阿里。他发现,无论是Oracle还是Greenplum、Hadoop,都不是大规模数据计算的最优解,必须自研一套自己的大数据处理平台。2009年这项关于大数据的技术长征开始。王坚带队,目标是自研大数据计算平台MaxCompute统一阿里巴巴内部的数据和大数据计算体系。事实证明,阿里做了正确的选择。四年攻坚,MaxCompute终于取得重大突破:2013年8月15日,阿里云历史性地突破了同一个集群内5000台服务器同时计算的局限,为未来的大规模服务奠定基础。十年后,单集群规模已超过1万台,能做到这一能力的科技公司在全球都寥寥可数。在阿里云云栖小镇,还竖着一尊飞天5K的纪念碑,碑上刻着参与解决这一技术难题的技术人员名字。解决世界级算力难题通过大数据计算平台,可以让订单实时准确汇聚,也可以精准预测变幻莫测的天气变化,各行各业都在大规模使用大数据来提供更好的服务,而实现这一能力就是海量数据分析的结果。 但要处理好这些数据并不容易。除了数据量的剧增,不同行业数据类型丰富多样,如结构化数据、非结构化数据等,都给大数据计算平台带来新的挑战。MaxCompute的创新之处就是采用Datalake技术,把不同的数据源用类似的方式存储,用统一的方法计算,提供一套标准化语言,快速实现不同类型数据的计算。基于这套创新技术,2015、2016年,阿里云刷新世界计算奥运会SortBenchmark的六项世界纪录;2017年,完成全球首次基于公共云的100TB BigBench大数据基准测试。如何快速“查询”也是大数据计算的核心之一。MaxCompute采用“交互式查询”来解决海量数据查询慢的瓶颈,通俗地说就是系统可以预判用户将会做哪些查询,提前准备,大大降低大规模数据查询的时间。此外,MaxCompute提出多租户云安全隔离技术,突破传统大数据平台的安全局限,将安全边界细化到用户、进程、内核级别,完全满足金融级的安全需求。顶级算力走向世界过去十年,MaxCompute能力不断提升:单日数据处理量从2015年100PB,2016年180PB,到2017年320PB,再到2018年的单日处理超过600PB。记录被不断刷新,并且得到了权威机构的认可:在Forrester发布的《The Forrester WaveTM: CloudData Warehouse, Q4 2018》中,阿里云MaxCompute、DataWorks、ADB等三款产品成功入选,并在产品功能(Current Offering)方面力压微软。这一世界级的大数据计算能力也逐渐展示其价值,帮助数万企业用更低成本、更高效率计算海量数据,为社会和消费者提供服务。在生活领域,墨迹天气开始通过MaxCompute为4亿用户提供气象预报服务,每天的用户查询超过5亿次。不仅如此,它们的存储和计算成本还令人意外地降低70%。在交通领域,城市大脑在杭州实时指挥1300个红绿灯路口、200多名交警。从2016年到2018年,杭州从全国最拥堵城市排行榜上下跌52名。在工业领域,阿里云的大数据处理技术帮助制造企业寻找上千个参数的最优搭配,提升制造的良品率。协鑫光伏、天合光能等行业龙头企业,都在尝试这一全新的生产模式。在政务领域,浙江最多跑一次通过大数据处理平台打通政务数据,将与老百姓办事最密切相关的100个事项70多亿条数据,按照统一标准汇入统一的数据仓,实现共通共享共用。老百姓办事不仅能最多跑一次,甚至有可能一次都不跑。而在海外,MaxCompute也已进入新加坡、欧洲等市场,将这一技术对外赋能给更多用户。从线上到线下,从生产制造到互联网电商,从国内到海外,MaxCompute的计算能力正在延伸到各行各业,极大地降低了社会的计算成本。MaxCompute产品官网 https://www.aliyun.com/product/odps本文作者:晋恒阅读原文本文为云栖社区原创内容,未经允许不得转载。

April 12, 2019 · 1 min · jiezi

如何免费创建云端爬虫集群

移步 GitHub

April 4, 2019 · 1 min · jiezi

寻找 K8s 1.14 Release 里的“蚌中之珠”

摘要: K8s 1.14 发布了,Release Note那么长,我们该从何读起?本文由张磊、心贵、临石、徙远、衷源、浔鸣等同学联合撰写。Kubernetes 1.14.0 Release 已经于3月25日正式发布。相信你也已经注意到,相比于1.13 和 1.12 版本,这次发布包含的重要变更非常多,其对应的 Release Note 的篇幅长度也创下了“新高”。面对这样一份“海量信息”的 Release Note,我们该如何从这份文档里进行高效的信息过滤和挖掘,帮助团队更精准、快速的梳理出这次发布最主要的技术脉络呢?在本篇文章中,我们将 1.14 的Release Note 按照主题进行了重新归纳和梳理,按照类别对重要变更进行了技术剖析和讨论。希望这种“分类解读”的方式,能够帮助大家更好的理解 1.14 这个发布的核心内容。Windows Node 正式生产可用随着1.14的发布,Kubernetes 对windows节点的生产级支持无疑是一个重要的里程碑。具体来说,1.14 版本针对 Windows 做了大量增强;Pod:Pod内支持readiness和liveness探针;支持进程隔离和volume共享的多容器Pod;Pod支持原生configmap和sercret;Pod支持emptyDir;支持对Pod进行资源配额等;但是像优雅删除、Termination message、Privileged Containers、HugePages、Pod驱逐策略等部分特性还未在1.14版本提供;Service:支持服务环境变量提供DNS解析;支持NodePort、ClusterIP、LoadBalancer、Headless service;暂不支持Pod的hostnetwork模式;常规 Workload controller:RS、deployment、statefulset、daemonset、job、cronjob均支持windows容器;除此之外,支持Pod和container维度的metrics、HPA、“kubectl exec”、调度抢占、resource quotas、CNI 网络支持等多种特性让windows workload更加云原生;由于windows的特殊兼容性,目前 host OS的版本必须和容器镜像OS版本一致,1.14版本支持win server 2019;未来版本中会考虑使用Hyper-V隔离机制来解决版本兼容性问题。而伴随着 Windows 容器的生态正在慢慢壮大,能够在生产级别支持 Windows 节点的容器服务开始见诸各大云厂商。阿里云容器服务(ACK)近期已经推出了 Windows Container 的支持,提供了linux/windows应用混合部署的统一管理能力。参见:Support for Windows Nodes is Graduating to Stable (#116 )本地持久化数据卷(Local PV) 正式可用长期以来,能够让 Kubernetes 直接用宿主机的本地存储设备(比如:本地 SSD 硬盘)来提供持久化数据卷(即:Local PV 功能),一直是社区里非常强烈的一个诉求。这个原因很容易理解:相对于远程存储(网络存储),Local PV 在时延性、易用性、稳定性和费用上具有独特的优势,尤其是对于相关特性比较敏感的应用,如数据库应用和搜索引擎应用来说,有着重要的意义。而在 1.14 中,Local PV 终于正式宣布 GA,为云上的持久化存储选择增加了一种重要的的可能。不过,必须要明确的是, 选择使用 Local PV,也意味着用户必须自己承担一些潜在的风险,这包括:目前社区的开源方案无法动态创建卷调度器需要由额外的调度逻辑工作,以确保调度的节点可以分配出足够的磁盘容量容错性差,如果pod正在运行的宿主机宕机或者磁盘发生异常,那么它的持久化卷里的信息可能丢失第一个问题,可以通过比如阿里云的 local-volume-provisioner 实现本地 SSD Nvme实例自动创建数据卷来解决,但对于容错性和健壮性的问题,就是比较棘手的了。参见:Durable Local Storage Management is Now GA (#121)Pod 优先级与抢占机制稳定可用Kubernetes 里的任务优先级(priority)和抢占机制(preemption)的目的十分明确:保证高优先级的任务可以在需要的时候通过抢占低优先级任务的方式得到运行。这其中,优先级定义了一个Pod在集群中的重要程度,这个重要程度体现且仅体现在两个地方:(1)高优先级的Pod在调度阶段更容易被优先调度(K8s采用队列调度模型),注意这里并不保证高优先级Pod永远被优先调度,实际影响调度顺序的因素有很多;(2)在集群整体负载较高时,如果出现高优先级Pod无法被调度的情况(集群中没有满足条件的Node供Pod运行),K8s会启动抢占机制,通过抢占已经运行的低优先级的Pod的方式,让高优先级的Pod可以运行起来。抢占机制便是在这里引入的。抢占机制指当调度器发现某个Pod(如Pod-A)无法在集群中找到合适的节点部署时(所有节点Predicates全部失败),会试图通过删除一些优先级低于Pod-A的Pod来“腾出空间”部署Pod-A,这样Pod-A就可以被调度了。这样一个“看似简单”的需求在分布式环境中实施起来有很多细节,例如:如何决定删除哪个节点的哪些Pod、如何保证为Pod-A腾出的空间不被其它Pod占用、如何保证Pod-A不被饿死(Starvation)、如何处理有亲和性需求的Pod调度约束、是否需要支持跨节点Preemption以支持某些特定的约束(例如某Failure Domain的反亲和约束)等等。这些内容,可以参见:Pod Priority and Preemption in Kubernetes (#564) 你一定要知道什么是 Pod Ready++在 1.14 版本之前,Kubernetes 判断一个Pod是否Ready,就是检查这个Pod的容器是否全部正常运行。但是这里有个问题,那就是容器或者说里面的主进程Ready,并不一定意味着这个应用副本就一定是就绪的。为了确认Pod确实可以正常可用,我们希望给它增加一些外部指标(比如,该 Pod 需要的 Service,DNS,存储等服务全部就绪),来反应这个Pod是否“真正”Ready。这个特性,就是1.14 里一个叫做“Pod Readiness Gates”、也叫做 Pod Ready ++ 的特性。它为pod的“Ready 状态” 提供了一个非常强大的扩展点。需要注意的是,用户需要编写一个外部控制器(Controller)来为这个Pod Readiness Gates 字段对应的指标设置值。参见:Pod Ready++ (#580) Kubernetes 原生应用管理能力1.14之后,Kubernetes 项目本身开始具备了原生的应用管理能力,这其中最重要的一个功能,就是 Kustomize。Kustomize 允许用户从一个基础 YAML 文件,通过 overlay 的方式生成最终部署应用所需的 YAML 文件,而不是像 Helm 那样通过字符串替换的方式来直接修改基础 YAML 文件(模板)。这样,在一个用户通过 overlay 生成新的 YAML 文件的同时,其他用户可以完全不受影响的使用任何一个基础 YAML 或者某一层生成出来的 YAML 。这使得每一个用户,都可以通过 fork/modify/rebase 这样 Git 风格的流程来管理海量的 YAML 文件。这种 PATCH 的思想跟 Docker 镜像是非常类似的,它既规避了“字符串替换”对 YAML 文件的入侵,也不需要用户学习蹩脚的 DSL 语法(比如 Lua)。在1.14之后,Kustomize 已经成为了 kubectl 的一个内置命令。不难看到,Kubernetes 社区正在探索一种 Helm 之外的、更加 Kubernetes 原生的应用管理方法。具体效果如何,我们不妨拭目以待。参见:Added Kustomize as a subcommand in kubectl (#73033, @Liujingfang1)用户友好度进一步提升随着大家对Kubernetes越来越熟悉,对kubectl依赖也越来越强烈,需求也越来越多样化。而在 1.14 中,kubectl 着重在以下几个方面,提升用户体验,加强对日常运维能力的支持。之前 kubectl cp 操作每次只能 copy 一个文件,没办法使用通配符拷贝一批文件,非常不方便。在1.14中,蚂蚁金服的工程师提交了一个拷贝操作的通配符功能,方便对容器中的文件进行操作。参见:#72641以往,用户通常无法方便的知道自己被管理员通过 RBAC 配置的权限到底有哪些。而从v1.14开始,用户可以通过 kubectl auth can-i –list –namespace=ns1 来查看自己在 ns1 这个namespace下可以访问哪些资源 (比如Pod,Service等),并有哪些操作的权限(比如Get,List,Patch,Delete等)了。参见:#64820Kubernetes 用户需要删除的API 资源,往往分散在多个namespace中,删除非常不方便。在v1.14新版本中,用户终于可以借助于 kubectl delete xxx –all-namespaces 来进行统一的删除操作了(这里 XXX 可以是Pod,Services,Deployment,自定义的CRD等等),并且还可以配合 -l 和 –field-selector 可以更精确地删除满足特定条件的资源。参见:#73716稳定性进一步提升和之前每个版本一样,Kubernetes 的新版本发布对稳定性和可靠性增强的关注一直是重中之重,下面我们列举出一些值得注意的修复和升级。在做Pod驱逐时,会优先尝试使用优雅删除模式,而不是暴力删除etcd内的Pod数据。这个修复能够使被驱逐的 Pod更加优雅的退出。参见:#72730Kubelet要重建Pod的容器时,如果旧容器是unknown状态,现在Kubelet会首先尝试Stop容器。这避免了一个 Pod的同一个容器申明会有多个实例同时运行的风险。参见:#73802在大规模集群中,节点因为个别Pod使用了大量磁盘 IO,可能会导致节点频繁的在Ready/NotReady状态之间变化。这种状态会引起大规模的、不可预期的 Pod Eviction,导致线上故障。蚂蚁金服的工程师针对 Docker 环境下的这个问题提交了修复,建议大家也排查一下其它运行时的集群里是否有同样的问题。参见:#74389当 Kubelet在压力较大情况下,可能会发生 Kubelet 的Pod 生命周期事件消费频次弱于事件产生频次,导致负责这个事件的 Channel 被占满,这种情况持续一段时间后会直接导致Kubelet 死锁。阿里巴巴的工程师针对修这个问题提交了修复。参见:#72709大规模场景下的性能提升与优化在 Kubernetes 的主干功能日趋稳定之后,社区已经开始更多的关注大规模场景下 Kubernetes 项目会暴露出来的各种各样的问题。在v1.14中,Kubernetes 社区从面向最终用户的角度做出了很多优化,比如:kubectl 在实现中会顺序遍历 APIServer暴露出的全部资源的Group/Version/Kind,直到查找到需要处理的资源。这种遍历方式导致了用户在大规模集群下使用 kubectl 的性能体验受到很大影响。在v1.14版本中,kubectl的顺序遍历行为终于改为了并行,极大地提升了kubectl的使用体验(经过测试,性能指标提升了10倍以上)。参见: #73345在 1.14 中,APIServer 里的一个重要变更,是对单次 PATCH 请求内容里的操作个数做出了限制,不能超过10000个,否则就不处理此请求。这样做的目的,是防止 APIServer 因为处理海量的甚至是恶意PATCH 请求导致整个集群瘫痪。这也其实也是社区的 CVE-2019-1002100 主要的修复方法。参见:#74000Kubernetes 的 Aggregated API允许 k8s 的开发人员编写一个自定义服务,并把这个服务注册到k8s的 API 里面像原生 API 一样使用。在这个情况下,APIServer 需要将用户自定义 API Spec 与原生的 API Spec 归并起来,这是一个非常消耗CPU 的性能痛点。而在v1.14中,社区大大优化了这个操作的速率,极大地提升了APIServer 归并 Spec 的性能(提升了不止十倍)。参见:#71223文中相关链接一览Release Note :https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.14.md#kubernetes-v114-release-notesSupport for Windows Nodes is Graduating to Stable (#116 ):https://github.com/kubernetes/enhancements/issues/116Durable Local Storage Management is Now GA (#121):https://github.com/kubernetes/enhancements/issues/121#issuecomment-457396290Pod Priority and Preemption in Kubernetes (#564) :https://github.com/kubernetes/enhancements/issues/564Pod Ready++ (#580) :https://github.com/kubernetes/enhancements/issues/580Added Kustomize as a subcommand in kubectl (#73033, @Liujingfang1):https://github.com/kubernetes/kubernetes/pull/73033https://github.com/Liujingfang1用户友好度:72641:https://github.com/kubernetes/kubernetes/pull/7264164820:https://github.com/kubernetes/kubernetes/pull/6482073716:https://github.com/kubernetes/kubernetes/pull/73716稳定性:72730:https://github.com/kubernetes/kubernetes/pull/7273073802:https://github.com/kubernetes/kubernetes/pull/7380274389:https://github.com/kubernetes/kubernetes/pull/7438972709:https://github.com/kubernetes/kubernetes/pull/72709大规模场景下的性能提升与优化:73345:https://github.com/kubernetes/kubernetes/pull/7334574000:https://github.com/kubernetes/kubernetes/pull/7400071223:https://github.com/kubernetes/kubernetes/pull/71223阿里云和CNCF联合开发推出的免费公开课,讲解以Kubernetes主体的云原生技术知识。一线技术专家精心打造,期待各位的学习反馈。 更多课程信息可以一步:官宣|《CNCF x Alibaba 云原生技术公开课》即将重磅上线本文作者:木环阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

April 1, 2019 · 2 min · jiezi

Kubernetes 如何打赢容器之战?

阿里妹导读:Kubernetes 近几年很热门,在各大技术论坛上被炒的很火。它提供了强大的容器编排能力,与此同时 DevOps 的概念也来到大家身边,广大的开发同学也能简单地运维复杂的商业化分布式系统,打破了传统开发和运维之间的界限。本文会以初学者的视角,希望能让读者更好地理解 Kubernetes 出现的背景、超前的设计理念和优秀的技术架构。背景PaaSPaaS 技术,一句话概括就是:它提供了“应用托管”的能力。早期的主流做法基本上是租 AWS 或者 OpenStack 的虚拟机,然后把这些虚拟机当作物理机一样,用脚本或者手工的方式在上面部署应用。这个过程中如何保证本地环境和云端环境的一致性是一个很大的课题,而提供云计算服务的公司的核心竞争力就是比拼谁做的更好。从某种意义上来说 PaaS 的出现,算是一个比较好的解决方案。以 Cloud Foundry 为例,在虚拟机上部署上 Cloud Foundry 项目后,用户可以很方便地把自己的应用上云。以上帝视角来看这个过程:Cloud Foundry 最核心的是提供了一套应用的打包和分发机制,它为不同的编程语言定义了不同的打包格式,它能把可执行文件、启动参数等等一起打包成压缩包然后上传至 Cloud Foundry 存储中心,最后由调度器选择虚拟机,由虚拟机上的 Agent 下载并启动应用。分布式系统随着软件的规模越来越大,业务模式越来越复杂,用户量的上升、地区的分布、系统性能的苛刻要求都促成服务架构从最初的单体变成 SOA 再到如今的微服务,未来还可能演变为 Service Mesh ,Serverless 等等。如今,一个完整的后端系统不再是单体应用架构了,多年前的 DDD 概念重新回到大家的视线中。现在的系统被不同的职责和功能拆成多个服务,服务之间复杂的关系以及单机的单点性能瓶颈让部署和运维变得很复杂,所以部署和运维大型分布式系统的需求急迫待解决。容器技术前面提到诸如 Cloud Foundry 的 PaaS,用户必须为不同语言、不同框架区分不同的打包方式,这个打包过程是非常具有灾难性的。而现实往往更糟糕,当在本地跑的好好的应用,由于和远端环境的不一致,在打包后却需要在云端各种调试,最终才能让应用“平稳”运行。而 Docker 的出现改变了一切,它凭借镜像解决了这个问题。Docker 一不做二不休,干脆把完整的操作系统目录也打包进去,如此高的集成度,保证了云端和本地环境的高度一致,并且随时随地轻易地移植。谁也不知道就因为“镜像”这个简单的功能,Docker 完成了对 PaaS 的降维打击,占有了市场。此时,一些聪明的技术公司纷纷跟进 Docker,推出了自家的容器集群管理项目,并且称之为 CaaS。容器技术利用 Namespace 实现隔离,利用 Cgroups 实现限制;在 Docker 实现上,通过镜像,为容器提供完整的系统执行环境,并且通过 UnionFS 实现 Layer 的设计。Docker 容器是完全使用沙箱机制,相互之间不会有任何接口。通过 Docker,实现进程、网络、挂载点和文件隔离,更好地利用宿主机资源。Docker 强大到不需要关心宿主机的依赖,所有的一切都可以在镜像构建时完成,这也是 Docker 目前成为容器技术标准的原因。所以我们能看到在 Kubernetes 中默认使用 Docker 作为容器(也支持 rkt)。Kubernetes铺垫了这么多,终于说到本文的主角了。说 Kubernetes 之前,不得不提 Compose、Swarm、Machine 三剑客,其实在 Kubernetes 还未一统江湖之前,它们已经能实现大部分容器编排的能力了。但是在真正的大型系统上,它们却远远不如 Mesosphere 公司出品的大型集群管理系统,更别说之后的 Kubernetes 了。在容器化和微服务时代,服务越来越多,容器个数也越来越多。Docker 如它 Logo 所示一样,一只只鲸鱼在大海里自由地游荡,而 Kubernetes 就像一个掌舵的船长,带着它们,有序的管理它们,这个过程其实就是容器编排。Kubernetes 起源于 Google,很多设计都是源自于 Borg,是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes 的目标是让部署容器化的应用简单并且高效,并且提供了应用部署,规划,更新,维护的一种机制。小结至此,读者了解了 Kubernetes 的前世今生,由 PaaS 的火热,引爆了容器技术的战争,而赢得这场战争中最关键的即是拥有强大的容器编排的能力,而 Kubernetes 无疑是这场战争的胜利者。设计理念这一部分,我们会围绕 Kubernetes 的四个设计理念看看这些做法能给我们带来什么。声明式 VS 命令式声明式和命令式是截然不同的两种编程方式,在命令式 API 中,我们可以直接发出服务器要执行的命令,例如: “运行容器”、“停止容器”等;在声明式 API 中,我们声明系统要执行的操作,系统将不断向该状态驱动。我们常用的 SQL 就是一种声明式语言,告诉数据库想要的结果集,数据库会帮我们设计获取这个结果集的执行路径,并返回结果集。众所周知,使用 SQL 语言获取数据,要比自行编写处理过程去获取数据容易的多。apiVersion: extensions/v1beta1kind: Deploymentmetadata: name: etcd-operatorspec: replicas: 1 template: metadata: labels: name: etcd-operator spec: containers: - name: etcd-operator image: quay.io/coreos/etcd-operator:v0.2.1 env: - name: MY_POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: MY_POD_NAME valueFrom: fieldRef: fieldPath: metadata.name我们来看看相同设计的 YAML,利用它,我们可以告诉 Kubernetes 最终想要的是什么,然后 Kubernetes 会完成目标。声明式 API 使系统更加健壮,在分布式系统中,任何组件都可能随时出现故障。当组件恢复时,需要弄清楚要做什么,使用命令式 API 时,处理起来就很棘手。但是使用声明式 API ,组件只需查看 API 服务器的当前状态,即可确定它需要执行的操作。显式的 APIKubernetes 是透明的,它没有隐藏的内部 API。换句话说 Kubernetes 系统内部用来交互的 API 和我们用来与 Kubernetes 交互的 API 相同。这样做的好处是,当 Kubernetes 默认的组件无法满足我们的需求时,我们可以利用已有的 API 实现我们自定义的特性。无侵入性感谢 Docker 容器技术的流行,使得 Kubernetes 为大家提供了无缝的使用方式。在容器化的时代,我们的应用达到镜像后,不需要改动就可以遨游在 Kubernetes 集群中。Kubernetes 还提供存储 Secret、Configuration 等包含但不局限于密码、证书、容器镜像信息、应用启动参数能力。如此,Kubernetes 以一种友好的方式将这些东西注入 Pod,减少了大家的工作量,而无需重写或者很大幅度改变原有的应用代码。有状态的移植在有状态的存储场景下,Kubernetes 如何做到对于服务和存储的分离呢?假设一个大型分布式系统使用了多家云厂商的存储方案,如何做到开发者无感于底层的存储技术体系,并且做到方便的移植?为了实现这一目标,Kubernetes 引入了 PersistentVolumeClaim(PVC)和 PersistentVolume(PV)API 对象。这些对象将存储实现与存储使用分离。PersistentVolumeClaim 对象用作用户以与实现无关的方式请求存储的方法,通过它来抹除对底层 PersistentVolume 的差异性。这样就使 Kubernetes 拥有了跨集群的移植能力。架构首先要提及的是 Kubernetes 使用很具代表性的 C/S 架构方式,Client 可以使用 kubectl 命令行或者 RESTful 接口与 Kubernetes 集群进行交互。下面这张图是从宏观上看 Kubernetes 的整体架构,每一个 Kubernetes 集群都由 Master 节点 和 很多的 Node 节点组成。MasterMaster 是 Kubernetes 集群的管理节点,负责管理集群,提供集群的资源数据访问入口。拥有 Etcd 存储服务,运行 API Server 进程,Controller Manager 服务进程及 Scheduler 服务进程,关联工作节点 Node。Kubernetes API Server 提供 HTTP Rest 接口的关键服务进程,是 Kubernetes 里所有资源的增、删、改、查等操作的唯一入口。也是集群控制的入口进程; Kubernetes Controller Manager 是 Kubernetes 所有资源对象的自动化控制中心,它驱使集群向着我们所需要的最终目的状态; Kubernetes Schedule 是负责 Pod 调度的进程。NodeNode 是 Kubernetes 集群架构中运行 Pod 的服务节点。Node 是 Kubernetes 集群操作的单元,用来承载被分配 Pod 的运行,是 Pod 运行的宿主机。关联 Master 管理节点,拥有名称和 IP、系统资源信息。运行 Docker Runtime、kubelet 和 kube-proxy。kubelet 负责对 Pod 对于的容器的创建、启停等任务,发送宿主机当前状态; kube-proxy 实现 Kubernetes Service 的通信与负载均衡机制的重要组件; Docker Runtime 负责本机容器的创建和管理工作。实现原理为了尽可能地让读者能明白 Kubernetes 是如何运作的,这里不会涉及到具体的细节实现,如有读者感兴趣可以自行参阅官网文档。这里以一个简单的应用部署示例来阐述一些概念和原理。创建 Kubernetes 集群介绍架构的时候我们知道,Kubernetes 集群由 Master 和 Node 组成。Master 管理集群的所有行为例如:应用调度、改变应用的状态,扩缩容,更新/降级应用等。Node 可以是是一个虚拟机或者物理机,它是应用的“逻辑主机”,每一个 Node 拥有一个 Kubelet,Kubelet 负责管理 Node 节点与 Master 节点的交互,同时 Node 还需要有容器操作的能力,比如 Docker 或者 rkt。理论上来说,一个 Kubernetes 为了应对生产环境的流量,最少部署3个 Node 节点。当我们需要在 Kubernetes 上部署应用时,我们告诉 Master 节点,Master 会调度容器跑在合适的 Node 节点上。我们可以使用 Minikube 在本地搭一个单 Node 的 Kubernetes 集群。部署应用当创建好一个 Kubernetes 集群后,就可以把容器化的应用跑在上面了。我们需要创建一个 Deployment,它会告诉 Kubernetes Master 如何去创建应用,也可以来更新应用。当应用实例创建后,Deployment 会不断地观察这些实例,如果 Node 上的 Pod 挂了,Deployment 会自动创建新的实例并且替换它。相比传统脚本运维的方式,这种方式更加优雅。我们能通过 kubectl 命令或者 YAML 文件来创建 Deployment,在创建的时候需要指定应用镜像和要跑的实例个数,之后 Kubernetes 会自动帮我们处理。查看 Pods 和 Nodes下面来介绍下 Pod 和 Node:当我们创建好 Deployment 的时候,Kubernetes 会自动创建 Pod 来承载应用实例。Pod 是一个抽象的概念,像一个“逻辑主机”,它代表一组应用容器的集合,这些应用容器共享资源,包括存储,网络和相同的内部集群 IP。任何一个 Pod 都需要跑在一个 Node 节点上。Node 是一个“虚拟机器”,它可以是虚拟机也可以是物理机,一个 Node 可以有多个 Pods,Kubernetes 会自动调度 Pod 到合适的 Node 上。Service 与 LabelSelectorPods 终有一死,也就是说 Pods 也有自己的生命周期,当一个 Pod 挂了的时候,ReplicaSet 会创建新的,并且调度到合适的 Node 节点上。考虑下访问的问题,Pod 替换伴随着 IP 的变化,对于访问者来说,变化的 IP 是合理的;并且当有多个 Pod 节点时,如何 SLB 访问也是个问题,Service 就是为了解决这些问题的。Service 是一个抽象的概念,它定义了一组逻辑 Pods,并且提供访问它们的策略。和其他对象一样,Service 也能通过 kubectl 或者 YAML 创建。Service 定义的 Pod 可以写在 LabelSelector 选项中(下文会介绍),也存在不指定 Pods 的情况,这种比较复杂,感兴趣的读者可以自行查阅资料。Service 有以下几种类型:ClusterIP(默认):在集群中内部IP上暴露服务,此类型使Service只能从群集中访问;NodePort:通过每个 Node 上的 IP 和静态端口(NodePort)暴露服务。NodePort 服务会路由到 ClusterIP 服务,这个 ClusterIP 服务会自动创建。通过请求 :,可以从集群的外部访问一个 NodePort 服务;LoadBalancer:使用云提供商的负载均衡器,可以向外部暴露服务。外部的负载均衡器可以路由到 NodePort 服务和 ClusterIP 服务;ExternalName:通过返回 CNAME 和它的值,(适用于外部 DNS 的场景)Labels 和 Selectors 能够让 Kubernetes 拥有逻辑运算的能力,有点像 SQL。举个例子:可以查找 app=hello_word 的所有对象,也可以查找 app in (a,b,c) abc的所有对象。Labels是一个绑定在对象上的 K/V 结构,它可以在创建或者之后的时候的定义,在任何时候都可以改变。扩容应用前文提到我们可以使用 Deployment 增加实例个数,下图是原始的集群状态:我们可以随意的更改 replicas (实例个数)来扩容,当我们更改了 Deployment 中的 replicas 值时,Kubernetes 会自动帮我们达到想要的目标实例个数,如下图:更新应用更新应用和扩容类似,我们可以更改 Deployment 中的容器镜像,然后 Kubernetes 会帮住我们应用更新(蓝绿、金丝雀等方式),通过此功能,我们还可以实现切换应用环境、回滚、不停机 CI/CD。下面是部署的过程,需要注意的是我们可以指定新创建的 Pod 最大个数和不可用 Pod 最大个数:总结到了最后,大家对 Kubernetes 有个大概的了解了,但 Kubernetes 远远不止本文所介绍的这些内容。在云原生概念逐渐清晰的今天,Kubernetes 作为 CNCF 中一个接地气的落地项目,其重要性不言而喻。本文作者: 淘敏阅读原文本文来自云栖社区合作伙伴“ 阿里技术”,如需转载请联系原作者。 ...

March 28, 2019 · 3 min · jiezi

集群 | 孙悟空分身术

本文首发于我的公众号 cloud_dev,专注于干货分享,号内有大量书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫。在孙悟空的七十二变中,我觉得最厉害的是分身能力,这也是他百试不得其爽的终极大招,每每都能打得妖怪摸不着北。集群,学名叫 Cluster,可以翻译为簇、聚类、集群等多种意思,不同的翻译,在技术世界里所表示的意思都不尽相同,但都有一个共同的指向,即群体。集群就是由一组计算机所组成的实体,通常作为一个整体向用户提供资源和服务。集群的研究和发展离不开人们对高性能计算的追求,像我们熟悉的向量机、对称多处理机、工作站、超级计算机等等都是对高性能计算追求下的产物。这些系统要么是提高 CPU 的主频和总线带宽来提高系统性能,要么是增加 CPU 个数和内存容量来提高性能,但这些手段对性能的提高都是有限的。有人做过实验,当 CPU 个数超过某一阈值时,系统的性能反而会变差。其主要的瓶颈就在于 CPU 访问内存的带宽并不能随着 CPU 个数的增加而有效增加。相反,集群系统的性能可扩展能力是线性增长的。我们可以简单通过增加机器数来增加集群的运算能力,相比购买高性能的大型计算机,同等运算能力下,我们可以获得更高的性价比。同时,系统的可靠性也得到了增强。历史早在七十年代计算机厂商和研究机构就开始了对集群系统的研究和开发,首先创造性发明集群的是 Seymour Cray(西摩·克雷)—— 超级计算机之父。Seymour 是一位美国工程师,在 1960 年代,CDC 公司开始涉足高性能计算领域,彼时还是大型机的天下,这些大型机设计非常复杂,生产周期漫长,价格还非常昂贵。于是,当时在 CDC 公司担任总设计师的 Seymour 就决心建造出一台他心目中的高性能计算机。Seymour 出于工程师的直觉,很快想到并行是提高计算机性能的有效方式。他使用廉价的方式来获得跟大型机一样的运算能力。他将多个普通的处理器连接起来,使它们能够协同工作,这就是高性能计算机的原型。后来,IBM、HP 等公司学习了 Seymour 的这套架构,高性能计算机开始迅速推广,逐步取代原有的大型机。高性能计算机为当时的登月计划等大型科研项目作出了非常重要的贡献。然后进入八十年代,在摩尔定律的指导下,CPU 频率不断提高,芯片不断降价,个人计算机强势崛起。苹果、微软等公司借助这股东风成为个人计算机时代的王者。随之而来的就是高性能计算机市场遭到了吞噬,被迫只能退守公司服务器市场。但很快,随着互联网的普及,高性能计算机又迎来新的一波热潮。互联网上用户量庞大,普通 PC 难以应付如此众多的网络请求,必须要依赖由高性能计算机组成的服务器集群。在 2000 年左右的网络泡沫时期,成就了很多像 Sun 这样的服务器生产商。如今,IT 行业向云计算冲击,诸如 Google、Apple、Amazon 等很巨头纷纷建立起了自己的数据中心。集群的规模在不断扩大,为海量的数据提高基础设施提供了支撑。根据不同的应用场景,集群也演变出多种形态,比如高性能集群、高可用集群、负载均衡集群等等。集群元素集群不是简单的硬件堆叠,而是硬件和软件的结合。从软件上说,集群至少需要:构建于 TCP/IP 协议上的通信软件,用于集群中节点之间的通信。一套中心管理软件,用于统一管理集群中节点的资源、任务和容错等等。这两点比较好理解,集群的规模往往是比较庞大的,对于管理员来说,需要随时能够知晓集群中各节点的业务正常与否,出问题了应该怎么保证业务能够不中断,遇到流量高峰和低谷的时候,又该怎么响应,这些操作如果纯靠人工来完成那必将很惨烈。依靠软件和网络来完成自动化的管理方式,可以将管理员解放出来。当然,以上说的两点是比较宽泛的,用户可以根据自身需求来部署不同的集群元素。一个比较经典的集群模型当属 Beowulf 集群,它通过一个节点统一将来自网络的请求分配给各个节点进行计算处理。集群与分布式集群与分布式像一对孪生兄弟,傻傻分不清楚。在我看来,它们之间没有特别明确的分界线,集群离不开分布式,分布式也需要集群。如果一定要做个区分,可以套用一个比喻来描述两者的区别:一家餐厅刚开业,由于成本限制招了一个厨师,慢慢地,餐厅生意越做越好,一个厨师已经很难应付过来,于是又招了一个,这两个厨师水平相当,都能做同样的事,两个厨师之间的关系就是集群。两厨师除了炒菜,还要负责洗菜、配菜等等的活,工作负荷已经严重超标,为了让厨师能专心炒菜,把菜做到极致,餐厅又招了配菜师来辅助厨师,厨师和配菜师之间的关系就是分布式。这个例子比较形象,在网站开发中也有类似的关系,两个全栈工程师之间就是集群的关系,前端工程师和后端工程师之间就属于分布式的关系。所以,一定要有区分的话就是:集群是一个业务部署在多个服务器上,而分布式是一个业务拆分成多个子业务部署在不同的服务器上。但在实际部署中,为了高性能,需要分布式部署,为了高可用,需要集群部署,这两者都是业务所必须的指标。所以,集群和分布式之间的关系是相互补充的。虚拟化随着虚拟化技术的发展,一台服务器可以虚拟出多个虚拟机,对外提供业务,这种方式大大提高了资源的利用率,集群的部署也逐步从物理机过渡到虚拟机,灵活性大大提高。但同时也带来了更多新的研究课题。虚拟化计算、虚拟化存储、虚拟化网络、虚拟化安全等等这些课题共同推动着云计算产业迈出一个又一个的台阶。数据中心数据中心是集中存放和运行服务器的地方,是规模最大的集群。随着云计算和大数据概念的风起云涌,Google、Amazon 等这些明星公司幕后的数据中心也开始走入大众的视野。数据中心要求有优秀的架构设计、电路设计、空间设计等等,还要有机制能够应对各种各样的意外,否则一点小小的失误,公司的股价恐怕就要跳水。地理位置的选择也是数据中心考虑的一个指标,随着绿色数据中心概念的兴起,越来越多人关注数据中心所带来的能源问题和环境问题,选择一个远离市区,并且能利用天然水源和气温的地方,将会为数据中心的建设节约大量的成本。Google 等大公司的数据中心就有意放在高纬度、高海拔的地区,以及有湖泊、河流流经地区,以享受天然的空调和冷却水。参考[1] 分布式与集群的区别是什么?[2] 数据中心网络架构演讲 [3] Linux 高性能计算集群[4] 高性能计算机传奇我的公众号 cloud_dev,号内有大量书籍和视频资源,后台回复「1024」即可领取,分享的内容包括但不限于云计算虚拟化、容器、OpenStack、K8S、雾计算、网络、工具、SDN、OVS、DPDK、Linux、Go、Python、C/C++编程技术等内容,欢迎大家关注。

March 28, 2019 · 1 min · jiezi

阿里工程师开发了一款免费工具,提升Kubernetes应用开发效率

对于使用了Kubernetes作为应用运行环境的开发者而言,在同一个集群中我们可以使用命名空间(Namespace)快速创建多套隔离环境,在相同命名空间下,服务间使用Service的内部DNS域名进行相互访问。 基于Kubernetes强大的隔离以及服务编排能力,可以实现一套定义编排(YAML)多处部署的能力。不过,一般来说Kubernetes使用的容器网络与开发者的所在的办公网络直接并不能直接连通。 因此,如何高效的利用Kubernetes进行服务间的联调测试,成为在日常开发工作中一道绕不开的坎。本文我们就来聊一聊,如何加速基于Kubernetes的研发效率。使用自动流水线为了能够让开发者能够更快的将修改的代码部署到集群测试环境中,一般来说我们会引入持续交付流水线,将代码的编译,镜像的打包上传以及部署通过自动化的方式来解决。如下所示:从一定程度上来说,这种方式可以避免开发人员进行大量重复性的工作。但是,虽然整个过程自动化了,但是开发人员也不得不每次进行代码变更之后都需要等待流水线的运行。对于开发人员来说,每次代码变更后等待流水线运行或许已经成为整个开发任务过程中体验最糟糕的部分。打破网络限制,本地联调理想状态下是开发者可以直接在本地启动服务,并且这个服务就可以无缝的和远程的kubernetes集群中的各个其它服务实现互相调用。需要解决两个问题:我依赖了其它的服务:运行在本地的代码可以直接通过podIP,clusterIP甚至是Kubernetes集群内的DNS地址访问到部署在集群中的其它应用,如下图左;其它的服务依赖了我:运行在Kubernetes集群中的其它应用可以在不做任何改变的情况下访问我到运行的本地的代码,如下图右。要实现刚才说的两种本地联调方式,主要需要解决以下3个问题:本地网络与Kubernetes集群网络直接的连通问题在本地实现Kubernetes中内部服务的DNS解析;如果将对集群中其它Pod访问的流量转移到本地;云效开发者工具KT为了简化在Kubernetes下进行联调测试的复杂度,云效在SSH隧道网络的基础上并结合Kubernetes特性构建了一款面向开发者的免费辅助工具KT(点击前往下载),如下所示:当本地运行的服务C’希望能够直接访问集群中default命名空间下的Service A和Service B时,运行如下命令:$ ktctl -namespace=defaultKT会自动在集群中部署SSH/DNS代理容器,并构建本地到Kubernetes集群的VPN网络并通过DNS代理实现集群服务DNS域名解析,在运行KT之后,开发者的本地程序可以直接像运行在集群中的服务一样通过service名字调用集群中部署的其它应用:而如果希望集群中的其它Pod(比如图中的PodD和PodE)能够通过ServiceC访问到本地运行的程序C‘,通过如下命令,指定需要替换的目标Deployment以及指定本地服务端口:#-swap-deployment指定需要替换的目标Deployment # -expose 指定本地服务运行的端口 ktctl -swap-deployment c-deployment -expose=8080KT在构建VPN网络的同时,还会自动通过代理容器接管集群原有的PodC实例,并直接转发的本地的8080端口。实现集群应用联调本地。经过上述两个命令,开发者就可以真正的使用云原生的方式来开发调试Kubernetes中的应用了。工作原理下面解析KT的工作原理,如果你已经迫不及待的想尝试KT的功能,可以直接前往下载KT工具。KT主要由两部分组成:在本地运行的命令行工具ktctl运行在集群中的SSH/DNS代理容器。在工作原理上KT实际上是结合Kubernetes自身能力实现的一个基于SSH的VPN网络。这这部分,笔者将详细介绍云效Kubernetes开发者工具KT的工作原理:打通SSH协议通道在Kubernetes命令行工具kubectl中内置的port-forward命令可以帮助用户建立本地端口到Kubernetes集群中特定Pod实例端口间的网络转发。当我们在集群中部署一个包含sshd服务的容器后,通过port-forward可以将容器的SSH服务端口映射到本地:# 将对本地2222端口转发到kt-porxy实例的22端口 $ kubectl port-forward deployments/kt-proxy 2222:22 Forwarding from 127.0.0.1:8080 -> 8080 Forwarding from [::1]:8080 -> 8080在运行端口转发后,就可以直接通过本地的2222端口通过SSH协议进入到Kubernetes集群的kt-proxy实例中。从而打通本地与集群之间的SSH网络链路。本地动态端口转发与VPN在打通SSH网络之后,我们就可以利用SSH通道实现本地到集群的网络请求,其中最基本的方式就是使用SSH动态端口转发的能力。使用如下命令,通过本地2000运行的代理,可以将网络请求通过集群中运行的kt-proxy容器进行转发,从而实现本地到集群网络请求的转发:# ssh -D [本地网卡地址:]本地端口 name@ip -p映射到kt-proxy的22端口的本地端口 ssh -D 2000 root@127.0.0.1 -p2222在启用SSH动态端口转发后,通过设置http_proxy环境变量后,即可直接在命令行中访问集群网络:# export http_proxy=socks5://127.0.0.1:ssh动态端口转发的代理端口 export http_proxy=socks5://127.0.0.1:2000不过原生SSH动态端口转发也有一定的限制那就是无法直接使用UDP协议,这里我们选择了一个替代方案sshuttle. 如下命令所示:# export http_proxy=socks5://127.0.0.1:ssh动态端口转发的代理端口 export http_proxy=socks5://127.0.0.1:2000 sshuttle –dns –to-ns 172.16.1.36 -e ‘ssh -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null’ -r root@127.0.0.1:2222 172.16.1.0/16 172.19.1.0/16 -vvsshuttle工具在SSH协议之上构建了一个简易的VPN网络,同时支持DNS协议转发。因此,接下来的问题就是实现一个自定义的DNS服务即可,而该服务在KT中是直接内置在KT代理镜像中。远程端口转发在本地到集群的链路打通之后。 接下来需要解决的就是从集群到本地的访问链路。这部分,我们会使用到SSH的远程端口转发能力,如下所示,指定所有对kt-proxy的8080端口的网络请求都会通过SSH隧道直接转发到本地的8080端口:# ssh -R 8080:localhost:8080 root@127.0.0.1 -p2222 ssh -R 8080:localhost:8080 root@127.0.0.1 -p2222因此,在KT的实现过程之中,结合Kubernetes基于标签的松耦合能力,我们只需要克隆原有应用实例的YAML描述,并将容器替换为kt-proxy即可。从而将对集群中原有应用的请求通过SSH远程端口转发到本地。综上,通过利用Kubernetes原生能力以及适度的扩展,开发者可以快速在本地利用KT打破本地网络与Kubernetes网络之间的界限,大大提升使用Kubernetes进行联调测试的效率。小结工具承载了对特定问题的解决方案,而工程技术实践则是对其价值的放大。阿里巴巴云效平台,致力于为开发者提供一站式的企业研发与协作服务,并将阿里多年的软件工程实践以一种更加开发的形态反馈技术社区,欢迎更多的技术开发者入驻。目前,Mac用户可以前往下载并体验KT工具作者:郑云龙,阿里巴巴研发效能部高级研发工程师本文作者:云效鼓励师阅读原文本文为云栖社区原创内容,未经允许不得转载。

March 26, 2019 · 1 min · jiezi

Pod在多可用区worker节点上的高可用部署

一、 需求分析当前kubernetes集群中的worker节点可以支持添加多可用区中的ECS,这种部署方式的目的是可以让一个应用的多个pod(至少两个)能够分布在不同的可用区,起码不能分布在同一个可用区,已达到高可用或者同城灾备的部署。二、 效果图三、 实现原理为了实现上述的效果,kubernetes提供了pod的亲和性和反亲和性来保证pod在节点级别,可用区级别的高可用部署;具体的值为topologyKey:failure-domain.beta.kubernetes.io/zone。四、 实现步骤在ACK上创建完集群后,不论从哪个可用区添加节点,都会对该节点打上对应的可用区标签,比如,一个节点是属于北京可用区a的,那么在加入到kubernetes集群后,该节点上会有一个这样的标签:failure-domain.beta.kubernetes.io/zone: cn-beijing-a。在有了上述标签后,对应用进行多可用区部署时,我们就可以使用一下yaml文件来使不同的pod分配到不同的可用区。 Yaml文件示例:apiVersion: apps/v1kind: Deploymentmetadata: name: redis-cachespec: selector: matchLabels: app: store replicas: 3 template: metadata: labels: app: store spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - store topologyKey: “failure-domain.beta.kubernetes.io/zone” containers: - name: redis-server image: redis:3.2-alpine上面yaml文件中的podAntiAffinity:部分规定了node的反亲和性,并且由于使用了topologyKey: “failure-domain.beta.kubernetes.io/zone”,如果failure-domain.beta.kubernetes.io/zone这个key有三种value,比如cn-beijing-a,cn-beijing-b,cn-beijing-c;那么pod会被分配在这三个不同的可用区。并且由于使用了preferredDuringSchedulingIgnoredDuringExecution,所以如果pod个数大于可用区个数的话,pod会尽可能的放在不同的可用区,最后会出现多出来的pod会与原有pod在同一个可用区。上面的使用方式还有很多种,包括node级别的,详细请参考:https://kubernetes.io/docs/co…由于云盘不能跨可用区挂载,如果有pod使用了存储卷,该pod需要被调度到与存储卷相同的可用区的机器上。其他存储卷比如NAS,OSS是可以采用上述部署方式的。本文作者:朱延生阅读原文本文为云栖社区原创内容,未经允许不得转载。

March 18, 2019 · 1 min · jiezi

探秘 Dubbo 的度量统计基础设施 - Dubbo Metrics

对服务进行实时监控,了解服务当前的运行指标和健康状态,是微服务体系中不可或缺的环节。Metrics 作为微服务的重要组件,为服务的监控提供了全面的数据基础。近日,Dubbo Metrics 发布了2.0.1版本,本文将为您探秘 Dubbo Metrics 的起源,及 7 大改进。Dubbo Metrics 的起源Dubbo Metrics(原Alibaba Metrics)是阿里巴巴集团内部广泛使用的度量埋点基础类库,有 Java 和 Node.js 两个版本,目前开源的是 Java 版本。内部版本诞生于2016年,经历过近三年的发展和双十一的考验,已经成为阿里巴巴集团内部微服务监控度量的事实标准,覆盖了从系统、JVM、中间件到应用各层的度量,并且在命名规则、数据格式、埋点方式和计算规则等方面,形成了一套统一的规范。Dubbo Metrics 的代码是基于 Dropwizard Metrics 衍生而来,版本号是3.1.0,当时决定 fork 到内部进行定制化开发的主要原因有两个。一是社区的发展非常缓慢,3.1.0之后的第3年才更新了下一个版本,我们担心社区无法及时响应业务需求;另一个更重要的原因是当时的3.1.0还不支持多维度的 Tag,只能基于 a.b.c 这样传统的指标命名方法,这就意味着 Dropwizard Metrics 只能在单维度进行度量。然后,在实际的业务过程中,很多维度并不能事先确定,而且在大规模分布式系统下,数据统计好以后,需要按照各种业务维度进行聚合,例如按机房、分组进行聚合,当时的 Dropwizard 也无法满足,种种原因使得我们做了一个决定,内部fork一个分支进行发展。Dubbo Metrics 做了哪些改进相对于 Dropwizard Metrics ,Dubbo Metrics 做的改进主要有以下几个方面:一、引入基于 Tag 的命名规范如前文所描述,多维度 Tag 在动态埋点,数据聚合等方面相对于传统的 metric 命名方法具有天然的优势,这里举一个例子,要统计一个 Dubbo 服务 DemoService 调用次数和 RT,假设这个服务叫做 DemoService,那么按照传统的命名方式,通常会命名为dubbo.provider.DemoService.qps和dubbo.provider.DemoService.rt。如果只有1个服务的话,这种方法并无太大的问题,但是如果一个微服务应用同时提供了多个 Dubbo 的 Service,那么要聚合统计所有Service 的 QPS 和 RT 就比较困难了。由于 metric 数据具有天然的时间序列属性,因此数据非常适合存储到时间序列数据库当中,要统计所有的 Dubbo 服务的 QPS,那么就需要查找所有名称为dubbo.provider..qps的指标,然后对他们进行求和。由于涉及到模糊搜索,这对于绝大部分数据库的实现都是比较费时的。如果要统计更加详细的 Dubbo 方法级别的 QPS 和 RT,那么实现上就会更加复杂了。Metric Key:用英文点号分隔的字符串,来表征这个指标的含义Metric Tag:定义了这个指标的不同切分维度,可以是单个,也可以是多个;tag key:用于描述维度的名称;tag value:用于描述维度的值;同时,考虑到一个公司所有微服务产生的所有指标,都会统一汇总到同一个平台进行处理,因此Metric Key 的命名方式为应当遵循同一套规范,避免发生命名冲突,其格式为appname.category[.subcategory].suffixappname: 应用名;category: 这个指标在该应用下的分类,多个单词用’‘连接,字母采用小写;subcategory: 这个指标在该应用下的某个分类下的子分类,多个单词用’‘连接,字母采用小写;suffix: 这个关键的后缀描述了这个指标所度量的具体类型,可以是计数,速率,或者是分布;在上述例子中,同样的指标可以命名为dubbo.provider.service.qps{service=“DemoService”},其中前面部分的名称是固定的,不会变化,括号里面的Tag,可以动态变化,甚至增加更多的维度,例如增加 method 维度dubbo.provider.service.qps{service=“DemoService”,method=“sayHello”},也可以是机器的 IP、机房信息等。这样的数据存储是时间序列数据库亲和的,基于这些数据可以轻松实现任意维度的聚合,筛选等操作。P.s. 2017年12月底,Dropwizard Metrics4.0 开始支持 Tag,Dubbo Metrics 中 ag 的实现参考了Dropwizard。spring-boot 2.0中提供的 MicroMeter 和 Prometheus 也均已引入了 Tag 的概念。二、添加精准统计功能Dubbo Metrics 的精准统计是和 Dropwizard,或者其他开源项目埋点统计库实现不太一样的地方。下面分别通过时间窗口的选择和吞吐率统计方式这两个纬度进行阐述。在统计吞吐率(如 QPS)的时候,Dropwizard的实现方式是滑动窗口+指数加权移动平均,也就是所谓的EWMA,在时间窗口上只提供1分钟、5分钟、15分钟的选择。固定窗口 vs 滑动窗口在数据统计的时候,我们需要事先定义好统计的时间窗口,通常有两种确立时间窗口的方法,分别是固定窗口和滑动窗口。固定时间窗口指的是以绝对时间为参考坐标系,在一个绝对时间窗口内进行统计,无论何时访问统计数据,时间窗口不变;而滑动窗口则是以当前时间为参考系,从当前时间往前推一个指定的窗口大小进行统计,窗口随着时间,数据的变化而发生变化。固定窗口的优点在于:一是窗口不需要移动,实现相对简单;二是由于不同的机器都是基于相同的时间窗口,集群聚合起来比较容易,只需按照相同的时间窗口聚合即可。其缺点是:如果窗口较大,实时性会受到影响,无法立即得到当前窗口的统计信息。例如,如果窗口为1分钟,则必须等到当前1分钟结束,才能得到这1分钟内的统计信息。滑动窗口的优点在于实时性更好,在任意时刻,能都看到当前时刻往前推演一个时间窗口内统计好的信息。相对而言,由于不同机器的采集时刻不同,要把不同机器上的数据聚合到一起,则需要通过所谓的 Down-Sampling 来实现。即按照固定时间窗口把窗口内收集到的数据应用到某一个聚合函数上。举个例子来说,假设集群有5台机器,按照15秒的频率按照平均值进行 Down-Sampling,若在00:00~00:15的时间窗口内,在00:01,00:03,00:06,00:09,00:11各收集到一个指标数据,则把这5个点的加权平均认为是00:00这个点的经过 Down- Sampling 之后的平均值。但在我们的实践过程中,滑动窗口仍会遇到了以下问题:很多业务场景都要求精确的时间窗口的数据,比如在双11的时候,想知道双11当天0点第1秒创建了多少订单,这种时候 Dropwizard 的滑动窗口很明显就不适用了。Dropwizard 提供的窗口仅仅是分钟级,双11的场景下需要精确到秒级。集群数据聚合的问题,每台机器上的滑动时间窗口可能都不一样,数据采集的时间也有间隔,导致聚合的结果并不准确。为了解决这些问题,Dubbo Metrics 提供了 BucketCounter 度量器,可以精确统计整分整秒的数据,时间窗口可以精确到1秒。只要每台机器上的时间是同步的,那么就能保证集群聚合后的结果是准确的。同时也支持基于滑动窗口的统计。瞬时速率(Rate) vs 指数移动加权平均(EWMA)经过多年的实践,我们逐渐发现,用户在观察监控的时候,首先关注的其实是集群数据,然后才是单机数据。然而单机上的吞吐率其实并没有太大意义。怎么理解呢?比如有一个微服务,共有2台机器,某个方法在某一段时间内产生了5次调用,所花的时间分别是机器1上的[5,17],机器2上的[6,8,8](假设单位为毫秒)。如果要统计集群范围内的平均 RT,一种方法可以先统计单机上的平均 RT,然后统计整体的平均 RT,按照这种方法,机器1上平均 RT 为11ms,机器2的平均 RT 为7.33ms,两者再次平均后,得到集群平均 RT 为9.17ms,但实际的结果是这样吗?如果我们把机器1和机器2上的数据整体拉到一起整体计算的话,会发现实际的平均 RT 为(5+17+6+8+8)/5=8.8ms,两者相差很明显。而且考虑到计算浮点数的精度丢失,以及集群规模扩大,这一误差会愈加明显。因此,我们得出一个结论:单机上的吞吐率对于集群吞吐率的计算没有意义,仅在在单机维度上看才是有意义的。而 Dropwizard 提供的指数加权移动平均其实也是一种平均,同时考虑了时间的因素,认为距离当前时间越近,则数据的权重越高,在时间拉的足够长的情况下,例如15分钟,这种方式是有意义的。而通过观察发现,其实在较短的时间窗口内,例如1s、5s,考虑时间维度的权重并没有太大的意义。因此在内部改造的过程中,Dubbo Metrics 做了如下改进:提供瞬时速率计算,反应单机维度的情况,同时去掉了加权平均,采用简单平均的方式计算;为了集群聚合需要,提供了时间窗口内的总次数和总 RT 的统计,方便精确计算集群维度的吞吐率;三、极致性能优化在大促场景下,如何提升统计性能,对于 Dubbo Metrics 来说是一个重要话题。在阿里的业务场景下,某个统计接口的 QPS 可能达到数万,例如访问 Cache 的场景,因此这种情况下 metrics 的统计逻辑很可能成为热点,我们做了一些针对性的优化:高并发场景下,数据累加表现最好的就是java.util.concurrent.atomic.LongAdder,因此几乎所有的操作最好都会归结到对这个类的操作上。避免调用 LongAdder#reset当数据过期之后,需要对数据进行清理,之前的实现里面为了重用对象,使用了LongAdder#reset进行清空,但实测发现LongAdder#reset其实是一个相当耗费cpu的操作,因此选择了用内存换 CPU,当需要清理的时候用一个新的 LongAdder 对象来代替。去除冗余累加操作某些度量器的实现里面,有些统计维度比较多,需要同时更新多个 LongAdder,例如 Dropwizard Metrics的 meter 实现里面计算1分/5分/15分移动平均,每次需要更新3个 LongAdder,但实际上这3次更新操作是重复的,只需要更新一次就行了。RT为0时避免调用Add方法大多数场景下对 RT 的统计都以毫秒为单位,有些时候当 RT 计算出来小于1ms的时候,传给metrics的 RT 为0。当我们发现 JDK 原生的 LongAdder 并没有对add(0)这个操作做优化,即使输入为0,还是把逻辑都走一遍,本质上调用的是sun.misc.Unsafe.UNSAFE.compareAndSwapLong。如果这个时候,metrics 判断 RT 为0的时候不对计数器进行 Add 操作,那么可以节省一次 Add 操作。这对于并发度较高的中间件如分布式缓存很有帮助,在我们内部某个应用实测中发现,在30%的情况下,访问分布式缓存的 RT 都是0ms。通过这个优化可以节约大量无意义的更新操作。QPS 和 RT 合并统计只需要对一个Long的更新,即可实现同时对调用次数和时间进行统计,已经逼近理论上的极限。经过观测发现,通常对于中间件的某些指标,成功率都非常高,正常情况下都在100%。为了统计成功率,需要统计成功次数和总次数,这种情况下几乎一样多,这样造成了一定的浪费,白白多做了一次加法。而如果反过来,只统计失败的次数,只有当失败的情况才会更新计数器,这样能大大降低加法操作。事实上,如果我们把每一种情况进行正交拆分,例如成功和失败,这样的话,总数可以通过各种情况的求和来实现。这样能进一步确保一次调用只更新一次计数。但别忘了,除了调用次数,还有方法执行 RT 要统计。还能再降低吗?答疑是可以的!假设 RT 以毫秒为单位进行统计,我们知道1个 Long 有64个bits(实际上Java里面的Long是有符号的,所以理论上只有63个 bits 可用),而 metrics 的一个统计周期最多只统计60s的数据,这64个 bits 无论怎样用都是用不掉的。那能不能把这63个 bits 拆开来,同时统计 count 和 RT 呢?实际上是可以的。我们把一个 Long 的63个 bits 的高25位用来表示一个统计周期内的总 count,低38位用于表示总 RT。——————————————| 1 bit | 25 bit | 38 bit || signed bit | total count | total rt |——————————————当一次调用过来来的时候,假设传过来的 RT 是n,那么每次累加的数不是1,也不是n,而是1 * 2^38 + n这么设计主要有一下几个考虑:count是每调用一次加一,RT 是每调用一次加N的操作,如果 count 在高位的话,每次加一,实际是一个固定的常数,而如果rt放在高位的话,每次都加的内容不一样,所以每次都要计算一次;25 bits 最多可以表示 2^25 = 33554432 个数,所以1分钟以内对于方法调用的统计这种场景来说肯定是不会溢出的;RT 可能会比较大,所以低位给了38bits, 2^38=274877906944 基本也是不可能超的。如果真的overflow了怎么办? 由于前面分析过,几乎不可能overflow,因此这个问题暂时没有解决,留待后面在解决。无锁 BucketCounter在之前的代码中,BucketCounter 需要确保在多线程并发访问下保证只有一个线程对 Bucket 进行更新,因此使用了一个对象锁,在最新版本中,对 BucketCounter 进行了重新实现,去掉了原来实现中的锁,仅通过 AtomicReference 和 CAS 进行操作,本地测试发现性能又提升了15%左右。四、全面的指标统计Dubbo Metrics 全面支持了从操作系统,JVM,中间件,再到应用层面的各级指标,并且对统一了各种命名指标,可以做到开箱即用,并支持通过配置随时开启和关闭某类指标的收集。目前支持的指标,主要包括:操作系统支持Linux/Windows/Mac,包含CPU/Load/Disk/Net Traffic/TCP。JVM支持classload, GC次数和时间, 文件句柄,young/old区占用,线程状态, 堆外内存,编译时间,部分指标支持自动差值计算。中间件Tomcat: 请求数,失败次数,处理时间,发送接收字节数,线程池活跃线程数等;Druid: SQL 执行次数,错误数,执行时间,影响行数等;Nginx: 接受,活跃连接数,读,写请求数,排队数,请求QPS,平均 RT 等;更详细的指标可以参见这里, 后续会陆续添加对Dubbo/Nacos/Sentinel/Fescar等的支持。五、REST支持Dubbo Metrics 提供了基于 JAX-RS 的 REST 接口暴露,可以轻松查询内部的各种指标,既可以独立启动HTTP Server提供服务(默认提供了一个基于Jersey+ sun Http server的简单实现),也可以嵌入已有的HTTP Server进行暴露指标。具体的接口可以参考这里:https://github.com/dubbo/metrics/wiki/query-from-http六、单机数据落盘数据如果完全存在内存里面,可能会出现因为拉取失败,或者应用本身抖动,导致数据丢失的可能。为了解决该问题,metrics引入了数据落盘的模块,提供了日志方式和二进制方式两种方式的落盘。日志方式默认通过JSON方式进行输出,可以通过日志组件进行拉取和聚合,文件的可读性也比较强,但是无法查询历史数据;二进制方式则提供了一种更加紧凑的存储,同时支持了对历史数据进行查询。目前内部使用的是这种方式。七、易用性和稳定性优化将埋点的API和实现进行拆分,方便对接不用的实现,而用户无需关注;支持注解方式进行埋点;借鉴了日志框架的设计,获取度量器更加方便;增加Compass/FastCompass,方便业务进行常用的埋点,例如统计qps,rt,成功率,错误数等等指标;Spring-boot-starter,即将开源,敬请期待;支持指标自动清理,防止长期不用的指标占用内存;URL 指标收敛,最大值保护,防止维度爆炸,错误统计导致的内存。如何使用使用方式很简单,和日志框架的Logger获取方式一致。Counter hello = MetricManager.getCounter(“test”, MetricName.build(“test.my.counter”));hello.inc();支持的度量器包括:Counter(计数器)Meter(吞吐率度量器)Histogram(直方分布度量器)Gauge(瞬态值度量器)Timer(吞吐率和响应时间分布度量器)Compass(吞吐率, 响应时间分布, 成功率和错误码度量器)FastCompass(一种快速高效统计吞吐率,平均响应时间,成功率和错误码的度量器)ClusterHistogram(集群分位数度量器)后续规划提供Spring-boot starter支持Prometheus,Spring MicroMeter对接Dubbo,Dubbo 中的数据统计实现替换为 Dubbo Metrics在 Dubbo Admin 上展示各种 metrics 数据对接 Dubbo 生态中的其他组件,如Nacos, Sentinel, Fescar等参考资料Dubbo Metrics @Github:https://github.com/dubbo/metricsWiki:https://github.com/dubbo/metrics/wiki (持续更新)本文作者:望陶,GitHub ID @ralf0131,Apache Dubbo PPMC Member,Apache Tomcat PMCMember,阿里巴巴技术专家。子观,GitHub ID @min,Apache Dubbo Commiter,阿里巴巴高级开发工程师,负责 Dubbo Admin 和 Dubbo Metrics 项目的开发和社区维护。本文作者:中间件小哥阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

March 15, 2019 · 2 min · jiezi

在 Ali Kubernetes 系统中,我们这样实践混沌工程

在传统的软件测试中,我们通常通过一个给定的条件来判断系统的反馈,通过断言来判断是否符合预期,测试条件和结果通常比较明确和固定。而混沌工程,是通过注入一些“不确定”因素,象放进了一群淘气的猴子,在系统资源、可用性、安全性、延迟、压力等方面进行捣乱,而此过程中,要求系统可以毫无影响的提供服务,用户无感知。这其实对系统的自愈能力,健壮性都有很高的要求。故障注入一般是指比较受控的一些实验条件,通过注入一些相对极端的异常场景,为系统提供可靠性测试的过程。 整体来说,混沌是一种故障注入规则,强调了一些不确定性、随机性,比较常见的"猴子"有 Netflix 的"猴子军团",可以用来随机关闭系统实例,注入延时,回收资源,检查安全漏洞等等。开源工具介绍除了一般系统的 monkey,基于 Kubernetes 已经有一些"猴子"工具可以测试系统的健壮性。接下来,介绍一下比较常见的三种 Kubernetes monkey:kube-monkeyhttps://github.com/asobti/kube-monkey运行方式:kube-monkey 通过 label 设置受害者 pod,创建了一个单独的 kube-monkey pod 对受害者 pod 施加影响;注入类型:目前支持的故障注入类型仅有杀容器;配置项:可以通过配置文件设置运行周期和频率,在一定时间内随机的杀死打标范围内的 pod。powerfulsealhttps://github.com/bloomberg/powerfulseal注入类型:powerfulseal 的故障注入类型包括杀 pod 和启停 node。运行方式:包括交互模式,自动模式、打标模式和示例模式。交互模式通过界面交互查询node/namespace/pod,启停 node 或杀死 pod 操作;自动模式通过读取配置文件确定注入范围,注入频率;打标模式通过给 pod 打标确定注入的靶向 pod 及注入频率;示例模式可以反映根据使用资源情况进行故障注入的过程。Chaos Toolkit-kubernetes[https://github.com/chaostoolk…;是 chaos 工具包中的一个,通过 chaos run experiment.json 设置 json 文件来指定 namespace,正则匹配名字等等来随机杀一个 pod。以上三种"猴子",主要是基于杀 pod 场景来注入故障,虽然是最有力的场面但是比较有局限性,对于商业化系统面临的复杂场景,是值得参考但是不够的。](https://github.com/chaostoolk…结合 Ali Kubernetes 故障场景分析Ali Kubernetes 作为一个管理大规模集群的商业调度系统,需要应对的不仅包括一些基本的 Kubernetes 中 pod 误删误停的故障现象,也包含一些底层 OS、内核、网络、误配置等灾难场景。同时由于其支撑业务生态的复杂性,全链路综合异常流也需要特殊的验证。为更系统的进行演练,在过程中主要进行了以下几部分工作:FMEA 分析就是失效模式和效果分析,旨在对系统范围内潜在的失效模式加以分析,以便按照严重程度加以分类,或者确定失效对于该系统的影响。从故障场景上,分析得出较为符合 Ali Kubernetes 的三大类场景:通用故障场景:包括网络相关故障(网络 iohang ,断网,网络延迟等),宿主机相关故障(机器重启,机器 load 高等)Ali Kubernetes 业务场景故障:包括 Kubernetes 相关的故障(pod 删除,pod patch等),pod 迁移,混部、etcd 等业务相关场景;chaos 故障:较为随机的故障注入,可以为以上任何故障的组合从影响面上,需要 case by case 确定影响范围为无任何影响,仅影响部分功能,影响核心功能等等;从验证恢复手段上,也可以分为自动恢复、手动恢复,同时需要关注监控情况及恢复时间。在分析过程中,我们发现,已有的开源工具无法完全满足 Ali Kubernetes 的故障场景。下面举 2 个典型故障场景:pod 被误删这个场景并不是简单的 pod 随机删除,而是在 kubelet 连错 apiserver 配置等异常情况下,重启 ali-kubelet 后,al 自行判断了容器在当前集群内不存在,自己做了删除操作。要引入这个故障需要修改 kubelet 组件的配置,重启 kubelet,才算是真正引入了故障,而当前的无论是 kube-monkey 还是 powerfulseal 场景都无法满足。master 组件断网有的人可能会说,直接指定 master 组件的机器引入断网操作,是不是就可以了呢?然鹅现实是比较骨感的,我们也许只知道这个 master 所在集群的 kubeconfig,组件的机器其实也可以随着每次升级变动的。在仅仅已知 kubeconfig 的情况下我们只能先查一下 master 组件的机器信息,再在机器上引入断网的操作,才算是一个整体的故障引入。而目前所有的开源工具也没有此类稍微复杂一些的场景,只是通过指定 pod namespace 来随机的删除一些 pod。所以综上所述,其实我们需要对此进行扩展开发,除了简单的杀 pod,我们亟需一套可以自由开发的小程序,把这个步骤拼接起来,进行更为复杂的故障注入。套件实现为了满足此类复杂的故障注入,我们使用了目前集团内正在开发的一套故障注入系统 monkeyking,并在它的基础上扩展了一些 kubernetes 相关的套件,来达到既可以注入 kubernetes 相关的故障,又可以注入一些通用故障,同时又可以相对自由的扩展故障集合的目的。这个故障注入的演练流程如下图所示:它的每一个步骤都可以是我们自由扩展的一个或者多个小程序,各个小程序之间的执行顺序也可以自由的定义。考虑到 Ali Kubernetes 的场景,我们在其中扩展了四大类小程序套件。通用故障小程序在这一部分主要实现了一些比较通用的 os 故障,网络故障,比如最基本的指定一个宿主机断网,指定宿主机重启这类。Kubernetes 套件小程序这一部分主要实现了一些通用的 Kubernetes 命令,通过指定这些命令和入参,我们可以执行比如 create delete apply patch 这些操作,来间接的达到注入一些 Kubernetes 相关故障的目的。实现原理如下:要点说明如下:下载集群证书的地址及证书的 md5 码都作为小程序的输入,在执行实际的 kubectl 生效命令前进行下载校验;底层 toolkit 中已经加入了 kubectl 命令行工具,无需自己找环境进行配置和下载;目前已经支持了 apply,create,delete,patch,get 操作,支持指定 label,namespace,-o json 的操作举个例子,上文中 master 组件故障的场景中,我们就可以利用以上的两类小程序来完成故障注入的操作:开源工具小程序目前我们和集团安全生产的 MonkeyKing 团队合作,联合在故障注入平台 monkeyking 中集成了开源工具 kube-monkey,实现过程借助了上文的 kubernetes 套件执行,可以通过打标的方式标记受害者,让 kube-monkey 随机的杀受害者 pod。步骤如下:环境准备锁演练环境在当前集群中初始化kube-monkey: 使用kubernetes套件的apply功能提交km-config.yaml文件,部署 kube-monkey deployment给应用标记受害者 label使用 Kubernetes 套件的 patch 功能,标记受害者验证步骤自定义组件校验应用服务是否可用故障恢复使用 Kubernetes 套件的 patch 功能,给受害者去标使用 Kubernetes 套件的 delete 功能,删除 kube-monkey deployment解锁演练环境其他业务相关小程序这一部分比较自由,主要根据 Ali Kubernetes 的业务需求,接入了一些常用的小程序。比如故障演练过程中,环境需要独占,不允许其他测试执行,在这里实现了一个小程序用来对环境进行加解锁操作;比如校验阶段需要验证服务是否可用,这里实现了一个通过 curl 命令校验返回值的方式验证服务是否可用的小程序;比如故障注入过程可能影响vip挂载,这里也实现了一个调用 vip 服务校验 vip 下 ip 数量及是否可用的小程序。总结在 Ali Kubernetes 中,我们将故障以场景化的方式进行沉淀,将底层 os,内核、网络、误配置等故障联合 Kubernetes 相关故障,引入混沌工程的理念进行注入,有效的发现了很多系统稳定性问题,驱动开发人员更多关注系统健壮性。后续我们会在 Ali Kubernetes 演进过程中持续发力,基于架构和业务场景输入更多 Kubernetes 相关的故障场景,为系统的高可用保驾护航。本文作者:jessie筱姜阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

March 14, 2019 · 1 min · jiezi

RocketMQ 在平安银行的实践和应用

随着互联网金融业务和相关技术的不断发展,传统金融行业为满足业务快速发展需求,正在积极引入各类开源技术,以快速抢占市场。那么,以金融和科技作为双驱动的平安银行在开源技术的引入方面是如何评估,运用到哪些业务场景,以及面对复杂的网络环境,是如何去部署的呢?本文将以 Apache RocketMQ 为例,和您一起了解平安银行在开源技术选型方面的思考和实践。RocketMQ 在平安银行的应用场景;复杂网络环境下的部署实践;多隔离区场景下的部署情况;多 IDC 场景下的部署情况;改造实践和遇到的小插曲;RocketMQ 在平安银行的应用场景目前,平安银行通过 RocketMQ 解决了数据预加、信息通知和状态变化方面的业务需求,接下来,我们通过 App 登录、资产总览和工资理财 3 个应用场景来展开讲下。App 登录:当用户打开平安银行 App 的时候,系统会根据用户的登录 ID 去加载相应的用户数据,比如银行卡、信用卡和理财产品等,以及一些系统通知。这个场景下,我们用到了 RocketMQ 的异步处理能力,即预加载需要使用的数据,提升用户体验。资产总览:进入平安银行 App 资产总览的页面,页面显示账户余额、各类理财产品(黄金、基金和股票等),以及贷款等方面的信息。平安银行对接了各类基金、黄金和股票等来自不同金融主体、不同系统的数据,具有种类多、异构系统多和变化快的特点。我们的目标就是让资产总览数据尽可能准确,不同种类的资产变动的时候发出通知,资产系统收到通知后,根据变化的数据来计算出用户当前的资产总览。工资理财:工资理财是指每月工资下发到银行卡后,系统可以实现自动买入用户设置好的理财产品,例如买一些定投类的理财产品。这里信息的传递流程是:银行卡里的余额出现变动,系统把变动信息发送到消息引擎Consumer 端进行消费,通知用户账户已经出现变化;系统判断变动是否来源于代发工资;如果是,系统会再发送一条消息;理财的 Consumer 进行消费;判断现在是不是应该买入工资理财类的产品;如果是,自动买入用户设定好的理财产品;自动买入之后,余额再次变动,系统会再一次通知,这一次通知,判断的就是一些其他的逻辑了。那么,在这些场景中,我们对消息引擎会有哪些要求呢?A、高可用、高可靠和高性能,这是金融行业引入开源技术的基本要求;B、堆积能力,代发工资的用户很多,一个公司的员工会在某个时间点集中发放;C、顺序能力,即账户变动在先,发出通知在后;D、事务性能力,如果没有事务性,有可能会出现账户变动了,但没有触发购买理财产品的情况;E、重试和延迟消息功能,比如工资发放的时候,可能是在晚上,这时候系统会自动把购买理财的动作放在第二天白天去操作,再发出通知;F、消息回溯能力,就是出现问题的时候,我们可以把这个消息进行回溯,重新进行消息的处理,提供完整的消息轨迹;在技术选型的过程中,RocketMQ 符合我们在这些典型使用场景中对消息产品的需求,在引入的过程中,平安银行也对社区做了相应的贡献。复杂网络环境下的部署实践多测试子环境下的服务调用场景平安银行有多套测试子环境,用来对不同的feature进行测试,即图中的 FAT、FAT001、FAT002、FAT003等。传统银行系统由大型机时代向更面向互联网用户的零售时代转型过程中,不可避免微服务化,传统较集中式系统会被划分为较多的微服务,正常的情况如下图,服务 A 调用服务 B,服务 B 调用服务 C,服务 C 调用服务 D。随着业务的需求,新的 feature,我们需要对服务 A 和 B 进行改动。相比在FAT环境里去部署测试,更合适的方式是另起一套 FAT 环境,这里我们命名为 FAT001,把服务A和B部署上去,A 调用 B,B会调用原来 FAT 环境里的 C 和 D。此时,另一个新的需求,需要对服务 A 和 C 进行改动。如果直接发布到FAT 或 FAT001 肯定是不对的,会影响正在进行的测试,此时,我们会再起一套测试环境,命名为FAT002,发布服务 A 和 C。由于 FAT002 里没有服务 B,所以服务A要调用服务 B 就需要去 FAT 环境(FAT 定义为较稳定的测试子环境)。服务 B 调用服务 C 的时候,就不应该调用本环境的 C了,而是调动 FAT002 的 C 才能实现测试功能。再假设,系统同时还会有另外一个 feature 在测试 C 和 D,此时的调用逻辑也是一样的,系统调用服务 A 和 B 的时候是在 FAT,调用服务 C 和 D 的时候会到 FAT003 的环境。以上的服务调用场景是可以通过微服务框架解决的,进行全链路测试,但在生产环境中,用户的真实请求比测试环境中会更复杂一些。真实的用户请求过程我们看一下真实的用户请求。APP发起一个请求请求,进入网关,需要知道请求哪一个测试环境。通常的做法是:测试人员需要在APP上选好子环境,例如选择 FAT001,我们可以直接把请求 FAT001 的网关(每个环境网关单独部署),或者在requestheader上添加标识,让网关去区分它来源于哪一个环境(网关统一部署)。假如网关判断请求来源于 FAT002,那就会把分发给 FAT002环境进行处理。消息层面,如何处理这类用户请求以上是服务调用的请求路径,比较好理解,但到了消息队列上,问题会变得复杂些,假如一个 feature 只是更改了消费者,那如何把这条消息传递到改的消费者应用上去进行测试,而不被其它环境的消费者消费掉,这是我们需要去考虑的问题。来看下具体的情况,集群部署了 Broke A 和 Broke B,TopicA 分别部署在这两个Broker上。 此时,Producer Group A 向 Topic A 中写数据,Consumer Group A去消费,这种情况下是不会有任何问题。但如果新增一套 FAT001 的环境,要求 FAT001 发布的消息,只能由 FAT001 来消费,FAT 不能消费,这种情况下我们该怎么解决?在消息上面加一些路由、或是加一些Tag、Filter、消息的Property?这些都不能解决我们的问题。️每个子环境部署一套 RocketMQ?一方面成本太高,另一方面如果这个feture测试完成了,需要把相关的 应用再切回 FAT 进行处理,实现太过复杂。️我们想一下,多个 feature 同时进行测试,DB 会部署一套还是多套?首先一个 feature 不会更改所在的应用,一般来说 DB 是部署一套的,在数据库里面添加字段,来识别数据是来源于哪一个子环境,如果多套部署,不更改的应用取不到新部署的 DB 数据,无法进行全链路测试,所以同样的,我们也没有在每个子环境都部署一套 RocketMQ,而是部署统一部署,通过 RPC 路由把请求路由到正确的生产者集,改造消息路由算法把消息路由到正确的消费者进行处理。真实的用户请求过程在上图中生产者变更的场景下,默认的场景 FAT发送,FAT 消费 ,没有问题的,假设 FAT001 的生产者发布了,需要 FAT001 发送到MQ集群,FAT 是可以直接消费。在上图生产者和消费者同时变更的场景下,如果消费者在 FAT001也部署了应用,需要FAT消费者不能消费由FAT001产生的消息,而是由 FAT001的消费者去消费。我们的处理方式是在逻辑上把Topic A下面的Queue进行分组,相当于加了逻辑分组,如果消费者在 FAT001 有部署,我们会把 Queue 的分组扩大,在其默认设置的情况下再翻一倍,新增的 Queue 就是给到 FAT001 进行消费的。再来看看只有消费者变更的场景,如上图。假设有个feature只需要更改消费者,部署在 FAT001。也是可以通过逻辑分组的方式,实现生产者根据请求来源来发送消息到队列 FAT001 逻辑分组内的 Queue,从而只让部署在 FAT001 的消费者消费。通过以上 3 个场景,我们了解到添加逻辑分组的必要性,实现过程并不复杂。主要做了以下调整:️这个逻辑分组什么时候建立?新建 Topic 的时候,全部建好?还是 Consumer 上线/下线的时候动态的去进行调整?我们选择了动态创建的方式,这个过程中,我们添加了 Meta Server 进行元数据管理,进行动态创建:添加 Meta Service,管理的元数据包括 Producer、Consumer、Topic、Queue 和 Subenv等信息:调整 Producer,取Request Head 里面请求来源(FAT、FAT001、FAT002…),如果 Topic 对应的存在分组,选择分组的 Queue,否则发到默认分组呢的Queue;调整 Consumer,上线时判断应用部署的分组(FAT、FAT001、FAT002…),如果Topic不存在对应的分组,则新建;存在,则 rebalalce (新Consumer节点上线),下线时,判断该分组是否还存在 其它Consumer实例,若不存在,删除分组,否则 rebalalce(Consumer某一节点下线);多隔离区场景下的部署实践由于对安全上的重视,金融行业的网络环境相比其他行业会更复杂。整个隔离区分为以下几个部分:DMZ 区:外网可以直接访问,用于放置网关;Web 区:面向的是用户手机,或者网页上可以看到的功能应用;核心区:包含核心的调用逻辑功能,和交易、订单相关的核心应用,例如 DB 和存储;外联区:用于访问外网,有时候也会部署一些 Poxy 代理,因为内网不能直接访问外网,需要通过代理去访问外网;专用区域:对接基金、三方存管等外部系统。在金融行业,如果某个系统是闭环的,那必须要去做隔离;管理区:是指对整个区域的应用要进行集中管理,且数据流动是单向的,只能取数据,不能通过管理区把某区域的数据推送到另一区域。此外,从安全的角度出发,所有的区域在生产环境下都通过防火墙进行隔离,这就给我们部署 RocketMQ 带来了很大的实施难度。如果只部署一套,面对这么多的防火墙,生产者消费者到集群的的流量跨墙,会给网络带来极大的不稳定,遇到瓶颈,防火墙几乎无法在线平滑扩容;如果每个子环境都部署一套,又带来运维复杂度,而且还是存在数据同步和跨墙消费的问题。最终,我们采用的是折中的办法,即统一部署加分隔离区部署,这样做的益处是:防火墙是开大策略,保证安全的前提下,符合监管要求;针对跨隔离区消费的问题,我们采用复制的方式,模拟消费者重新写入目标集群;多IDC场景下的部署实践同城多IDC,可以认为近似局域网,比较好处理,但异地多IDC多活场景,目前我们还没有特别好的解方案,多活不可避免面临数据分片、数据合并和数据冲突的解决等问题。如果 Topic 下数据有多活需求,我们暂时通过复制方式来处理。但这类手工模拟消费者消费数据写入新集群的复制方式,会存在一些问题,即复制到另一个集群之后 offset 会改变,处理逻辑就会有偏差。我们通过 pull 的方式自定义的去根据 offset 去进行消费。当故障转移到新的集群需要去消费的时候,需要获取到新集群里面正确的offset 值。此时,这个值和之前集群里的已经不一样了,需要根据时间得到新集群里正确的offset 值,再去进行消费。在没有更好的解决方案前,治理就显得很关键了。不过,我们注意到,在 RocketMQ 最新发布的版本里,提供了 DLedger 的特性,DLedger 定位的是一个工业级的 Java Library,可以友好地嵌入各类 Java 系统中,满足其高可用、高可靠、强一致的需求。我们会尽快对这一特性进行集成和测试。改造实践和遇到的小插曲我们在对 RocketMQ 的使用过程中,添加了以下功能或特性:A. 为生产者提供消息的堆积能力。B. 将所有配置管理部署到配置中心,并做云端化处理,以满足动态修改的需求。C. 在 4.3 版本还未提供事务处理能力前,我们在本地数据库里去建一张消息表,数据库更改数据状态的时候,会同步将数据写入消息表。若发送失败,则进行补偿。并在客户端里进行封装。D. 实现统一的消息者幂等处理。E. 添加身份认证和消息认证(注:RocketMQ 4.3 版本中已经实现身份认证功能)当然,也遇到了一些小插曲,基本都是使用上的小问题,可能大家也会碰到:A. 一个应用使用多个RocketMQ集群时,未加载到正确的配置。在Client 端,如果没有对 instancename 进行配置,一个应用连多个集群会失败。B. 在大数据的场景下,内存溢出。订阅的 Topic 越多,每个 Queue 在本地缓存的 message 也会越多,默认每个 Queue 1000条,可能会把内存打爆,可根据实际情况调整。C. 删除数据时 IO 抖动,默认每天凌晨4点删除数据,量上来后出现 IO 抖动,配置了消息删除策略,默认逗号分隔开,多配几个时间删除就可以了。D. Broker上日志报延迟消息找不到数据文件。在主备切换的演练过程中,出现了延迟消息在 Broker 上处理异常的情况。当主切换到备端时,延迟消息在 Broker 上保存的文件被自动删除,再切回主,由于延时消息的元数据感觉在,会查询文件进行处理,此时已找不到文件。E. 挂 NAS 的时候,IP 获取了 NAS 的私网地址,并被提交给了服务端。以上就是我们在部署过程中遇到的一些小插曲,基本都是可以很快定位原因,解决的。总的来看,RocketMQ 对平安银行的消息系统建设的帮助是非常大的,尤其是满足了数据持久化、顺序消费和回溯的需求,此外,在消息的查询方面,也比我们之前使用的消息引擎好很多。最后再分享一点自己对中间件的一点感悟:中间件使用重在治理,规范不先行,开发两行泪。本文作者:吴建峰,GitHub ID @devilfeng,来自平安银行平台架构部基础框架团队。更多 RocketMQ 的实践案例:RocketMQ x 微众银行RocketMQ x 同程艺龙RocketMQ x 滴滴出行本文作者:中间件小哥阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

March 11, 2019 · 2 min · jiezi

Dubbo Mesh 在闲鱼生产环境中的落地实践

本文作者至简曾在 2018 QCon 上海站以《Service Mesh 的本质、价值和应用探索》为题做了一次分享,其中谈到了 Dubbo Mesh 的整体发展思路是“借力开源、反哺开源”,也讲到了 Service Mesh 在阿里巴巴的发路径将经历以下三大阶段:撬动做透价值渗透实现技术换代Dubbo Mesh 在闲鱼生产环境的落地,分享的是以多语言为撬动点的阶段性总结。文章首发于「QCon」,阿里巴巴中间件授权转载。闲鱼场景的特点闲鱼采用的编程语言是 Dart,思路是通过 Flutter 和 Dart 实现 iOS、Android 两个客户端以及 Dart 服务端,以“三端一体”的思路去探索多端融合的高效软件开发模式。更多细节请参考作者同事陈新新在 2018 QCon 上海站的主题分享《Flutter & Dart 三端一体化开发》。本文将关注三端中的 Dart 服务端上运用 Dubbo Mesh 去解耦 Dubbo RPC 框架的初步实践成果。Dart 服务端是一个服务调用胶水层,收到来自接入网关发来的 HTTP 请求后,通过 C++ SDK 调用集团广泛提供的 Dubbo 服务完成业务逻辑处理后返回结果。然而,C++ SDK 的功能与 Java 的存在一定的差距,比如缺失限流降级等对于保障大促稳定性很重要的功能。从长远发展的角度,闲鱼团队希望通过 Dubbo Mesh 能屏蔽或简化不同技术栈使用中间件(比如,RPC、限流降级、监控、配置管理等)的复杂性。这一诉求的由来,是闲鱼团队通过几个月的实践,发现在 Dart 语言中通过 C++ SDK 逐个接入不同中间件存在定制和维护成本高的问题。值得说明,所谓的“定制”是因为 C++ SDK 的能力弱于 Java SDK 而要做补齐所致。Dart 服务端自身的业务逻辑很轻且在一些场景下需要调用 20 多次 Dubbo 服务,这对于 Dubbo Mesh 的技术挑战会显得更大。在 Dubbo Mesh 还没在生产环境落地过而缺乏第一手数据的情形下,其性能是否完全满足业务的要求是大家普遍关心的。架构与实现图中的虚框代表了一个Pouch容器(也可以是一台物理机或虚拟机)。左边两个容器部署了 Dubbo Mesh,剩下最右边的则没有。目前 Dubbo Mesh 主要包含 Bonder、Pilot、Envoy 三个进程,以及被轻量化的 Thin SDK。其中:Envoy 承担了数据平面的角色,所有 mesh 流量将由它完成服务发现与路由而中转。Envoy 由 Lyft 初创且目前成为了 CNCF 的毕业项目,我们在之上增加了对 Dubbo 协议的支持,并将之反哺到了开源社区(还有不少代码在等待社区 review 通过后才能进到 GitHub 的代码仓库)。Pilot 和 Bonder 共同承担控制平面的角色,实现服务注册、进程拉起与保活、集群信息和配置推送等功能。Pilot 进程的代码源于开源 Istio 的 pilot-discovery 组件,我们针对阿里巴巴集团环境做了一定的改造(比如,与Nacos进行适配去访问服务注册中心),且采用下沉到应用机器的方式进行部署,这一点与开源的集群化部署很不一样。背后的思考是,Pilot 的集群化部署对于大规模集群信息的同步是非常大的一个挑战,今天开源的 Istio 并不具备这一能力,未来需要 Nacos 团队对之进行增强,在没有完全准备好前通过下沉部署的方式能加速 Service Mesh 的探索历程。Thin SDK 是 Fat SDK 经过裁剪后只保留了对 Dubbo 协议进行编解码的能力。为了容灾,当 Thin SDK 位于 Consumer 侧时增加了一条容灾通道,细节将在文后做进一步展开。数据链路全部采用单条 TCP 长连接,这一点与非 mesh 场景是一致的。Pilot 与 Envoy 两进程间采用的是 gRPC/xDS 协议进行通讯。图中同时示例了 mesh 下的 Consumer 能同时调用 mesh 下的服务(图中以 www.mesh.com 域名做示例)和非 mesh 下的服务(图中以 www.non-mesh.com 域名做示例)。闲鱼落地的场景为了避免对 20 多个依赖服务进行改造,流量走的是 mesh 下的 Consumer 调用非 mesh 下的 Provider 这一形式,读者可以理解为图中最左边的容器部署的是 Dart 服务端,它将调用图中最右边容器所提供的服务去实现业务逻辑。容灾从 Dubbo Mesh 下的 Provider 角度,由于通常是集群化部署的,当一个 Provider 出现问题(无论是 mesh 组件引起的,还是 Provider 自身导致的)而使服务无法调通时,Consumer 侧的 Envoy 所实现的重试机制会将服务请求转发到其他 Provider。换句话说,集群化部署的 Provider 天然具备一定的容灾能力,在 mesh 场景下无需特别处理。站在 Dubbo Mesh 的 Consumer 立场,如果完全依赖 mesh 链路去调用 Provider,当 mesh 链路出现问题时则会导致所有服务都调不通,这往往会引发业务可用性问题。为此,Thin SDK 中提供了一个直连 Provider 的机制,只不过实现方式比 Fat SDK 轻量了许多。Thin SDK 会定期从 Envoy 的 Admin 接口获取所依赖服务的 Provider 的 IP 列表,以备检测到 mesh 链路存在问题时用于直连。比如,针对每一个依赖的服务获取最多 10 个 Provider 的 IP 地址,当 mesh 链路不通时以 round robin 算法向这些 Provider 直接发起调用。由于容灾是针对 mesh 链路的短暂失败而准备的,所以 IP 地址的多少并不是一个非常关键的点。Thin SDK 检测 mesh 链路的异常大致有如下场景:与 Envoy 的长连接出现中断,这是 Envoy 发生 crash 所致。所发起的服务调用收到 No Route Found、No Healthy Upstream 等错误响应。优化在闲鱼落地 Dubbo Mesh 的初期我们走了一个“弯路”。具体说来,最开始为了快速落地而采用了 Dubbo over HTTP 1.1/2 的模式,也即,将 Dubbo 协议封装在 HTTP 1.1/2 的消息体中完成服务调用。这一方案虽然能很好地享受 Envoy 已完整支持 HTTP 1.1/2 协议而带来的开发工作量少的好处,但性能测试表明其资源开销并不符合大家的预期。体现于,不仅 Consumer 侧使用 mesh 后带来更高的 CPU 开销,Provider 侧也因为要提供通过 HTTP 1.1/2 进行调用的能力而导致多出 20% 的 CPU 开销且存在改造工作。最终,我们回到让 Envoy 原生支持 Dubbo 协议的道路上来。Envoy 支持 Dubbo 协议经历了两大阶段。第一个阶段 Envoy 与上游的通讯并没有采用单条长连接,使得 Provider 的 CPU 开销因为多连接而存在不可忽视的递增。第二个阶段则完全采用单条长连接,通过多路复用的模式去除了前一阶段给 Provider 所带去的额外 CPU 开销。Dubbo Mesh 在闲鱼预发环境上线进行性能与功能验证时,我们意外地发现,Istio 原生 Pilot 的实现会将全量集群信息都推送给处于 Consumer 侧的 Envoy(Provider 侧没有这一问题),导致 Pilot 自身的 CPU 开销过大,而频繁的全量集群信息推送也使得 Envoy 不时会出现 CPU 负荷毛刺并遭受没有必要的内存开销。为此,我们针对这一问题做了集群信息按需加载的重大改造,这一优化对于更大规模与范围下运用 Dubbo Mesh 具有非常重要的意义。优化的大致思路是:Thin SDK 提供一个 API 供 Consumer 的应用在初始化时调用,周知其所需调用的服务列表。Thin SDK 通过 HTTP API 将所依赖的服务列表告诉 Bonder,Bonder 将之保存到本地文件。Envoy 启动时读取 Bonder 所保存的服务列表文件,将之当作元信息转给 Pilot。Pilot 向 Nacos 只订阅服务列表中的集群信息更新消息且只将这些消息推送给 Envoy。监控可观测性(observability)是 Service Mesh 非常重要的内容,在服务调用链路上插入了 Envoy 的情形下,愈加需要通过更强的监控措施去治理其上的所有微服务。Dubbo Mesh 的监控方案并没有使用 Istio/Mixer 这样的设计,而是沿用了阿里巴巴集团内部的方式,即信息由各进程以日志的形式输出,然后通过日志采集程序将之送到指定的服务端进行后期加工并最终展示于控制台。目前 Dubbo Mesh 通过 EagleEye 去跟踪调用链,通过ARMS去展示其他的监控信息。性能评估为了评估 Dubbo Mesh 的性能能否满足闲鱼业务的需要,我们设计了如下图所示的性能比对测试方案。其中:测试机器是阿里巴巴集团生产环境中的 3 台 4 核 8G 内存的 Pouch 容器。蓝色方框代表的是进程。测试数据全部从部署了 DartServer 和 Envoy 两进程的测试机 2 上获得。性能数据分别在非 mesh(图中红色数据流)和 mesh(图中蓝色数据流)两个场景下获得。显然,Mesh 场景下的服务流量多了 Envoy 进程所带来的一跳。DartServer 收到来自施压的 Loader 进程所发来的一个请求后,将发出 21 次到 Provider 进程的 RPC 调用。在评估 Dubbo Mesh 的性能时,这 21 次是串行发出的(下文列出的测试数据是在这一情形下收集的),实际闲鱼生产环境上线时考虑了进行并行发送去进一步降低整体调用时延(即便没有 mesh 时,闲鱼的业务也是这样实现的)。Provider 进程端并没有部署 Envoy 进程。这省去了初期引入 Dubbo Mesh 对 Provider 端的改造成本,降低了落地的工作量和难度。设计测试方案时,我们与闲鱼的同学共创了如何回答打算运用 Dubbo Mesh 的业务方一定会问的问题,即“使用 Dubbo Mesh 后对 RT(Response Time)和 CPU 负荷的影响有多大”。背后的动机是,业务方希望通过 RT 这一指标去了解 Dubbo Mesh 对用户体验的影响,基于 CPU 负荷的增长去掌握运用新技术所引发的成本。面对这一问题通常的回答是“在某某 QPS 下,RT 增加了 x%,CPU 负荷增加了 y%”,但这样的回答如果不进行具体测试是无法给出的(会出现“鸡和蛋的问题”)。因为每个业务的天然不同使得一个完整请求的 RT 会存在很大的差别(从几毫秒到几百毫秒),而实现业务逻辑所需的计算量又最终决定了机器的 CPU 负荷水平。基于此,我们设计的测试方案在于评估引入 Dubbo Mesh 后,每经过一跳 Envoy 所引入的 RT 和 CPU 增量。当这一数据出来后,业务方完全可以基于自己业务的现有数据去计算出引入 Dubbo Mesh 后的而掌握大致的影响情况。显然,背后的逻辑假设是“Envoy 对于每个 Dubbo 服务调用的计算量是一样的”,事实也确实如此。测试数据以下是 Loader 发出的请求在并发度为 100 的情形下所采集的数据。表中:Envoy 的 QPS 是 Loader 的 21 倍,原因在上面测试方案部分有交代。“单跳”的数据是从“21 跳合计”直接除以 21 所得,其严谨性值得商榷,但用于初步评估仍具参考价值(有数据比没有数据强)。“整机负荷”代表了在 mesh 场景下测试机器 2 上 DartServer 和 Envoy 两进程的 CPU 开销总和。测试表明,CPU 负荷高时 Envoy 带来的单跳 RT 增幅更大(比如表中 Loader 的 QPS 是 480 时)。给出整机负荷是为了提醒读者关注引入 mesh 前业务的正常单机水位,以便更为客观地评估运用 Dubbo Mesh 将带来的潜在影响。“CPU 负荷增幅”是指 CPU 增加的幅度。由于测试机是 4 核的,所以整机的 CPU 负荷是 400。从表中数据来看,随着机器整体负荷的增加“CPU 负荷增幅”在高段存在波动,这与 RT 在高段的持续增大存在相关,从 RT 在整体测试中完全符合线性增长来看整体数据合理。当然, 后面值得深入研究数据背后的隐藏技术细节以便深入优化。线上数据Dubbo Mesh 正式生产环境上线后,我们通过对上线前后的某接口的 RT 数据进行了全天的比对,以便大致掌握 mesh 化后的影响。2019-01-14 该接口全面切成了走 Dubbo Mesh,我们取的是 2019-01-20 日的数据。图中蓝色是 mesh 化后的 RT 表现(RT 均值 3.3),而橙色是 mesh 化前的 RT 表现(RT 均值 3.27,取的是 2019-01-13 的数据)。由于线上每天的环境都有所不同,要做绝对的比较并不可能。但通过上面的比较不难看出,mesh 化前后对于整体 RT 的影响相当的小。当整体 RT 小于 5 毫秒是如此,如果整体 RT 是几十、几百毫秒则影响就更小。为了帮助更全面地看待业务流量的波动特点,下面分别列出了两天非 mesh(2019-01-06 和 2019-01-13)和两天 mesh(2019-01-20 和 2019-01-23)的比对数据。总之,生产环境上的数据表现与前面性能评估方案下所获得的测试数据能很好地吻合。洞见Dubbo Mesh 在闲鱼生产环境的落地实践让我们收获了如下的洞见:服务发现的时效性是 Service Mesh 技术的首要关键。 以集群方式提供服务的情形下(这是分布式应用的常态),因为应用发布而导致集群中机器状态的变更如何及时准确地推送到数据平面是极具挑战的问题。对于阿里巴巴集团来说,这是 Nacos 团队致力于解决的问题。开源版本的 Istio 能否在生产环境中运用于大规模分布式应用也首先取决于这一能力。频繁的集群信息推送,将给控制平面和数据平面都带去负荷扰动,如何通过技术手段控制好扰动是需要特别关注的,对于数据平面来说编程语言的“确定性”(比如,没有 VM、没有 GC)在其中将起到不可忽视的作用。数据平面的软件实现最大程度地减少内存分配与释放将显著地改善性能。有两大举措可以考虑:逻辑与数据相分离。 以在 Envoy 中实现 Dubbo 协议为例,Envoy 每收到一个 RPC 请求都会动态地创建 fitler 去处理,一旦实现逻辑与数据相分离,filter 的创建对于每一个 worker 线程有且只有一次,通过这一个 filter 去处理所有的 RPC 请求。使用内存池。 Envoy 的实现中基本没有用到内存池,如果采用内存池对分配出来的各种 bufffer 通过链表进行缓存,这将省去大量的内存分配与释放而改善性能。再则,对于处理一个 RPC 请求而多次分散分配的动作整合成集中一次性分配也是值得运用的优化技巧。数据平面的 runtime profiling 是关键技术。 Service Mesh 虽然对业务代码没有侵入性,但对服务流量具有侵入性,如何在出现业务毛刺的情形下,快速地通过 runtime profiling 去发现问题或自证清白是非常值得关注的点。心得一年不到的探索旅程,让团队更加笃定“借力开源,反哺开源”的发展思路。随着对 Istio 和 Envoy 实现细节的更多掌握,团队很强列地感受到了走“站在巨人的肩膀上”发展的道路少走了很多弯路,除了快速跟进业界的发展步伐与思路,还将省下精力去做更有价值的事和创新。此外,Istio 和 Envoy 两个开源项目的工程质量都很高,单元测试等质量保证手段是日常开发工作中的基础环节,而我们也完全采纳了这些实践。比如,内部搭建了 CI 环境、每次代码提交将自动触发单元测试、代码经过 code review 并完成单元测试才能入库、自动化性能测试等。展望在 2019 年接下来的日子,我们将着手:与 Sentinel 团队形成合力,将 Sentinel 的能力纳入到 Dubbo Mesh 中补全对 HTTP 和 Dubbo 协议的限流、降级和熔断能力。在阿里巴巴集团大范围 Kubernetes(Sigma 3.1)落地的背景下,与兄弟团队探索更加优雅的服务流量透明拦截技术方案。迎合 Serverless 的技术发展趋势,深化通过 Dubbo Mesh 更好地轻量化应用,以及基于 Dubbo Mesh 对服务流量的天然敏感性去更好地实现 auto-scaling。在产品的易用性和工程效率方面踏实进取。未来,我们将及时与读者分享阿里巴巴集团在 Service Mesh 这一新技术领域的探索成果,也期待与大家有更多的互动交流。本文作者:至简,阿里巴巴中间件高级技术专家,是阿里巴巴集团 Service Mesh 方向的重要参与者和推动者。关于 Dubbo Mesh 的首次公开分享本文作者:中间件小哥阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

March 11, 2019 · 3 min · jiezi

通过阿里云K8S Ingress Controller实现路由配置的动态更新

摘要: 本文主要描述了阿里云Kubernetes集群Ingress Controller如何通过动态更新的方式来极大地缓解转发平面Nginx频繁Reload带来的影响。简介在Kubernetes集群中,Ingress作为集群内服务对外暴露的访问接入点,其几乎承载着集群内服务访问的所有流量。我们知道,Nginx Ingress Controller是Kubernetes社区很重要的一个子项目,其内部主要依托于高性能的负载均衡软件Nginx,将Kubernetes Ingress资源对象实时地自动化转换为Nginx配置规则来对外提供期望的授权访问入口。现实问题当随着Kubernetes集群中部署的微服务越来越多,对外暴露的路由规则越来越复杂,服务后端Endpoint变化的越来越频繁,那么对应地都会引起Nginx Ingress Controller组件内Nginx配置文件的变化越来越频繁;而我们知道,任何一行Nginx配置的变化,都需要Reload Nginx才能生效,这在变化频率较低的场景下索性还能接受,但在高频率变化的场景下就会引起Nginx的频繁Reload。而Nginx频繁Reload带来的问题,这已是一个老生常谈的话题了,其问题本质主要还是源于Nginx本身最初的架构设计模型:一般在Linux服务器中,我们会配置使用Nginx的EPOLL多进程模式;当我们修改了Nginx配置文件后,需要通过nginx -s reload命令来重新热加载新的Nginx配置规则;当Nginx Master进程接收到reload signal后,其会从指定路径重新加载新的Nginx配置文件内容,并校验配置规则的有效性,若检验为有效的配置文件,则会依据新的配置文件中的worker_processes值fork出指定数量的新的Nginx Worker进程,此时新fork出来的子进程完全继承了父进程的内存数据ngx_cycle(其包含了新的解析后的Nginx配置规则),同时将配置中的每一个Listen Socket FD注册到内核的EPOLL事件监听中,此时这些新的Nginx Worker进程可以接收处理来自客户端的请求;同时Nginx Master进程会发送QUIT signal通知老的Nginx Worker进程平滑退出,当老的Nginx Worker进程接收到QTUI信号后,将其之前注册到EPOLL中的监听Event移除,至此不再接收处理新的客户端请求,并依据老配置文件中设置的worker_shutdown_timeout值来设置定时器,然后继续处理完已接收的客户端请求;若在worker_shutdown_timeout之前处理完已有的客户端请求,则自动退出,若未处理完,则被强制Kill退出,此时就会导致该客户端请求响应异常。因此,对于在高频率变化的场景下,Nginx频繁Reload会带来较明显的请求访问问题:造成一定的QPS抖动和访问失败情况对于长连接服务会被频繁断掉造成大量的处于shutting down的Nginx Worker进程,进而引起内存膨胀动态更新为缓解Nginx频繁Reload带来的影响,我们需要通过动态更新的方式来加载Nginx配置规则,即在不Fork新Nginx Worker进程的情况下来实时更新已加载到内存中的Nginx配置规则。首先我们看下Nginx的配置文件样式,主要包含下面几部分配置章节:# 1. main configurationdaemon off;worker_processes 4;events { # 2. event configuration multi_accept on; worker_connections 1024; use epoll;}http { # 3. http main configuration access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; upstream { # 4. upstream configuration server 0.0.0.1; } server { # 5. server configuration server_name _ ; listen 80 default_server; location / { # 6. location configuration proxy_pass http://upstream_balancer; }}而在Kubernetes集群中,一个Ingress资源对象主要被解析映射到Nginx的HTTP Main Block、Server Block、Upstream Block和Location Block等章节的配置规则上,因此我们可以将这几部分频繁变化的配置内容以Shared Memory的方式统一维持在内存中,同时在Ingress Controller内部暴露出管控端口,通过API的方式来实时管理Nginx路由规则配置:当K8S Ingress Controller监控到集群内Ingress及相关联的资源发生变化时,均可通过Internal API将最新的Nginx配置规则推送到统一的共享内存配置中,而不用再通过Reload Nginx的方式来使新配置生效,至此当Nginx处理任何新接收的客户端请求时,都可以基于最新的共享内存中的配置进行规则匹配和路由转发;配置说明1、目前阿里云容器服务Kubernetes集群中最新版本的Nginx Ingress Controller组件默认已开启Upstream的动态更新,同时支持应用服务的灰度发布和蓝绿发布功能,具体配置说明可参考这里;我们可以通过如下命令来查看当前共享内存中的Nginx Upstream的配置列表:kubectl -n kube-system exec -it <NGINX-INGRESS-CONOTROLLER-POD-NAME> – curl http://127.0.0.1:18080/configuration/backends2、同时也支持HTTPS证书的动态更新,可通过修改nginx-ingress-controller deployment的如下参数配置来开启Nginx Ingress Controller的证书动态更新:- args: - /nginx-ingress-controller - –configmap=$(POD_NAMESPACE)/nginx-configuration - –tcp-services-configmap=$(POD_NAMESPACE)/tcp-services - –udp-services-configmap=$(POD_NAMESPACE)/udp-services - –annotations-prefix=nginx.ingress.kubernetes.io - –publish-service=$(POD_NAMESPACE)/nginx-ingress-lb - –enable-dynamic-certificates=true ### 添加该配置 - –v=2当开启HTTPS证书的动态更新后,Ingress的TLS证书都统一维护在Nginx的共享内存中,我们可通过如下命令来查看当前共享内存中配置的证书列表:kubectl -n kube-system exec -it <NGINX-INGRESS-CONOTROLLER-POD-NAME> – curl http://127.0.0.1:18080/configuration/certs3、进一步地我们也支持Nginx Server和Location配置的动态更新,可通过修改nginx-ingress-controller deployment的如下参数配置来开启Nginx Ingress Controller的Server和Location的动态更新:- args: - /nginx-ingress-controller - –configmap=$(POD_NAMESPACE)/nginx-configuration - –tcp-services-configmap=$(POD_NAMESPACE)/tcp-services - –udp-services-configmap=$(POD_NAMESPACE)/udp-services - –annotations-prefix=nginx.ingress.kubernetes.io - –publish-service=$(POD_NAMESPACE)/nginx-ingress-lb - –enable-dynamic-certificates=true ### 添加该配置 - –enable-dynamic-servers=true ### 添加该配置,同时也要enable-dynamic-certificates - –v=2同样地,当我们开启了Nginx Ingress Controller的Server动态更新后,所有Nginx Server和Location的配置都统一维护在共享内存中,我们同样可以通过如下命令来查看当前共享内存中的Server配置列表:kubectl -n kube-system exec -it <NGINX-INGRESS-CONOTROLLER-POD-NAME> – curl http://127.0.0.1:18080/configuration/servers注意说明:当开启Server的动态更新特性后,部分Ingress Annotation配置暂不支持,正在逐步优化支持中,相应地您可直接通过ConfigMap方式来进行配置;本文作者:chenqz阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

March 8, 2019 · 1 min · jiezi

阿里云TSDB在大数据集群监控中的方案与实战

目前大部分的互联网企业基本上都有搭建自己的大数据集群,为了能更好让我们的大数据集群更加高效安全的工作,一个优秀的监控方案是必不可少的;所以今天给大家带来的这篇文章就是讲阿里云TSDB在上海某大型互联网企业中的大数据集群监控方案中的实战案例,希望能为感兴趣的同学提供一些帮助。背景和需求阿里云时序时空数据库 (原阿里云时间序列数据库, 简称 TSDB) 是一种高性能,低成本,稳定可靠的在线时序数据库服务;提供高效读写,高压缩比存储、时序数据插值及聚合计算,广泛应用于物联网(IoT)设备监控系统 ,企业能源管理系统(EMS),生产安全监控系统,电力检测系统等行业场景。 TSDB 提供百万级时序数据秒级写入,高压缩比低成本存储、预降采样、插值、多维聚合计算,查询结果可视化功能;解决由于设备采集点数量巨大,数据采集频率高,造成的存储成本高,写入和查询分析效率低的问题。Elastic MapReduce(EMR)是阿里云提供的一种大数据处理的系统解决方案。EMR基于开源生态,包括 Hadoop、Spark、Kafka、Flink、Storm等组件,为企业提供集群、作业、数据管理等服务的一站式企业大数据平台。上海某大型互联网企业是阿里云EMR的Top客户,在阿里云上购买的EMR实例有近千台hadoop机器,这些机器目前除了阿里云本身ECS级别的监控以外,没有一套成熟的这对大数据的监控运维告警系统,对大数据业务来讲存在很大的风险。现在客户的需求是对购买的EMR集群做监控和告警,单台有20多个监控指标,采集精度可以根据客户需求调整,另外还要求对原有的业务无侵入,不需要业务层做太多的配置重启类操作。痛点和挑战该大型互联网企业客户最初计划采用的是Prometheus作为监控和告警解决方案,并且基于Prometheus的监控方案也在该企业内部其他系统应用了。这里提到了Prometheus,就多说几句。随着业内基于Kubernetes的微服务的盛行,其生态兼容的开源监控系统Prometheus也逐渐被大家热捧。Prometheus是一个开源监控系统,它前身是SoundCloud的监控系统,在2016年继Kurberntes之后,加入了Cloud Native Computing Foundation。目前许多公司和组织开始使用Prometheus,该项目的开发人员和用户社区非常活跃,越来越多的开发人员和用户参与到该项目中。下图就是prometheus方案的架构:这个方案在实际部署过程中发现Prometheus在存储和查询上存在性能的问题,主要是Prometheus本身采用的local storage方案在大数据量下的扩展性写入查询性能存在瓶颈。另外在这个方案的适配性不强,要改很多参数重启才行,这对于线上正在运行的业务来说,是不可接受的,需要重新设计解决方案。阿里云TSDB解决方案监控和告警整体上来说包括三个环节:1.采集指标2.存储指标3.查询告警因此基本方案就可以简化为:采集工具 + 数据库 + 查询告警。其中,数据库可以通过阿里云TSDB来解决存储和查询上的性能问题,查询告警可以通过成熟的开源工具Grafana。由于该互联网企业客户的要求对原有的业务无侵入,不需要业务层做太多的配置重启类操作,因此解决方案的调研就重点落在了采集工具的调研上了。对于采集工具而言,结合该互联网企业客户已经部署的Prometheus,且阿里云TSDB兼容开源时序数据库OpenTSDB的写入和查询协议,因此从减少成本和工作量的角度来看,可以考虑的方式是有两种:1. 使用Prometheus官方提供的开源的OpenTSDB Adapter 对接原生的Prometheus ,实现数据写入到TSDB。基本架构为:这种方案和该互联网企业客户的开发同学沟通后,发现满足不了对业务无侵入,不重启的需求,因此选择放弃;2. 采用其他开源工具,实现数据采集写入到TSDB。开源社区较为活跃,已经提供了不少开源的采集工具,因此我门评估了以下几个开源的采集工具:Collectd,https://collectd.orgtelegraf, https://github.com/influxdata/telegraf* statsd, https://github.com/etsy/statsdtcollector, http://opentsdb.net/docs/build/html/user_guide/utilities/tcollector.html从开发语言、部署方式以及是否支持定制开发等角度,我们初步选择tcollector作为采集工具。tcollector是一个客户端程序,用来收集本机的数据,并将数据发送到OpenTSDB。tcollector可以为你做下面几件事:运行所有的采集者并收集数据;完成所有发送数据到TSDB的连接管理任务;不必在你写的每个采集者中嵌入这些代码;是否删除重复数据;处理所有有线协议,以后今后的改进;因此,基于tcollector + TSDB + Grafana的监控告警架构如下,其中tcollector以http协议从目标结点上拉取监控指标,并以http的OpenTSDB协议将指标推送至阿里云TSDB。这个方案在不修改tcollector源码的基础上,能够满足客户对hadoop的监控。但是在PoC后,客户增加了对EMR实例中其他大数据组件的监控需求,如Hive, Spark, Zookeeper, HBase, Presto, Flink, azkaban, kafka, storm等。经过我们调研,tcollector对于这些组件的支持程度如下:原生支持:hbase;需定制化开发,不重启实例:Hive, Spark, Zookeeper;需定制化开发,需重启实例:Flink, azkaban, kafka, storm;经过一定工作量的制化开发,基于tcollector的方案基本可以满足用户的需求。最终我们在该互联网企业客户的EMR大数据集群的监控告警方案架构为:tcollector非常简单易部署,可以简单高效地完成了客户的需求。而且配置部署时,可以不用区分大数据组件的角色,解决了之前开源采集工具需要针对不同角色,来手动配置并启动相应插件的问题。至此,TSDB完美得解决了该互联网企业客户大数据集群监控接入TSDB的案例,让TSDB在迈向完善生态的路上更进一步了。另外值得一提的是,为了解决目前广泛使用的Prometheus开源系统在大量时序数据的存储、写入和查询存在性能瓶颈问题,阿里云TSDB也已经开始兼容了Prometheus生态,并且已经在多个客户场景进行了实战。后面我们会推出针对Prometheus的系列文章,对Prometheus感兴趣或者已经是Prometheus用户但是遇到性能问题的同学可以持续关注我们。阿里云时序时空数据库TSDB 1元购!立即体验:https://promotion.aliyun.com/ntms/act/tsdbtry.html?spm=5176.149792.775960.1.dd9e34e2zgsuEM&wh_ttid=pc本文作者:焦先阅读原文本文为云栖社区原创内容,未经允许不得转载。

March 6, 2019 · 1 min · jiezi

云计算底层技术之高性能集群趣谈

本文首发于我的公众号 CloudDeveloper(ID: cloud_dev),专注于干货分享,号内有大量书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫。在孙悟空的七十二变中,我觉得最厉害的是分身能力,这也是他百试不得其爽的终极大招,每每都能打得妖怪摸不着北。集群,学名叫 Cluster,可以翻译为簇、聚类、集群等多种意思,不同的翻译,在技术世界里所表示的意思都不尽相同,但都有一个共同的指向,即群体。集群就是由一组计算机所组成的实体,通常作为一个整体向用户提供资源和服务。集群的研究和发展离不开人们对高性能计算的追求,像我们熟悉的向量机、对称多处理机、工作站、超级计算机等等都是对高性能计算追求下的产物。这些系统要么是提高 CPU 的主频和总线带宽来提高系统性能,要么是增加 CPU 个数和内存容量来提高性能,但这些手段对性能的提高都是有限的。有人做过实验,当 CPU 个数超过某一阈值时,系统的性能反而会变差。其主要的瓶颈就在于 CPU 访问内存的带宽并不能随着 CPU 个数的增加而有效增加。相反,集群系统的性能可扩展能力是线性增长的。我们可以简单通过增加机器数来增加集群的运算能力,相比购买高性能的大型计算机,同等运算能力下,我们可以获得更高的性价比。同时,系统的可靠性也得到了增强。历史早在七十年代计算机厂商和研究机构就开始了对集群系统的研究和开发,首先创造性发明集群的是 Seymour Cray(西摩·克雷)—— 超级计算机之父。Seymour 是一位美国工程师,在 1960 年代,CDC 公司开始涉足高性能计算领域,彼时还是大型机的天下,这些大型机设计非常复杂,生产周期漫长,价格还非常昂贵。于是,当时在 CDC 公司担任总设计师的 Seymour 就决心建造出一台他心目中的高性能计算机。Seymour 出于工程师的直觉,很快想到并行是提高计算机性能的有效方式。他使用廉价的方式来获得跟大型机一样的运算能力。他将多个普通的处理器连接起来,使它们能够协同工作,这就是高性能计算机的原型。后来,IBM、HP 等公司学习了 Seymour 的这套架构,高性能计算机开始迅速推广,逐步取代原有的大型机。高性能计算机为当时的登月计划等大型科研项目作出了非常重要的贡献。然后进入八十年代,在摩尔定律的指导下,CPU 频率不断提高,芯片不断降价,个人计算机强势崛起。苹果、微软等公司借助这股东风成为个人计算机时代的王者。随之而来的就是高性能计算机市场遭到了吞噬,被迫只能退守公司服务器市场。但很快,随着互联网的普及,高性能计算机又迎来新的一波热潮。互联网上用户量庞大,普通 PC 难以应付如此众多的网络请求,必须要依赖由高性能计算机组成的服务器集群。在 2000 年左右的网络泡沫时期,成就了很多像 Sun 这样的服务器生产商。如今,IT 行业向云计算冲击,诸如 Google、Apple、Amazon 等很巨头纷纷建立起了自己的数据中心。集群的规模在不断扩大,为海量的数据提高基础设施提供了支撑。根据不同的应用场景,集群也演变出多种形态,比如高性能集群、高可用集群、负载均衡集群等等。集群元素集群不是简单的硬件堆叠,而是硬件和软件的结合。从软件上说,集群至少需要:构建于 TCP/IP 协议上的通信软件,用于集群中节点之间的通信。一套中心管理软件,用于统一管理集群中节点的资源、任务和容错等等。这两点比较好理解,集群的规模往往是比较庞大的,对于管理员来说,需要随时能够知晓集群中各节点的业务正常与否,出问题了应该怎么保证业务能够不中断,遇到流量高峰和低谷的时候,又该怎么响应,这些操作如果纯靠人工来完成那必将很惨烈。依靠软件和网络来完成自动化的管理方式,可以将管理员解放出来。当然,以上说的两点是比较宽泛的,用户可以根据自身需求来部署不同的集群元素。一个比较经典的集群模型当属 Beowulf 集群,它通过一个节点统一将来自网络的请求分配给各个节点进行计算处理。集群与分布式集群与分布式像一对孪生兄弟,傻傻分不清楚。在我看来,它们之间没有特别明确的分界线,集群离不开分布式,分布式也需要集群。如果一定要做个区分,可以套用一个比喻来描述两者的区别:一家餐厅刚开业,由于成本限制招了一个厨师,慢慢地,餐厅生意越做越好,一个厨师已经很难应付过来,于是又招了一个,这两个厨师水平相当,都能做同样的事,两个厨师之间的关系就是集群。两厨师除了炒菜,还要负责洗菜、配菜等等的活,工作负荷已经严重超标,为了让厨师能专心炒菜,把菜做到极致,餐厅又招了配菜师来辅助厨师,厨师和配菜师之间的关系就是分布式。这个例子比较形象,在网站开发中也有类似的关系,两个全栈工程师之间就是集群的关系,前端工程师和后端工程师之间就属于分布式的关系。所以,一定要有区分的话就是:集群是一个业务部署在多个服务器上,而分布式是一个业务拆分成多个子业务部署在不同的服务器上。但在实际部署中,为了高性能,需要分布式部署,为了高可用,需要集群部署,这两者都是业务所必须的指标。所以,集群和分布式之间的关系是相互补充的。虚拟化随着虚拟化技术的发展,一台服务器可以虚拟出多个虚拟机,对外提供业务,这种方式大大提高了资源的利用率,集群的部署也逐步从物理机过渡到虚拟机,灵活性大大提高。但同时也带来了更多新的研究课题。虚拟化计算、虚拟化存储、虚拟化网络、虚拟化安全等等这些课题共同推动着云计算产业迈出一个又一个的台阶。数据中心数据中心是集中存放和运行服务器的地方,是规模最大的集群。随着云计算和大数据概念的风起云涌,Google、Amazon 等这些明星公司幕后的数据中心也开始走入大众的视野。数据中心要求有优秀的架构设计、电路设计、空间设计等等,还要有机制能够应对各种各样的意外,否则一点小小的失误,公司的股价恐怕就要跳水。地理位置的选择也是数据中心考虑的一个指标,随着绿色数据中心概念的兴起,越来越多人关注数据中心所带来的能源问题和环境问题,选择一个远离市区,并且能利用天然水源和气温的地方,将会为数据中心的建设节约大量的成本。Google 等大公司的数据中心就有意放在高纬度、高海拔的地区,以及有湖泊、河流流经地区,以享受天然的空调和冷却水。参考[1] 分布式与集群的区别是什么?[2] 数据中心网络架构演讲 [3] Linux 高性能计算集群[4] 高性能计算机传奇我的公众号 CloudDeveloper(ID: cloud_dev),号内有大量书籍和视频资源,后台回复「1024」即可领取,分享的内容包括但不限于云计算虚拟化、容器、OpenStack、K8S、雾计算、网络、工具、SDN、OVS、DPDK、Linux、Go、Python、C/C++编程技术等内容,欢迎大家关注。

March 6, 2019 · 1 min · jiezi

助力深度学习!阿里开源可插拔 GPU 共享调度工具

根据 Gartner 对全球 CIO 的调查结果显示,人工智能将成为 2019 年组织革命的颠覆性力量。对于人工智能来说,算力即正义,成本即能力,利用 Docker 和 Kubernetes 代表云原生技术为 AI 提供了一种新的工作模式,将 GPU 机器放到统一的资源池进行调度和管理,这避免了GPU 资源利用率低下和人工管理的成本。因此,全球主要的容器集群服务厂商 Kubernetes 都提供了 Nvidia GPU 容器集群调度能力,但是通常都是将一个 GPU 卡分配给一个容器。这虽然可以实现比较好的隔离性,确保使用 GPU 的应用不会被其他应用影响;对于深度学习模型训练的场景也非常适合,但是,针对模型开发和模型预测的场景还是会显得比较浪费。基于此,大家有了共享 GPU 的集群调度需求。Kubernetes 共享 GPU 集群调度共享 GPU 的集群调度就是能够让更多的模型开发和预测服务共享同一个 GPU 卡,进而提高集群中 Nvidia GPU 的利用率。而这就需要提供 GPU 资源的划分,而这里 GPU 资源划分的维度指的就是 GPU 显存和 Cuda Kernel 线程的划分。通常在集群级别谈支持共享 GPU 是以下两件事情:1.调度2.隔离,我们这里主要讨论的是调度,隔离的方案目前需要用户通过应用限制(比如使用 Tensorflow 的per_process_gpu_memory_fraction 来控制),未来会提供基于 Nvidia 的 MPS 的可选项, 也会考虑 GPU 的方案。而对于细粒度的 GPU 卡调度,目前 Kubernetes 社区并没有很好的方案,这是由于 Kubernetes 对于 GPU 这类扩展资源的定义仅仅支持整数粒度的加加减减,无法支持复杂资源的分配。比如用户希望使用 Pod A 占用半张 GPU卡,这在目前 Kubernetes 的架构设计中无法实现资源分配的记录和调用。这里挑战是多卡 GPU 共享是实际矢量资源问题,而 Extened Resource 是标量资源的描述。针对此问题,我们设计了一个 Out Of Tree 的共享 GPU 调度方案,该方案依赖于 Kubernetes 的现有的工作机制:Extended Resource 定义Scheduler Extender 机制Device Plugin 机制Kubectl 的扩展机制这个 GPU 共享调度扩展的好处是:利用 Kubernetes 的扩展和插件机制实现,对于 API Server,Scheduler,Controller Manager 以及 Kubelet 等核心组件没有侵入性。这就方便了使用者可以在不同 Kubernetes 版本上应用这个方案,无需 rebase 代码和重新构建 Kubernetes 二进制包。用户场景集群管理员:“我想提高集群的 GPU 使用率;在开发过程中,多个用户共享模型开发环境。”应用开发人员:“我希望能够同时在 Volta GPU 上运行多个推理任务。”目标能够让使用者通过 API 描述对于一个可共享资源的申请, 并能实现该种资源的调度非目标不支持该共享资源的隔离不支持超卖设计原则明确问题简化设计,第一步只负责调度和部署,后续再实现运行时显存管控。有很多的客户明确的诉求是首先可以支持多AI应用可以调度到同一个 GPU 上,他们可以接受从应用级别控制显存的大小,利用类似gpu_options.per_process_gpu_memory_fraction控制应用的显存使用量。那我们要解决的问题就先简化到以显存为调度标尺,并且把显存使用的大小以参数的方式传递给容器内部。不做侵入式修改本设计中不会修改 Kubernetes 核心的 Extended Resource 的设计, Scheduler 的实现,Device Plugin 的机制以及 Kubelet 的相关设计。重用 Extended Resource 描述共享资源的申请 API。这样的好处在于提供一个可以移植的方案,用户可以在原生 Kubernetes 上使用这个方案。按显存和按卡调度的方式可以在集群内并存,但是同一个节点内是互斥的,不支持二者并存;要么是按卡数目,要么是按显存分配。详细设计前提:依旧延用 Kubernetes Extended Resource 定义,但是衡量维度最小单位从 1 个 GPU 卡变为 GPU 显存的 MiB。如果所节点使用的 GPU 为单卡 16GiB 显存,它对应的资源就是 16276MiB;由于用户对于共享GPU的诉求在于模型开发和模型预测场景,在此场景下,用户申请的GPU资源上限不会超过一张卡,也就是申请的资源上限为单卡。而我们的工作首先是定义了两个新的 Extended Resource: 第一个是 gpu-mem, 对应的是 GPU 显存;第二个是 gpu-count,对应的是 GPU 卡数。 通过两个标量资源描述矢量资源, 并且结合这一资源,提供支持共享 GPU 的工作机制。下面是基本的架构图:核心功能模块:GPU Share Scheduler Extender: 利用 Kubernetes 的调度器扩展机制,负责在全局调度器 Filter 和 Bind 的时候判断节点上单个 GPU 卡是否能够提供足够的 GPU Mem,并且在 Bind 的时刻将 GPU 的分配结果通过 annotation 记录到 Pod Spec 以供后续 Filter 检查分配结果。GPU Share Device Plugin: 利用 Device Plugin 机制,在节点上被 Kubelet 调用负责 GPU 卡的分配,依赖 scheduler Extender 分配结果执行。具体流程:1. 资源上报GPU Share Device Plugin 利用 nvml 库查询到 GPU 卡的数量和每张 GPU 卡的显存, 通过ListAndWatch()将节点的 GPU 总显存(数量 显存)作为另外 Extended Resource 汇报给 Kubelet; Kubelet 进一步汇报给 Kubernetes API Server。 举例说明,如果节点含有两块 GPU 卡,并且每块卡包含 16276MiB,从用户的角度来看:该节点的 GPU 资源为 16276 2 = 32552; 同时也会将节点上的 GPU 卡数量 2 作为另外一个 Extended Resource 上报。2. 扩展调度GPU Share Scheduler Extender 可以在分配 gpu-mem 给 Pod 的同时将分配信息以 annotation 的形式保留在 Pod spec 中,并且在过滤时刻根据此信息判断每张卡是否包含足够可用的 gpu-mem 分配。2.1 Kubernetes 默认调度器在进行完所有过滤(filter)行为后会通过 http 方式调用 GPU Share Scheduler Extender的filter 方法, 这是由于默认调度器计算 Extended Resource 时,只能判断资源总量是否有满足需求的空闲资源,无法具体判断单张卡上是否满足需求;所以就需要由 GPU Share Scheduler Extender 检查单张卡上是否含有可用资源。以下图为例, 在由 3 个包含两块 GPU 卡的节点组成的 Kubernetes 集群中,当用户申请gpu-mem=8138时,默认调度器会扫描所有节点,发现 N1 所剩的资源为 (16276 * 2 - 16276 -12207 = 4069 )不满足资源需求,N1 节点被过滤掉。而 N2 和 N3 节点所剩资源都为 8138MiB,从整体调度的角度看,都符合默认调度器的条件;此时默认调度器会委托 GPU Share Scheduler Extender 进行二次过滤,在二次过滤中,GPU Share Scheduler Extender 需要判断单张卡是否满足调度需求,在查看 N2 节点时发现该节点虽然有 8138MiB 可用资源,但是落到每张卡上看,GPU0 和分别 GPU1 只有 4069MiB 的可用资源,无法满足单卡 8138MiB 的诉求。而 N3 节点虽然也是总共有 8138MiB 可用资源,但是这些可用资源都属于 GPU0,满足单卡可调度的需求。由此,通过 GPU Share Scheduler Extender 的筛选就可以实现精准的条件筛选。2.2 当调度器找到满足条件的节点,就会委托 GPU Share Scheduler Extender 的 bind 方法进行节点和 Pod 的绑定,这里 Extender 需要做的是两件事情以 binpack 的规则找到节点中最优选择的 GPU 卡 id,此处的最优含义是对于同一个节点不同的 GPU 卡,以 binpack 的原则作为判断条件,优先选择空闲资源满足条件但同时又是所剩资源最少的 GPU 卡,并且将其作为ALIYUN_COM_GPU_MEM_IDX保存到 Pod 的 annotation 中;同时也保存该 Pod 申请的 GPU Memory 作为ALIYUN_COM_GPU_MEM_POD和ALIYUN_COM_GPU_MEM_ASSUME_TIME保存至 Pod 的 annotation 中,并且在此时进行 Pod 和所选节点的绑定。注意:这时还会保存ALIYUN_COM_GPU_MEM_ASSIGNED的 Pod annotation,它被初始化为“false”。它表示该 Pod 在调度时刻被指定到了某块 GPU 卡,但是并没有真正在节点上创建该 Pod。ALIYUN_COM_GPU_MEM_ASSUME_TIME代表了指定时间。如果此时发现分配节点上没有 GPU 资源符合条件,此时不进行绑定,直接不报错退出,默认调度器会在 assume 超时后重新调度。调用 Kubernetes API 执行节点和 Pod 的绑定以下图为例,当 GPU Share Scheduler Extender 要把 gpu-mem:8138 的 Pod 和经过筛选出来的节点 N1 绑定,首先会比较不同 GPU 的可用资源,分别为 GPU0(12207),GPU1(8138),GPU2(4069),GPU3(16276),其中 GPU2 所剩资源不满足需求,被舍弃掉;而另外三个满足条件的 GPU 中, GPU1 恰恰是符合空闲资源满足条件但同时又是所剩资源最少的 GPU 卡,因此 GPU1 被选出。3. 节点上运行当 Pod 和节点绑定的事件被 Kubelet 接收到后,Kubelet 就会在节点上创建真正的 Pod 实体,在这个过程中, Kubelet 会调用 GPU Share Device Plugin 的Allocate方法, Allocate方法的参数是 Pod 申请的 gpu-mem。而在Allocate方法中,会根据 GPU Share Scheduler Extender 的调度决策运行对应的 Pod会列出该节点中所有状态为 Pending 并且ALIYUN_COM_GPU_MEM_ASSIGNED为false的 GPU Share Pod选择出其中 Pod Annotation 的ALIYUN_COM_GPU_MEM_POD的数量与 Allocate 申请数量一致的 Pod。如果有多个符合这种条件的 Pod,就会选择其中ALIYUN_COM_GPU_MEM_ASSUME_TIME最早的 Pod。将该 Pod 的 annotation ALIYUN_COM_GPU_MEM_ASSIGNED设置为true,并且将 Pod annotation 中的 GPU 信息转化为环境变量返回给 Kubelet 用以真正的创建 Pod。相关项目目前项目已经开源到 github.com 上gpushare-scheduler-extendergpushare-device-plugin部署请参照部署文档测试样例首先创建一个使用aliyun.com/gpu-mem的应用apiVersion: apps/v1kind: Deploymentmetadata: name: binpack-1 labels: app: binpack-1spec: replicas: 1 selector: # define how the deployment finds the pods it manages matchLabels: app: binpack-1 template: # define the pods specifications metadata: labels: app: binpack-1 spec: containers: - name: binpack-1 image: cheyang/gpu-player:v2 resources: limits: # MiB aliyun.com/gpu-mem: 1024使用请参照使用文档构建请参照如何构建视频 Demo1: 部署多个 GPU Share 的 Pod,发现他们以 binpack 的方式被放置到同一个 GPU 卡上视频地址:https://cloud.video.taobao.com//play/u/2987821887/p/2/e/6/t/1/214292079721.mp42: 避免错误调度申请资源超过单个 GPU 可用资源的 Pod视频地址:https://cloud.video.taobao.com//play/u/2987821887/p/2/e/6/t/1/214235285109.mp4Roadmap在 Device Plugin 中提供 Nvidia MPS 的可选支持;支持该方案可以在由 kubeadm 初始化的 Kubernetes 集群自动化部署;提升 Scheduler Extener 的高可用性;为 GPU, RDMA 和弹性网卡提供通用方案。本文作者:jessie筱姜阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

March 4, 2019 · 3 min · jiezi

Spark in action on Kubernetes - Playground搭建与架构浅析

前言Spark是非常流行的大数据处理引擎,数据科学家们使用Spark以及相关生态的大数据套件完成了大量又丰富场景的数据分析与挖掘。Spark目前已经逐渐成为了业界在数据处理领域的行业标准。但是Spark本身的设计更偏向使用静态的资源管理,虽然Spark也支持了类似Yarn等动态的资源管理器,但是这些资源管理并不是面向动态的云基础设施而设计的,在速度、成本、效率等领域缺乏解决方案。随着Kubernetes的快速发展,数据科学家们开始考虑是否可以用Kubernetes的弹性与面向云原生等特点与Spark进行结合。在Spark 2.3中,Resource Manager中添加了Kubernetes原生的支持,而本系列我们会给大家介绍如何用更Kubernetes的方式在集群中使用Spark进行数据分析。本系列不需要开发者有丰富的Spark使用经验,对着系列的逐渐深入,会穿插讲解使用到的Spark特性。搭建Playground很多的开发者在接触Hadoop的时候,被安装流程的复杂度打消了很多的积极性。为了降低学习的门槛,本系列会通过spark-on-k8s-operator作为Playground,简化大家的安装流程。spark-on-k8s-operator顾名思义是为了简化Spark操作而开发的operator,如果对operator不是很了解的开发者,可以先自行搜索了解下,理解operator能做什么可以快速帮你掌握spark-on-k8s-operator的要领。在讲解内部原理前,我们先将环境搭建起来,通过一个简单的demo,跑通整个的运行时环境。1. 安装spark-on-k8s-operator官方的文档是通过Helm Chart进行安装的,由于很多开发者的环境无法连通google的repo,因此此处我们通过标准的yaml进行安装。## 下载repogit clone git@github.com:AliyunContainerService/spark-on-k8s-operator.git## 安装crdkubectl apply -f manifest/spark-operator-crds.yaml ## 安装operator的服务账号与授权策略kubectl apply -f manifest/spark-operator-rbac.yaml ## 安装spark任务的服务账号与授权策略kubectl apply -f manifest/spark-rbac.yaml ## 安装spark-on-k8s-operator kubectl apply -f manifest/spark-operator.yaml 验证安装结果此时在spark-operator的命名空间下的无状态应用下,可以看到一个运行中的sparkoperator,表名此时组件已经安装成功,接下来我们运行一个demo应用来验证组件是否可以正常工作。2. Demo验证学习Spark的时候,我们运行的第一个任务是官方文档中介绍的圆周率运行的例子。今天我们换一种方式,通过Kubernetes的方式再运行一次。## 下发spark-pi任务kubectl apply -f examples/spark-pi.yaml 任务下发成功后,可以通过命令行观察任务的状态。## 查询任务kubectl describe sparkapplication spark-pi## 任务结果 Name: spark-piNamespace: defaultLabels: <none>Annotations: kubectl.kubernetes.io/last-applied-configuration: {“apiVersion”:“sparkoperator.k8s.io/v1alpha1”,“kind”:“SparkApplication”,“metadata”:{“annotations”:{},“name”:“spark-pi”,“namespace”:“defaul…API Version: sparkoperator.k8s.io/v1alpha1Kind: SparkApplicationMetadata: Creation Timestamp: 2019-01-20T10:47:08Z Generation: 1 Resource Version: 4923532 Self Link: /apis/sparkoperator.k8s.io/v1alpha1/namespaces/default/sparkapplications/spark-pi UID: bbe7445c-1ca0-11e9-9ad4-062fd7c19a7bSpec: Deps: Driver: Core Limit: 200m Cores: 0.1 Labels: Version: 2.4.0 Memory: 512m Service Account: spark Volume Mounts: Mount Path: /tmp Name: test-volume Executor: Cores: 1 Instances: 1 Labels: Version: 2.4.0 Memory: 512m Volume Mounts: Mount Path: /tmp Name: test-volume Image: gcr.io/spark-operator/spark:v2.4.0 Image Pull Policy: Always Main Application File: local:///opt/spark/examples/jars/spark-examples_2.11-2.4.0.jar Main Class: org.apache.spark.examples.SparkPi Mode: cluster Restart Policy: Type: Never Type: Scala Volumes: Host Path: Path: /tmp Type: Directory Name: test-volumeStatus: Application State: Error Message: State: COMPLETED Driver Info: Pod Name: spark-pi-driver Web UI Port: 31182 Web UI Service Name: spark-pi-ui-svc Execution Attempts: 1 Executor State: Spark - Pi - 1547981232122 - Exec - 1: COMPLETED Last Submission Attempt Time: 2019-01-20T10:47:14Z Spark Application Id: spark-application-1547981285779 Submission Attempts: 1 Termination Time: 2019-01-20T10:48:56ZEvents: Type Reason Age From Message —- —— —- —- ——- Normal SparkApplicationAdded 55m spark-operator SparkApplication spark-pi was added, Enqueuing it for submission Normal SparkApplicationSubmitted 55m spark-operator SparkApplication spark-pi was submitted successfully Normal SparkDriverPending 55m (x2 over 55m) spark-operator Driver spark-pi-driver is pending Normal SparkExecutorPending 54m (x3 over 54m) spark-operator Executor spark-pi-1547981232122-exec-1 is pending Normal SparkExecutorRunning 53m (x4 over 54m) spark-operator Executor spark-pi-1547981232122-exec-1 is running Normal SparkDriverRunning 53m (x12 over 55m) spark-operator Driver spark-pi-driver is running Normal SparkExecutorCompleted 53m (x2 over 53m) spark-operator Executor spark-pi-1547981232122-exec-1 completed此时我们发现任务已经执行成功,查看这个Pod的日志,我们可以到计算最终的结果为Pi is roughly 3.1470557352786765。至此,在Kubernetes上,已经跑通了第一个Job,接下来我们要来详解一下刚才这一波操作到底都做了些什么。Spark Operator的基础架构浅析这张图是Spark Operator的流程图,在上面的操作中,第一个步骤里面,实际上是将图中的中心位置蓝色的Spark Operator安装到集群中,Spark Opeartor本身即是是一个CRD的Controller也是一个Mutating Admission Webhook的Controller。当我们下发spark-pi模板的时候,会转换为一个名叫SparkApplication的CRD对象,然后Spark Operator会监听Apiserver,并将SparkApplication对象进行解析,变成spark-submit的命令并进行提交,提交后会生成Driver Pod,用简单的方式理解,Driver Pod就是一个封装了Spark Jar的镜像。如果是本地任务,就直接在Driver Pod中执行;如果是集群任务,就会通过Driver Pod再生成Exector Pod进行执行。当任务结束后,可以通过Driver Pod进行运行日志的查看。此外在任务的执行中,Spark Operator还会动态attach一个Spark UI到Driver Pod上,希望查看任务状态的开发者,可以通过这个UI页面进行任务状态的查看。最后在本文中,我们讨论了Spark Operator的设计初衷,如何快速搭建一个Spark Operator的Playground以及Spark Operator的基本架构与流程。在下一篇文章中,我们会深入到Spark Operator的内部,为大家讲解其内部的实现原理以及如何与Spark更无缝的集成。本文作者:莫源 阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

February 26, 2019 · 2 min · jiezi

基于 Kubernetes 实践弹性的 CI/CD 系统

大家好,我是来自阿里云容器服务团队的华相。首先简单解释一下何为 Kubernetes 来帮助大家理解。Kuberentes 是一个生产可用的容器编排系统。Kuberentes 一方面在集群中把所有 Node 资源做一个资源池,然后它调度的单元是 Pod,当然 Pod 里面可以有多个容器。 就像一个人左手抓着 ECS 资源或计算资源,右手抓容器,然后把它们两个匹配起来,这样它就可以作为一个容器的编排系统。而 Cloudnative 这个概念现在会经常被大家提起,很多人迷惑 Cloudnative 又与 Kuberentes 有什么关联?我们又该如何判断一个应用是 Cloudnative 呢?我认为有以下三个判断标准:第一,它能够给资源做池化;第二,应用可以快速接入池的网络。在 Kuberentes 里面有一层自己的独立网络,然后只需要知道我要去访问哪个服务名就可以,就是各种服务发现的一些功能,它可以通过 service mesh 去做一个快速地访问;第三是有故障转移功能,如果一个池子里面有一台主机,或者某一个节点 down 掉了,然后整个应用就不可用了,这肯定不算是 Cloudnative 的应用。比较这三点就可以发现 Kuberentes 做的非常好。首先我们看一个资源池的概念,Kuberentes 一个大的集群就是一个资源池,我们再也不用去关心说我这个应用要跑在哪台主机上了,我只要把我们部署的 yaml 文件往 Kuberentes 上发布就可以了,它会自动做这些调度,并且它可以快速地接入我们整个应用的网络,然后故障转移也是自动。接下来我就来分享如何基于 Kuberentes 实现一个弹性的 CI/CD 系统。CI/CD 的现状首先了解一下 CI/CD 的现状。CI/CD 这个概念实际上已经提出很多年了,但是随着技术地演进和新工具地不断推出,它在整个流程和实现方式上逐渐丰富。而我们通常最早接触 CI/CD 就是代码提交,随之触发一个事件,然后在某个 CI/CD 系统上做自动构建。下图可以反映目前 CI/CD 的现状:另外还有 Gitlab CI,它主要特点是与 Gitlab 代码管理工具结合地比较好。Jenkins 2.0 开始引入 pipeline as code 特性,pipeline as code 可以帮我们自动生成一个 jenkins file。在 Jenkins 1.0 时,如果我们想要配置一条流水线,需要先登录 Jenkins 建一个项目,然后在里面写一些 shell。这样虽然能达到同样的效果,但是它有一个最大的弊端,就是可复制性和迁移性不好。而且它与 Devops 有天然地割裂,比如一般是由运维人员来管理 Jenkins 系统,开发人员编写代码,但是这个代码怎么去构建,发布到哪里,开发人员完全不知道。这就造成了开发和运维地割裂。但 pipeline as code 方式出现了之后,jenkins file 与代码源码可以放在同样的仓库里面。首先它有一个非常大的好处是发布的流程也可以纳入版本管理,这样对一个错误就可追溯。这是一个非常大地改动,但是实际上我们在与客户沟通中发现,虽然很多人在 Jenkins 上都已经升到 2.0 系列了,但是它们的用法还是完全在 1.0 系列,很多用户都没有把 jenkins file 这种方式用起来。另外一个就是对容器地支持,大概 2016 年左右,那时对容器的支持是非常弱的,在容器里面运行 Jenkins,同时构建的产物也是 Docker 会非常麻烦。 但是, Drone 对容器的支持力度就非常好。首先它完全用 Docker 方式来运行,就是说你的构建环境也在一个容器里,你需要构建一个 Docker build 镜像,然后在推送出去的时候,它也在容器里面运行,然后它需要一个 privilege 权限。它这种方式有几个特别好的地方,首先它不会对宿主机产生任何残留,比如说你这个容器一销毁,构建中产生的一些中间文件完全都跟着销毁了,但是你如果用 Jenkins 的话,随着用的时间越来越久会沉淀出很多临时文件,它占的空间会越来越大。你需要定期做一些清理,而且清理过程中你又不能直接一键清空,所以这是很麻烦的过程。然后插件的管理 Jenkins 还有一个特别让人头疼的地方,就是它的插件升级。首先你在 Jenkins 登录进去,然后就做插件升级。如果说我想临时在一个新的环境里面,起一个 Jenkins 先测试一下或做一些调试可能每新建一个环境,都需要把这些插件升级一次。而且刚才我们说的在 Jenkins 里面做的所有配置,也都需要重新配置一遍,这是一个非常繁琐的一个过程。但是 Drone 这个工具它有一个特别好的地方,就是所有的插件都是 Docker 容器,比如说你在 pipeline 里用这个插件,你只要声明用这个插件就可以了,你不用去自己管理把插件下载到哪里,然后怎么安装,它这个一切都是全自动,只要说你网络能把插件容器镜像访问到就可以了,这非常便利。然后关于生态的构建,Jenkins 的最大的优势就是它的插件非常多,就是你想用的各种东西都有,而且它基础的底座非常好,你的插件可以实现的能力非常的强。比如说 pipeline 就是这种方式,它从 1.0 到 2.0 虽然有了,但是它完全是通过插件来实现的。但是现在 Jenkins 的发展又开始有点第二春的感觉。他开始对 Kuberentes 的支持力度明显的加大了很多,首先从 JenkinsX 开始,它融合了一些 Kuberentes 生态相关的一些工具,比如 Harbor、Helm 它可以非常便利地在 Kuberentes 集群上来做一些构建,并且把一些做服务的固化的一些编排文件放到 Helm 里面。另外,现在它有一个新的子项目叫 config as code,也就是说他把所有 Jenkin 里面做了一些配置,都可以输出成一个 code 的形式,就是对整个 Jenkins 的迁移,或者说复制都是一个很便利的改进。讲了那么多,实际上最后我们选择的东西还是 Jenkins,因为最重要的是生态的构建,他们已经很好了。今天我们要讲的在做一个弹性在 CI/CD 这个 Jenkins 上已经有这个插件了,但是在 Drone 的社区里面,有人提这个事,但是现在还没有看到。CI/CD 工具的选择接下来,我们看一下 CI/CD 这些工具的选择和他们的发展。首先最老牌的肯定是 Jenkins。实际上在容器技术兴起之前,CI/CD 简直约等于 Jenkins。但是在出现容器技术之后,很多新生 CI/CD 的工具也应运而生,比如说图中 Drone 工具,它是一个完全基于容器来实现的 CI/CD 工具。它与容器地结合地非常好,并且它的构建过程是完全在容器中实现的。第三个是 Gitlab CI,它主要特点是与 Gitlab 代码管理工具结合地比较好。Jenkins 2.0 时开始引入 pipeline as code 特性,什么叫 pipeline as code?pipeline as code 可以帮我们自动生成一个 jenkins file。在 Jenkins 1.0 时,如果我们想要配置一条流水线,需要先登录 Jenkins,然后建一个项目,然后在里面写一些 shell。这样虽然能达到同样的效果,但是它有一个最大的弊端,就是可复制性和迁移性不好。而且它与 Devops 有天然地割裂,比如一般是运维人员来管理 Jenkins 这个系统。开发人员编写代码,但是这个代码怎么去构建,发布到哪里,他是完全不知道的,是运维人员在Jenkins 里面配的。这个就造成了开发和运维地割裂。但 pipeline as code 这种方式出现了之后,我们可以把 jenkins file 跟代码源码放在同样的仓库里面。首先它有一个非常大的好处就是我们发布的流程也可以纳入版本管理,这样对一个错误就可追溯。这是一个非常大地改动,但是实际上我们在与客户沟通中发现,虽然很多人在 Jenkins 上都已经升到 2.0 系列了,但是它们的用法还是完全在 1.0 系列,很多用户都没有把 jenkins file 这种方式用起来。另外一个就是对容器地支持,大概 2016 年左右,那时对容器的支持是非常弱的,在容器里面运行 Jenkins,同时构建的产物也是 Doker 会非常麻烦。 但是, Drone 对容器的支持力度就非常好。首先它完全用 Doker 方式来运行,就是说你的构建环境也在一个容器里,你需要构建一个 Doker build 镜像,然后在推送出去的时候,它也在容器里面运行,然后它需要一个 privilege 权限。它这种方式有几个特别好的地方,首先它不会对宿主机产生任何残留,比如说你这个容器一销毁,构建中产生的一些中间文件完全都跟着销毁了,但是你如果用 Jenkins 的话,随着用的时间越来越久会沉淀出很多临时文件,它占的空间会越来越大。你需要定期做一些清理,而且清理过程中你又不能直接一键清空,所以这是很麻烦的过程。然后插件的管理 Jenkins 还有一个特别让人头疼的地方,就是它的插件升级。首先你在 Jenkins 登录进去,然后就做插件升级。如果说我想临时在一个新的环境里面,起一个 Jenkins 先测试一下或做一些调试可能每新建一个环境,都需要把这些插件升级一次。而且刚才我们说的在 Jenkins 里面做的所有配置,也都需要重新配置一遍,这是一个非常繁琐的一个过程。但是 Drone 这个工具它有一个特别好的地方,就是所有的插件都是 Doker 容器,比如说你在 pipeline 里用这个插件,你只要声明用这个插件就可以了,你不用去自己管理把插件下载到哪里,然后怎么安装,它这个一切都是全自动,只要说你网络能把插件容器镜像访问到就可以了,这非常便利。然后关于生态的构建,Jenkins 的最大的优势就是它的插件非常多,就是你想用的各种东西都有,而且它基础的底座非常好,你的插件可以实现的能力非常的强。比如说 pipeline 就是这种方式,它从 1.0 到 2.0 虽然有了,但是它完全是通过插件来实现的。但是现在 Jenkins 的发展又开始有点第二春的感觉。他开始对 Kuberentes 的支持力度明显的加大了很多,首先从 JenkinsX 开始,它融合了一些 Kuberentes 生态相关的一些工具,比如 Harbor、Helm 它可以非常便利地在 Kuberentes 集群上来做一些构建,并且把一些做服务的固化的一些编排文件放到 Helm 里面。另外,现在它有一个新的子项目叫 config as code,也就是说他把所有 Jenkin 里面做了一些配置,都可以输出成一个 code 的形式,就是对整个 Jenkins 的迁移,或者说复制都是一个很便利的改进。讲了那么多,实际上最后我们选择的东西还是 Jenkins,因为最重要的是生态的构建,他们已经很好了。今天我们要讲的在做一个弹性在 CI/CD 这个 Jenkins 上已经有这个插件了,但是在 Drone 的社区里面,有人提这个事,但是现在还没有看到。CI/CD的系统业务场景然后我们看一下 CI/CD 它的系统的业务场景,它有一个比较典型的场景与特点,首先它面向开发人员,这是比较少见的,因为开发人员一般都比较挑剔一点。所以你要是这个系统做的不够稳健了,或者说响应时间比较长一点的话,会被经常吐槽。然后就是有时效性要求,因为我们代码写完之后,往上提交,我们都不希望在这个代码的构建中一直排队,我们希望马上就开始进行构建,并且资源足够丰富。另外一个就是它的资源占用的波峰波谷是非常明显的。就因为开发人员不可能时时刻刻都在提交代码,有的人可能一天提交几次,有的人会提交很多次。因为我之前看过有一个分享,有一个人画了一条反映自家公司构建任务的曲线。他们公司大概是每天下午三、四点的时候代码提交量最高,其他时间都比较平缓。这说明他们公司三、四点的时候,程序员提交代码开始划水了。然后随着 CI/CD 资源地需求越来越高,构建集群是一个必须要做的一件事情。就是提高负载能力,缩短任务的排队时间。当然真正的集群有一个让人觉得很不太好的地方,就是它的 Master 实际上只有一个,当然这个也可以通过插件来做改进。容器可以给我们 CI/CD 系统来注入新的能力,就是环境隔离的能力。我们可以通过 Kubernetes 来为 CI/CD 系统注入更多的能力,然后矛盾点就出现了。开发人员总是希望 CI/CD 系统能够快速地响应代码提交的一个事件,但是每个公司资源都不可能是无限的。因为就像上面提到的,如果每天下午三、四点的时候是一个代码提交的高峰,这个时候可能需要 30 或 40 台机器才能满足构建的任务。但是我不可能每天就开着 30 或 40 台机器在这里,就为了每天下午三、四点,可能会构建一、两个小时。Kubernetes 可以为 jenkins 注入新的能力,让 CI/CD 系统实现弹性的能力。我们期望的目标是什么呢?有构建任务的时候,可以自动为我们资源增加新的机器也好,或增加新的运计算能力也好,反正就是当我需要的时候,可以帮我自动地做一个资源扩张,但是同时也在我不需要的时候,可以自动把这些资源释放掉。我们期望的目标就是这样,Kuberentes 就可以为 Jenkins 来做这样的能力。Kuberentes 作为一个容器编排的系统,它所能提供的能力,它可以快速地弹出一些新的实例,并且把它们自动调度到空闲的机器上,做一个资源池,在资源池里面做一个调度,并且他执行完任务之后,它可以做一个回收。而且如果把这 Jenkins Master 也部署在 Kuberentes 之上,它可以对 Master 做一个故障转移,就是说如果我们系统可以容忍的话,Master 就算挂了,我可以快速把它调到另外一台机器上,这个响应时间不会很长。Kuberentes-plugin这里面也是用一个插件来实现,这个插件名字比较直接叫 Kuberentes-plugin,它这个插件所能提供的能力就是说,他直接管理一个 Kuberentes 集群,它在 Jenkins 里面安装之后,它可以监听 Jenkins 的构建任务。有构建任务,在等待资源的时候,它就可以向 Kuberenetes 去申请一个新的资源,申请一个新的 Pod 去做自动地构建完之后,它就会自动的清理。先简单介绍一下它的能力,因为这个插件安装完之后,它对 pipeline 的语法也有一个改造,一会我们来看一下实例。但是就算到了这一步,还是不行的。首先,Kuberentes 的集群规划还是一个问题。比说我有个集群有 30 个节点,真正的 master 部署在这上面,然后装了那些插件,做了一个管理之后,我们可以发现来了一个新的任务,它就起一个新的 Pod,把这个构建任务给执行制定完。执行完之后,这 Pod 自动销毁不占集群的资源。 平时我们可以在这集群上做一些别的任务,但这个终究还是有一点不好,就是我们这个集群到底规划多大,并且这个集群我们平时不做构建任务的时候,可以在上面做一些别的任务。但是如果正在做任务,突然来了一些构建任务,它可能会出现资源的冲突问题。Kubernetes Autoscaler总的来说,还是有一些不完美的地方,那么我们可以利用 Kuberentes 一些比较没那么常见的特性,来解决我们刚才说的这个问题。这两个东西一个是叫 Autoscaler,一个叫 Virtual node。我们先看一下 Autoscaler,Autoscaler 是一个 Kubernetes 官方的一个组件。在 Kuberentes 的 group 下面支持三种能力:Cluster Autoscaler,可以对集群节点做自动伸缩;Vertical Pod Autoscaler,对集群的 Pod 竖直方向的资源伸缩。因为 Kuberentes 本身里面就带着 HPA 可以做水平方向的 Pod 伸缩、节点数量的伸缩;这个特性还不是生产可用的特性;Addone Resizer,是 Kuberentes 上那些 addone 比如说 Ingress Controler、 DNS 可以根据 Node 的数量来对资源的分配做调整。Cluster autoscaler我要讲的是 Cluster autoscaler,是对集群 node 节点数量做一个扩缩容。 首先我们看一下,这个是在阿里云我们容器服务上所实现的 Autoscaler 的一个方式。我们看一下这个图,这个是 HPA 和 Autoscler 做结合使用的一个场景。HPA 监听监控的事件时发现资源使用率上升到一定程度了之后,HPA 会自动通知 workload,来弹出一个新的 Pod,弹出一个新的 Pod,可能这时候集群资源就已经不够了,所以这个 Pod 可能就会 pending 在这里。它就会触发 Autoscaler 的事件,Autoscaler 就会根据我们之前配置好的 ESS 这个模板来去弹出来一台新的 Node,然后自动地把 Node 加入到我们集群里面。 它是利用了 ESS 定制的模板功能,并且它可以支持多种的 Node 实例的类型,可以支持普通实例,支持 gpu,还有抢占式实例。Virtual node然后第二种是 Virtual node,Virtual node 实现方式是基于微软开源的 Virtual Kubelet 这个项目。它做了一个虚拟的 Kubelet,然后向 Kubernetes 集群里面去注册上面。但如果不太好理解的话,可以想象一下 MySQL proxy ,然后他把自己伪装成一个MySQL server,然后后端可能管理着非常多的 MySQL server,并且它可以帮你自动的做一些 SQL 查询的路由或者拼接。Virtual kubelet 做的也是类似的工作,就是说它本身向着 Kubernetes 注册说我是一个节点,但实际上它后端管理的可能是整个公有云上的非常多的资源,他可能对接公有云的一些 ECI 或者说对接的这些 VPC,这是一个它的大体的示意图。在阿里云上他们对接的是阿里云的 ECI 做一个弹性的容器实例,它响应时间就非常快,因为它不需要把 Node 去加入到集群里面,它是大概能够到一分钟一百个 Pod 左右这种性能。而且我们可以在 Pod 上声明这种资源的使用情况,这是一个非常快的响应速度时间。然后刚才说我们利用这两种方式,就可以对我们 CI/CD 弹性的系统做出新的改造,我们不用非常早规划好我们集群的规模,我们可以让集群规模在需要的时候自动的做一些伸缩的动作。但是你做了这些动作之后,我们做了这些把真正的放在容器里面的这些动作之后,引入了一些新的门槛:docker-outside-of-docker 和 docker in docker。我们在 Docker 中运行 Jenkins 时,通常有两种方式,一个是把宿主机的 docker.sock 挂载到容器里面,让 Jenkins 通过这个文件来和本机的 docker daemon 做一个通信,然后它在这里面做 docker build 构建镜像,或者把这些镜像 push 到远程的仓库里面,所以它中间产生的所有镜像都会堆积在本机上,这是一个问题。在一些 serverless 的那些场景上使用,它就会有一些限制,因为 serverless 本身就不允许把 socket 文件给挂在进去。另外一个就是 docker in docker 这种方式,它的优点就在于在容器里面它启动一个新的 Docker daemon,它所有的中间产物、构建产物随着容器都一起销毁,但是它有问题,它就是需要 privilege 的权限。很多时候我们是尽量不要用它。另外一个就是说你做 docker build 的时候能在宿主机上做的时候,它如果有已经有镜像了,它会直接就使用这个镜像,但是你用 docker in docker 这种方式来使用的,它每次都会重新拉进项,拉镜像也是需要一定时间,这个取决于我们各个使用场景来判断。新的构建工具——Kaniko这时又引入了一个谷歌开源的新工具——Kaniko。它做的东西是 docker in docker 的方式。它有一个非常大的好处就是不依赖 Docker,而且所以它不需要 privilege 权限就可以在容器里面用用户态的模式,来完全构建 docker image。用户态执行 Dockerfile 的命令,它把这个镜像完全构建出来。这算是一个比较期望的弹性的 CI/CD 系统。然后这个时候就是说从真正的节点到底层的计算资源全部是弹性扩缩的,而且满足交付的需求,可以非常精细化地管理我们的资源。Demo 演示然后我们可以看一下 Demo 演示:https://github.com/hymian/webdemo 这里是我准备好的一个例子,重点在这个 Jenkinsfile 文件,里面定义了agent 的 pod template,包含两个容器,一个用来做 golang 的 build,一个用来做 image 的 build。然后我们现在构建它。开始构建了,刚开始的,因为是现在我们在这环境里面只有一个,只有一个 master,所以他就是没有不会有构建节点。大家可以看到,它现在新启动了一个 Pod,这个 Pod 是作为节点加进来的,但是因为我在这个 Pod 模板里面定义了一个 label,所以它没有这个节点,所以它 Pod 状态是 pending 的。所以我们在构建日志里面显示的这个是 agent 节点是离线的。 但是我们在这个集群里面定义了一个弹性伸缩的一个东西,当没有节点的时候,它会自动做一个新节点分配加入,可以看到有一个节点正在加入,这个我就可以稍等一下。就是说这段时间可能会有个一分钟两分钟的时间。这个是异常,是因为这个节点正在向集群加入,所以它显示是异常,这是我们从命令行看一下,好,已经是四个节点了,加了一个节点,这时候我们看 Pod,这时候在 agent 正在创建,这时候大家可能有一个小的细节,大家可以看一下,就是 0/3 是显示 Pod,它有三个容器,但是我刚才在这个里面定义的,它实际上是 Pod 里面只有两个容器,这就是我们刚才 PPT 上写的一个地方。 JNLP 那个容器,是 plugin 自动注入的一个容器,它通过这个容器实时的向 master 汇报构建的一个中间的状态,我把它的日志给发送出去。这个是 agent 的节点在初始化的一个过程一个事情这时候 slave节点已经在运行了。我这边已经输出完了,构建完成。我的分享内容就这些,谢谢大家。本文作者:jessie筱姜阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

February 20, 2019 · 3 min · jiezi

如何在Kubernetes集群动态使用 NAS 持久卷

介绍:本文介绍的动态生成NAS存储卷的方案:在一个已有文件系统上,自动生成一个目录,这个目录定义为目标存储卷;镜像地址:registry.cn-hangzhou.aliyuncs.com/acs/alicloud-nas-controller:v1.11.5.4-433631d-aliyun默认生成资源:生成的PV名字为:pvc-${pvc-uid}生成目录的名字:namespace-pvcname-pvname可以再pvc的annotations中如下声明,自定义名字:生成的pv、目录名字为下面定义的名字。 annotations: pv-name-created: replace-user-id2. 部署NAS Controller创建alicloud-nas-controller,实现动态provider nas pv;创建alicloud-nas storageclass,为nas pv provision 提供模板;apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: alicloud-nasprovisioner: alicloud/nasreclaimPolicy: Deleteparameters: drivertype: flexvolume nfsversion: “4.0” options: “”—kind: DeploymentapiVersion: extensions/v1beta1metadata: name: alicloud-nas-controller namespace: kube-systemspec: replicas: 1 strategy: type: Recreate template: metadata: labels: app: alicloud-nas-controller spec: tolerations: - effect: NoSchedule operator: Exists key: node-role.kubernetes.io/master - effect: NoSchedule operator: Exists key: node.cloudprovider.kubernetes.io/uninitialized serviceAccount: admin containers: - name: alicloud-nas-controller image: registry.cn-hangzhou.aliyuncs.com/acs/alicloud-nas-controller:v1.11.5.4-433631d-aliyun imagePullPolicy: Always volumeMounts: - mountPath: /persistentvolumes name: nfs-client-root env: - name: NFS_SERVER value: 154154b095-.cn-beijing.nas.aliyuncs.com - name: NFS_PATH value: / volumes: - name: nfs-client-root flexVolume: driver: alicloud/nas options: path: / server: 154154b095-.cn-beijing.nas.aliyuncs.com vers: “4.0"StorageClass使用说明:drivertype: 用来表示生成pv存储类型,可选nfs, flexvolume. nfs: 默认选项,表示使用k8s原生NFS驱动挂载; flexvolume: 表示使用阿里云提供的Flexvolume NAS驱动挂载;nfsversion: 挂载nfs使用的版本,支持3,4.0.默认为4.0; drivertype为flexvolume的时候在这里配置; 为nfs的时候通过mountOptions 配置;options:为挂载nfs的可选项配置; drivertype为flexvolume的时候在这里配置; 为nfs的时候通过mountOptions 配置;StorageClass举例:## 使用kubernetes提供的NFS驱动,并配置mountOptions,reclaimPolicy为Delete;apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: alicloud-nas-nfsmountOptions:- vers=4.0- noresvportprovisioner: alicloud/nasreclaimPolicy: Delete## 使用阿里云提供的Flexvolume NAS驱动,配置nfs版本、options;apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: alicloud-nas-flexprovisioner: alicloud/nasreclaimPolicy: Deleteparameters: drivertype: flexvolume nfsversion: “3” options: “noresvport"3. 创建应用-Deployment:kind: PersistentVolumeClaimapiVersion: v1metadata: name: replace-user-id annotations: pv-name-created: replace-user-idspec: storageClassName: alicloud-nas accessModes: - ReadWriteMany resources: requests: storage: 5Gi—apiVersion: extensions/v1beta1kind: Deploymentmetadata: name: “deploy-nas"spec: replicas: 1 strategy: type: Recreate template: metadata: labels: app: deploy-nas spec: containers: - name: “nginx” image: “nginx” volumeMounts: - name: pvc-nas mountPath: “/data” volumes: - name: pvc-nas persistentVolumeClaim: claimName: replace-user-id执行:# userID=“hello-123”# cat deploy.yaml | sed “s/replace-user-id/"$userID"/g” | kubectl create -f -# kubectl get pod | grep deploy-nasdeploy-nas-85696b6bfc-t5dmh 1/1 Running 0 28m# kubectl get pvc | grep hellhello-123 Bound hello-123 5Gi RWX alicloud-nas-flex 28m# kubectl get pv | grep hellhello-123 5Gi RWX Delete Bound default/hello-123 alicloud-nas-flex 28m# Nas目录下查看生成目录:# ls -l | grep hellodrwxrwxrwx 2 root root 4096 2月 19 09:58 hello-1234. 创建应用-StatefulSet:使用volumeTemplateClaim不支持使用pv-name-created配置pv名字;apiVersion: v1kind: Servicemetadata: name: nginx labels: app: nginxspec: ports: - port: 80 name: web clusterIP: None selector: app: nginx—apiVersion: apps/v1beta1kind: StatefulSetmetadata: name: webspec: replicas: 2 serviceName: “nginx” template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:alpine volumeMounts: - mountPath: “/data” name: pvc-sts volumeClaimTemplates: - metadata: name: pvc-sts spec: accessModes: - ReadWriteOnce storageClassName: alicloud-nas-flex resources: requests: storage: 2Gi 创建后查看:# kubectl get pod | grep webweb-0 1/1 Running 0 7sweb-1 1/1 Running 0 4s# kubectl get pvc | grep webpvc-sts-web-0 Bound pvc-65ab251a-33ec-11e9-a151-00163e066784 2Gi RWO alicloud-nas-flex 13mpvc-sts-web-1 Bound pvc-8437c50e-33ed-11e9-a151-00163e066784 2Gi RWO alicloud-nas-flex 5m# kubectl get pv | grep webpvc-65ab251a-33ec-11e9-a151-00163e066784 2Gi RWO Delete Bound default/pvc-sts-web-0 alicloud-nas-flex 13mpvc-8437c50e-33ed-11e9-a151-00163e066784 2Gi RWO Delete Bound default/pvc-sts-web-1 alicloud-nas-flex 5m# Nas目录下查看生成目录:# ls -l | grep stsdrwxrwxrwx 2 root root 4096 2月 19 10:16 default-pvc-sts-web-0-pvc-65ab251a-33ec-11e9-a151-00163e066784drwxrwxrwx 2 root root 4096 2月 19 10:24 default-pvc-sts-web-1-pvc-8437c50e-33ed-11e9-a151-00163e0667845. 创建应用-Pod:kind: PersistentVolumeClaimapiVersion: v1metadata: name: replace-user-id annotations: pv-name-created: replace-user-idspec: storageClassName: alicloud-nas-flex accessModes: - ReadWriteMany resources: requests: storage: 5Gi—apiVersion: v1kind: Podmetadata: name: “nas-pod"spec: containers: - name: “nginx” image: “nginx” volumeMounts: - name: pvc-nas mountPath: “/data” volumes: - name: pvc-nas persistentVolumeClaim: claimName: replace-user-id # userID=“pod-123”# cat pod.yaml | sed “s/replace-user-id/"$userID"/g” | kubectl create -f -# kubectl get pod | grep podnas-pod 1/1 Running 0 32s# kubectl get pvc | grep podpod-123 Bound pod-123 5Gi RWX alicloud-nas-flex 44s# kubectl get pv | grep podpod-123 5Gi RWX Delete Bound default/pod-123 alicloud-nas-flex 48s# ls -l | grep poddrwxrwxrwx 2 root root 4096 2月 19 10:54 pod-123本文作者:kanjunbao阅读原文本文为云栖社区原创内容,未经允许不得转载。

February 20, 2019 · 3 min · jiezi

Kubernetes的共享GPU集群调度

问题背景全球主要的容器集群服务厂商的Kubernetes服务都提供了Nvidia GPU容器调度能力,但是通常都是将一个GPU卡分配给一个容器。这可以实现比较好的隔离性,确保使用GPU的应用不会被其他应用影响;对于深度学习模型训练的场景非常适合,但是如果对于模型开发和模型预测的场景就会比较浪费。 大家的诉求是能够让更多的预测服务共享同一个GPU卡上,进而提高集群中Nvidia GPU的利用率。而这就需要提供GPU资源的划分,而这里GPU资源划分的维度指的就是GPU显存和Cuda Kernel线程的划分。通常在集群级别谈支持共享GPU,通常是两件事情:1.调度 2.隔离,我们这里主要讨论的是调度,隔离的方案未来会基于Nvidia的MPS来实现。而对于细粒度的GPU卡调度,目前Kubernetes社区并没有很好的方案,这是由于Kubernetes对于GPU这类扩展资源的定义仅仅支持整数粒度的加加减减,无法支持复杂资源的分配。比如用户希望使用Pod A占用半张GPU卡,这在目前Kubernetes的架构设计中无法实现资源分配的记录和调用。这里挑战是多卡GPU共享是实际矢量资源问题,而Extened Resource是标量资源的描述。针对此问题,我们设计了一个outoftree的共享GPU调度方案,该方案依赖于Kubernetes的现有工作机制:Extended Resource定义Scheduler Extender机制Device Plugin机制用户场景作为集群管理员,我想提高集群的GPU使用率;在开发过程中,多个用户共享模型开发环境作为应用开发人员,我希望能够同时在Volta GPU上运行多个推理任务目标能够让使用者通过API描述对于一个可共享资源的申请, 并能实现该种资源的调度非目标不支持该共享资源的隔离不支持超卖设计原则明确问题简化设计,第一步只负责调度和部署,后续再实现运行时显存管控。有很多的客户明确的诉求是首先可以支持多AI应用可以调度到同一个GPU上,他们可以接受从应用级别控制显存的大小,利用类似gpu_options.per_process_gpu_memory_fraction控制应用的显存使用量。那我们要解决的问题就先简化到以显存为调度标尺,并且把显存使用的大小以参数的方式传递给容器内部。不做侵入式修改本设计中不会修改Kubernetes核心的Extended Resource的设计, Scheduler的实现,Device Plugin的机制以及Kubelet的相关设计。重用Extended Resource描述共享资源的申请API。这样的好处在于提供一个可以移植的方案,用户可以在原生Kubernetes上使用这个方案。按显存和按卡调度的方式可以在集群内并存,但是同一个节点内是互斥的,不支持二者并存;要么是按卡数目,要么是按显存分配。详细设计前提:依旧延用Kubernetes Extended Resource定义,但是衡量维度最小单位从1个GPU卡变为GPU显存的MiB。如果所节点使用的GPU为单卡16GiB显存,它对应的资源就是16276MiB由于用户对于共享GPU的诉求在于模型开发和模型预测场景,在此场景下,用户申请的GPU资源上限不会超过一张卡,也就是申请的资源上限为单卡而我们的工作首先是定义了两个新的Extended Resource: 第一个是gpu-mem, 对应的是GPU显存;第二个是gpu-count,对应的是GPU卡数。 通过两个标量资源描述矢量资源, 并且结合这一资源,提供支持共享GPU的工作机制。下面是基本的架构图:核心功能模块:GPU Share Scheduler Extender: 利用Kubernetes的调度器扩展机制,负责在全局调度器Filter和Bind的时候判断节点上单个GPU卡是否能够提供足够的GPU Mem,并且在Bind的时刻将GPU的分配结果通过annotation记录到Pod Spec以供后续Filter检查分配结果。GPU Share Device Plugin: 利用Device Plugin机制,在节点上被Kubelet调用负责GPU卡的分配,依赖scheduler Extender分配结果执行。具体流程:1. 资源上报GPU Share Device Plugin利用nvml库查询到GPU卡的数量和每张GPU卡的显存, 通过ListAndWatch()将节点的GPU总显存(数量 显存)作为另外Extended Resource汇报给Kubelet; Kubelet进一步汇报给Kubernetes API Server。 举例说明,如果节点含有两块GPU卡,并且每块卡包含16276MiB,从用户的角度来看:该节点的GPU资源为16276 2 = 32552; 同时也会将节点上的GPU卡数量2作为另外一个Extended Resource上报。2. 扩展调度GPU Share Scheduler Extender可以在分配gpu-mem给Pod的同时将分配信息以annotation的形式保留在Pod spec中,并且在过滤时刻根据此信息判断每张卡是否包含足够可用的gpu-mem分配。2.1 Kubernetes默认调度器在进行完所有过滤(filter)行为后会通过http方式调用GPU Share Scheduler Extender的filter方法, 这是由于默认调度器计算Extended Resource时,只能判断资源总量是否有满足需求的空闲资源,无法具体判断单张卡上是否满足需求;所以就需要由GPU Share Scheduler Extender检查单张卡上是否含有可用资源。以下图为例, 在由3个包含两块GPU卡的节点组成的Kubernetes集群中,当用户申请gpu-mem=8138时,默认调度器会扫描所有节点,发现N1所剩的资源为 (16276 * 2 - 16276 -12207 = 4069 )不满足资源需求,N1节点被过滤掉。 而N2和N3节点所剩资源都为8138MiB,从整体调度的角度看,都符合默认调度器的条件;此时默认调度器会委托GPU Share Scheduler Extender进行二次过滤,在二次过滤中,GPU Share Scheduler Extender需要判断单张卡是否满足调度需求,在查看N2节点时发现该节点虽然有8138MiB可用资源,但是落到每张卡上看,GPU0和分别GPU1只有4069MiB的可用资源,无法满足单卡8138MiB的诉求。而N3节点虽然也是总共有8138MiB可用资源,但是这些可用资源都属于GPU0,满足单卡可调度的需求。由此,通过GPU Share Scheduler Extender的筛选就可以实现精准的条件筛选。2.2 当调度器找到满足条件的节点,就会委托GPU Share Scheduler Extender的bind方法进行节点和Pod的绑定,这里Extender需要做的是两件事情以binpack的规则找到节点中最优选择的GPU卡id,此处的最优含义是对于同一个节点不同的GPU卡,以binpack的原则作为判断条件,优先选择空闲资源满足条件但同时又是所剩资源最少的GPU卡,并且将其作为ALIYUN_COM_GPU_MEM_IDX保存到Pod的annotation中;同时也保存该Pod申请的GPU Memory作为ALIYUN_COM_GPU_MEM_POD和ALIYUN_COM_GPU_MEM_ASSUME_TIME保存至Pod的annotation中,并且在此时进行Pod和所选节点的绑定。注意:这时还会保存ALIYUN_COM_GPU_MEM_ASSIGNED的Pod annotation,它被初始化为“false”。它表示该Pod在调度时刻被指定到了某块GPU卡,但是并没有真正在节点上创建该Pod。ALIYUN_COM_GPU_MEM_ASSUME_TIME代表了指定时间。如果此时发现分配节点上没有GPU资源符合条件,此时不进行绑定,直接不报错退出,默认调度器会在assume超时后重新调度。调用Kubernetes API执行节点和Pod的绑定以下图为例,当GPU Share Scheduler Extender要把gpu-mem:8138的Pod和经过筛选出来的节点N1绑定,首先会比较不同GPU的可用资源,分别为GPU0(12207),GPU1(8138),GPU2(4069),GPU3(16276),其中GPU2所剩资源不满足需求,被舍弃掉;而另外三个满足条件的GPU中, GPU1恰恰是符合空闲资源满足条件但同时又是所剩资源最少的GPU卡,因此GPU1被选出。3. 节点上运行当Pod和节点绑定的事件被Kubelet接收到后,Kubelet就会在节点上创建真正的Pod实体,在这个过程中, Kubelet会调用GPU Share Device Plugin的Allocate方法, Allocate方法的参数是Pod申请的gpu-mem。而在Allocate方法中,会根据GPU Share Scheduler Extender的调度决策运行对应的Pod3.1 会列出该节点中所有状态为Pending并且ALIYUN_COM_GPU_MEM_ASSIGNED为false的GPU Share Pod3.2 选择出其中Pod Annotation的ALIYUN_COM_GPU_MEM_POD的数量与Allocate申请数量一致的Pod。如果有多个符合这种条件的Pod,就会选择其中ALIYUN_COM_GPU_MEM_ASSUME_TIME最早的Pod。3.3 将该Pod的annotation ALIYUN_COM_GPU_MEM_ASSIGNED设置为true,并且将Pod annotation中的GPU信息转化为环境变量返回给Kubelet用以真正的创建Pod。相关项目目前项目已经开源到github.com上gpushare-scheduler-extendergpushare-device-plugin部署请参照部署文档测试样例1. 首先创建一个使用aliyun.com/gpu-mem的应用apiVersion: apps/v1kind: Deploymentmetadata: name: binpack-1 labels: app: binpack-1spec: replicas: 1 selector: # define how the deployment finds the pods it manages matchLabels: app: binpack-1 template: # define the pods specifications metadata: labels: app: binpack-1 spec: containers: - name: binpack-1 image: cheyang/gpu-player:v2 resources: limits: # MiB aliyun.com/gpu-mem: 1024使用请参照使用文档构建请参照如何构建视频DemoDemo 1: 部署多个GPU Share的Pod,发现他们以binpack的方式被放置到同一个GPU卡上视频地址:http://cloud.video.taobao.com…Demo 2:避免错误调度申请资源超过单个GPU可用资源的Pod视频地址:http://cloud.video.taobao.com…Roadmap利用nvidia MPS实现隔离支持该方案可以在由kubeadm初始化的Kubernetes集群自动化部署Scheduler Extener的高可用性为GPU, RDMA 和弹性网卡提供通用方案本文作者:必嘫阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

February 19, 2019 · 1 min · jiezi

“有趣”的投影:当PCA失效时怎么办?

摘要: ——试试PPA,一个关于探索性数据分析的替代方案!目前,大多数的数据科学家都比较熟悉主成分分析 (Principal Components Analysis,PCA),它是一个探索性的数据分析工具。可以这样简要的描述:研究人员经常使用PCA来降低维度,希望在他们的数据中找出有用的信息(例如疾病与非疾病的分类)。PCA是通过寻找正交投影(Orthogonal Projection)向量来实现这一点的,正交投影向量说明了数据中的最大方差量。在实践中,这通常是用奇异值分解(Singular Value Decomposition,SVD)的方法来找到主成分(特征向量),并通过其对数据总方差的贡献(特征值)加权。毫无疑问,在我的专业领域以及许多其它的领域中,PCA是最常用的数据分析工具,但是当它不起作用的时候会发生什么呢?这是否意味着抽样试验的效果不好呢?这是否意味着数据中没有有用的信息呢?我们的小组致力于为化学专业开发新的数据分析工具。在这里,我要给为大家介绍一个PCA的替代方案,叫做投影追踪分析(Projection Pursuit Analysis ,PPA)。基于方差运算的PCAPCA失败在哪了呢?像上面描述的那样,PCA通过在数据中找到最大方差的方向来进行操作。那么如果投射到那个方向上没有效果呢?下图是由200个样本的模拟数据组成的,这些数据形成了两个分离的集群,它们沿着Y轴的方差大于沿着X轴的方差。如果我们对这个二维数据进行PCA操作,那么会得到投影向量v,它将是2×1的列向量([0;1])。投射到这个向量上的原始数据X(200x2)给出了我们的得分T=Xv。在把这些得分可视化之后表明了两个集群之间没有明显的分离。相反,如果我们投射到x轴上(v=[1;0]),那么很容易地就会看到这两个集群中的分离状态。那么我们如何在高维的数据中找到这个向量呢?投影追踪投影追踪方法最初是由Friedman和Tukey在1974年的时候提出来的,他们试图根据投影指数的最大化或最小化来在数据中找到“有趣的”投影。通过扩展,在PCA框架中,投影指数(方差)被最大化了。现在的问题是,什么样的是好的预测指数呢?数据科学家们在定义新的投影指数方面已经做了大量的研究,但是今天我要关注的一个已经被证明对探索化学领域数据有用的指标是峰态系数(kurtosis)。基于峰态系数的投影追踪(Kurtosis-based projection pursuit)第四个统计矩,峰态系数,已被证明了是一个很有用的投影指数 (https://www.sciencedirect.com/science/article/pii/S0003267011010804)。当峰态系数最大化时,它往往会显示数据中的异常值。这会有些用处,但是实际上它并不是我们想要寻找并显示类或集群信息的东西。然而,当峰态系数最小化时,它将1个维度中的数据分为2组(2个维度中分为4组,3个维度中分为8组)。现在最大的问题是如何使用峰态系数查找这些投影向量?Quasai-power学习算法. 请见https://www.sciencedirect.com/science/article/pii/S0003267011010804。本文中,Hou和Wentzell证明了利用下面的学习算法可以找到最小化峰态系数的投影向量:实例模拟让我们同时利用PCA和PPA两种技术来模拟一些数据。与打开的图形类似,我们的数据将会分为两个类,每个类有100个样本,并且只需要1个维度来显示类分离。第一个类在x轴上以-4为中心,标准偏差为5,而第二类则以+4为中心,标准偏差也是5。为了使这个模拟更真实,让我们通过乘以一个2 x 600的随机旋转矩阵,将这个200 x 2的矩阵旋转为600个维度。这就是我们现在需要利用探索工具来找到数据中一些有趣的投影的地方。首先,让列的平均值集中我们的数据,同时应用PCA,并将第一个成分可视化为一个样本数量的函数。我们会看到,向下投射到第一个PC上的数据不会显示类信息。那我们现在就来应用PPA。PPA能够找到对我们有用的投影(即提供类分离的投影)。PPA的问题尽管在大多数的情况下,我们发现PPA的性能都优于PCA,但是当PPA没有效果的时候,有一些重要的注意事项需要在这里说明一下。当类的大小不相等的时候,PPA就不会正常地工作了,例如,如果我在上面的实例中使用5:1的类比率并应用PPA,我们会得到以下结果:由于分离的几何学方面的原因,当类的数量不是2的n次方时,PPA也会有问题。PPA也会遇到过度拟合问题,并且通常需要执行数据压缩,大约需要10:1的样本与变量比率。否则,该算法就将人工地把样本忽略掉。我们小组目前的工作是开发一些能缓解这些问题的方法,好消息是我们应该在未来的几个月之内就会发表一些关于这方面的论文!我一定会及时通知大家的。本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。

January 28, 2019 · 1 min · jiezi

在阿里,我们如何管理测试环境

前言阿里的许多实践看似简单,背后却蕴涵着许多思考,譬如测试环境的管理。互联网产品的服务通常是由Web应用、中间件、数据库和许多后台业务程序组成的,一套运行环境就是一个自成一体的小生态。最基本的运行环境是线上环境,部署产品的正式发布版本,为用户提供持续可靠的服务。除此以外,还有许多不对外部用户开放的运行环境,用于产品团队日常的开发和验证,统称为测试环境。正式环境的稳定性,除去软件自身的质量因素,主要与运行的主机、网络等基础设施相关,而测试环境的稳定性则更多受到人为因素影响。由于频繁的版本变更,以及部署未经充分验证的代码,测试环境出故障的情况屡见不鲜。良好的代码提交习惯、适当的变更前检查有助于减少故障的发生,但无法彻底杜绝后患。增加多套测试环境副本能够有效控制故障的影响范围,然而企业的资源终归有限,降低测试环境成本和提高测试环境稳定性成为了矛盾的两面。在这个领域里,独具匠心的阿里研发效能团队设计了一种服务级复用的虚拟化技术,称为“特性环境”,其巧妙的思路令人赞叹。本文将围绕测试环境管理的话题,聊聊这种具有阿里特色的工作方式。测试环境管理的困局测试环境的用途很广泛,常见的测试环境譬如系统集成测试环境、用户验收测试环境、预发布测试环境、灰度测试环境等,它们体现了产品的交付生命周期,也间接反映出整个团队的组织结构。小作坊型产品团队的测试环境管理起来十分简单,每个工程师本地就能启动全套软件组件进行调试,倘若不放心,再加上一个公共的集成测试环境也就足够。随着产品规模扩大,本地启动所有服务组件逐渐变得既费时又费事,工程师们只能在本地运行一部分待调试的组件,然后利用公共测试环境上的其余组件组成完整系统。与此同时,团队规模的扩张,使得每个团队成员的职责进一步细分,新的子团队被划分出来,这意味着项目的沟通成本增加,公共测试环境的稳定性开始变得难以控制。在这个过程中,测试环境管理复杂性带来的影响,不仅体现在服务联调变得繁琐,更直接反映在交付流程和资源成本的变化上。在交付流程方面,一个显著的变化是测试环境种类增多。出于不同的用途和目的,工程师们设计出了各式各样的专用测试环境。这些测试环境的组合形成了各个企业独具特色的交付流程。下图展示了一种用于大型项目的复杂交付流程。从单独服务的角度来看,环境与环境之间是由流水线相连的,再加上自动化测试或手工审批操作组成关卡,实现环境之间的传递。通常越高级别环境的部署频率越低,因此相对稳定性也越高。与之相反,在级别较低的环境上,就随时可能存在新的部署,会打扰正在使用该环境的其他人。有时为了复现某些特殊的问题场景,一些开发者不得不直接登录到服务器上面去“搞事情”,进一步影响环境的稳定性和可用性。面对随时可能崩溃的测试环境,小企业会试着去“堵”:约束服务变更时间、设立严格的变更规范,大企业则善于用“疏”:增加测试环境副本,隔离故障影响范围。显然,不堪重负的测试环境一定越“堵”越“漏”,千年以前大禹治水的故事早就揭示了的道理,刻意的管控拯救不了脆弱的测试环境。近年来,DevOps文化的兴起,端到端解放了开发者的双手,这对于测试环境的管理而言却是一把双刃剑。一方面,DevOps鼓励开发人员参与运维,了解产品的完整生命周期,有助于减少不必要的低级运维事故;另一方面,DevOps让更多的手伸向测试环境,更多的变更、更多的Hotfix出现了。这些实践从全局来看利大于弊,然而并不能缓解测试环境的动荡。单纯的流程疏通同样拯救不了脆弱的测试环境。那么该投入的还得投入。将不同团队所用的低级别测试环境各自独立,此时每个团队看到的都是线性流水线,从整体上观察,则会程现出河流汇聚的形状。由此推广,理想情况下,每位开发者都应该得到独占且稳定的测试环境,各自不受干扰的完成工作。然而由于成本因素,现实中在团队内往往只能共享有限的测试资源,不同成员在测试环境相互干扰成为影响软件开发质量的隐患。增加测试环境副本数本质上是一种提高成本换取效率的方法,然而许多试图在成本和效率之间寻找最优平衡的探索者们,似乎都在同一条不归路上越行越远。由于客观的规模和体量,上述这些测试环境管理的麻烦事儿,阿里的产品团队都无法幸免。首先是测试环境种类的管理。在阿里内部,同样有十分丰富的测试环境区分。各种测试环境的命名与其作用息息相关,虽然业界有些常用的名称,但都未形成权威的标准。实际上,环境的名称只是一种形式,关键还在于各种测试环境应当分别适配于特定应用场景,且场景之间应当或多或少存在一些差异。这种差异有些在于运行的服务种类,譬如性能测试环境很可能只需要运行与压力测试相关的那部分访问量最大的关键业务服务,其他服务运行了也是浪费资源。有些差异在于接入数据的来源,譬如开发自测的环境的数据源与正式环境肯定不一样,这样测试使用的假数据就不会污染线上用户的请求;预发布环境(或用户验收测试环境)会用与正式环境一致的数据源(或正式数据源的拷贝),以便反映新功能在真实数据上运行的情况;自动化测试相关的环境会有单独的一套测试数据库,以避测试运行过程中受到其他人为操作的干扰。还有些差异在于使用者的不同,譬如灰度和预发布环境都使用正式的数据源,但灰度环境的使用者是一小撮真实的外部用户,而预发布环境的使用者都是内部人员。总之,没必要为一个不存在业务特殊性的测试场景专门发明一种测试环境。在集团层面,阿里对流水线形式的约束相对宽松。客观的讲,只有在一线的开发团队知道最适合团队的交付流程应该是什么样子。阿里的开发平台只是规范了一些推荐的流水线模板,开发者可在此基础上进行发挥。列举几个典型的模板例子:这里出现了几种外界不太常见的环境类型名称,稍后会详细介绍。其次是测试环境成本的管理。成本管理的问题十分棘手且十分值得深究。与测试环境相关的成本主要包括管理环境所需的“人工成本”和购买基础设施所需的“资产成本”。通过自动化以及自服务化的工具可以有效降低人工相关的成本,自动化又是个很大的话题,宜另起一篇文章讨论,此处暂且收住。资产购买成本的降低依赖技术的改良和进步(排除规模化采购带来的价格变化因素),而基础设施技术的发展史包括两大领域:硬件和软件。硬件发展带来的成本大幅下降,通常来自于新的材料、新的生产工艺、以及新的硬件设计思路;软件发展带来的基础设施成本大幅下降,目前看来,大多来自于虚拟化(即资源隔离复用)技术的突破。最早的虚拟化技术是虚拟机,早在20世纪50年代,IBM就开始利用这种硬件级的虚拟化方法获得成倍的资源利用率提升。虚拟机上的不同隔离环境之间各自运行完整操作系统,具有很好的隔离性,通用性强,但对于运行业务服务的场景,显得略为笨重。2000年后,KVM、XEN等开源项目使得硬件级虚拟化广泛普及。与此同时,另一种更轻量的虚拟化技术出现了,以OpenVZ、LXC为代表的早期容器技术,实现了建立于操作系统内核之上的运行环境虚拟化,减少了独立操作系统的资源消耗,以牺牲一定隔离性为代价,获得更高的资源利用率。之后诞生的Docker以其镜像封装和单进程容器的理念,将这种内核级虚拟化技术推上百万人追捧的高度。阿里紧随技术前进的步伐,早早的就用上了虚拟机和容器,在2017年双十一时,在线业务服务的容器化比例已经达到100%。然而,接下来的挑战是,基础设施资源利用率还能做得更高吗?甩掉了虚拟机的硬件指令转换和操作系统开销,运行在容器中的程序与普通程序之间只有一层薄薄的内核Namespace隔离,完全没有运行时性能损耗,虚拟化在这个方向上似乎已经发展到了极限。唯一的可能是,抛开通用场景,专注到测试环境管理的特定场景上,继续寻找突破。终于,阿里在这个领域里发现了新的宝藏:服务级虚拟化。所谓服务级虚拟化,本质上是基于消息路由的控制,实现集群中部分服务的复用。在服务级虚拟化方式下,许多外表庞大的独立测试环境实际只需要消耗极小的额外基础设施资源,即使给每个开发者配备一套专用的测试环境集群都不再是吹牛。具体来说,在阿里的交付流程上,包含两种特殊类型的测试环境:“公共基础环境”和“特性环境”,它们形成了具有阿里特色的测试环境使用方法。公共基础环境是一个全套的服务运行环境,它通常运行一个相对稳定的服务版本,也有些团队将始终部署各服务的最新版本的低级别环境(称为“日常环境”)作为公共基础环境。特性环境是这套方法中最有意思的地方,它是虚拟的环境。从表面上看,每个特性环境都是一套独立完整的测试环境,由一系列服务组成集群,而实际上,除了个别当前使用者想要测试的服务,其余服务都是通过路由系统和消息中间件虚拟出来的,指向公共基础环境的相应服务。由于在阿里通常的开发流程中,开发任务需要经过特性分支、发布分支和诸多相关环节最后发布上线,大多数环境都从发布分支部署,唯独这种开发者自用的虚拟环境部署来自代码特性分支的版本,故可称为“特性环境”(阿里内部叫“项目环境”)。举个具体例子,某交易系统的完整部署需要由鉴权服务、交易服务、订单服务、结算服务等十几种小系统以及相应的数据库、缓存池、消息中间件等组成,那么它的公共基础环境就是这样一套具备所有服务和周边组件的完整环境。假设此时有两套特性环境在运行,一套只启动了交易服务,另一套启动了交易服务、订单服务和结算服务。对于第一套特性环境的使用者而言,虽然除交易服务外的所有服务实际上都由公共基础环境代理,但在使用时就像是自己独占一整套完整环境:可以随意部署和更新环境中交易服务的版本,并对它进行调试,不用担心会影响其他用户。对于第二套特性环境的使用者,则可以对部署在该环境中的三个服务进行联调和验证,倘若在场景中使用到了鉴权服务,则由公共基础环境的鉴权服务来响应。咋看起来,这不就是动态修改域名对应的路由地址、或者消息主题对应的投递地址么?实事并没那么简单,因为不能为了某个特性环境而修改公共基础环境的路由,所以单靠正统路由机制只能实现单向目标控制,即特性环境里的服务主动发起调用能够正确路由,若请求的发起方在公共基础环境上,就无法知道该将请求发给哪个特性环境了。对于HTTP类型的请求甚至很难处理回调的情况,当处于公共基础环境的服务进行回调时,域名解析会将目标指向公共基础环境上的同名服务。如何才能实现数据双向的正确路由和投递呢?不妨先回到这个问题的本质上来:请求应该进入哪个特性环境,是与请求的发起人相关的。因此实现双向绑定的关键在于,识别请求发起人所处的特性环境和进行端到端的路由控制。这个过程与“灰度发布”很有几分相似,可采用类似的思路解决。得益于阿里在中间件领域的技术积累,和鹰眼等路由追踪工具的广泛使用,识别请求发起人和追溯回调链路都不算难事。如此一来,路由控制也就水到渠成了。当使用特性环境时,用户需要“加入”到该环境,这个操作会将用户标识(如IP地址或用户ID)与指定的特性环境关联起来,每个用户只能同时属于一个特性环境。当数据请求经过路由中间件(消息队列、消息网关、HTTP网关等),一旦识别到请求的发起人当前处在特性环境中,就会尝试把请求路由给该环境中的服务,若该环境没有与目标一致的服务,才路由或投递到公共基础环境上。特性环境并不是孤立存在的,它可以建立在容器技术之上,从而获得更大的灵活性。正如将容器建立在虚拟机之上得到基础设施获取的便利性一样,在特性环境中,通过容器快速而动态的部署服务,意味着用户可以随时向特性环境中增加一个需要修改或调试的服务,也可以将环境中的某个服务随时销毁,让公共基础环境的自动接替它。还有一个问题是服务集群调试。配合AoneFlow的特性分支工作方式,倘若将几个服务的不同特性分支部署到同一个特性环境,就可以进行多特性的即时联调,从而将特性环境用于集成测试。不过,即使特性环境的创建成本很低,毕竟服务是部署在测试集群上的。这意味着每次修改代码都需要等待流水线的构建和部署,节约了空间开销,却没有缩短时间开销。为了进一步的降低成本、提高效率,阿里团队又捣鼓出了一种开脑洞的玩法:将本地开发机加入特性环境。在集团内部,由于开发机和测试环境都使用内网IP地址,稍加变通其实不难将特定的测试环境请求直接路由到开发机。这意味着,在特性环境的用户即使访问一个实际来自公共基础环境的服务,在后续处理链路上的一部分服务也可以来自特性环境,甚至来自本地环境。现在,调试集群中的服务变得非常简单,再也不用等待漫长的流水线构建,就像整个测试环境都运行在本地一样。DIY体验特性环境觉得服务级虚拟化太小众,离普通开发者很远?实事并非如此,我们现在就可以动手DIY个体验版的特性环境来玩。阿里的特性环境实现了包括HTTP调用、RPC调用、消息队列、消息通知等各类常用服务通信方式的双向路由服务级虚拟化。要完成这样的功能齐全的测试环境有点费劲,从通用性角度考虑,咱不妨从最符合大众口味的HTTP协议开始,做个支持单向路由的简易款。为了便于管理环境,最好得有一个能跑容器的集群,在开源社区里,功能齐全的Kubernetes是个不错的选择。在Kubernetes中有些与路由控制有关的概念,它们都以资源对象的形式展现给用户。简单介绍一下,Namespace对象能隔离服务的路由域(与容器隔离使用的内核Namespace不是一个东西,勿混淆),Service对象用来指定服务的路由目标和名称,Deployment对象对应真实部署的服务。类型是ClusterIP(以及NodePort和LoadBalancer类型,暂且忽略它们)的Service对象可路由相同Namespace内的一个真实服务,类型是ExternalName的Service对象则可作为外部服务在当前Namespace的路由代理。这些资源对象的管理都可以使用YAML格式的文件来描述,大致了解完这些,就可以开始动工了。基础设施和Kubernetes集群搭建的过程略过,下面直接进正题。先得准备路由兜底的公共基础环境,这是一个全量测试环境,包括被测系统里的所有服务和其他基础设施。暂不考虑对外访问,公共基础环境中的所有服务相应的Service对象都可以使用ClusterIP类型,假设它们对应的Namespace名称为pub-base-env。这样一来,Kubernetes会为此环境中的每个服务自动赋予Namespace内可用的域名“服务名.svc.cluster”和集群全局域名“服务名.pub-base-env.svc.cluster”。有了兜底的保障后,就可以开始创建特性环境了,最简单的特性环境可以只包含一个真实服务(例如trade-service),其余服务全部用ExternalName类型的Service对象代理到公共基础环境上。假设它使用名称为feature-env-1的Namespace,其描述的YAML如下(省略了非关键字段的信息):kind: Namespacemetadata:name: feature-env-1*kind: Servicemetadata:name: trade-servicenamespace: feature-env-1spec:type: ClusterIP…*kind: Deploymentmetadata:name: trade-servicenamespace: feature-env-1spec:…*kind: Servicemetadata:name: order-servicenamespace: feature-env-1spec:type: ExternalNameexternalName: order-service.pub-base-env.svc.cluster…*kind: Service…注意其中的order-service服务,它在当前特性环境Namespace中可以使用局部域名order-service.svc.cluster访问,请求会路由到它配置的全局域名order-service.pub-base-env.svc.cluster,即公共基础环境的同名服务上处理。处于该Namespace中的其它服务感知不到这个差异,而是会觉得这个Namespace中部署了所有相关的服务。若在特性的开发过程中,开发者对order-service服务也进行了修改,此时应该将修改过的服务版本添加到环境里来。只需修改order-service的Service对象属性(使用Kubernetes的patch操作),将其改为ClusterIP类型,同时在当前Namespace中创建一个Deployment对象与之关联即可。由于修改Service对象只对相应Namespace(即相应的特性环境)内的服务有效,无法影响从公共基础环境回调的请求,因此路由是单向的。在这种情况下,特性环境中必须包含待测调用链路的入口服务和包含回调操作的服务。例如待测的特性是由界面操作发起的,提供用户界面的服务就是入口服务。即使该服务没有修改,也应该在特性环境中部署它的主线版本。通过这种机制也不难实现把集群服务局部替换成本地服务进行调试开发的功能,倘若集群和本地主机都在内网,将ExternalName类型的Service对象指向本地的IP地址和服务端口就可以了。否则需要为本地服务增加公网路由,通过动态域名解析来实现。与此同时,云效也正在逐步完善基于Kubernetes的特性环境解决方案,届时将会提供更加全面的路由隔离支持。值得一提的是,由于公有云的特殊性,在联调时将本地主机加入云上集群是个必须克服的难题。为此云效实现了通过隧道网络+kube-proxy自身路由能力,将本地局域网主机(无需公网IP地址)加入到不在同一内网Kubernetes集群进行联调的方式。其中的技术细节也将在近期的云效公众号向大家揭晓,敬请留意。小结当许多人还在等待,在虚拟机和容器之后,下一轮虚拟化技术的风口何时到来的时候,阿里已经给出了一种答案。创业者的心态让阿里人懂得,能省必须省。其实,限制创新的往往不是技术而是想象力,服务级虚拟化的理念突破了人们对环境副本的传统认知,以独特的角度化解了测试环境成本与稳定性的矛盾。作为一种颇具特色的技术载体,特性环境的价值不仅仅在于轻量的测试环境管理体验,更在于为每位开发人员带来流畅的工作方式,实则是“简约而不简单”。实践出真知,阿里巴巴云效平台致力于解决大型项目协作、敏捷高速迭代、海量代码托管、高效测试工具、分布式秒级构建、大规模集群部署发布等世界级业务和技术难题,为阿里巴巴集团内部、生态伙伴以及云上开发者服务。诚挚欢迎业界同行与我们探讨交流。相关阅读:在阿里,我们如何管理代码分支当kubernetes应用遇到阿里分批发布模式本文作者:云效鼓励师阅读原文本文为云栖社区原创内容,未经允许不得转载。

January 25, 2019 · 1 min · jiezi

Spark in action on Kubernetes - Playground搭建与架构浅析

前言Spark是非常流行的大数据处理引擎,数据科学家们使用Spark以及相关生态的大数据套件完成了大量又丰富场景的数据分析与挖掘。Spark目前已经逐渐成为了业界在数据处理领域的行业标准。但是Spark本身的设计更偏向使用静态的资源管理,虽然Spark也支持了类似Yarn等动态的资源管理器,但是这些资源管理并不是面向动态的云基础设施而设计的,在速度、成本、效率等领域缺乏解决方案。随着Kubernetes的快速发展,数据科学家们开始考虑是否可以用Kubernetes的弹性与面向云原生等特点与Spark进行结合。在Spark 2.3中,Resource Manager中添加了Kubernetes原生的支持,而本系列我们会给大家介绍如何用更Kubernetes的方式在集群中使用Spark进行数据分析。本系列不需要开发者有丰富的Spark使用经验,对着系列的逐渐深入,会穿插讲解使用到的Spark特性。搭建Playground很多的开发者在接触Hadoop的时候,被安装流程的复杂度打消了很多的积极性。为了降低学习的门槛,本系列会通过spark-on-k8s-operator作为Playground,简化大家的安装流程。spark-on-k8s-operator顾名思义是为了简化Spark操作而开发的operator,如果对operator不是很了解的开发者,可以先自行搜索了解下,理解operator能做什么可以快速帮你掌握spark-on-k8s-operator的要领。在讲解内部原理前,我们先将环境搭建起来,通过一个简单的demo,跑通整个的运行时环境。1. 安装spark-on-k8s-operator官方的文档是通过Helm Chart进行安装的,由于很多开发者的环境无法连通google的repo,因此此处我们通过标准的yaml进行安装。## 下载repogit clone git@github.com:AliyunContainerService/spark-on-k8s-operator.git## 安装crdkubectl apply -f manifest/spark-operator-crds.yaml ## 安装operator的服务账号与授权策略kubectl apply -f manifest/spark-operator-rbac.yaml ## 安装spark任务的服务账号与授权策略kubectl apply -f manifest/spark-rbac.yaml ## 安装spark-on-k8s-operator kubectl apply -f manifest/spark-operator.yaml 验证安装结果此时在spark-operator的命名空间下的无状态应用下,可以看到一个运行中的sparkoperator,表名此时组件已经安装成功,接下来我们运行一个demo应用来验证组件是否可以正常工作。2. Demo验证学习Spark的时候,我们运行的第一个任务是官方文档中介绍的圆周率运行的例子。今天我们换一种方式,通过Kubernetes的方式再运行一次。## 下发spark-pi任务kubectl apply -f examples/spark-pi.yaml 任务下发成功后,可以通过命令行观察任务的状态。## 查询任务kubectl describe sparkapplication spark-pi## 任务结果 Name: spark-piNamespace: defaultLabels: <none>Annotations: kubectl.kubernetes.io/last-applied-configuration: {“apiVersion”:“sparkoperator.k8s.io/v1alpha1”,“kind”:“SparkApplication”,“metadata”:{“annotations”:{},“name”:“spark-pi”,“namespace”:“defaul…API Version: sparkoperator.k8s.io/v1alpha1Kind: SparkApplicationMetadata: Creation Timestamp: 2019-01-20T10:47:08Z Generation: 1 Resource Version: 4923532 Self Link: /apis/sparkoperator.k8s.io/v1alpha1/namespaces/default/sparkapplications/spark-pi UID: bbe7445c-1ca0-11e9-9ad4-062fd7c19a7bSpec: Deps: Driver: Core Limit: 200m Cores: 0.1 Labels: Version: 2.4.0 Memory: 512m Service Account: spark Volume Mounts: Mount Path: /tmp Name: test-volume Executor: Cores: 1 Instances: 1 Labels: Version: 2.4.0 Memory: 512m Volume Mounts: Mount Path: /tmp Name: test-volume Image: gcr.io/spark-operator/spark:v2.4.0 Image Pull Policy: Always Main Application File: local:///opt/spark/examples/jars/spark-examples_2.11-2.4.0.jar Main Class: org.apache.spark.examples.SparkPi Mode: cluster Restart Policy: Type: Never Type: Scala Volumes: Host Path: Path: /tmp Type: Directory Name: test-volumeStatus: Application State: Error Message: State: COMPLETED Driver Info: Pod Name: spark-pi-driver Web UI Port: 31182 Web UI Service Name: spark-pi-ui-svc Execution Attempts: 1 Executor State: Spark - Pi - 1547981232122 - Exec - 1: COMPLETED Last Submission Attempt Time: 2019-01-20T10:47:14Z Spark Application Id: spark-application-1547981285779 Submission Attempts: 1 Termination Time: 2019-01-20T10:48:56ZEvents: Type Reason Age From Message —- —— —- —- ——- Normal SparkApplicationAdded 55m spark-operator SparkApplication spark-pi was added, Enqueuing it for submission Normal SparkApplicationSubmitted 55m spark-operator SparkApplication spark-pi was submitted successfully Normal SparkDriverPending 55m (x2 over 55m) spark-operator Driver spark-pi-driver is pending Normal SparkExecutorPending 54m (x3 over 54m) spark-operator Executor spark-pi-1547981232122-exec-1 is pending Normal SparkExecutorRunning 53m (x4 over 54m) spark-operator Executor spark-pi-1547981232122-exec-1 is running Normal SparkDriverRunning 53m (x12 over 55m) spark-operator Driver spark-pi-driver is running Normal SparkExecutorCompleted 53m (x2 over 53m) spark-operator Executor spark-pi-1547981232122-exec-1 completed此时我们发现任务已经执行成功,查看这个Pod的日志,我们可以到计算最终的结果为Pi is roughly 3.1470557352786765。至此,在Kubernetes上,已经跑通了第一个Job,接下来我们要来详解一下刚才这一波操作到底都做了些什么。Spark Operator的基础架构浅析这张图是Spark Operator的流程图,在上面的操作中,第一个步骤里面,实际上是将图中的中心位置蓝色的Spark Operator安装到集群中,Spark Opeartor本身即是是一个CRD的Controller也是一个Mutating Admission Webhook的Controller。当我们下发spark-pi模板的时候,会转换为一个名叫SparkApplication的CRD对象,然后Spark Operator会监听Apiserver,并将SparkApplication对象进行解析,变成spark-submit的命令并进行提交,提交后会生成Driver Pod,用简单的方式理解,Driver Pod就是一个封装了Spark Jar的镜像。如果是本地任务,就直接在Driver Pod中执行;如果是集群任务,就会通过Driver Pod再生成Exector Pod进行执行。当任务结束后,可以通过Driver Pod进行运行日志的查看。此外在任务的执行中,Spark Operator还会动态attach一个Spark UI到Driver Pod上,希望查看任务状态的开发者,可以通过这个UI页面进行任务状态的查看。最后在本文中,我们讨论了Spark Operator的设计初衷,如何快速搭建一个Spark Operator的Playground以及Spark Operator的基本架构与流程。在下一篇文章中,我们会深入到Spark Operator的内部,为大家讲解其内部的实现原理以及如何与Spark更无缝的集成。本文作者:莫源阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

January 23, 2019 · 2 min · jiezi

阿里重磅开源首款自研科学计算引擎Mars,揭秘超大规模科学计算

摘要: 由阿里巴巴统一大数据计算平台MaxCompute研发团队,历经1年多研发,打破大数据、科学计算领域边界,完成第一个版本并开源。 Mars,一个基于张量的统一分布式计算框架。使用 Mars 进行科学计算,不仅使得完成大规模科学计算任务从MapReduce实现上千行代码降低到Mars数行代码,更在性能上有大幅提升。日前,阿里巴巴正式对外发布了分布式科学计算引擎 Mars 的开源代码地址,开发者们可以在pypi上自主下载安装,或在Github上获取源代码并参与开发。此前,早在2018年9月的杭州云栖大会上,阿里巴巴就公布了这项开源计划。Mars 突破了现有大数据计算引擎的关系代数为主的计算模型,将分布式技术引入科学计算/数值计算领域,极大地扩展了科学计算的计算规模和效率。目前已应用于阿里巴巴及其云上客户的业务和生产场景。本文将为大家详细介绍Mars的设计初衷和技术架构。*概述科学计算即数值计算,是指应用计算机处理科学研究和工程技术中所遇到的数学计算问题。比如图像处理、机器学习、深度学习等很多领域都会用到科学计算。有很多语言和库都提供了科学计算工具。这其中,Numpy以其简洁易用的语法和强大的性能成为佼佼者,并以此为基础形成了庞大的技术栈。(下图所示)Numpy的核心概念多维数组是各种上层工具的基础。多维数组也被称为张量,相较于二维表/矩阵,张量具有更强大的表达能力。因此,现在流行的深度学习框架也都广泛的基于张量的数据结构。随着机器学习/深度学习的热潮,张量的概念已逐渐为人所熟知,对张量进行通用计算的规模需求也与日俱增。但现实是如Numpy这样优秀的科学计算库仍旧停留在单机时代,无法突破规模瓶颈。当下流行的分布式计算引擎也并非为科学计算而生,上层接口不匹配导致科学计算任务很难用传统的SQL/MapReduce编写,执行引擎本身没有针对科学计算优化更使得计算效率难以令人满意。基于以上科学计算现状,由阿里巴巴统一大数据计算平台MaxCompute研发团队,历经1年多研发,打破大数据、科学计算领域边界,完成第一个版本并开源。 Mars,一个基于张量的统一分布式计算框架。使用 Mars 进行科学计算,不仅使得完成大规模科学计算任务从MapReduce实现上千行代码降低到Mars数行代码,更在性能上有大幅提升。目前,Mars 实现了 tensor 的部分,即numpy 分布式化, 实现了 70% 常见的 numpy 接口。后续,在 Mars 0.2 的版本中, 正在将 pandas 分布式化,即将提供完全兼容 pandas 的接口,以构建整个生态。 Mars作为新一代超大规模科学计算引擎,不仅普惠科学计算进入分布式时代,更让大数据进行高效的科学计算成为可能。Mars的核心能力符合使用习惯的接口Mars 通过 tensor 模块提供兼容 Numpy 的接口,用户可以将已有的基于 Numpy 编写的代码,只需替换 import,就可将代码逻辑移植到 Mars,并直接获得比原来大数万倍规模,同时处理能力提高数十倍的能力。目前,Mars 实现了大约 70% 的常见 Numpy 接口。充分利用GPU加速除此之外,Mars 还扩展了 Numpy,充分利用了GPU在科学计算领域的已有成果。创建张量时,通过指定 gpu=True 就可以让后续计算在GPU上执行。比如:a = mt.random.rand(1000, 2000, gpu=True) # 指定在 GPU 上创建(a + 1).sum(axis=1).execute()稀疏矩阵Mars 还支持二维稀疏矩阵,创建稀疏矩阵的时候,通过指定 sparse=True 即可。以eye 接口为例,它创建了一个单位对角矩阵,这个矩阵只有对角线上有值,其他位置上都是 0,所以,我们可以用稀疏的方式存储。a = mt.eye(1000, sparse=True) # 指定创建稀疏矩阵(a + 1).sum(axis=1).execute()系统设计接下来介绍 Mars 的系统设计,让大家了解 Mars 是如何让科学计算任务自动并行化并拥有强大的性能。分而治之—tileMars 通常对科学计算任务采用分而治之的方式。给定一个张量,Mars 会自动将其在各个维度上切分成小的 Chunk 来分别处理。对于 Mars 实现的所有的算子,都支持自动切分任务并行。这个自动切分的过程在Mars里被称为 tile。比如,给定一个 1000 2000 的张量,如果每个维度上的 chunk 大小为 500,那么这个张量就会被 tile 成 2 4 一共 8 个 chunk。对于后续的算子,比如加法(Add)和求和(SUM),也都会自动执行 tile 操作。一个张量的运算的 tile 过程如下图所示。延迟执行和 Fusion 优化目前 Mars 编写的代码需要显式调用 execute 触发,这是基于 Mars 的延迟执行机制。用户在写中间代码时,并不会需要任何的实际数据计算。这样的好处是可以对中间过程做更多优化,让整个任务的执行更优。目前 Mars 里主要用到了 fusion 优化,即把多个操作合并成一个执行。对于前面一个图的例子,在 tile 完成之后,Mars 会对细粒度的 Chunk 级别图进行 fusion 优化,比如8个 RAND+ADD+SUM,每个可以被分别合并成一个节点,一方面可以通过调用如 numexpr 库来生成加速代码,另一方面,减少实际运行节点的数量也可以有效减少调度执行图的开销。多种调度方式Mars 支持多种调度方式:| 多线程模式:Mars 可以使用多线程来在本地调度执行 Chunk 级别的图。对于 Numpy 来说,大部分算子都是使用单线程执行,仅使用这种调度方式,也可以使得 Mars 在单机即可获得 tile 化的执行图的能力,突破 Numpy 的单机内存限制,同时充分利用单机所有 CPU/GPU 资源,获得比 Numpy 快数倍的性能。| 单机集群模式: Mars 可以在单机启动整个分布式运行时,利用多进程来加速任务的执行;这种模式适合模拟面向分布式环境的开发调试。| 分布式 : Mars 可以启动一个或者多个 scheduler,以及多个 worker,scheduler 会调度 Chunk 级别的算子到各个 worker 去执行。下图是 Mars 分布式的执行架构:Mars 分布式执行时会启动多个 scheduler 和 多个 worker,图中是3个 scheduler 和5个 worker,这些 scheduler 组成一致性哈希环。用户在客户端显式或隐式创建一个 session,会根据一致性哈希在其中一个 scheduler 上分配 SessionActor,然后用户通过 execute 提交了一个张量的计算,会创建 GraphActor 来管理这个张量的执行,这个张量会在 GraphActor 中被 tile 成 chunk 级别的图。这里假设有3个 chunk,那么会在 scheduler 上创建3个 OperandActor 分别对应。这些 OperandActor 会根据自己的依赖是否完成、以及集群资源是否足够来提交到各个 worker 上执行。在所有 OperandActor 都完成后会通知 GraphActor 任务完成,然后客户端就可以拉取数据来展示或者绘图。向内和向外伸缩Mars 灵活的 tile 化执行图配合多种调度模式,可以使得相同的 Mars 编写的代码随意向内(scale in)和向外(scale out)伸缩。向内伸缩到单机,可以利用多核来并行执行科学计算任务;向外伸缩到分布式集群,可以支持到上千台 worker 规模来完成单机无论如何都难以完成的任务。Benchmark在一个真实的场景中,我们遇到了巨型矩阵乘法的计算需求,需要完成两个均为千亿元素,大小约为2.25T的矩阵相乘。Mars通过5行代码,使用1600 CU(200个 worker,每 worker 为 8核 32G内存),在2个半小时内完成计算。在此之前,同类计算只能使用 MapReduce 编写千余行代码模拟进行,完成同样的任务需要动用 9000 CU 并耗时10个小时。让我们再看两个对比。下图是对36亿数据矩阵的每个元素加一再乘以二,红色的叉表示 Numpy 的计算时间,绿色的实线是 Mars 的计算时间,蓝色虚线是理论计算时间。可以看到单机 Mars 就比 Numpy 快数倍,随着 Worker 的增加,可以获得几乎线性的加速比。下图是进一步扩大计算规模,把数据扩大到144亿元素,对这些元素加一乘以二以后再求和。这时候输入数据就有 115G,单机的 Numpy 已经无法完成运算,Mars 依然可以完成运算,且随着机器的增多可以获得还不错的加速比。开源地址Mars 已经在 Github 开源:https://github.com/mars-project/mars ,且后续会全部在 Github 上使用标准开源软件的方式来进行开发,欢迎大家使用 Mars,并成为 Mars 的 contributor。Mars科学计算引擎产品发布会发布直播回放>>发布活动页>> 大数据计算服务MaxCompute官网>>MaxCompute试用申请页面>>聚能聊>>本文作者:晋恒阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

January 17, 2019 · 2 min · jiezi

Mars 如何分布式地执行

先前,我们已经介绍过 Mars 是什么。如今 Mars 已在 Github 开源并对内上线试用,本文将介绍 Mars 已实现的分布式执行架构,欢迎大家提出意见。架构Mars 提供了一套分布式执行 Tensor 的库。该库使用 mars.actors 实现的 Actor 模型编写,包含 Scheduler、Worker 和 Web 服务。用户向 Mars Web Service 提交的是由 Tensor 组成的 Graph。Web Service 接收这些图并提交到一台 Scheduler。在提交作业到各个 Worker 之前,Mars Scheduler 先将 Tensor 图编译成一张由 Chunk 和 Operand 组成的图,此后对图进行分析和切分。此后,Scheduler 在所有 Scheduler 中根据一致性哈希创建一系列控制单个 Operand 执行的 OperandActor。Operand 以符合拓扑序的顺序进行调度,当所有 Operand 完成执行,整张图将被标记为已完成,客户端能够从 Web 中拉取结果。整个执行过程如下图所述。作业提交用户端通过 RESTful API 向 Mars 服务提交作业。用户通过编写 Tensor 上的代码,此后通过 session.run(tensor) 将 Tensor 操作转换为 Tensor 构成的 Graph 并提交到 Web API。此后,Web API 将作业提交到 SessionActor 并在集群中创建一个 GraphActor 用于图的分析和管理。用户端则开始查询图的执行状态,直至执行结束。在 GraphActor 中,我们首先根据 chunks 设置将 Tensor 图转换为 Operand 和 Chunk 组成的图,这一过程使得图可以被进一步拆分并能够并行执行。此后,我们在图上进行一系列的分析以获得 Operand 的优先级,同时向起始 Operand 指派 Worker,关于这一部分的细节可以参考 准备执行图 章节。此后,每个 Operand 均建立一个 OperandActor 用于控制该 Operand 的具体执行。当 Operand 处于 READY状态(如同在 Operand 状态 章节描述的那样),Scheduler 将会为 Operand 选择目标 Worker,随后作业被提交 Worker 进行实际的执行。执行控制当一个 Operand 被提交到 Worker,OperandActor 等待 Worker 上的回调。如果 Operand 执行成功,Operand 的后继将被调度。如果 Operand 执行失败,OperandActor 将会尝试数次,如果仍失败则将此次执行标记为失败。取消作业用户端可以使用 RESTful API 取消运行中的作业。取消请求将被写入 Graph 的状态存储中,同时 GraphActor 上的取消接口将被调用。如果作业在准备阶段,它将在检测到停止请求后立即结束,否则请求将被下发到每个 OperandActor,并设置状态为 CANCELLING。如果此时 Operand 没有运行,Operand 状态将被直接置为 CANCELLED。如果 Operand 正在运行,停止请求将被下发到 Worker 中并导致一个 ExecutionInterrupted 错误,该错误将返回给 OperandActor,此时 Operand 的状态将被标记为 CANCELLED。准备执行图当一个 Tensor 图被提交到 Mars Scheduler,一张包含更细粒度的,由 Operand 和 Chunk 构成的图将根据数据源中包含的 chunks 参数被生成。图压缩当完成 Chunk 图的生成后,我们将会通过合并图中相邻的节点来减小图的规模,这一合并也能让我们充分利用 numexpr 这样的加速库来加速计算过程。目前 Mars 仅会合并形成单条链的 Operand。例如,当执行下面的代码import mars.tensor as mta = mt.random.rand(100, chunks=100)b = mt.random.rand(100, chunks=100)c = (a + b).sum()Mars 将会合并 Operand ADD 和 SUM 成为 FUSE 节点。RAND Operand 不会被合并,因为它们并没有和 ADD 及 SUM 组成一条简单的直线。初始 Worker 分配为 Operand 分配 Worker 对于图执行的性能而言至关重要。随机分配初始 Operand 可能导致巨大的网络开销,并有可能导致不同 Worker 间作业分配的不平衡。因为非初始节点的分配能够根据其前驱生成数据的物理分布及各个 Worker 的空闲情况方便地确定,在执行图准备阶段,我们只考虑初始 Operand 的分配问题。初始 Worker 分配需要遵循几个准则。首先,分配给每个 Worker 执行的 Operand 需要尽量保持平衡满,这能够使计算集群在整个执行阶段都有较高的利用率,这在执行的最后阶段显得尤其重要。其次,初始节点分配需要使后续节点执行时的网络”传输尽量小。也就是说,初始点分配需要充分遵循局部性原则。需要注意的是,上述准则在某些情况下会彼此冲突。一个网络传输量最小的分配方案可能会非常偏斜。我们开发了一套启发式算法来获取两个目标的平衡,该算法描述如下:选择列表中的第一个初始节点和第一台机器;从 Operand 图转换出的无向图中自该点开始进行深度优先搜索;如果另一个未被分配的初始节点被访问到,我们将其分配给步骤1中选择的机器;当访问到的 Operand 总数大于平均每个 Worker 接受的 Operand 个数时,停止分配;前往步骤1,如果仍有 Worker 未被分配 Operand,否则结束。调度策略当一个 Operand 组成的 Graph 执行时,合适的执行顺序会减少集群中暂存的数据总量,从而减小数据被 Spill 到磁盘的可能性。合适的 Worker 能够减少执行时网络传输的总量。Operand 选择策略合适的执行顺序能够显著减小集群中暂存的数据总量。下图中展示了 Tree Reduction 的例子,圆形代表 Operand,方形代表 Chunk,红色代表 Operand 正在执行,蓝色代表 Operand 可被执行,绿色代表 Operand 产生的 Chunk 已被存储,灰色代表 Operand 及其相关数据已被释放。假设我们有两台 Worker,并且每个 Operand 的资源使用量均相等,每张图展示的是不同策略下经过5个时间单元的执行后的状态。左图展示的是节点依照层次分别执行,而右图展示的是依照接近深度优先的顺序执行。左图中,有6个 Chunk 的数据需要暂存,右图只有2个。因为我们的目标是减少存储在集群中的数据总数,我们为进入 READY 状态的 Operand 设定了一套优先级策略:深度更大的 Operand 需要被优先执行;被更深的 Operand 依赖的 Operand 需要被优先执行;输出规模更小的节点需要被优先执行。Worker 选择策略当 Scheduler 准备执行图时,初始 Operand 的 Worker 已被确定。我们选择后续 Operand 分配 Worker 的依据是输入数据所在的 Worker。如果某个 Worker 拥有的输入数据大小最大,则该 Worker 将被选择用于执行后续 Operand。如果这样的 Worker 有多个,则各个候选 Worker 的资源状况将起到决定作用。Operand 状态Mars 中的每一个操作符都被一个 OperandActor 单独调度。执行的过程是一个状态转移的过程。在 OperandActor 中,我们为每一个状态的进入过程定义一个状态转移函数。起始 Operand 在初始化时位于 READY 状态,非起始 Operand 在初始化时则位于 UNSCHEDULED 状态。当给定的条件满足,Operand 将转移到另一个状态并执行相应的操作。状态转移的流程可以参考下图:我们在下面描述每个状态的含义及 Mats 在这些状态下执行的操作。UNSCHEDUED:一个 Operand 位于此状态,当它的上游数据没有准备好。READY:一个 Operand 位于此状态,当所有上游输入数据均已准备完毕。在进入这一状态时,OperandActor 向 AssignerActor 中选择的所有 Worker 提交作业。如果某一 Worker 准备运行作业,它将向 Scheduler 发送消息,Scheduler 将向其他 Worker 发送停止运行的消息,此后向该 Worker 发送消息以启动作业执行。RUNNING:一个 Operand 位于此状态,当它的执行已经启动。在进入此状态时,OperandActor 会检查作业是否已经提交。如果尚未提交,OperandActor 将构造一个由 FetchChunk Operand 和当前 Operand 组成的图,并将其提交到 Worker 中。此后,OperandActor 会在 Worker 中注册一个回调来获取作业执行完成的消息。FINISHED:一个 Operand 位于此状态,当作业执行已完成。当 Operand 进入此状态,且 Operand 无后继,一个消息将被发送到 GraphActor 以决定是否整个 Graph 的执行都已结束。与此同时,OperandActor 向它的前驱和后继发送执行完成的消息。如果一个前驱收到此消息,它将检查是否所有的后继都已执行完成。如是,当前 Operand 上的数据可以被释放。如果一个后继收到此消息,它将检查是否所有的前驱已完成。如是,该后继的状态可以转移到 READY。FREED:一个 Operand 位于此状态,当其上所有数据都已被释放。CANCELLED:一个 Operand 位于此状态,当所有重新执行的尝试均告失败。当 Operand 进入此状态,它将把相同状态传递到后继节点。CANCELLING:一个 Operand 位于此状态,当它正在被取消执行。如果此前作业正在执行,一个取消执行的请求会被发送到 Worker 上。CANCELLED:一个 Operand 位于此状态,当执行已被取消并停止运行。如果执行进入这一状态,OperandActor 会尝试将书友的后继都转为 CANCELLING。Worker 中的执行细节一个 Mars Worker 包含多个进程,以减少全局解释器锁(GIL)对执行的影响。具体的执行在独立的进程中完成。为减少不必要的内存拷贝和进程间通讯,Mars Worker 使用共享内存来存储执行结果。当一个作业被提交到 Worker,它将首先被置于队列中等待分配内存。当内存被分配后,其他 Worker 上的数据,或者当前 Worker 上已被 spill 到磁盘的数据将会被重新载入内存中。此时,所有计算需要的数据已经都在内存中,真正的计算过程将启动。当计算完成,Worker 将会把作业放到共享存储空间中。这四种执行状态的转换关系见下图。执行控制Mars Worker 通过 ExecutionActor 控制所有 Operand 在 Worker 中的执行。该 Actor 本身并不参与实际运算或者数据传输,只是向其他 Actor 提交任务。Scheduler 中的 OperandActor 通过 ExecutionActor 上的 enqueue_graph 调用向 Worker 提交作业。Worker 接受 Operand 提交并且将其换存在队列中。当作业可以执行时,ExecutionActor 将会向 Scheduler 发送消息,Scheduler 将确定是否将执行该操作。当 Scheduler 确定在当前 Worker 上执行 Operand,它将调用 start_execution 方法,并通过 add_finish_callback注册一个回调。这一设计允许执行结果被多个位置接收,这对故障恢复有价值。ExecutionActor 使用 mars.promise 模块来同时处理多个 Operand 的执行请求。具体的执行步骤通过 Promise 类的 then 方法相串联。当最终的执行结果被存储,之前注册的回调将被触发。如果在之前的任意执行步骤中发生错误,该错误会被传导到最后 catch 方法注册的处理函数中并得到处理。Operand 的排序所有在 READY 状态的 Operand 都被提交到 Scheduler 选择的 Worker 中。因此,在执行的绝大多数时间里,提交到 Operand 的 Worker 个数通常都高于单个 Worker 能够处理的 Operand 总数。因此,Worker 需要对 Operand 进行排序,此后选择一部分 Worker 来执行。这一排序过程在 TaskQueueActor 中进行,该 Actor 中维护一个优先队列,其中存储 Operand 的相关信息。与此同时,TaskQueueActor 定时运行一个作业分配任务,对处于优先队列头部的 Operand 分配执行资源直至没有多余的资源来运行 Operand,这一分配过程也会在新 Operand 提交或者 Operand 执行完成时触发。内存管理Mars Worker 管理两部分内存。第一部分是每个 Worker 进程私有的内存空间,由每个进程自己持有。第二部分是所有进程共享的内存空间,由 Apache Arrow 中的 plasma_store 持有。为了避免进程内存溢出,我们引入了 Worker 级别的 QuotaActor,用于分配进程内存。当一个 Operand 开始执行前,它将为输入和输出 Chunk 向 QuotaActor 发送批量内存请求。如果剩余的内存空间可以满足请求,该请求会被 QuotaActor 接受。否则,请求将排队等待空闲资源。当相关内存使用被释放,请求的资源会被释放,此时,QuotaActor 能够为其他 Operand 分配资源。共享内存由 plasma_store 管理,通常会占据整个内存的 50%。由于不存在溢出的可能,这部分内存无需经过 QuotaActor 而是直接通过 plasma_store 的相关方法进行分配。当共享内存使用殆尽,Mars Worker 会尝试将一部分不在使用的 Chunk spill 到磁盘中,以腾出空间容纳新的 Chunk。从共享内存 spill 到磁盘的 Chunk 数据可能会被未来的 Operand 重新使用,而从磁盘重新载入共享内存的操作可能会非常耗费 IO 资源,尤其在共享内存已经耗尽,需要 spill 其他 Chunk 到磁盘以容纳载入的 Chunk 时。因此,当数据共享并不需要时,例如该 Chunk 只会被一个 Operand 使用,我们会将 Chunk 直接载入进程私有内存中,而不是共享内存,这可以显著减少作业总执行时间。未来工作Mars 目前正在快速迭代,近期将考虑实现 Worker 级别的 failover 及 shuffle 支持,Scheduler 级别的 failover 也在计划中。本文作者:继盛阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

January 11, 2019 · 3 min · jiezi

Kubernetes API 与 Operator,不为人知的开发者战争

如果我问你,如何把一个 etcd 集群部署在 Google Cloud 或者阿里云上,你一定会不假思索的给出答案:当然是用 etcd Operator!实际上,几乎在一夜之间,Kubernetes Operator 这个新生事物,就成了开发和部署分布式应用的一项事实标准。时至今日,无论是 etcd、TiDB、Redis,还是 Kafka、RocketMQ、Spark、TensorFlow,几乎每一个你能叫上名字来的分布式项目,都由官方维护着各自的 Kubernetes Operator。而 Operator 官方库里,也一直维护着一个知名分布式项目的 Operator 汇总。https://github.com/operator-framework/awesome-operators短短一年多时间,这个列表的长度已经增长了几十倍。 而且更有意思的是,如果你仔细翻阅这个 Operator 列表,你就不难发现这样一个有趣的事实:现今 Kubernetes Operator 的意义,恐怕已经远远超过了“分布式应用部署”的这个原始的范畴,而已然成为了容器化时代应用开发与发布的一个全新途径。所以,你才会在这个列表里看到,Android SDK 的开发者们,正在使用 Operator “一键”生成和更新 Android 开发环境;而 Linux 系统工程师们,则在使用Operator “一键”重现性能测试集群。如果说,Docker 镜像的提出,完成了应用静态描述的标准化。那么 Kubernetes Operator 的出现,终于为应用的动态描述提出了一套行之有效的实现规范。更为重要的是,对于 TiDB、Kafka、RocketMQ 等分布式应用的开发者来说,这些应用运行起来之后的动态描述,才是对一个分布式应用真正有意义的信息。而在此之前,用户如果要想将 TiDB、Kafka 这样的分布式应用很好的使用起来,就不得不去尝试编写一套复杂的管理脚本,甚至为此学习大量与项目本身无关的运维知识。更为麻烦的是,这些脚本、知识、和经验,并没有一个很好的办法能够有效的沉淀下来。而任何一种技术的传授,如果严重依赖于口口相传而不是固化的代码和逻辑的话,那么它的维护成本和使用门槛,就可以说是“灾难级”的。所以说,Kubernetes Operator 发布之初最大的意义,就在于它将分布式应用的使用门槛直接降到了最低。那么这个门槛具体有多低呢?一般来说,无论这个分布式应用项目有多复杂,只要它为用户提供了 Operator,那么这个项目的使用就只需要两条命令即可搞定,以 Kafka 为例:这两条命令执行完成后,一个 Kafka 集群运行所需的节点,以及它们所依赖的 ZooKeeper 节点,就会以容器的方式自动出现在你的 Kubernetes 集群里了。不过,简化运维和部署,其实只是 Operator 在用户层面的表象。而在更底层的技术层面,Operator 最大的价值,在于它为“容器究竟能不能管理有状态应用”这个颇具争议话题,画上了一个优雅的句号。要知道,在2014-2015年的时候,伴随着 Docker 公司和 Docker 项目的走红,整个云计算生态几乎都陷入了名为“容器”的狂热当中。然而,相比于 “容器化”浪潮的如火如荼,这个圈子却始终对“有状态应用”讳莫如深。事实上,有状态应用(比如, 前面提到的Kafka )跟无状态应用(比如,一个简单的Jave Web网站)的不同之处,就在于前者对某些外部资源有着绑定性的依赖,比如远程存储,或者网络设备,以及,有状态应用的多个示例之间往往有着拓扑关系。这两种设计,在软件工程的世界里可以说再普通不过了,而且我们几乎可以下这样一个结论:所有的分布式应用都是有状态应用。但是,在容器的世界里,分布式应用却成了一个“异类”。我们知道,容器的本质,其实就是一个被限制了“世界观”的进程。在这种隔离和限制的大基调下,容器技术本身的“人格基因”,就是对外部世界(即:宿主机)的“视而不见”和“充耳不闻”。所以我们经常说,容器的“状态”一定是“易失”的。其实,容器对它的“小世界”之外的状态和数据漠不关心,正是这种“隔离性”的主要体现。但状态“易失”并不能说是容器的缺陷:我们既然对容器可以重现完整的应用执行环境的“一致性”拍手称赞,那就必然要对这种能力背后的限制了然于心。这种默契,也正是早期的 Docker 公司所向披靡的重要背景:在这个阶段,相比于“容器化”的巨大吸引力,开发者是可以暂时接受一部分应用不能运行在容器里的。而分布式应用容器化的困境,其实就在于它成为了这种“容器化”默契的“终极破坏者”。一个应用本身可以拥有多个可扩展的实例,这本来是容器化应用令人津津乐道的一个优势。但是一旦这些实例像分布式应用这样具有了拓扑关系,以及,这些实例本身不完全等价的时候,容器化的解决方案就再次变得“丑陋”起来:这种情况下,应用开发者们不仅又要为这些容器实例编写一套难以维护的管理脚本,还必须要想办法应对容器重启后状态丢失的难题。而这些容器状态的维护,实际上往往需要打破容器的隔离性、让容器对外部世界有所感知才能做到,这就使得容器化与有状态,成为了两种完全相悖的需求。不过,从上面的叙述中相信你也应该已经察觉到,分布式应用容器化的难点,并不在于容器本身有什么重大缺陷,而在于我们一直以来缺乏一种对“状态”的合理的抽象与描述,使得状态可以和容器进程本身解耦开来。这也就解释了为什么,在 Kubernetes 这样的外部编排框架逐渐成熟起了之后,业界才逐渐对有状态应用管理开始有了比较清晰的理解和认识。而我们知道, Kubernetes 项目最具价值的理念,就是它围绕 etcd 构建出来的一套“面向终态”编排体系,这套体系在开源社区里,就是大名鼎鼎的“声明式 API”。“声明式 API”的核心原理,就是当用户向 Kubernetes 提交了一个 API 对象的描述之后,Kubernetes 会负责为你保证整个集群里各项资源的状态,都与你的 API 对象描述的需求相一致。更重要的是,这个保证是一项“无条件的”、“没有期限”的承诺:对于每个保存在 etcd 里的 API 对象,Kubernetes 都通过启动一种叫做“控制器模式”(Controller Pattern)的无限循环,不断检查,然后调谐,最后确保整个集群的状态与这个 API 对象的描述一致。比如,你提交的 API 对象是一个应用,描述的是这个应用必须有三个实例,那么无论接下来你的 API 对象发生任何“风吹草动”,控制器都会检查一遍这个集群里是不是真的有三个应用实例在运行。并且,它会根据这次检查的结果来决定,是不是需要对集群做某些操作来完成这次“调谐”过程。当然,这里控制器正是依靠 etcd 的 Watch API 来实现对 API 对象变化的感知的。在整个过程中,你提交的 API 对象就是 Kubernetes 控制器眼中的“金科玉律”,是接下来控制器执行调谐逻辑要达到的唯一状态。这就是我们所说的“终态”的含义。而 Operator 的设计,其实就是把这个“控制器”模式的思想,贯彻的更加彻底。在 Operator 里,你提交的 API 对象不再是一个单体应用的描述,而是一个完整的分布式应用集群的描述。这里的区别在于,整个分布式应用集群的状态和定义,都成了Kubernetes 控制器需要保证的“终态”。比如,这个应用有几个实例,实例间的关系如何处理,实例需要把数据存储在哪里,如何对实例数据进行备份和恢复,都是这个控制器需要根据 API 对象的变化进行处理的逻辑。从上述叙述中,你就应该能够明白, Operator 其实就是一段代码,这段代码 Watch 了 etcd 里一个描述分布式应用集群的API 对象,然后这段代码通过实现 Kubernetes 的控制器模式,来保证这个集群始终跟用户的定义完全相同。而在这个过程中,Operator 也有能力利用 Kubernetes 的存储、网络插件等外部资源,协同的为应用状态的保持提供帮助。所以说,Operator 本身在实现上,其实是在 Kubernetes 声明式 API 基础上的一种“微创新”。它合理的利用了 Kubernetes API 可以添加自定义 API 类型的能力,然后又巧妙的通过 Kubernetes 原生的“控制器模式”,完成了一个面向分布式应用终态的调谐过程。而 Operator 本身在用法上,则是一个需要用户大量编写代码的的开发者工具。 不过,这个编写代码的过程,并没有像很多人当初料想的那样导致 Operator 项目走向小众,反而在短短三年的时间里, Operator 就迅速成为了容器化分布式应用管理的事实标准。时至今日,Operator 项目的生态地位已经毋庸置疑。就在刚刚结束的2018年 KubeCon 北美峰会上,Operator 项目和大量的用户案例一次又一次出现在聚光灯前,不断的印证着这个小小的“微创新”对整个云计算社区所产生的深远影响。不过,在 Operator 项目引人瞩目的成长经历背后,你是否考虑过这样一个问题:Kubernetes 项目一直以来,其实都内置着一个管理有状态应用的能力叫作 StatefulSet。而如果你稍微了解 Kubernetes 项目的话就不难发现,Operator 和 StatefulSet,虽然在对应用状态的抽象上有所不同,但它们的设计原理,几乎是完全一致的,即:这两种机制的本质,都是围绕Kubernetes API 对象的“终态”进行调谐的一个控制器(Controller)而已。可是,为什么在一个开源社区里,会同时存在这样的两个核心原理完全一致、设计目标也几乎相同的有状态应用管理方案呢?作为 CoreOS 公司后来广为人知的“左膀右臂”之一(即:etcd 和 Operator),Operator 项目能够在 Kubernetes 生态里争取到今天的位置,是不是也是 CoreOS 公司的开源战略使然呢?事实上,Operator 项目并没有像很多人想象的那样出生就含着金钥匙。只不过,在当时的确没有人能想到,当 CoreOS 的两名工程师带着一个业余项目从一间平淡无奇的公寓走出后不久,一场围绕着 Kubernetes API 生态、以争夺“分布式应用开发者”为核心的的重量级角逐,就徐徐拉开了序幕。*2016 年秋天,原 CoreOS 公司的工程师邓洪超像往常一样,来到了同事位于福斯特城(Foster City)的公寓进行结对编程。每周四相约在这里结对,是这两位工程师多年来约定俗成的惯例。不过,与以往不同的是,相比于往常天马行空般的头脑风暴,这一次,这两位工程师的脑子里正在琢磨着的,是一个非常“接地气”的小项目。我们知道,Kubernetes 项目实现“容器编排”的核心,在于一个叫做“控制器模式”的机制,即:通过对 etcd 里的 API 对象的变化进行监视(Watch),Kubernetes 项目就可以在一个叫做 Controller 的组件里对这些变化进行响应。而无论是 Pod 等应用对象,还是 iptables、存储设备等服务对象,任何一个 API 对象发生变化,那么 Kubernetes 接下来需要执行的响应逻辑,就是对应的 Controller 里定义的编排动作。所以,一个自然而然的想法就是,作为 Kubernetes 项目的用户,我能不能自己编写一个 Controller 来定义我所期望的编排动作呢?比如:当一个 Pod 对象被更新的时候,我的 Controller 可以在“原地”对 Pod 进行“重启”,而不是像 Deployment 那样必须先删除 Pod,然后再创建 Pod。这个想法,其实是很多应用开发者以及 PaaS 用户的强烈需求,也是一直以来萦绕在 CoreOS 公司 CEO Alex Polvi 脑海里的一个念头。而在一次简单的内部讨论提及之后,这个念头很快就激发出了两位工程师的技术灵感,成为了周四结对编程的新主题。而这一次,他们决定把这个小项目,起名叫做:Operator。所以顾名思义,Operator 这个项目最开始的初衷,是用来帮助开发者实现运维(Operate)能力的。但 Operator 的核心思想,却并不是“替开发者做运维工作”,而是“让开发者自己编写运维工具”。更有意思的是,这个运维工具的编写标准,或者说,编写 Operator 代码可以参考的模板,正是 Kubernetes 的“控制器模式(Controller Pattern)”。前面已经说过, Kubernetes 的“控制器模式”,是围绕着比如 Pod 这样的 API 对象,在 Controller 通过响应它的增删改查来定义对 Pod 的编排动作。而 Operator 的设计思路,就是允许开发者在 Kubernetes 里添加一个新的 API 对象,用来描述一个分布式应用的集群。然后,在这个 API 对象的 Controller 里,开发者就可以定义对这个分布式应用集群的运维动作了。举个例子, 假设下面这个 YAML 文件定义的,是一个 3 节点 etcd 集群的描述:有了这样一个 etcdCluster 对象,那么开发者接下来要做的事情,就是编写一个 etcdCluster Controller,使得当任何用户提交这样一个 YAML 文件给 Kubernetes 之后,我们自己编写的 Controller 就会响应 etcdCluster “增加”事件,为用户创建出 3 个节点的 etcd 集群出来。然后,它还会按照我们在 Controller 编写的事件响应逻辑,自动的对这个集群的节点更新、删除等事件做出处理,执行我定义的其他运维功能。像这样一个 etcdCluster Controller,就是 etcd Operator 的核心组成部分了。而作为 etcd 的开发者,CoreOS 的两位工程师把对 etcd 集群的运维工作编写成 Go 语言代码,一点都不困难。可是,要完成这个 Operator 真正困难在于:Kubernetes 只认识 Pod、Node、Service 等这些 Kubernetes 自己原生的 API 对象,它怎么可能认识开发者自己定义的这个 etcdCluster 对象呢?在当时, Kubernetes 项目允许用户自己添加 API 对象的插件能力,叫做 Third Party Resource,简称:TPR。TPR 允许你提交一个 YAML 文件,来定义你想要的的新 API 对象的名字,比如:etcdCluster;也允许你定义这个对象允许的合法的属性,比如:int 格式的 size 字段, string 格式的 version 字段。然后,你就可以提交一个具体的 etcdCluster 对象的描述文件给 Kubernetes,等待该对应的 Controller 进行处理。而这个 Controller,就是 Operator 的主干代码了。所以接下来,CoreOS 的两位工程师轻车熟路,在 Operator 里对 etcdCluster 对象的增、删、改事件的响应位置,写上了创建、删除、更新 etcd 节点的操作逻辑。然后,调试运行,看着一个 etcd 集群按照 YAML 文件里的描述被创建起来。大功告成!就这样,在一个普通的周四下午,世界上第一个 Operator 诞生在了湾区的一所公寓当中。而对于 CoreOS 的两位工程师来说,编写这个小工具的主要目的,就是借助 Kubernetes 的核心原理来自动化的管理 etcd 集群,更重要的是,不需要使用 Kubernetes 里自带的 StatefulSet。你可能已经知道,Kubernetes 里本身就内置了一个叫做 StatefulSet 的功能,是专门用来管理有状态应用的。而 StatefulSet 的核心原理,其实是对分布式应用的两种状态进行了保持:分布式应用的拓扑状态,或者说,节点之间的启动顺序;分布式应用的存储状态,或者说,每个节点依赖的持久化数据。可是,为了能够实现上述两种状态的保持机制,StatefulSet 的设计就给应用开发者带来了额外的束缚。比如,etcd 集群各节点之间的拓扑关系,并不依赖于节点名字或者角色(比如 Master 或者 Slave)来确定,而是记录在每个 etcd 节点的启动参数当中。这使得 StatefulSet 通过“为节点分配有序的 DNS 名字”的拓扑保持方式,实际上没有了用武之地,反而还得要求开发者在节点的启动命令里添加大量的逻辑来生成正确的启动命令,非常不优雅。类似的,对于存储状态来说,etcd 集群对数据的备份和恢复方法,也跟 StatefulSet 依赖的的远程持久化数据卷方案并没有太大关系。不难看到, StatefulSet 其实比较适用于应用本身节点管理能力不完善的项目,比如 MySQL。而对于 etcd 这种已经借助 Raft 实现了自管理的分布式应用来说, StatefulSet 的使用方法和带来的各种限制,其实是非常别扭的。而带着工程师特有的较真儿精神,邓洪超和他的同事借助 Kubernetes 原生的扩展机制实现的,正是一个比 StatefulSet 更加灵活、能够把控制权重新交还给开发者的分布式应用管理工具。他们把这个工具起名叫做 Operator,并在几个月后的 KubeCon 上进行了一次 Demo ,推荐大家尝试使用 Operator 来部署 etcd 集群。没有人能想到的是,这个当时还处于 PoC 状态的小项目一经公布,就立刻激发起了整个社区的模仿和学习的热潮。很快,大量的应用开发者纷纷涌进 Kubernetes 社区,争先恐后的宣布自己的分布式项目可以通过 Operator 运行起来。而敏锐的公有云提供商们很快看出了这其中的端倪:Operator 这个小框架,已然成为了分布式应用和有状态应用“上云”的必经之路。Prometheus,Rook,伴随着越来越多的、以往在容器里运行起来困难重重的应用,通过 Operator 走上了 Kubernetes 之后,Kubernetes 项目第一次出现在了开发者生态的核心位置。这个局面,已经远远超出了邓洪超甚至 CoreOS 公司自己的预期。更重要的是,不同于 StatefulSet 等 Kubernetes 原生的编排概念,Operator 依赖的 Kubernetes 能力,只有最核心的声明式 API 与控制器模式;Operator 具体的实现逻辑,则编写在自定义 Controller 的代码中。这种设计给开发者赋予了极高的自由度,这在整个云计算和 PaaS 领域的发展过程中,都是非常罕见的。此外,相比于 Helm、Docker Compose 等描述应用静态关系的编排工具,Operator 定义的乃是应用运行起来后整个集群的动态逻辑。得益于 Kubernetes 项目良好的声明式 API 的设计和开发者友好的 API 编程范式,Operator 在保证上述自由度的同时,又可以始终如一的展现出清晰的架构和设计逻辑,使得应用的开发者们,可以通过复制粘贴就快速搭建出一个 Operator 的框架,然后专注于填写自己的业务逻辑。在向来讲究“用脚投票”的开发者生态当中,Operator 这样一个编程友好、架构清晰、方便代码复制粘贴的小工具,本身就已经具备了某些成功的特质。然而,Operator 的意外走红,并没有让 CoreOS 公司“一夜成名”,反而差点将这个初出茅庐的项目,扼杀在萌芽状态。在当时的 Kubernetes 社区里,跟应用开发者打交道并不是一个非常常见的事情。而 Operator 项目的诞生,却把 Kubernetes 项目第一次拉近到了开发者的面前,这让整个社区感觉了不适应。而作为 Kubernetes 项目 API 治理的负责人,Google 团队对这种冲突的感受最为明显。对于 Google 团队来说,Controller 以及控制器模式,应该是一个隐藏在 Kubernetes 内部实现里的核心机制,并不适合直接开放给开发者来使用。退一步说,即使开放出去,这个 Controller 的设计和用法,也应该按照 Kubernetes 现有的 API 层规范来进行,最好能成为 Kubernetes 内置 Controller Manager 管理下的一部分。可是, Operator 却把直接编写 Controller 代码的自由度完全交给了开发者,成为了一个游离于 Kubernetes Controller Manager 之外的外部组件。带着这个想法,社区里的很多团队从 Operator 项目诞生一开始,就对它的设计和演进方向提出了质疑,甚至建议将 Operator 的名字修改为 Custom Kubernetes Controller。而无巧不成书,就在 Google 和 CoreOS 在 Controller 的话语权上争执不下的时候, Kubernetes 项目的发起人之一 Brendan Burns 突然宣布加入了微软,这让 Google 团队和 Operator 项目的关系一下子跌倒了冰点。你可能会有些困惑:Brendan Burns 与 Kubernetes 的关系我是清楚的,但这跟 Operator 又有什么瓜葛吗?实际上,你可能很难想到,Brendan Burns 和他的团队,才是 TPR (Third Party Resource)这个特性最初的发起人。所以,几乎在一夜之间,Operator 项目链路上的每一个环节,都与 Google 团队完美的擦肩而过。眼睁睁的看着这个正冉冉升起的开发者工具突然就跟自己完全没了关系,这个中滋味,确实不太好受。于是,在 2017年初,Google 团队和 RedHat 公司开始主动在社区推广 UAS(User Aggregated APIServer),也就是后来 APIServer Aggregator 的雏形。APIServer Aggregator 的设计思路是允许用户编写一个自定义的 APIServer,在这里面添加自定义 API。然后,这个 APIServer 就可以跟 Kubernetes 原生的 APIServer 绑定部署在一起统一提供服务了。不难看到,这个设计与 Google 团队认为自定义 API 必须在 Kubernetes 现有框架下进行管理的想法还是比较一致的。紧接着,RedHat 和 Google 联盟开始游说社区使用 UAS 机制取代 TPR,并且建议直接从 Kubernetes 项目里废弃 TPR 这个功能。一时间,社区里谣言四起,不少已经通过 TPR 实现的项目,也开始转而使用 UAS 来重构以求自保。 而 Operator 这个严重依赖于 TPR 的小项目,还没来得及发展壮大,就被推向了关闭的边缘。面对几乎要与社区背道而驰的困境,CoreOS 公司的 CTO Brandon Philips 做出了一个大胆的决定:让社区里的所有开发者发声,挽救 TPR 和 Operator。2017 年 2月,Brandon Philips 在 GitHub 上开了一个帖子(Gist), 号召所有使用 TPR 或者 Operator 项目的开发者在这里留下的自己的项目链接或者描述。这个帖子,迅速的成为了当年容器技术圈最热门的事件之一,登上了 HackerNews 的头条。有趣的是,这个帖子直到今天也仍然健在,甚至还在被更新,你可以点击这个链接去感受一下当时的盛况。https://gist.github.com/philips/a97a143546c87b86b870a82a753db14c而伴随着 Kubernetes 项目的迅速崛起,短短一年时间不到,夹缝中求生存的 Operator 项目,开始对公有云市场产生了不可逆转的影响,也逐步改变了开发者们对“云”以及云上应用开发模式的基本认知。甚至就连 Google Cloud 自己最大的客户之一 Snapchat ,也成为了 Operator 项目的忠实用户。在来自社区的巨大压力下,在这个由成千上万开发者们自发维护起来的 Operator 生态面前,Google 和 RedHat 公司最终选择了反省和退让。有意思的是,这个退让的结果,再一次为这次闹剧增添了几分戏剧性。就在 Brandon Phillips 的开发者搜集帖发布了不到三个月后,RedHat 和 Google 公司的工程师突然在 Kubernetes 社区里宣布:TPR 即将被废弃,取而代之的是一个名叫 CRD,Custom Resource Definition 的东西。于是,开发者们开始忧心忡忡的按照文档,将原本使用 TPR 的代码都升级成 CRD。而就在这时,他们却惊奇的发现,这两种机制除了名字之外,好像并没有任何不同。所谓的升级工作,其实就是将代码里的 TPR 字样全局替换成 CRD 而已。难道,这只是虚惊一场?其实,很少有人注意到,在 TPR 被替换成 CRD 之后,Brendan Burns 和微软团队就再也没有出现在“自定义 API”这个至关重要的领域里了。而 CRD 现在的负责人,都是来自 Google 和 RedHat 的工程师。在这次升级事件之后不久,CoreOS 公司在它的官方网站上发布了一篇叫做:TPR Is Dead! Kubernetes 1.7 Turns to CRD 的博客(https://coreos.com/blog/custom-resource-kubernetes-v17),旨在指导用户从 TRP 升级成 CRD。不过,现在回头再看一眼这篇文章,平淡无奇的讲述背后,你能否感受到当年这场“开发者战争”的蛛丝马迹呢?其实,Operator 并不平坦的晋级之路,只是 Kubernetes API 生态风起云涌的冰山一角。几乎在每个星期,甚至每一天,都有太多围绕着 Kubernetes 开发者生态的角逐,在这个无比繁荣的社区背后,以不为人知的方式开始或者谢幕。而这一切纷争的根本原因却无比直白。Kubernetes 项目,已经被广泛认可为云计算时代应用开发者们的终端入口。这正是为何,无论是 Google、微软,还是 CoreOS 以及 Heptio,所有这个生态里的大小玩家,都在不遗余力的在 Kubernetes API 层上捍卫着自己的话语权,以期在这个未来云时代的开发者入口上,争取到自己的一席之地。而在完成了对收 CoreOS 的收购之后,RedHat 终于在这一领域拿到了可以跟 Google 和微软一较高低的关键位置。2018年,RedHat 不失时机的发布了 Operator Framework,希望通过 Operator 周边工具和生态的进一步完善,把 Operator 确立成为分布式应用开发与管理的关键依赖。而伴随着 Operator 越来越多的介入到应用开发和部署流程之后, Kubernetes API 一定会继续向上演进,进一步影响开发者的认知和编程习惯。这,已经成为了云计算生态继续发展下去的必然趋势。而作为这个趋势坚定不移的贯彻者,无论是 Istio,还是 Knative,都在用同样的经历告诉我们这样的道理:只有构建在 Kubernetes 这个云时代基础设施事实标准上的开发者工具,才有可能成为下一个开发者领域的 “Operator” 。本文作者:amber涂南阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

January 11, 2019 · 4 min · jiezi

阿里云容器服务DaemonSet实践

DaemonSet 保证在每个 Node 上都运行一个容器副本,常用来部署一些集群的日志、监控或者其他系统管理应用。下面以日志收集 fluentd 为例,看下如何使用阿里云容器服务控制台创建DaemonSet。准备Kubernetes环境在阿里云容器服务控制台中创建Kubernetes 集群(1.11.5),3 master,3 worker安装fluentd1、选择应用->守护进程集->使用镜像创建填写应用名称,选择部署集群、命名空间,进入下一步2、选择镜像并进行相应配置注意:这里挂载了配置项fluentd-conf,用来覆盖镜像中的默认配置,需要提前创建出来,内容如下:apiVersion: v1kind: ConfigMapmetadata: name: fluentd-conf namespace: kube-systemdata: td-agent.conf: | <match fluent.> type null </match> <source> type tail path /var/log/containers/.log pos_file /var/log/es-containers.log.pos time_format %Y-%m-%dT%H:%M:%S.%NZ tag kubernetes. format json read_from_head true </source> <filter kubernetes.> type kubernetes_metadata verify_ssl false </filter>否则会遇到pod 启动问题[error]: config error file="/etc/td-agent/td-agent.conf" error=“Invalid Kubernetes API v1 endpoint https://172.21.0.1:443/api: SSL_connect returned=1 errno=0 state=error: certificate verify failed"3、设置更新策略可以在高级配置中选择升级方式:滚动升级(RollingUpdate):更新 DaemonSet 模版后,自动删除旧的 Pod 并创建新的 Pod替换升级(OnDelete):更新模板后,只有手动删除了旧的 Pod 后才会创建新的 Pod4、指定节点调度只选择worker节点安装。设置节点亲和性如图。5、创建完成点击创建,可以看到创建成功。6、问题排查与更新按着上述步骤可以看到在3个worker节点分别起了对应的pod,但pod并没有成功启动。选择其中的一个容器,查看一下日志发现如下错误:config error file="/etc/td-agent/td-agent.conf” error=“Exception encountered fetching metadata from Kubernetes API endpoint: pods is forbidden: User cannot list pods at the cluster scope"Google后发现需要设置ClusterRoleapiVersion: v1kind: ServiceAccountmetadata: name: fluent-account namespace: kube-system—apiVersion: rbac.authorization.k8s.io/v1beta1kind: ClusterRoleBindingmetadata: name: fluent-accountroleRef: kind: ClusterRole name: view apiGroup: rbac.authorization.k8s.iosubjects: - kind: ServiceAccount name: fluent-account namespace: kube-system创建成功后更新fluent-es 的yaml,编辑yaml,提交更新。Pod启动成功,日志已经可以正常采集了。总结使用阿里云容器服务控制台支持方便的创建DaemonSet,欢迎使用体验。https://cs.console.aliyun.com/本文作者:来随便逛逛阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

January 4, 2019 · 1 min · jiezi

Apache Flink,流计算?不仅仅是流计算!

阿里妹导读:2018年12月下旬,由阿里巴巴集团主办的Flink Forward China在北京国家会议中心举行。Flink Forward是由Apache软件基金会授权的全球范围内的Flink技术大会,2015年开始在德国柏林举办,今年第一次进入中国。今天,计算平台事业部的资深技术专家莫问,将带领我们重温这场大数据技术的饕餮盛宴,感受Apache Flink 作为下一代大数据计算引擎的繁荣生态。Flink Forward China 大会邀请到了来自阿里巴巴、腾讯、华为、滴滴、美团点评、字节跳动、爱奇艺、去哪儿、Uber、DellEMC、DA(Flink 创始公司)等国内外知名企业以及Apache软件基金会的嘉宾为大家分享了Apache Flink的成长历程、应用场景和发展趋势。Flink Forward China 2018 嘉宾PPT及演讲视频:https://github.com/flink-china/flink-forward-china-2018参与有道,如何更“好”地贡献 Apache 项目上午大会由Apache软件基金会的秘书长Craig Russell开场,Craig首先分享了Apache开源之道,以及开源社区的精神和体制,然后以Apache Flink项目的成长经历为背景,向大家介绍了如何创建以及管理一个Apache开源项目,如何为Apache开源项目做贡献,并跟随开源项目一起成长和收获。通过Craig的分享,我们也更详细地了解到了Apache Flink的发展经历。Flink早期起源于德国柏林工业大学的一个研究项目Stratosphere,并于2014年4月捐献给Apache软件基金会,同时重新定位品牌为Flink,经过8个月孵化期,在2014年12月成功从Apache软件基金会毕业,成为Apache顶级项目,从此开始在大数据领域航行。经过最近4年的持续快速发展,Apache Flink社区已经培养出了42名Committer和19名PMC Member,不断加入的新鲜血液为Apache Flink社区持续贡献代码,并推动社区健康快速的发展。云上计算普惠科技在Craig分享后,阿里巴巴集团副总裁、搜索事业部与计算平台事业部负责人周靖人进行了主题演讲。靖人首先向大家介绍了阿里巴巴大数据云上计算的现状和趋势,让大家看到了阿里巴巴大数据业务场景的超大规模,以及未来更大的挑战。为了更好地支持阿里巴巴未来大数据的发展,阿里大数据发展策略一方面要进一步提升计算力和智能化,增强企业级服务能力。同时也要加强技术的生态化建设,大力支持并推动开源技术社区的发展,兼容行业生态标准,发展生态伙伴联盟,推动生态建设。目前阿里巴巴已经参与贡献230+开源项目,具备8000+合作伙伴和2000+ ISV,云上生态也已经突破1000,000开发人员。在大数据领域,阿里巴巴最近几年对Apache Flink社区进行了持续大力的投入,贡献超过15w行代码,主导建立了Flink China中文社区,加速Flink在国内的生态建设,并于今年开始在北京、杭州、上海、深圳等地多次组织Flink Meetup,促进国内Flink技术人员更方便的分享交流。靖人在分享的最后宣布了阿里巴巴内部Flink版本(Blink)将于2019年1月正式开源,本次开源内部版本的目标主要是希望让广大Flink用户能提前享受到阿里巴巴对Flink的改进和贡献。阿里巴巴同时会尽快将Blink中对Flink的各项改进和优化贡献给Flink社区,坚持对Apache Flink一个社区的拥抱和支持。Apache Flink,如何重新定义计算?在靖人宣布阿里巴巴开源内部Flink版本(Blink)后,阿里巴巴集团研究员蒋晓伟分享了Apache Flink在阿里巴巴内部的成长路线以及技术演进之路。阿里巴巴从2015年开始调研Flink,并于2016年第一次在搜索场景中上线Flink,在经过搜索大数据场景的检验后,2017年Flink开始在阿里巴巴集团范围内支持各项实时计算业务, 到目前为止阿里巴巴基于Flink打造的实时计算平台,已经支持了包括淘宝、天猫、支付宝、高德、飞猪、优酷、菜鸟、饿了么等所有阿里巴巴集团下的所有子公司的数据业务,并通过阿里云向中小企业提供一站式实时计算服务。在2018年的双11中,阿里实时计算平台已经实现了峰值每秒17亿次,当天万亿级的消息处理能力。Apache Flink目前在阿里巴巴内部最典型的业务场景是实时BI,阿里巴巴内部有着海量的在线交易以及用户数据,实时看到各个维度的数据统计可以及时地感知并指导阿里巴巴的运营。下图是一个典型的阿里实时BI流程,阿里的在线服务系统和数据库会实时产生大量日志数据并进入消息队列,FlinkJob会从消息队列中实时读取处理这些数据,然后将各种统计分析结果实时更新到KV/Table存储系统中,例如:HBase,终端用户可以通过Dashboard实时看到各种维度的数据统计分析结果。在双11当天,各种维度的实时数据报表是指导双11决策的依据,其中最为关键的就是全球直播的实时GMV成交额。Flink已经连续两年支持阿里巴巴双11实时GMV大屏,一个看似简单的数字,其背后实际上需要大量Flink计算任务平稳、精准地运行支撑。Flink在阿里巴巴另一个典型的应用场景是在线机器学习,传统的离线机器学习方法需要T+1的分析用户历史行为,训练出模型,当第二天模型上线后就已经是过去式,用户当前的需求和预期可能已经完全改变。为了给用户更好的购物消费体验,阿里巴巴的机器学习系统早已经进化到在线学习时代,例如:当一个用户在搜索完一个Query,浏览结果页时,或者点击查看部分商品时,阿里巴巴的在线学习系统已经可以利用这个间隙了解到这个用户当时的意图和偏好,并在下次用户Query时给出更好的排序,并向用户推荐更合适的商品,这种方式不仅可以进一步提升业务效率,同时也能为用户带来更好的产品体验,尤其是在双11这种大促场景,用户的行为时效性都是很短的,只有通过实时在线学习方式,才能做出更加精确的个性化预测和推荐。在线学习系统的优势在于可以实时收集并处理用户的行为数据,从而进行实时流式的特征计算和在线训练,并将模型的增量更新实时同步回在线系统,形成数据闭环,通过不断迭代自动优化系统效率和用户体验。在阿里的业务规模下,整个在线学习流程将会面对海量的用户数据规模、和极其复杂的计算挑战,但在Flink的驱动下,整个流程可以在秒级完成。通过以上两种经典场景可以看出阿里巴巴实时业务场景在各方面的挑战都很大,直接将Flink社区版本在阿里上线使用是不现实的,因此阿里巴巴实时计算团队这两年也对Flink进行了全面的优化、改进和功能扩展,其中有些功能和改进已经推回到了Flink社区。在Flink Runtime领域,阿里巴巴贡献了:全新的分布式系统架构:一方面对Flink的Job调度和资源管理进行了解耦,使得Flink可以原生运行在YARN,K8S之上;另一方面将Flink的Job调度从集中式转为了分布式,使得Flink集群规模可以更大的扩展。完善的容错机制:Flink默认在任何task和master失败后,都会整个Job 重启,阿里巴巴提出的region-based failover策略以及job manager failover/ha机制,让Flink可以运行地更加可靠稳定;大量的性能优化:Flink早期只提供全量Checkpoint机制,这在阿里巴巴大规模State场景下无法正常运行,阿里巴巴提出了增量Checkpoint机制,让Flink即使在TB级State场景下也可以高效运行;Flink Job经常在内部算子或者UDF中访问外部存储系统,例如:mysql,hbase,redis等,一旦出现个别query被卡住,整个task就被卡住,并通过反压影响到整个job,阿里巴巴提出了async IO机制,大幅降低了同步IO访问带来的影响。 此外,阿里巴巴贡献了credit-based的全新网络流控机制,使得Flink网络数据传输性能得到了显著提升。在Flink SQL领域,阿里巴巴贡献了全新的Streaming SQL语义和功能。例如:Agg Retraction,UDX支持,DDL支持和大量的Connector适配。在阿里巴巴,我们发现很多经典的业务场景都是同时具备实时流处理和离线批处理两种需求,而且流处理和批处理中的业务逻辑几乎是一样的,但用户需要开发两套代码,两套集群资源部署,导致额外的成本。例如阿里巴巴的商品搜索索引构建流程,白天需要将商品的更新信息流式同步到搜索引擎中,让用户可以在搜索引擎中看到实时的商品信息,晚上需要将全量的阿里巴巴商品进行批处理构建全量索引,这就是传统的Lambda架构。阿里巴巴的解法是希望提供一套批流融合计算引擎,让用户只需开发一套业务代码,就可以在实时和离线两种场景下复用,这也是在2015年阿里巴巴选择Flink作为未来大数据引擎的初衷。 Flink基于流处理机制实现批流融合相对Spark基于批处理机制实现批流融合的思想更自然,更合理,也更有优势,因此阿里巴巴在基于Flink支持大量核心实时计算场景的同时,也在不断改进Flink的架构,使其朝着真正批流融合的统一计算引擎方向前进。在Flink Runtime领域,阿里巴巴提出了全新的Operator Framework/API设计,使其能够同时适应批流两种算子特性;同时在Job调度和网络Shuffle两种核心机制上,都实现了灵活的插件化机制,使其能够适应批流不同场景的需求。在Flink SQL领域,阿里巴巴提出了全新的Query Execution和Optimizer架构,利用高效的二级制数据结构,更加合理的内存利用方式,更细粒度的Codegen机制以及更加丰富的优化器策略,使得Streaming 和Batch SQL都有了非常大的性能提升。经过大量架构改进和性能优化后,阿里巴巴内部Flink版本(Blink)在批处理上也实现了重大成果突破,在1T,10T和30T的TPC-DS的Benchmark中,Blink的性能数据均明显超出Spark,并且性能优势在数据量不断增加的趋势下越来越明显,这也从结果上验证了Flink基于流做批的架构优势。目前,阿里巴巴的内部Flink版本(Blink)已经开始支持内部批流融合的应用场景,例如阿里巴巴的搜索推荐算法平台,流式和批量的特征以及训练流程都已经统一基于Flink在运行。蒋晓伟在分享的最后给出了对Flink未来的一些展望,他认为Flink除了批流融合,还有很多新的方向值得去扩展,例如:Flink可以进一步加强在机器学习和图计算生态上的投入,从而在AI浪潮中实现新的突破。此外,Flink天然具备基于事件驱动的处理思想,天然的反压和流控机制,以及自带状态管理和弹性扩缩容的能力,这些优势都在促使基于Flink构建微服务框架成为一种新的思想和解决方案。总结蒋晓伟老师的分享,Apache Flink过去虽然在流计算领域已经获得很大的成功,但Flink并没有停滞,而是正在不断在突破自己的边界,Flink不仅仅是Streaming Engine,也不仅仅是Bigdata Engine,未来更希望努力成为Application Engine。流处理即未来接下来来自DA(Flink创始公司)的CTO - Stephan Ewen也对Flink的发展趋势给出类似的观点。Stephan认为“Streaming Takes on Everything”即流处理是一切计算的基础, Flink一方面需要朝着离线方向发展,实现批流融合大数据计算能力,另一方面也需要朝着更加实时在线方向发展,支持Event-Driven Application。前面已经重点阐述了Flink在批流融合计算方面的进展,接下来我们重点介绍下Flink在Event-Driven Application方向的思路。传统的应用服务架构一般是Online App +Database的架构,Online App负责接收用户Request,然后进行内部计算,最后将Result返回给用户,Application的内部状态数据存储在Database中;在Flink的event-drivenApplication架构中,可以认为Flink Source接收Request, Sink返回Result,JobGraph进行内部计算,状态数据都存储在State中。传统应用服务架构需要自己负责分布式和弹性管理,并由Database负责数据一致性管理;而Flink在这两方面是存在天然优势的,因为Flink天然是分布式系统,可以自己管理弹性伸缩,此外Flink内置了状态管理和exactly once一致性语义,因此基于Flink可以更方便、高效实现Transactional Application。城市级实时计算的力量在Apache Flink社区大神Stephan Ewen的分享后,来自阿里云的AI首席科学家闵万里向大家分享了实时计算在阿里云智慧城市中发挥的力量,通过分享多个真实应用案例,让大家对实时技术有了更多的体感和认识。在城市大脑的业务场景中,不仅要能实时处理来自各种传感器收集到的信息,对现实世界发生的事情进行响应,同时也要对未来将要发生的事情进行预测,例如:接下来那里可能要发生交通拥堵,从而提前做出干预,这才是更大的价值。整个城市大脑的架构都运行在阿里云基础设施之上,Apache Flink承担了核心实时计算引擎的角色,负责处理各种结构化和非结构化数据。在2018年9月的云栖大会上,阿里云发布了杭州城市大脑2.0,覆盖杭州420平方公里,可以监控到超过150万辆在途行驶机动车的实况信息,这个看似简单的事情在过去是很难做到的,现在我们通过1300多个路口的摄像头、传感器以及高德App的实时信息,通过Flink进行三流合一的处理,就可以实时感知到整个城市交通的脉搏信息,并通过进一步分析可以得出延误、安全等交通指数,预测感知城市的态势发展。在杭州,城市大脑通过实时分析4000多个交通摄像头采集的视频流,可以实时监控路上车辆的异常事件,例如:车辆超速、逆行和擦碰等,并将这些异常事件实时同步到交警指挥中心进行实时报警,目前杭州的交通事件报警已经有95%来自城市大脑自动通报的,这背后都是通过Flink进行各种复杂的计算逻辑实时算出来的。实时计算让交警处理交通故障的方式从过去的被动等待变成了主动处理,从而大幅提升城市交通的效率,为老百姓带来实实在在的好处。这50%,关乎生死2018年,城市大脑第一次走出国门,来到马来西亚吉隆坡,基于实时大数据对交通进行智能调度,它可以根据救护车的行驶信息,以及沿途路况信息,智能调整红绿灯,为救护车开辟绿色快速通道,这项技术为救护车节省了近50%的时间到达医院,这50%的时间可能意味着人的生和死,在这里技术显得不再骨感,实时计算的力量也许可以挽救生命。在工业生产IOT场景中,大量设备的传感器都收集了海量的指标数据,这些信息过去都被暂存2个月后丢弃了,唯一的用途就是在出现生产故障时拿来分析用,在有了大数据实时计算能力后,这些指标都可以被实时监控起来,作为及时调控生产流程的依据。协鑫光伏是全球最大的光伏切片企业,阿里云利用实时设备监控,帮助其提高了1%的良品率,每年可以增加上亿元的收入。滴滴实时计算平台架构与实践Keynote最后一位嘉宾是来自滴滴出行的研究员罗李,大家都知道滴滴出行是一个实时出行平台和交易引擎,它的数据和场景天然是实时的,各种网约车服务产生的数据都需要实时处理和分析。滴滴的实时业务场景主要包括实时风控、实时发券、实时异常检测,实时交易、服务和工单监控,以及实时乘客、司机和订单特征处理等。滴滴实时计算平台发展已经经历了三个阶段,第一阶段是各个业务方自建小集群,造成集群和资源碎片化问题;第二阶段由公司统一建立了大集群,提供统一的平台化服务,降低了集群资源和维护成本;第三阶段是通过Flink SQL方式提供平台化服务,通过SQL语言优势进一步降低业务开发成本,提升开发效率。滴滴现阶段基于Apache Flink引擎建设的实时计算平台以开源的Hadoop技术体系作为平台底座,并通过DataStream, SQL和CEP三种API向滴滴内部业务提供实时计算服务,同时在平台层也已经具备相对完善的WebIDE、数据血缘管理、监控报警和多组合隔离等机制。在滴滴实时业务的快速发展推动下,其实时计算集群已经达到千台规模,每天运行2000+流计算任务,可以处理PB级的数据。滴滴在搭建Flink实时计算平台的过程中,在内部也对Flink做了一些改进,例如在 Stream SQL领域扩展了DDL,丰富了 UDF,支持了TTL的双流Join和维表Join等;在CEP领域,增加了更多算子支持和规则动态修改能力等,其中部分优化已经推回了社区。最后,罗李介绍了滴滴实时计算平台的未来规划,主要方向在于进一步推广Stream SQL提升业务开发效率,推动CEP在更多业务场景落地,同时完成公司内部原有Spark Streaming向Flink的迁移,并发力IOT领域。在下午的几个分会场中,来自阿里巴巴、腾讯、华为、滴滴、美团点评、字节跳动、爱奇艺、去哪儿、Uber、EMC、DA(Flink 创始公司)的多位嘉宾和讲师都围绕Flink技术生态和应用场景进行了分享和交流。从分享的内容上可以看出,BAT三家中阿里巴巴和腾讯都已经完全拥抱了Flink;美团、滴滴和字节跳动(TMD)三家新兴互联网企业在实时计算场景也都已经以Flink作为主流技术方向开始建设,滴滴在Keynote上分享已经令人印象深刻,美团的实时计算集群也已经突破4000台规模,字节跳动(头条和抖音的母公司)的Flink生产集群规模更是超过了1w台的惊人规模 。由此可见Apache Flink的技术理念已经在业界得到了大量认可,基于Flink的实时计算解决方案开始在国内占据主流趋势。下一步Flink需要一方面继续完善流计算能力,争取在IOT等更多场景落地,与此同时进一步加强在批流融合能力上的全面突破,并完善在机器学习和AI生态上的建设,以及在event-driven的application和微服务场景上进行更长远的探索。本文作者: 莫问阅读原文本文来自云栖社区合作伙伴“阿里技术”,如需转载请联系原作者。 ...

January 3, 2019 · 1 min · jiezi

使用Terraform创建托管版Kubernetes

目前,阿里云容器服务已经可以创建托管版Kubernetes集群了。相比于默认的Kubernetes集群,托管版本会主动替您运维一套高可用的Master组件,免去了默认版本集群中三个节点,从而节约所需的资金成本及维护时的人力成本。在容器服务控制台,我们为您提供了便捷使用的可视界面一步一步引导式地创建该类型集群。但当您需要反复创建托管版集群,大批量创建集群,或者您就是天生抗拒控制台手工操作的那一类人,可以了解并尝试使用一下Terraform了。Terraform是一款Infrastructure作为Code的工具,可以将云端资源代码化。关于Terraform的基本介绍本文不再赘述,有兴趣的同学可以参考“云生态下的基础架构资源管理利器Terraform”等云栖社区的优秀文章。目前我们一直在支持阿里云Terraform Provider,已经实现了阿里云上面绝大部分的云产品的对接。在2018年圣诞节来临之前,阿里云Terraform Provider已经发布v1.26.0版本,其中已经支持了创建托管版Kubernetes集群,下面我们来一起看下如何实现命令行快速部署一个这样的集群。创建托管版Kubernetes集群首先我们打开“阿里云Terraform Provider文档 - 托管版Kubernetes”的帮助文档,可以看到该资源资源提供的参数列表。参数分参入参数和出参属性。入参列表内包含了必填参数以及可选参数,例如name和name_prefix就是一对必填参写,但它们互斥,即不能同时填写。如果填了名,集群名就是名的值,如果填了name_prefix,集群名会以name_prefix开头自动生成一个。我们对照文档中的参数列表Argument Reference,先草拟出一个集群的描述,为了方便起见,我把填写每个参数的理由都注释在代码中。# 引入阿里云 Terraform Providerprovider “alicloud” { # 填入您的账号 Access Key access_key = “FOO” # 填入您的账号 Secret Key secret_key = “BAR” # 填入想创建的 Region region = “cn-hangzhou” # 可选参数,默认不填就使用最新版本 version = “v1.26.0”}# 必要的资源标识# alicloud_cs_managed_kubernetes 表明是托管版 Kubernetes 集群# k8s 代表该资源实例的名称resource “alicloud_cs_managed_kubernetes” “k8s” { # 集群名称,可以带中划线,一个账户内的集群名称不能相同 name = “test-managed-kubernetes” # 可以从 ECS 控制台上面查询到可用区信息,以及对应的 ECS 实例类型库存 # 以下代表 Worker 节点将部署在 cn-hangzhou-h 这个可用区,采用 ecs.c5.xlarge 这个机型。 availability_zone = “cn-hangzhou-h” worker_instance_types = [“ecs.c5.xlarge”] # 配置该集群 Worker 节点数为 2 个,该数字后续可以再扩容 worker_numbers = [2] # Worker 节点使用高效云盘 worker_disk_category = “cloud_efficiency” # 默认为 true,会在 VPC 内创建一个 Nat 网关用于 ECS 连上互联网 new_nat_gateway = true # 配置所有 ECS 的默认 Root 密码,此处也可以用密钥对 key_name 代替,但需要提前创建 password = “Test12345” # Kubernetes 集群内所有 Pod 使用的子网网段,不能与 service_cidr 和 ECS 所在网段冲突 # 默认创建的 VPC 是 192.168.0.0/16 这个网段内的,所以 pod_cidr 和 service_cidr 可以使用 172 网段 # 请参考 VPC下 Kubernetes 的网络地址段规划 pod_cidr = “172.20.0.0/16” service_cidr = “172.21.0.0/20” # 安装云监控插件 install_cloud_monitor = true}我们可以将以上的配置保存为一个main.tf描述文件,在该文件的当前目录下执行terraform init和terraform apply。xh4n3@xh4n3:/ops/terraform-example% terraform init –get-plugins=true -upgradeInitializing provider plugins…- Checking for available provider plugins on https://releases.hashicorp.com…- Downloading plugin for provider “alicloud” (1.26.0)…Terraform has been successfully initialized!You may now begin working with Terraform. Try running “terraform plan” to seeany changes that are required for your infrastructure. All Terraform commandsshould now work.xh4n3@xh4n3:/ops/terraform-example% terraform applyAn execution plan has been generated and is shown below.Resource actions are indicated with the following symbols: + createTerraform will perform the following actions: + alicloud_cs_managed_kubernetes.k8s id: <computed> availability_zone: “cn-hangzhou-h” install_cloud_monitor: “true” name: “test-managed-kubernetes” name_prefix: “Terraform-Creation” new_nat_gateway: “true” password: <sensitive> pod_cidr: “172.20.0.0/16” security_group_id: <computed> service_cidr: “172.21.0.0/20” vpc_id: <computed> vswitch_ids.#: <computed> worker_disk_category: “cloud_efficiency” worker_disk_size: “40” worker_instance_charge_type: “PostPaid” worker_instance_types.#: “1” worker_instance_types.0: “ecs.c5.xlarge” worker_nodes.#: <computed> worker_numbers.#: “1” worker_numbers.0: “2"Plan: 1 to add, 0 to change, 0 to destroy.Do you want to perform these actions? Terraform will perform the actions described above. Only ‘yes’ will be accepted to approve. Enter a value:从上述日志中可以看到,terraform init会把我们用到的提供者插件下载好,terraform apply会根据我们的main.tf描述文件计算出需要执行的操作,上述显示将会创建一个alicloud_cs_managed_kubernetes.k8s的资源,需要我们输入是来确认创建。确认创建后,创建大约会耗时五分钟,terraform会输出类似下面的日志。# 以上省略Do you want to perform these actions? Terraform will perform the actions described above. Only ‘yes’ will be accepted to approve. Enter a value: yesalicloud_cs_managed_kubernetes.k8s: Creating… availability_zone: "” => “cn-hangzhou-h” install_cloud_monitor: "" => “true” name: "" => “test-managed-kubernetes” name_prefix: "" => “Terraform-Creation” new_nat_gateway: "" => “true” password: “<sensitive>” => “<sensitive>” pod_cidr: "" => “172.20.0.0/16” security_group_id: "" => “<computed>” service_cidr: "" => “172.21.0.0/20” vpc_id: "" => “<computed>” vswitch_ids.#: "" => “<computed>” worker_disk_category: "" => “cloud_efficiency” worker_disk_size: "" => “40” worker_instance_charge_type: "" => “PostPaid” worker_instance_types.#: "" => “1” worker_instance_types.0: "" => “ecs.c5.xlarge” worker_nodes.#: "" => “<computed>” worker_numbers.#: "" => “1” worker_numbers.0: "" => “2"alicloud_cs_managed_kubernetes.k8s: Still creating… (10s elapsed)alicloud_cs_managed_kubernetes.k8s: Still creating… (20s elapsed)alicloud_cs_managed_kubernetes.k8s: Still creating… (30s elapsed)# 以上省略alicloud_cs_managed_kubernetes.k8s: Creation complete after 6m5s (ID: cc54df7d990a24ed18c1e0ebacd36418c)Apply complete! Resources: 1 added, 0 changed, 0 destroyed.当出现申请完成!资源:1添加字样的时候,集群已经成功创建,此时我们也可以登录控制台后在控集群列表中看到集群。修改托管版Kubernetes集群在Terraform Provider中,我们提供了一部分参数的修改能力,一般情况下,所有非Force New Resouce(强制新建资源)的参数都可以被修改。下面我们修改部分参数,注释内容为更新的项目。provider “alicloud” { access_key = “FOO” secret_key = “BAR” region = “cn-hangzhou” version = “v1.26.0”}resource “alicloud_cs_managed_kubernetes” “k8s” { # 更换集群的名称为 test-managed-kubernetes-updated name = “test-managed-kubernetes-updated” availability_zone = “cn-hangzhou-h” worker_instance_types = [“ecs.c5.xlarge”] # 修改 worker_numbers 为 3,可以扩容一个 worker 节点 worker_numbers = [3] worker_disk_category = “cloud_efficiency” new_nat_gateway = true password = “Test12345” pod_cidr = “172.20.0.0/16” service_cidr = “172.21.0.0/20” install_cloud_monitor = true # 导出集群的连接配置文件到 /tmp 目录 kube_config = “/tmp/config” # 导出集群的证书相关文件到 /tmp 目录,下同 client_cert = “/tmp/client-cert.pem” client_key = “/tmp/client-key.pem” cluster_ca_cert = “/tmp/cluster-ca-cert.pem”}同创建集群一样,修改集群时使用的命令也是terraform apply。执行后我们得到以下日志输出,输入是并回车,我们就可以把该集群的名称改为test-managed-kubernetes-updated,worker节点扩容至3节点,同时将导出证书和连接文件到本机的/ tmp目录。xh4n3@xh4n3:~/ops/terraform-example% terraform applyalicloud_cs_managed_kubernetes.k8s: Refreshing state… (ID: cc54df7d990a24ed18c1e0ebacd36418c)An execution plan has been generated and is shown below.Resource actions are indicated with the following symbols: ~ update in-placeTerraform will perform the following actions: ~ alicloud_cs_managed_kubernetes.k8s client_cert: "” => “/tmp/client-cert.pem” client_key: "" => “/tmp/client-key.pem” cluster_ca_cert: "" => “/tmp/cluster-ca-cert.pem” kube_config: "" => “/tmp/config” name: “test-managed-kubernetes” => “test-managed-kubernetes-updated” worker_numbers.0: “2” => “3"Plan: 0 to add, 1 to change, 0 to destroy.Do you want to perform these actions? Terraform will perform the actions described above. Only ‘yes’ will be accepted to approve. Enter a value: yesalicloud_cs_managed_kubernetes.k8s: Modifying… (ID: cc54df7d990a24ed18c1e0ebacd36418c) client_cert: "” => “/tmp/client-cert.pem” client_key: "" => “/tmp/client-key.pem” cluster_ca_cert: "" => “/tmp/cluster-ca-cert.pem” kube_config: "" => “/tmp/config” name: “test-managed-kubernetes” => “test-managed-kubernetes-updated” worker_numbers.0: “2” => “3"alicloud_cs_managed_kubernetes.k8s: Still modifying… (ID: cc54df7d990a24ed18c1e0ebacd36418c, 10s elapsed)alicloud_cs_managed_kubernetes.k8s: Still modifying… (ID: cc54df7d990a24ed18c1e0ebacd36418c, 20s elapsed)alicloud_cs_managed_kubernetes.k8s: Still modifying… (ID: cc54df7d990a24ed18c1e0ebacd36418c, 30s elapsed)# 以上省略alicloud_cs_managed_kubernetes.k8s: Modifications complete after 4m4s (ID: cc54df7d990a24ed18c1e0ebacd36418c)Apply complete! Resources: 0 added, 1 changed, 0 destroyed.Terraform适用于运行成功后,控制台中显示的集群信息已经表明现在集群已经变成了我们期望的状态。在本机上,我们也通过导出的连接文件,用kubectl连接到集群。附录控制台创建托管版Kubernetes集群帮助文档https://help.aliyun.com/document_detail/95108.html云生态下的基础架构资源管理利器Terraform https://yq.aliyun.com/articles/215592阿里云Terraform提供者代码库https://github.com/terraform-providers/terraform-provider-alicloud阿里云Terraform提供商文档https://www.terraform.io/docs/providers/alicloud/index.html阿里云Terraform Provider文档 -托管版Kubernetes https://www.terraform.io/docs/providers/alicloud/r/cs_managed_kubernetes.htmlVPC下Kubernetes的网络地址段规划https://help.aliyun.com/document_detail/86500.htmlTerraform部署容器服务Kubernetes集群及WordPress的应用https://yq.aliyun.com/articles/641627本文作者:予栖.阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

December 26, 2018 · 4 min · jiezi

在Kubernetes上运行区块链服务(BaaS)

笔者注:本文是在2018年11月15日由Linux基金会CNCF主办的KubeCon & CloudNativeCon China 2018大会的“Running Blockchain as a Service (BaaS) on Kubernetes”演讲内容基础上整理而成,从技术上介绍了阿里云如何将基于区块链Hyperledger Fabric的BaaS和容器集群技术Kubernetes进行结合的设计理念和实践经验分享。大家好!我是来自于阿里云区块链团队的余珊,今天给大家分享的是《在Kubernetes上运行区块链服务(BaaS)》这个主题。以上是今天分享的内容大纲,其中重点在第三部分,我们将对BaaS结合Kubernetes的一些典型问题进行深入探讨。首先我们分享一下在我们眼中的区块链和BaaS的定义是什么。从狭义上来说,区块链是一种分布式共享账本技术,基于智能合约,在各参与方之间达成对交易的共识,并实现账本交易历史的不可篡改。这个定义是大家所熟知的,并且是从技术和功能上进行的概括。而从广义上来说,我们认为,区块链也是一种在机构、个人、机器之间,构建分布式信任网络、连接可信数据、实现价值流动的新的架构和协作模式。这也是跳出技术和功能维度,从更高维度去进行的理解和总结。对于另一个概念"BaaS",即"Blockchain as a Service", 我们认为,是云平台之上的区块链平台服务,提供了区块链系统的部署、运维、治理能力,以及提供了区块链应用运行和管理的能力。区块链从其类型上可分为私有链、公有链、联盟链三种类型,而从系统拓扑上我们可以将其对应为下述三种模式。对于传统的中心化系统或私有链来说,它基本属于一种星型中心化系统。对于公有链来说,是一种将所有参与企业和个人都对等连接在一起的完全去中心化系统。而对于联盟链来说,是一种带分层结构的多中心化系统。而阿里云今天主要关注的是面向企业场景的联盟链技术类型。下面我们来探讨一下为什么将区块链与容器技术以及Kubernetes进行结合。首先,我们来分析一下区块链的特点。我们将其分为区块链系统和区块链业务应用两类。区块链系统是以数据为核心、高度分布式、Full-Mesh网络拓扑、Long-Running、复杂系统类型。数据为核心:其中最重要的是账本上的数据。高度分布式:因为区块链节点可能部署于不同机房、不同region、不同国家等等。Full-Mesh: 区块链节点之间要依赖全连通的网络以实现共识、账本同步等过程。Long-Running:区块链服务和节点是长时间运行,而不是像Web应用或批处理任务那样短生命周期的。复杂系统类型:区块链系统不是一两个模块构成的简单应用,而是往往一整天解决方案或系统的形式。区块链业务应用:没有统一的标准,可能包含各种应用类型,包括无状态应用、有状态应用、Web应用、数据型应用等等类型。接下来,我们分析一下区块链结合容器技术会带来哪些优势:容器技术为区块链系统和业务应用提供了标准化的软件打包、分发的能力。容器技术实现了区块链运行环境的一致性,以及与底层基础架构的解耦,使得区块链系统和业务应用可以很方便地移植和运行在各种平台之上。进一步的,我们发现,区块链使用Kubernetes集群技术可获得以下几方面的优势:Kubernetes提供了灵活的区块链所需要的底层资源的调度能力,如计算、存储、网络等。Kubernetes强大的运维管理能力,使得我们的区块链服务的产品上线速度以及运维的效率大大提升。Kubernetes支持各种应用类型以及微服务架构,因此对于上面区块链系统和区块链业务应用各自的需求都能很好地满足。使用Kubernetes,可以更好地跟云平台进行集成,因为今天在业界它已经成为了各大云厂商云原生应用的标准底座了。Kubernetes还提供了丰富的安全和隔离功能,这对我们区块链的安全防护体系是很大的增强。另外,围绕Kubernetes有着非常活跃的社区和丰富的技术和业务生态,因此为结合区块链的研发提供了强大的技术支持和资源。这里解答图中的一个疑问,微服务架构是否适合区块链,这要结合上面的区块链特点分析来看待:对区块链系统来说,内部组件之间是强耦合、强依赖的关系,比较难解耦,内部各组件本身不是通用化的服务定位,也不是REST化服务接口,更多是例如gRPC调用,因此不是太适合微服务架构。但是对区块链业务应用来说,则很适合考虑与微服务架构进行结合。上面这幅图展示了阿里云区块链产品形态的演进历史,同时也可以看出我们在区块链结合容器以及Kubernetes方面所在的工作。在2017年10月,我们开始提供基于容器服务的区块链解决方案,支持Hyperledger Fabric,为企业提供一键式的区块链自动部署能力,当时是基于Docker Swarm集群技术。紧接着在2017年12月,我们推出了支持Kubernetes的容器服务区块链解决方案,并且在业界也是较早开始使用Helm Chart部署区块链的。在今年7月底,我们正式推出了阿里云区块链服务BaaS,支持Hyperledger Fabric,同样也是基于Kubernetes。而在今年9月杭州云栖大会上,阿里云BaaS也正式支持了蚂蚁区块链,在这背后蚂蚁区块链也通过适配改造工作实现了在Kubernetes上的部署运行。这一页展示的是阿里云BaaS的产品架构大图。其中最核心的是BaaS,目前已经支持Hyperledger Fabric和蚂蚁区块链。它们的运行实例底座都是基于阿里云容器服务Kubernetes集群。今天的演讲内容主要是围绕Hyperledger Fabric跟Kubernetes结合这方面展开讨论的。上面这一页展示了阿里云容器服务Kubernetes版的产品架构图。这里我们展示了一套跨region的Hyperledger Fabric联盟链的部署架构图。在联盟管理方的Kubernetes集群上部署了Orderer organization和Peer Organization, 而在其他业务参与方所在region的Kubernetes上部署了各自的Peer Organization. 这里的CA、Peer、Orderer、Kafka、ZooKeeper的每个实例都是用了Kubernetes的Service和Deployment类型对象来定义。此外区块链的业务应用可以部署在Kubernetes上或者其他环境上,通过SLB映射到集群worker节点的NodePort上,来访问区块链的各个service。接下来我们进入重点的第三部分,对于实现BaaS运行在Kubernetes的过程,我们曾经遇到的一些有代表性的问题,以及我们的解决思路和实践经验。首先是关于区块链BaaS的打包、发布、服务编排等方面的问题。对于以Hyperledger Fabric为代表的区块链系统来说,这方面面临的主要问题是:区块链系统本身较为复杂,在一套典型部署里可能涉及到三十多个容器、近二十个服务、十来个容器镜像;而且这些服务相互之间有较强的依赖。对于这个问题,我们的解决思路是:在打包部署方面,从一开始我们便选用了容器镜像以及Kuberentes的Helm Chart作为标准的格式和工具。这里尤其提一下,为了保证联盟链各组织创建的独立性和灵活性,我们采用的是一类组织(例如Orderer Org或Peer Org)使用一套chart的方式。在存储库管理方面,目前使用的是阿里云OSS作为Chart Repo(当然可以使用功能更丰富的如ChartMuseum等工具),使用阿里云容器镜像服务作为镜像仓库。这里我们还采用了region化的镜像仓库配置,加快大体积镜像的下载速度,同时采用imagePullSecret保护镜像的安全。在配置方式方面,我们采用了Kubernetes的ConfigMap和Secrets来存储主要的配置和安全信息,以及使用Chart Values来让管控可以根据客户的输入去定制BaaS联盟链实例。在服务编排方面,为了满足服务的依赖性需求,我们结合了Chart Template,Chart的Hook(钩子)机制,以及Kubernetes的Init Container加上Shell脚本方式,实现各种服务尤其在启动过程中的依赖和顺序保证。对于企业来说,业务系统的高可用性是非常重要的,尤其是对生产环境的系统运行和应用访问。这里我们分享一下在BaaS的每一个层面上的高可用设计思路,以及Kubernetes在其中起到怎样的帮助。首先在云基础架构和云资源服务层,我们通过云数据中心的多可用区、所依赖的云服务本身的高可用性和高可靠性来提供保障。在BaaS管控层,通过管控组件的多实例化部署避免单点故障。在容器服务的Kubernetes集群,采用3个master节点和多个worker节点的方式提供应用底座的高可用。在Hyperledger Fabric这一层,它的Orderer、Peer、Kafka、ZooKeeper、CA等类型节点均有集群或高可用互备的设计,比如任一节点挂掉的话,其他节点依然能正常提供服务。但这里有一个关键的点,就是在Kubernetes集群上部署的时候,为了避免这些本应高可用互备的Fabric节点的pod被调度到同一个worker node上,我们采用了Kubernetes Pod Anti-Affinity的功能区将高可用集群的pod调度到不同的worker上,这样保证了真正高可用的部署,提高了对故障的容忍度。在区块链业务应用层,则需要各个企业客户对应用进行周全的高可用设计和实现。在运行时,应用访问Fabric各个服务的这一环节,我们BaaS内置了云平台的SLB负载均衡能力(包含对服务端口的健康检查),以及Fabric的Service Discovery,来保证即使后端部分节点或服务不可用时,应用的调用链路都会被调度到可用的节点或服务上。下面我们谈谈BaaS数据持久化存储的问题。虽然上面已经介绍了BaaS的高可用性设计,但我们仍需考虑如何将链上账本数据、区块链关键配置等重要内容持久化保存到可靠的外部存储而不是容器内部,这样便可以在服务器节点全部发生故障,或者系统重启、备份恢复等场合依然可以实现对系统和数据的恢复。首先,作为背景,我们分析了如果使用本地盘方式可能存在的问题:Kubernetes本身对pod的调度默认并没有限定worker节点,因此如果使用本地盘,就会因为在重启或恢复过程中调度导致的pod漂移而无法读取原来worker节点上的本地盘。对于第一个问题,Kubernetes提供了NodeSelector的机制可以让pod可以绑定worker节点进行部署,不会调度到其他worker节点上,这样就可以保证能始终访问到一个本地盘。但这又带来另一个问题,即在容灾的场景,如果这个节点包括其本地盘受到损坏无法恢复时,会导致整个pod也无法恢复。因此,我们在设计BaaS中的选择是阿里云的NAS文件系统存储、以及阿里云的云盘。在数据可靠性方面,NAS和云盘可以分别提供99.999999999%和99.9999999%的数据可靠性。此外,我们都选用了SSD类型以保证I/O性能。在Kubernetes部署的时候,Fabric的节点通过Persistent Volume和Persistent Volume Claim挂载上相应的存储,并且这些存储是为每一个Fabric的业务organization独立分配的,保证了业务数据的隔离性。在和参加KubeCon大会的一些区块链用户交流的时候,有朋友提到随着账本数据的持续增长,可以怎样解决存储问题。在我们的实践中,我们发现阿里云的NAS有一些很适合区块链账本存储的一些特点:首先,阿里云NAS可提供存储容量动态无缝扩容,在这过程中Fabric节点或区块链业务应用均无需重启或停机,对存储扩容过程完全无感知。其次,有用户担心随着存储数据量的增大,存储的性能是否会明显下降。恰恰相反的是,在阿里云NAS随着所使用的数据量变得越大,NAS所提供的吞吐性能会变得更高,这样可以打消企业用户在长期生产运行方面的顾虑。在上图的右边是Fabric不同类型的区块链节点使用不同类型存储的一个示意图。接下来我们探讨一下在设计搭建BaaS联盟链跨企业的网络方面遇到的挑战。对于大多数区块链技术而言,包括Hyerpedger Fabric, 在网络上要求区块链节点之间形成Full Mesh全连通网络,以实现节点间的账本数据同步、区块广播、节点发现、交易背书等过程,同时企业也要求保障跨企业链路的安全性。对于这些需求,我们梳理了业界目前常见的几类解决方案如下,并进一步分析它们存在的一些不足之处。方案一是采用单一VPC的联盟链网络方案,在这种模式下,联盟链的所有区块链节点均被部署到一套Kubernetes集群网络或VPC内。这种方案实质上是一种私有链的模式,失去了联盟链的各方自治的价值。方案二是基于公网的联盟链网络方案,区块链节点分布式部署在不同区域,通过公网IP对外提供服务以及实现互相通信。这种方案可以较灵活、较低成本低满足大多数基本需求,但对于高级需求如企业级安全网络则不能很好地满足。方案三是基于专线互联的联盟链网络方案,它采用运营商专线方式将不同网络或数据中心进行两两互联,在业界一些企业中得到了采用。但这里面主要存在两方面的问题,首先是如果联盟链参与企业采用了不同电信运营商的专线方案的话,项目实施的复杂性和成本都会很高;其次,如果几家企业已经建好了这样一个联盟网络,对于新来的参与企业,它的接入复杂度和成本也是一个不小的问题。针对上述各种问题,我们在阿里云BaaS基础之上,结合了CEN云企业网,提供了一种安全的联盟链网络方案,主要面向高端需求的企业用户。方案的核心,是采用CEN云企业网打通不同企业的VPC网络,就像一张跨企业的环网,这样不同企业不同的VPC内的网络就可以在CEN内实现全连通。在实现网络连通之后,因为阿里云BaaS联盟链中的Peer,Orderer,CA等服务是通过域名来访问的,目的是提升应用访问的灵活性,而在CEN的这套方案中,我们可以结合云解析PrivateZone,来实现企业环网内各企业VPC之间的统一域名解析。而且上述的网络连通性和域名解析仅限于联盟内部,不会暴露到外网。除了在公共云环境之外,对于那些将区块链节点部署于本地IDC的企业来说,他们也可以通过VPN或者专线方式,接入到云上已和CEN打通的任一VPC中,便可实现和联盟任意节点的通信。作为一个小提醒,在方案实施环节,需要注意提前规划好不同VPC内的内网地址分配,避免在环网中发生冲突。这样我们便形成了一套真正跨企业、跨账户,打通各个VPC的安全联盟链网络方案。下面我们将探讨一个非常有挑战性的问题。众所周知,智能合约是区块链的一个核心。Hyperledger Fabric中的智能合约即chaincode是运行于容器当中。在上面这幅图里我们总结了Hyperledger Fabric的chaincode容器生成过程的示意图:Peer通过Docker Client发起对Docker Daemon的调用,以fabric-ccenv为基础镜像创建出一个chaincode构建容器(chaincode builder container)Peer将chaincode源代码传入chaincode构建容器,在里面完成智能合约编译Peer再调用Docker Daemon创建以fabric-baseos为基础镜像的chaincode镜像,并将在第2步编译好的chaincode二进制文件内置在chaincode镜像中。启动运行chaincode容器。从上述过程我们分析一下这里面存在的一些问题:由于该过程是独立于Kubernetes体系之外运行的,难以对chaincode容器进行生命周期管理。无法基于Kubernetes的namaspace隔离、NetworkPolicy等机制实现对chaincode容器的安全管理。针对上面分析发现的问题,我们研究了几种问题解决的思路。第一种思路,是将chaincode容器纳入到Kubernete的体系(如pod)进行管理。这在我们的角度看来,其实是最理想的方案。因为它不仅可以实现chaincode容器全生命周期与Fabric其他类型节点一致的管理方式,并且可以结合Kubernetes的NetowrkPolicy控制chaincode容器的网络访问策略。其实此前Hyperledger Fabric社区已经创建了一个相关的需求即JIRA(FAB-7406),但目前仍未实现。假设未来在此功能实现之后,我们进一步展望一下,还可以将智能合约的容器调度运行于Serverless Kubernetes之上,提供kernal级别的隔离,保证应用容器之间的安全隔离。第二种思路,如社区和网上的一些观点所提到的,将chaincode容器放入Docker-in-Docker(DIND)环境运行。这个思路背后的出发点,主要是为了降低对宿主机Docker Daemon的依赖以及动态生成chaincode镜像和容器的不可管理性。对于这个思路,我们也基于Hyperledger Fabric和Kubernetes进行了试验,在右边的这部分Kubernetes部署模板yaml代码里,绿色框的部分是用于配置DIND的容器作为peer pod的一个sidecar,同时将DIND容器内的Docker Daemon通过本地端口2375以环境变量的形式配置到peer的参数中,使得peer可以将chaincode创建相关请求发送到DIND内。通过对结果的观察和分析,我们发现了以下这几点。DIND的思路有如下一些优点:无需依赖宿主节点的/var/run/docker.sock。无需专门清理每个Kubernetes worker节点的chaincode镜像。但DIND有着一些更为明显的不足:每次创建部署或恢复peer节点会变得很慢,因为DIND内需要去拉取fabric-ccenv镜像,其大小约1.4GB;而如果用传统部署方式的话,只需在worker节点拉取一次镜像即可。Chaincode的实例化(instantiate)过程稍微变慢,推测这和DIND容器本身运行所需的开销有一定关系。当peer节点或者整个组织(organization)删掉重建之后(复用原有的数据目录),启动速度比起传统方式会慢很多,这背后的原因和第1点相同。在业界实践中,DIND方法主要用于CI/CD的场景,但对于生产环境使用的话,则在稳定性等方面仍有较多的挑战。DIND的思路仍然不能解决chaincode容器的安全访问控制和隔离的问题。第三种思路,是我们目前在BaaS中采用的方法,即综合各种配置的手段先解决最主要的问题。这包括以下几个方面的工作:首先,通过Fabric peer的合理配置(如图中右上角的示例配置)保证chaincode和peer的通信。其次,使用docker rm和docker rmi命令清理chaincode容器和镜像(它们均包含“dev-”前缀)。这里面有不同的可选位置。2.1 适合事后清理的可选位置是采用DaemonSet结合lifecycle.preStop.exec.command的位置来运行这些清理命令。2.2 适合事前清理的可选位置是在initContainer中运行上述清理命令。采用iptables规则,对chaincode容器进行网络隔离。主要是通过在Helm Chart安装阶段配置Kubernetes worker节点的iptables规则,实现限制chaincode容器对Kubernetes网络和对外部网络的访问(同时也可以限制进入chaincode容器的网络访问)。通过上述一系列手段,我们得到了对chaincode容器实现生命周期管理、安全隔离和网络访问限制的一个实用的方案。未来我们也会继续朝着思路一这种最理想方式进行更多的探索。今天阿里巴巴集团的区块链已经在多个行业、多种场景实现了结合以及业务落地,包含了如商品溯源、数字内容版权、供应链金融、数据资产共享、公益慈善、医疗处方等等。我们的客户在生产环境已经达到了百万级的交易规模以及百GB的账本数据,这也为我们提供了很丰富的区块链应用实践经验。基于这些实践,我们想跟大家分享的是,其实区块链应用设计开发并不复杂,这一页总结了构建于Kubernete之上的区块链系统和应用的基本模式。可以看到,Kubernetes帮我们解决了底层基础架构和资源的复杂性,提供了应用的标准底座;而区块链服务BaaS则帮我们解决了区块链系统配置部署和运维的复杂性,提供了统一的接口,那么对企业来说,便可以聚焦在业务流程和业务逻辑的实现,及业务应用的开发上,以及与业务数据的交互和管理上来,实现核心价值的最大化。下面,我们将进行阿里云BaaS Hyperledger Fabric的一个demo,主要展示一下几方面的过程:首先,快速创建跨企业(跨账号)、跨region的联盟链。接着,动态添加新组织、新通道,完成企业间协同,包括邀请企业,以及企业各自的审批流程。在一些关键操作点上,BaaS内置了风控保障,强制邀请短信验证才允许完成操作,这看似麻烦的环节实际上是企业对生产安全保障以及审计都非常看重和需要的。最后,我们在BaaS上部署了经典的Marbles虚拟数字资产交易的应用,包含chaincode的部署和client SDK应用的部署。最后,欢迎有兴趣的朋友进一步了解和使用阿里云的区块链服务BaaS,通过扫描图中的两个二维码可快速访问相关产品主页,申请开通免费公测试用,以及访问产品文档获得更多使用和开发指南。以上就是我今天跟大家分享的全部内容,谢谢大家!本文作者:余珊阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

December 19, 2018 · 1 min · jiezi

阿里云开发者工具上手体验

近期参加了阿里云官方的一个开发者工具有奖评测活动,感兴趣的朋友可以去官网了解下,以下是我对这款工具的使用体验,欢迎各位朋友进行交流和斧正。Alibaba Cloud Toolkit(以下简称工具集)是阿里中间件团队发布的一款面向阿里云服务的开发工具集,用来提升开发者使用阿里云产品时的用户体验。本文将对使用该工具集部署EDAS应用的各种能力进行一番评测。Alibaba Cloud Toolkit主要包含三种类型的工具,分别是IDE插件(目前仅支持Eclipse,IDEA插件据说正在开发中,很快会发布)、Maven插件和命令行工具。在对这三种类型的工具进行详细评测之前,我们先来了解一下使用Web界面部署普通EDAS应用的过程。第一步,需要先申请一些ECS并将这些ECS导入到已经创建的集群中。图1. 集群和集群中的ECS第二步,创建应用。在创建应用的时候选择使用该集群,并选择集群中的ECS作为部署目标。同时打开“立即部署”选项,再选择应用部署方式、应用运行环境和Java环境等,然后上传部署包,在确定了版本以及批次和分批方式后,就可以创建并部署应用了(图2)。图2. 创建并部署应用这个过程看似简单,却有如下一些问题。首先,界面是基于Web的,虽然简单易用,但是自动化能力不强,需要人为干预才能工作,效率不高;其次,用户需要自己打包和上传部署文件,导致开发和部署过程割裂。有了上面一些对EDAS传统部署过程的了解,我们再分别使用工具集中的不同工具来尝试重新部署应用,看看会有什么不同。IDE插件通常而言,开发人员都会使用IDE来提升软件的开发效率,因此Alibaba Cloud Toolkit提供基于主流IDE的扩展插件就是顺其自然的事情,拿Eclipse为例,在Eclipse市场中就能搜索到Alibaba Cloud Toolkit,该插不仅支持EDAS,也有很多其他的功能,但这里我们主要关注面向EDAS的集成能力。安装好插件以后,导入一个项目(可以是原生Dubbo,原生Spring Cloud或HSF项目),然后在Project Explore窗口右键点击该项目,会出现Alibaba Cloud上下文菜单,选择该菜单项后会出现Deploy to EDAS…子菜单项(图3)。图3. Alibaba Cloud菜单及子菜单如果是第一次使用该插件,会弹出一个设置窗口(图4)用来设置访问账户所需的Access Key ID和Access Key Secret,设置完成以后就会出现Deploy to EDAS窗口(图5)。图4. 设置访问账户的Access Key ID和Access Key Secret图5. 部署应用该窗口的主要功能一目了然,选择Region、Namespace、Application和Group后,点击Deploy即开始部署。该插件的优势正如前文所言,解决了开发到部署过程上下文切换的问题,可以在一个场景下完成这两种工作。而劣势(或者说功能的不足)是其能力还不能完全与传统的基于Web部署过程对齐:比如无法选择批次、分配方式,以及在第一次部署的时候无法选择容器和Java版本等等,希望未来的版本能够加以改进。Maven插件使用Java的开发人员多数会使用Apache Maven来管理依赖、编译、测试、打包和发布等过程,因此Alibaba Cloud Toolkit也提供了与Maven的集成能力,即edas-maven-plugin。有关配置和使用方法,在官网的《通过 edas-maven-plugin 插件自动化部署应用》文档中已经有详细说明,就不在此赘述。比起IDE插件来说,Maven插件能够更有效的解决自动化问题,尤其是跟持续集成与持续交付系统对接的时候更为有用。在一个配置完善的自动化系统中,开发人员将开发完成的代码提交到代码仓库,此时可以自动触发应用的构建、单元测试与打包,打包好的交付物会通过edas-maven-plugin部署到测试环境,运行一遍冒烟测试之后,再被部署到预发环境供测试人员测试。整个过程可以做到完全无人值守。该Maven插件也同样存在很多不尽如人意的地方,比如配置项中需要使用应用或分组的ID来指定部署目标,虽然在Web界面上提供有相关的配置可以复制粘贴,但是依然不如直接使用名称来得方便。另外在执行mvn edas:deploy命令的时候必须要在package阶段之后(即命令必须为mvn package edas:deploy),否则无法找到要部署的包。最后同IDE插件遇到的问题相同,如果只有一个空应用,而没有指定过该应用的容器和Java版本的话,那么使用Maven插件部署的时候可能会出现问题。希望这些不足能够在未来的版本中得到解决。命令行工具命令行工具在整个Alibaba Cloud Toolkit里面是功能最强大的,当然也是使用门槛最高的,我们来分别了解一下。说其功能强大,是因为命令行工具是对EDAS Open API的封装,因此只要是接口中提供的功能,都可以使用命令行工具来调用。这个功能并不算新颖,以前在没有提供命令行工具的时候,一些用户也会通过使用Python脚本调用Open API的方式来达到相同的目的,只是官方提供了这个能力之后,对于大部分的开发者而言减少了这部分的工作量。再者,该命令行工具是与aliyun这个命令集成到一起的,因此如果企业对自动化运维有很高要求的话,使用aliyun edas这个子命令可以避免绝大多数的手动操作,包括但不限于创建命名空间、创建集群、集群导入、创建应用以及部署应用、创建分组、应用生命周期管理等等。增强自动化且提高运维效率的同时,更多的可以避免因人为操作失误而导致的安全生产风险,间接提高了产品质量。有关命令行工具的具体配置和使用方法请参考文档《使用CLI快速部署EDAS应用》。说其使用门槛高,主要在于单一命令只能完成一个原子操作,且操作过程大多是异步的,这就要求实现复杂功能的时候需要编写脚本来完成执行结果的轮询与命令串联。虽然这些工作对于开发人员来说算不上什么问题,但是总之是有可改进空间的。以上便是Alibaba Cloud Toolkit提供的针对EDAS产品的全部功能的试用体验以及对其优点和现有不足的分析,鉴于笔者水平有限,提出的问题点并不一定完全准确。总而言之,该工具集的出现确实在很大程度上提升了开发人员的工作效率,也让各种CI/CD以及自动化运维等能力成为可能,确实是一个值得企业用户尤其是开发者用户去尝试的优秀工具集。

December 18, 2018 · 1 min · jiezi

阿里数据库的极致弹性之路

阿里妹导读:数据库从IOE(IBM小机、Oracle商业DB、EMC存储)一路走来,大家都知道数据库是资源重依赖的软件,对服务器的三大件CPU、内存、磁盘几乎都有要求。数据库作为广泛使用的数据存储系统,其SQL请求背后涉及的物理读、逻辑读、排序过滤等消耗了IO和CPU资源,业务SQL不同,执行计划不同,资源消耗就不同,因而不同业务对资源规格的需求也不一样。正因如此,我们更需要抽象规格,更好地让不同资源诉求的数据库实例混跑在相同的物理机上,提升整体利用率。今天,阿里资深技术专家天羽为我们讲述阿里数据库的极致弹性之路。除了日常业务需求,阿里的双11场景,让我们持续思考如何低成本高效率地支持峰值流量,把这些思考变成现实,变成技术竞争力。在大促资源弹性上有这么几个思路:使用公共云标准资源弹性,直接用阿里云的标准资源支撑大促后归还。这个是最直接的想法,但这里的难度是业务需求和云资源在性能、成本上的差距,不要定制化机器。混部能力,存量业务的分类混部、分时混部。使用离线资源支撑大促,既是分类混部,双11零点离线降级,高峰后在线归还资源也是分时复用。快上快下,在有能力使用云、离线资源后,尽量缩短占用周期。碎片化资源,数据库一直是块石头,是一个大块完整的规格。如果把数据库自己的大库变成小库,就可以使用其他业务的碎片化资源,包括公共云上的资源。大促的成本=持有资源X持有周期,更通用的资源(云)、更快的部署(容器化)是缩短持有周期的关键,如何更少地使用资源(使用离线或只扩计算资源),就依赖存储计算分离架构的实施。沿着极致弹性的目标,数据库经历了混合云弹性、容器化弹性、计算存储分离弹性三个阶段,基础架构从高性能ECS混合云、容器化混合云、存储计算分离的公共云和离线混部一步步升级。基本上架构演进就是每年验证一个单元,第二年全网铺开,每年挖个坑然后和团队一起努力爬出来,每次演进需要跨团队背靠背紧密合作,快速拿下目标,这也是阿里最神奇的力量。借助于底层软硬件技术发展,一步步的架构升级使得弹性混部越来越灵活和快速。 一、混合云弹性,高性能ECS应运而生2015年之前,我们的大促弹性叫人肉弹性,也就是大促要搬机器,比如集团用云的机型支撑大促,大促结束后搬机器归还给云。但就在2015年底的一次会议上,李津问能否把数据库跑到ECS上,如果可以,就真正帮助了云产品成熟,当时张瑞和我讨论了一下,在会议上就答复了:我们决定试一下。这个合作非常契合会议主题“挑战不可能——集团技术云计算战区12月月会召集令”。对于数据库跑在虚拟机上,我们判断最大的消耗在IO和网络的虚拟化上,因此如何做到接近本机性能,怎么穿透虚拟化就是一个问题。网络的用户态技术DPDK已经比较成熟,但如何做到足够高的效率,是否offload到硬件来做计算是个问题。文件系统IO的用户态链路有个Intel的SPDK方案,Intel推出后各大厂商还在验证中,还没有规模的应用。我们就在这个时候启动的这个项目,叫高性能ECS。通过和ECS团队紧密合作,最终我们做到了最差场景高性能ECS相比本地盘性能损耗低于10%。2016年在集团通过了日常验证,2017年大促开始大规模用云资源直接弹性。这个项目除了打造高性能ECS产品,更重要的是沉淀了网络和文件IO的纯用户态链路技术,这是一个技术拐点的产生,为阿里后续存储计算分离相关产品的高性能突破打下了基础。二、容器化弹性,提升资源效率随着单机服务器的能力提升,阿里数据库在2011年就开始使用单机多实例的方案,通过Cgroup和文件系统目录、端口的部署隔离,支持单机多实例,把单机资源利用起来。但依然存在如下问题:内存的OOM时有发生存在IO争抢问题多租户混部存在主机账号等安全问题数据库主备机型一致性随着单机部署密度越来越高,社区Docker也开始发展起来,尽管还不成熟,Docker本身依赖Cgroup做资源隔离,解决不了Cgroup的IO争抢或OOM问题,但它通过资源隔离和namespace隔离的结合,尝试对资源规格以及部署做新的定义,因此我们看到了容器化更多的优势:标准化规格,数据库与机型解耦,主备不需要对称。这对规模化运维带来极大的效率。Namespace隔离带来混部能力,资源池统一。不同数据库类型,不同数据库版本随便混。让DB具备与其他应用类型混部的条件。2015年数据库开始验证容器化技术,2016年在日常环境中大量使用。因此在集团统一调度的项目启动后,我们就定下了2016年电商一个交易单元全部容器化支撑大促的目标,承载交易大盘约30%,并顺利完成。2017年数据库就是全网容器化的目标,目前数据库全网容器化比例已经接近100%。容器化除了提升部署弹性效率,更重要的是透明底层资源差异,在没有启动智能调度(通过自动迁移提升利用率)前,仅仅从容器化带来的机器复用和多版本混部,就提升了10个点的利用率,资源池的统一和标准部署模板也加快了资源交付效率。容器化完成了底层各种资源的抽象,标准化了规格,而镜像部署带来了部署上的便利,基于数据库PaaS和统一调度层的通力合作,数据库的弹性变得更加快速灵活,哪里有资源,哪里就能跑起数据库。 三、计算资源极致弹性,存储计算分离架构升级实现了容器化混合云,是不是每年大促使用高性能ECS,容器化部署就可以了呢?其实还是有不足的:数据库弹性需要搬数据,把数据搬到ECS上是非常耗时的工作。 弹性规模太大,如果超过公有云售卖周期,会增加持有成本。因此如何做到更快、更通用的弹性能力,是一个新的技术问题。随着2016年调度的发展,大家考虑机器是不是应该无盘化,是不是应该存储计算分离,从而加快调度效率,而数据库的存储计算分离更是争议很大。数据库的Share Nothing分布式扩展已经深入人心,存储计算分离会不会回到IOE状态?如果IDC是一个数据中心,应用就是计算,DB就是存储,DB自己再做存储计算分离有意义吗?数据是主备双副本的,存储计算分离后变成三副本,存储集群的容量池化能balance掉额外副本的成本吗?为此我开始测算存储计算分离架构在大促场景下的投入产出,我们来看下大促场景,弹性大促时,业务需求计算能力数倍甚至10倍以上扩容,承担大促峰值压力,而磁盘因为存储长期数据,峰值的数据量在整体占比不高,因此磁盘容量基本不需要扩容。在以前本地磁盘跑主备的架构,无法计算、存储分开扩容,大促指标越高,添加标准机器越多,成本浪费越大,因为磁盘是标准数据库机器的主要成本。而存储计算分离的情况下,测算下来,我们看到在较低日常压力下存储计算分离成本是比本地盘高的,但再往上,存储计算分离只需要增加计算,存储集群因为池化后,不只容量池化了,性能也池化了,任何高负载实例的IO都是打散到整个集群分担的,磁盘吞吐和IOPS复用,不需扩性能,成本优势非常明显。磁盘不扩容,只扩计算自然成本低很多。传统的思考是存储集群容量池化的优势,但在大促场景我们更多用到的是性能的池化,突破单机瓶颈,因此我们提出了电商异地多活所有单元存储计算分离,其余业务继续使用本地磁盘进行同城容灾的目标架构。提出这个设想,而这个架构的可行性如何判断?基于一些数字就可以推断,大家知道SSD磁盘的读写响应时间在100-200微秒,而16k的网络传输在10微秒内,因此尽管存储计算分离增加两到三次的网络交互,加上存储软件本身的消耗,整体有机会做到读写延时在 500微秒的范围内。在数据库实例压测中我们发现,随着并发增加,存储集群具备更大的QPS水位上线,这印证了性能池化突破单机瓶颈带来的吞吐提升。数据库团队在2017年开始验证存储计算分离,基于25G的TCP网络实现存储计算分离部署,当年就承担了10%大促流量。我们基于分布式存储做到了700微秒的响应时间,这里内核态和软件栈的消耗较大,为此X-DB也针对性地做了慢IO优化,特别是日志刷盘的优化,开启原子写去掉了double write buffer提升吞吐能力。这个过程中,我们沉淀了存储的资源调度系统,目前已经作为统一调度的组件服务集团业务。我们对当前架构性能不太满意,有了X-DB的慢IO优化、存储计算分离跨网络的IO路径、存储资源调度等技术沉淀,加上阿里巴巴RDMA网络架构的发展,2017下半年数据库开始和盘古团队一起,做端到端全用户态的存储计算分离方案。四、全用户态IO链路的存储计算分离架构落地 从数据库软件X-DB的IO调用开始,就走我们自己研发的用户态文件系统DBFS,DBFS使用盘古的用户态客户端,直接通过RDMA网络访问后端盘古分布式文件系统,整个IO链路完全绕过了内核栈。这里DBFS绕过了内核文件系统,自然也绕过了pagecache,为此DBFS针对数据库场景,实现了更简洁高效的BufferIO机制。因为IO都是跨网络远程访问,因此RDMA起到了重要作用,以下是RDMA与TCP网络在不同包大小下的延时对比,除了延时优势外,RDMA对长尾IO的tail latency能够有效控制,对一个数据库请求涉及多次IO来说,对用户请求的响应时间能够更有效保证。RDMA技术的应用是DB大规模存储计算分离的前提条件,通过我们的数据实测,DBFS+RDMA链路的延时已经和Ext4+本地盘达到相同水平。今年我们首次大规模部署RDMA,如履薄冰。经过多次压测、演练, RDMA配套监控和运维体系建设已经完善起来,我们能够在1分钟内识别服务器网卡或交换机的网络端口故障触发告警,能够故障快速隔离,支持业务流量快速切走,支持集群或单机的网络RDMA向TCP降级切换等等。在我们的切流演练中,从DBFS看到RDMA链路的写延时比TCP降低了一倍。我们在全链路压测中,基于RDMA技术保障了在单个数据库实例接近2GB吞吐下磁盘响应时间稳定在500微秒左右,没有毛刺。盘古分布式存储为了同时支持RDMA、EC压缩、快照等功能,做了大量的设计优化,尤其对写IO做了大量优化,当然也包括RDMA/TCP切流,故障隔离等稳定性方面的工作。作为阿里的存储底盘,其在线服务规模已经非常庞大。整个技术链路讲清楚之后,说一下我们在规模应用中遇到的难题,首先,容器的网络虚拟化Bridge和RDMA天然不兼容,由于容器走Bridge网络模式分配IP,而这个是走内核的。为了应用RDMA,我们必须使用Host网络模式进行容器化,走Host + X-DB + DBFS + RDMA +盘古存储这样的全用户态链路。其次,对于公有云环境,我们通过VPC打通形成混合云环境,因此应用通过VPC访问数据库,而数据库使用物理IP用于RDMA访问盘古以及X-DB内部X-Paxos。这个方案复杂而有效,得益于DBPaaS管控的快速迭代和容器化资源调度的灵活性,这些新技术能够快速落地,在变化中稳步推进。今年年初,我们定下了2018大促的支撑形态,即异地多活的中心机房将计算弹性到大数据的离线资源,单元机房将计算弹性到公共云资源,不搬数据直接弹性扩容,快上快下的大促目标。今年DB全局一盘棋,完成了资源调整,实现了电商各站点的存储计算分离架构升级,并通过X-DB异地多副本架构灵活部署,实现了弹性大促目标。基于底层盘古分布式的共享存储,弹性不需要迁移数据,只需要挂载磁盘,数据库可以像应用一样快速弹性,做到一个集群10分钟完成弹性扩容。同时在全链路压测过程中,对出现性能瓶颈的业务,我们可以边压边弹,快速弹到更大的规格上。基于快速弹性的能力,今年DB所有站点的大促扩容都在三天内完成,这在以前是不可能实现的,这就是存计分离的架构带来的效率。最后,感谢阿里内部通力合作的盘古、网络、调度、IDC等团队,正是大家的支持让阿里数据库的基础架构才能不断升级,不断提升效率和成本的竞争力。数据库存储计算分离的架构升级,大大节约了大促资源成本。目前我们的弹性能力正在日常化,通过数据预测,自动触发弹性扩容,我们的目标是让单机容量问题导致故障成为历史。 接下来我们平台将向智能化发展,对于数据库来说,只有基础架构足够强大,足够快速,灵活,弹性,智能化才能有效发挥。本文作者:天羽 阅读原文本文来自云栖社区合作伙伴“阿里技术”,如需转载请联系原作者。

December 11, 2018 · 1 min · jiezi

完爆 Best Fit,看阿里如何优化 Sigma 在线调度策略节约亿级成本

摘要:2018 年“双 11”的交易额又达到了一个历史新高度 2135 亿。相比十年前,我们的交易额增长了 360 多倍,而交易峰值增长了 1200 多倍。相对应的,系统数呈现爆发式增长。系统在支撑“双 11”过程中的复杂度和难度呈现指数级形式上升趋势。作为阿里巴巴全集团范围的容器调度系统,Sigma 在“双11”期间成功支撑了全集团所有容器(交易线中间件、数据库、广告等 20 多个业务)的调配,是阿⾥巴巴运维系统重要的底层基础设施。Sigma 已经是阿里全网所有机房在线服务管控的核心角色,管控的宿主机资源达到百万级,重要程度不言而喻,其算法的优劣程度影响了集团整体的业务稳定性,资源利用率。当用戶向调度系统申请容器所需的计算资源(如 CPU 、 内存、磁盘)时,调度器负责挑选出满足各项规格要求的物理机来部署这些容器。在相同的资源需求下,调度策略的优劣决定着集群计算资源利用的水平。本文将简要介绍群体增强学习算法在调度策略优化中的应用。1.计算资源调度及在线策略当用户向 Sigma 申请容器所需的计算资源(如 CPU、Memory、磁盘等)时,调度器负责挑选出满足各项规格要求的物理机来部署这些容器。通常,满足各项要求的物理机并非唯一,且水位各不相同,不同的分配方式最终得到的分配率存在差异,因此,调度器的一项核心任务就是按照某一策略从众多候选机器中挑出最合适的物理机。在文献中,计算资源调度一般被表述为矢量装箱问题(vector bin packing problem),如果各应用的容器数量事先已知(如大促场景),调度器可一次性为所有容器生成优化的排布方案,此时问题可以表述为整数规划,可使用通用求解器或专门开发的算法来求解;如果各应用的请求陆续到达 Sigma (如日常场景),调度器需要在每次请求到达时即时(在线)生成部署决策,此时问题可表述为马尔可夫决策过程 (Markov Decision Process, MDP),原则上可以通过值迭代或策略迭代求得最优策略。最常用的调度策略包括 First-Fit (FF) 和 Best-Fit (BF)。如果使用 First-Fit算法,调度器会将容器部署到遍历中碰到的第一个满足所有要求的物理机上;而Best-Fit算法则会在满足要求的物理机中挑选分配水位最高的机器来部署容器。对于经典的 bin packing 问题(即一维矢量装箱问题),First-Fit 和 Best-Fit 的近似比均为1.7,即二者都可保证所使用的机器数不超出最优方案的170%;对于2维及以上的矢量装箱问题,理论上不存在有着明确近似比保证的多项式算法。当物理机的某个资源维度明显为瓶颈而导致其它资源维度普遍有剩余时,其有效维度可视为1,使用 First-Fit 或 Best-Fit 一般可以取得不错的分配率;而一旦瓶颈并未集中体现在同一维度,两种策略的效果就要大打问号了。除了资源维度上的要求,实际调度中还有容灾和干扰隔离上的考虑:比如同一应用的容器不允许全部部署到同一台物理机上,很多应用甚至每台机器上只允许有一个实例;某些应用之间还存在互斥关系(如资源争抢),严重影响应用的性能,因此也不允许它们被部署到同一物理机上。这些限制条件的引入,使得常用策略越发水土不服了。通过人肉反复试错,勉强扛住了多次大促建站的压力。然而,随着各业务的扩张,线上容器的规模越来越大,资源变得越来越紧张,人肉调参的效率渐渐力不从心。为了把调度同学从调参中解放出来,让有限的资源扛住更大的压力,达摩院机器智能技术实验室(M.I.T.)的决策智能算法团队和Sigma调度团队展开了紧密合作,对在线调度策略问题进行了研究,并开发了基于群体增强学习(SwarmRL)的算法。2.在线调度模型记当前待部署容器的规格为向量 p∈P,为其分配资源时集群状态为向量 s∈S , 候选物理机的集合为 A⊆A,策略可表示为函数 :S×P→A(∈)。当按策略 选择物理机 a=(s,p)来部署该容器时,该选择的即时成本为 r(a),集群的新状态 s′ 由状态量 s 、p 以及动作 a 共同决定,记为 s′=L(s,p,a) ;记后续到达的容器规格 p′, 对于在线调度,p′ 为随机量。引入折扣系数 ∈[0,1],系统的 Bellman 方程为:最优调度策略可表示为:理论上,通过随机梯度下降,我们可以在策略空间 中搜索较优的策略,但相要更进一步的优化,甚至得到全局最优策略,则需要借助其它方法,特别是当最优策略可能是 multi-modal 形式。3.群体增强学习 SwarmRL为防止策略的优化陷入较差的局部最优解,同时拥有较快的收敛速度,我们基于群体增加学习的框架来设计算法。与传统的增强学习方法相比,算法使用多个 agent 来探索问题的策略空间,且多个 agent 之间存在互相学习机制,这使得算法有了跳出局部陷阱的能力。为获取各状态值(V^^)的估计,一个准确的 Sigma 模拟器必不可少,团队内部同学基于 Sigma 的调度器开发了“完全保真”的模拟器 Cerebro 。算法首先随机初始化一群 agent 的策略,针对每个策略,通过模拟器获取相应的的状态值估计,记录当前全局最佳策略。在后续的每次迭代中,各个 agent 不断更新自身的局部最佳策略,并参照局部最佳策略与群体当前全局最佳策略,对 agent 自身的当前策略进行更新,再进行模拟,获取新策略的状态值估计,更新全局最佳策略。如此循环,直到满足收敛条件。在各个 agent 状态值的估计中,样本(多个随机抽取的集群快照和扩容请求序列)和各 agent 的当前策略被输入模拟器 Cerebro,追踪模拟时集群状态的轨迹,即可得到该轨迹的总成本;基于多个样本的轨迹总成本求平均,即得到相应策略下的状态估计值。在 SwarmRL 中,策略的演进方向与步长用“速度” (v) 来表示,速度的变化涉及局部最佳策略 (L) 和群体全局最佳策略 (G ) 与 agent 当前策略 () 的差异,并受策略惯性因子 w、本地学习因子C1(self-learning)、群体学习因子 C2 (social-learning) 等参数的调控:其中 1,2∈[0,1] 为随机量,为可行性保持映射,用于将逸出可行域的 agent 重新“拉回”可行域。在迭代中,局部最佳策略 (L) 和群体全局最佳策略 (G ) 不断更新:4.算法应用下面我们先用一个随机生成的小算例来对比一下算法的效果。算例中涉及 30 个应用(见下表),其容器规格主要为 4c8g 与 8c16g,所用宿主机的规格均为 96c512g。若在调度时,请求的顺序和数量均为已知(“上帝视角”),即进行事后排布,使用整数规划求得的最优解对应的分配率为 94.44 % (这也是所有调度策略在该算例上所得分配率的上界),共启用 15 台宿主机,具体排布方案为:现实场景中,每个请求所处顺序和容器数量仅在其到达 Sigma 时才揭晓,若采用 Best-Fit 进行动态调度,所得分配率为 70.83%,共启用 20 台宿主机,具体排布如下:若采用 SwarmRL 学习所得策略进行动态分配,分配率为 94.44%,共启用 15 台宿主机,最终容器排布如下:在该算例中,SwarmRL 学习所得策略的表现(94.44%)与“上帝视角”下最优排布的表现(上界)一致,明显优于 Best-Fit 的表现(70.83%),改进幅度达 23.61%.我们再随机生成规模较大的请求数据:共计 3K 个请求,5K 个容器,其规格分布如下图,由于该场景下整数规划模型的变量规模太大,已经无法在短时间内直接求取“上帝视角”的最优解。对比 Best-Fit (以及人肉策略),算法所得新策略的效果如下:相对于 Best-Fit,新策略节约宿主机 13 台(4.48%),分配率提升 4.30%;相对于人肉策略,新策略节约 7 台(2.46%)宿主机,分配率改进 2.36%.考虑到实际场景中应用请求到达顺序的随机性,我们随机打乱请求生成多个不同的请求顺序,再分别应用三个策略按不同的请求顺序进行动态分配:Best-Fit 在不同请求顺序下宿主机数量的极差为 39 台,相对人肉策略的 84 台而言,表现相对稳定,其波动幅度约为人肉策略的一半;人肉策略的平均分配率低至 81.85%,对比原顺序下的 93.44%,可见人肉策略的性能并不稳定,表现出较剧烈的波动。而学习所得新策略的表现则相当稳定,其宿主机数量的极差仅为 3 台,波动幅度约为人肉策略的 30 分之一;新策略的分配率平均比人肉策略的分配率高 13.78%,比 Best-Fit 的高 3.02%.5.总结与展望从提升分配率、节省资源的角度来看,SwarmRL 算法可以产生出优于常用(以及人肉)的策略,并且有着较为稳定的表现。算法部署到线上环境后,公共资源池的分配率峰值与之前相比有了明显的提升。随着 CPU share 和混部的铺开,除分配率外,新的场景将涉及更多目标,比如打散、负载均衡等,这些目标甚至还有互相矛盾的地方,而 SwarmRL 的运行机制天然适合具有多个目标的策略优化问题,可以十分方便地在策略空间中构造 Pareto Front,因而,后续我们将继续研究新场景下的在线调度策略问题,充分挖掘 SwarmRL 的潜力,进一步提升 Sigma 的调度能力。参考文献David Simchi-Levi, Xin Chen and Julien Bramel (2014). The Logic of Logistics: Theory, Algorithms, and Applications for Logistics Management (3rd ed). SpringerRichard S. Sutton and Andrew G. Barto (2017). Reinforcement Learning: An Introduction. The MIT PressHitoshi Iima, Yasuaki Kuroe and Kazuo Emoto (2011). Swarm reinforcement learning methods for problems with continuous state-action space, IEEE ICSMCYossi Azar, Ilan R. Cohen, Amos Fiat and Alan Roytman (2016). Packing small vectors. SODA'16Yossi Azar, Ilan R. Cohen, Seny Kamara and Bruce Shepherd (2013). Tight bounds for online vector bin packing. STOC‘13本文作者:amber涂南阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

December 7, 2018 · 2 min · jiezi