首页 文章 精选 留言 我的

精选列表

搜索[pipeline],共2104篇文章
优秀的个人博客,低调大师

每日一博 | 构建数据湖上低延迟数据 Pipeline 的实践

T 摘要· 云原生与数据湖是当今大数据领域最热的 2 个话题,本文着重从为什么传统数仓 无法满足业务需求? 为何需要建设数据湖?数据湖整体技术架构、Apache Hudi 存储模式与视图、如何解决冷数据频繁更新、如何在数据湖上进行准实时 分析、数据湖上调度为何选型 Apache DolphinScheduler、二次开发新特性以及规划等多个角度进行了阐述。 讲师介绍 杨华,T3 出行大数据平台负责人。Apache Hudi Committer & PMC、Apache Kylin Committer 及 Flink Cube 引擎作者。Apache Flink 国内早期布道者及活跃贡献者。曾在腾讯主导 Flink 在腾讯从落地到支撑日均近 20 万亿消息的处理。 赵玉威,T3 出行高级工程师,对大数据任务调度有深入研究。 这里也简要介绍一下 T3 出行:T3出行是由一汽、东风、长安联合腾讯、阿里巴巴等共同投资打造,有中国网约车“国家队”之称。 10 月 25 日的 COSCon’20 & Apache Roadshow - China 上,来自 T3 出行大数据平台负责人杨华和 高级工程师赵玉威同学带来了题为《T3 出行构建数据湖上低延迟数据管道的实践》的分享。以下是分享视频: 1 什么是数据湖 什么是数据湖 引用来自 AWS 对数据湖的定义: Adata lake is a centralized repository that allows you to store all yourstructured and unstructured data at any scale. You can store your data as-is,without having to first structure the data, and run different types ofanalytics—from dashboards and visualizations to big data processing, real-timeanalytics, and machine learning to guide better decisions. 数据湖是一个集中式的存储库,允许您以任意规模存储所有结构化和非结构化数据。您可以按原样存储数据(无需先对数据进行结构化处理),并运行不同类型的分析–从控制面板和可视化到大数据处理、实时分析和机器学习,以指导做出更好的决策。 2 T3出行为什么需要数据湖 出行行业存在着下次出行前支付这个支付长尾问题,这造成了超长的业务闭环窗口,历史冷数据随机更新还有多级更新、链路长等特点, T3 出行数据湖整体技术架构 数据湖框架 - Apache Hudi 简介 Hudi 插件化的架构 Hudi 存储模式与视图 T3 出行如何在数据湖上进行准实时分析 Hudi 与 DolphinScheduler 的集成 Why DolphinScheduler? 目前在业界应用较多的工作流调度系统包括 Oozie、Azkaban、Airflow 以及 Dolphin Scheduler 等。 从高可用、易用性、社区活跃度、可拓展性、与 Hadoop 生态圈集成以及维护成本几个维度进行了调研对比: T3 出行 从EasyScheduler 升级为 DolphinScheduler DolphinScheduler 最近发布的 1.3.2 版本,性能较 EasyScheduler 有 2~3 倍的提升,主要体现在调度策略、执行效率、单位时间吞吐、堆积处理等几个核心性能指标上。 DolphinScheduler 与 EasyScheduler 压测对比 l调度密度:调度周期为 1h,工作流每隔 20 秒调度一次 l集群非调度时间内处于空闲状态,状态基本一致;在调度周期内只有工作流内的任务在耗用资源 DolphinScheduler 与 EasyScheduler系统运作的差异 在 DolphinScheduler 新架构(黑线)中Master 职能更加丰富,Worker 则更加专注于执行。 在 EasyScheduler 中 Worker 不仅要主动“揽活”,还要负责“善后”工作。 任务的执行状态要通过访问数据库才能获得,对于那些任务复杂的工作流来说,时效性,任务吞吐,数据库压力都会成为调度性能的瓶颈。 DolphinScheduler 提升细节 - Netty 的引入 在 EasyScheduler 架构中,由于 Master 与 Worker 间没有直接交互的渠道,因而使得Master 的职能比较单一,同时降低了 Worker 的执行效率;两者通过第三方系统“曲线”通信带来的弊端是:耗费了大量时间与资源在数据库与ZooKeeper的操作上,牺牲性能以保障系统能够运作,这种过度使用底层组件的方式也为集群及调度自身的稳定埋下了隐患。 DolphinScheduler 提升细节 - Balance 机制 在 EasyScheduler 中 Worker的使用率与负载率难以均衡: lMaster 只负责工作流的拆分,无法管控任务如何分发; lWorker 通过非公平锁的方式从 zk 的任务队列中竞争拉取任务,无法合理分配 为此 DolphinScheduler 提供了三种任务分配策略:随机,轮询和资源线性加权。 Ø随机分发策略与非公平锁竞争类似; Ø轮询分发策略只能保证使用率与负载率的均衡; Ø资源线性加权根据 cpu,内存及 loadAverage 加权计算出各 worker 负荷指标,择优分发 线性加权是 DolphinScheduler 默认的分发策略,计算密集型或者内存紧吃的任务不会轻易得再由负荷较高的 Worker 去执行。 DolphinScheduler 提升细节 -易用性提升 除了性能方面,社区也一直致力于易用性的提升,使调度对运维人员及业务开发人员更加亲和友好。 Ø支持 K8s:DolphinScheduler 支持 K8s 部署; Ø简化配置:分离 install.sh 中的参数配置和集群部署配置,install.sh 仅供集群部署,集群参数配置文件抽取到 conf/config/install_config.conf 中; Ø工作流布局优化:提供一键美化工作流 DAG 功能,这对于通过 http client 与调度交互时非常实用。开发人员只需要关注 DAG 中的依赖关系即可,坐标信息,连接信息交给格式化工具来处理。 3 T3出行做了哪些改进 在充分利用 DolphinScheduler 原生功能特性的基础上,基于平台与业务的赋能驱动,T3对DolphinScheduler进行了大量嵌入式开发,目的是: l解决调度嵌入平台时遇到的兼容性问题,同时提供插件化所需的接口规范 l提供定制化任务类型的支持与现有任务类型的拓展 l特定场景下原生调度模式的适配及重构 l数仓业务由 EasyScheduler 向DolphinScheduler升级的版本兼容性问题 T3开发调度新特性 -调度场景拓展 提供 httpclient 用于平台内组件与 DolphinScheduler 交互。多数情况下,平台内业务都倾向于通过消息触发的方式与调度进行交互,通过 http client 调度可以将核心功能完全释放到平台侧,对于上层业务来说甚至不感知调度的存在。 通过平台可以对调度上的任务进行 CURD 操作,以及状态信息及日志的查看 T3开发调度新特性 -服务滚动升级 调度系统自适应平台最终体现在服务的变更,服务集成滚动升级是自适应的前提与低成本的保障。 T3开发调度新特性 -策略式通知管理 订阅式策略通知管理,细粒度的任务监控体系: ü策略动态配置、启用与屏蔽 ü细粒度事件管理,避免通知时出现“羊群效应” ü同一事件源一对多告警群组 ü同一群组内同一事件源单一触发 T3开发调度新特性 -对接 Prometheus ü服务集成 PushGateway 完成指标推送 ü多维度展示统计类与趋势变化类指标 ü易拓展,支持指标定制化,动态生效 T3 正在doing-事件驱动调度模式 事件驱动调度:把不同系统的业务逻辑用事件关联起来,来驱动业务或者流程继续执行。 l内部事件源:例如调度中一个工作流中的子任务节点,它是通过所有父节点执行完毕这个事件驱动触发的; l外部事件源:例如外部某个组件,当其激活后需要立即拉起任务,获取数据以提供服务,”激活”就是事件 l事件重放:对于外部事件源,事件驱动只需要业务方抛出事件即可(异步任务调度除外),调度则应该负责持久化该事件以具备重放能力。 l解决方案:配置定时任务轮询捕获外部事件源虽然可行,但调度使用监听来驱动事件无疑更节约资源,任务触发实时性更高;并且事件中可以传递任务所须的参数,当调度监听到事件后解析参数然后组装成对应的任务,调度执行。 T3 正在doing-异步回调调度模式 异步任务调度:核心是提供结果回调功能。 l使用场景:调度上某个任务执行完成后,需要将这个消息传达到外部以推动第三方系统内业务的流转,必要时消息中需要携带第三方所需的配置参数,结果信息等 l与事件驱动调度的区别: •该场景下,调度系统任务结束成为了外部事件源 •调度系统不能只是简单地将事件抛出,还需兼顾延迟回调,回调失败重试,回调审计等功能 l解决方案:对于回调的方式,可以参考 hudi 使用的 http 回调,或者 Kafka回调。 T3正在doing -策略式任务集成 当调度原生的任务类型无法满足业务线的个性需求时,需要不断地去适配,并且适配内容间鲜有共性,无法复用。对此,调度可以将差集内的任务执行策略交由业务自定义,自身负责策略模板的提供与执行策略的解析与管理。 T3正在doing -策略延迟调度 延迟任务调度:当任务提交后,在指定时间后延迟执行 l类似场景:包括用户下单后,一定时间后未付款自动关闭订单;用户打车后,一定时间后自动评价等 l常规方案与缺陷:扫描业务表,筛选出符合条件的数据对其进行操作,但存在扫描间隔影响任务延迟触发的精准性及可靠性等问题 l改进措施:调度维护延迟队列或在任务配置参数中新增延迟选项,即可以保证延迟执行的精确性,同时也能发挥自身高可用,可重试,能告警,提供管理视图的优势 4 T3的未来规划 T3打算做TODO-运维管理 提供指标概览页面单独的统计类运维概览页面,通过图表的形式展示任务相关的统计类指标据,例如: l近 M 天内执行时长的 TopN 实例或异常次数最多的 TopN 实例的柱状图; l可以标识数据量变化或调度负载变化的实例近 M 天运行时长的折线图; l提供 SQL 类图表生成器,可定制化 T3 打算做TODO- 路由策略 Ø故障转移:失败策略可选配置“故障转移”,工作节点故障后,自动 failover 切换到一台运行正常的工作点上重试 Ø忙碌转移:增加等待策略,当任务处于 WAITING 状态达到一定时间,由管理节点重新分配,尝试将任务转移到相对空闲的工作节点 T3 打算做TODO- 审计日志 T3打算做TODO- 数据血缘 Ø血缘关系管理:记录上下游数据资源编码,数据项编码和数据资源转换规则等数据血缘信息,动态更新 Ø血缘关系分析:对数据资源进行数据流向分析和溯源分析,更进一步可以提供数据血缘图谱展示 Ø血缘关系查询:支持按照数据类别、数据项和转换规则进行数据血缘查询Ø数据价值评估:通过数据血缘标出数据流转的引用/更新频次,展示各级数据的应用热度 T3打算做TODO-调度客户端 l状态管理:提供命令行,方便监管调度服务状态,提供统计信息 例如:scheduler restart worker-server;scheduler state 等 l任务管理器:不同于 http client 的 java 客户端形式,通过客户端脚本作为环境变量,以 shell 命令的方式拓展平台与调度的交互方式 例如:scheduler submit ...; schedulerkill ...; scheduler rerun ... 等 T3打算做TODO-跨集群调度与容灾 l跨集群调度:调度内服务通过标签的形式标识为不同集群组,提供类似 agent的服务由一个 ui 页面统一管理。 l容灾:在实现跨集群调度的基础上,主备集群容灾的全量与增量数据备份都可以通过调度定时完成,并通过调度提供的异步调度与事件通知机制来监管备份过程。 5 参与贡献 参与 DolphinScheduler 社区有非常多的参与贡献的方式,包括文档、翻译、布道、答疑、测试、以及代码等,此外也极其欢迎各种实践文章,DolphinScheduler开源社区非常期待您的参与。 贡献第一个PR(文档、代码)我们也希望是简单的,试想如果是一个新人一上来就贡献1个改了几十个文件的 PR 将会对参与review 的伙伴的心理造成多大的摧残,😝 如何参与贡献链接:https://dolphinscheduler.apache.org/zh-cn/docs/development/contribute.html 文档github地址:https://github.com/apache/incubator-dolphinscheduler-website 来吧,DolphinScheduler开源社区需要您的参与,为中国开源崛起添砖加瓦吧,哪怕只是小小的一块瓦,汇聚起来的力量也是巨大的 DolphinScheduler's Github Repo 传送门 ↓↓↓ https://github.com/apache/incubator-dolphinscheduler 喜欢❤️ DolphinScheduler 的话,别忘了 Star 收藏一下哟~ 点击“阅读原文”获取会议PPT资料 本文分享自微信公众号 - 海豚调度(dolphin-scheduler)。如有侵权,请联系 support@oschina.cn 删除。本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

优秀的个人博客,低调大师

【Spark Summit East 2017】基于Spark构建的Netflix推荐ML Pipeline

更多精彩内容参见云栖社区大数据频道https://yq.aliyun.com/big-data;此外,通过Maxcompute及其配套产品,低廉的大数据分析仅需几步,详情访问https://www.aliyun.com/product/odps。 本讲义出自Tsai在Spark Summit East 2017上的演讲,主要介绍了Netflix如何使用Apache Spark作为分布式计算框架以及机器学习技术来构建自己的算法来为8000万以上的用户进行个性化推荐,并介绍了在面对Netflix量级的用户带来的挑战中使用的技术和遇到的陷阱。

优秀的个人博客,低调大师

如何使用Docker、Docker-Compose和Rancher搭建部署Pipeline(三)

在这一部分,我们将一步步的走进Rancher,细致的探讨Rancher将如何解决在部署与容器管理时出现的种种的问题。回顾教程的第二部分,你会发现我们已经将应用的部署迁移至Docker Compose,并且已经建立了一系列工作步骤来部署我们的应用。这将使得开发人员能够轻松的对他们的应用部署逻辑进行修正,运维人员也可以查看应用的部署时间。当然,在上一个部分教程的一系列操作中,也存在一些显而易见的问题需要解决。 使用Docker-Compose时面临的挑战 首先,运维人员必须手动地调整所有服务的执行计划。部署人员需要决定将哪一个应用部署至哪一台主机,这意味着部署人员需要时刻对每一台主机的剩余可用资源都有了解,如果某一台主机或者容器崩溃了,部署的操作人员将需要对应用进行重新部署。实际生产中,这意味着主机常常处于负载失衡的状态,并且服务在崩溃之后需要很长时间才能得到恢复。 其次,使用Docker-Compose时,想要获得你的服务的当前状态是十分困难的。举个例子来说,我们经常会从运维人员、项目经理以及开发者口中听到这样的问题:“现在部署环境中运行的到底是XX应用程序的哪个版本?”如果我们采用的是手动调整服务的执行计划的方式,想要得到这个问题的答案通常需要询问指定的进行操作的工程师,工程师们需要登陆服务器并运行docker中的ps命令来查看容器的信息。然而面对这些问题,Rancher将会给我们提供极大的便利:每个人都可以非常容易地获取已经部署的服务的信息,而不需要临时请求运维人员的帮助。 使用Rancher之前,我们试着了解过不少其他能够管理Docker主机或集群的解决方案。然而这些解决方案都没有注意到这是对Docker主机或集群在多种环境(multi-environment)下的管理,这将成为最大的麻烦与负担之一。如果有服务以不同的负载运行在8种不同的环境下,我们需要的是一个统一的方式来管理集群,而不会想要访问8个不同的服务。并且,我们希望让重新构建环境对于我们而言,变成分分钟就能完成的任务,这样开发者就可以随意地更改开发环境。然而,对于生产环境而言,我们希望提供给他们的只是有限的只读访问权限。面对这样的需求,一个采用基于角色的访问控制(RBAC)模型的集中管理方案就显得十分必要了。我们最初决定尝试Rancher就是因为它在部署上非常简单。 当Rancher面临这些挑战 在短短半天的时间里,使用AWS ELB、Elasticache、RDS和现有的Docker主机,我们已经将Rancher部署好并成功运行。能够方便地配置认证信息也是Rancher的优点之一。 我们并不会深入Rancher本身部署的细节,Rancher部署文档中已经说的很明白了。相反,我们将从刚刚完成初始设置那一步开始,说明将如何将原有的设置(教程第一部分和第二部分中所提及的)迁移进来。 我们就从创建不同的环境开始吧,为了使得这个过程尽量简单些,我们将对开发环境(dev)、部署环境(stage)以及生产环境(prod)分别进行设置。每个环境都已有运行在Ubuntu之上的Docker主机,且这些Docker主机是由内部的Ansible配置的,Ansible安装了Docker、我们的监控代理、并进行了一些组织特定的更改。在Rancher上,你只需要运行一条命令,将Docker主机在Rancher server内部进行注册,就可以将已有的Docker主机添加至每个环境中。 添加一台Rancher主机 在大多数情况下,想要添加一台主机需要经过一系列的操作:通过鼠标在网页上完成一些点击,接下来切换至某个特定的环境,最后在终端系统上输入命令。然而,如果你使用Rancher API,我们可以在Ansible工具的帮助下使得这一系列的操作转化为完全自动化的设置。出于好奇,在下面我们截取了playbook中有关这一操作的部分内容(大多是根据 Hussein Galas的repo中的内容做出的逻辑上的修改而得到的)。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 name:installdependencies for urimodule apt:name=python-httplib2update_cache=yes name:check if therancher-agentisrunning command:dockerps–filter‘name=rancher-agent’ register:containers name:getregistrationcommandfromrancher uri: method:GET user:“{{RANCHER_API_KEY}}” password:“{{RANCHER_SECRET_KEY}}” force_basic_auth:yes status_code: 200 url:“https: //rancher.abc.net/v1/projects/{{RANCHER_PROJECT_ID}}/registrationtokens” return_content:yes validate_certs:yes register:rancher_token_url when:“‘rancher-agent’notincontainers.stdout” name:registerthehostmachinewithrancher shell:> dockerrun-d–privileged -v/var/run/docker.sock:/var/run/docker.sock {{rancher_token_url.json[‘data’][ 0 ][‘image’]}} {{rancher_token_url.json[‘data’][ 0 ][‘command’].split()|last}} when:“‘rancher-agent’notincontainers.stdout” 随着工作的一步步进行,我们已经完成了环境的创建并已经将主机在Rancher server中注册,现在就让我们来了解一下,如何将我们的部署工作流整合至Rancher中。我们知道,对于每一台Docker来说,其中都有着一些正在运行的容器,这些系统的部署是通过Ansible工具借助Jenkins完成的。Rancher提供了以下开箱即用的功能: 管理已有的容器(比如:启动、修改、查看日志、启动一个交互式的shell) 获得关于运行中的和停止运行的容器的信息(比如:镜像信息、初始化命令信息、命令信息,端口映射信息以及环境变量信息) 查看主机和容器层级上的资源使用情况(比如:CPU使用率、内存占用率、以及磁盘和网络的使用情况) 独立的容器 很快,我们就已经将Docker主机注册至Rancher Server中,现在我们可以查看容器在各种环境下的运行状态信息了。不仅如此,如果想要将这些信息分享给其他团队,我们仅仅需要针对某个环境给予他们一些有限的权限。通过以上的方式,在想要获得状态信息时我们就完全没有必要请求操作人员登录Docker主机,再通过人工的方式去查询,同时这样也减少了申请获得环境信息的请求的数目,因为我们已经将某些访问权限分配至各个团队了。举个例子来说,如果为开发团队分配环境信息的只读权限,那么将会在开发团队与部署操作团队之间架起一座沟通的桥梁,这样两个团队都会对这个环境的状态比以往更加的关心。在这个基础上,故障的排除也变成了一种小组间相互合作的过程,而不是以往的那种单向的、依赖同步信息流的解决方式,相互合作的方式也会减少解决突发事件的总时间。 到现在为止,我们已经将已有的Docker主机加入Rancher Server,并且基于已经阅读完了的教程的第一部分关于Jenkins和Rancher的内容,下一步,我们打算改进的部分是我们已有的部署流水线,我们将会对已有的部署流水线进行修改,以便于使用Rancher compose,Rancher Compose将代替之前Ansible工具提到的Docker compose。不过在我们深入下一部分之前,我们首先需要了解关于Rancher的应用、调度、Docker Compose和Rancher Compose的一些信息。 应用与服务:Rancher将每个独立的容器(指的是部署在Rancher之外的容器,或者是通过Rancher UI生成的一次性功能的容器)、应用和服务彼此分离开。简单地说,应用是一组服务,而所有容器都需要利用服务(关于应用和服务的内容之后将会由更加详细的介绍)以构建一个应用。独立的容器需要手动地进行调度。 调度:在之前的部署技术中,运维人员需要决定容器应当在哪一台主机上运行。如果使用的是部署脚本,那么意味着运维人员需要决定部署脚本在哪一台或哪几台主机上运行;如果使用Ansible,这将意味着运维人员需要决定哪些主机或组需要到Jenkins中工作。不论是哪一种方式,都需要运维人员去做一些决定,但是在大多数情况下,他们做出的决定都缺乏一些可靠的依据,这对我们的部署工作很是不利(比如说某一台主机的CPU使用率高达100%)。很多解决方案,比如像Docker Swarm、Kubernetes、Mesos和Rancher都采用了调度器来解决这类问题。对于需要执行的某个操作,调度器将会请求获得一组主机的信息,并判断出哪几台是适合执行这个操作的。调度器会根据默认的需求设定或者用户定义的特定需求,比如CPU使用率高低、亲和性或反亲和性规则(比如:禁止在同一台主机上部署两个相同容器)等类似的需求,以逐渐缩小主机选择的范围。如果我是一个负责部署的运维人员,调度器将会极大的减少我的工作负担(尤其是我在深夜加班忙于部署时),因为调度器对以上信息的计算比我快的多,也准的多。Rancher在我们通过应用部署服务的时候能够提供一个开箱即用调度器。 Docker compose:Rancher使用Docker compose来创建应用并定义服务。由于我们已经将服务转化为Docker compose的文件,我们在此基础上创建应用就变得容易了许多。应用可以手动的从UI界面中创建,也可以通过Rancher compose在命令行(CLI)下快速的创建。 Rancher compose:Rancher compose是一种通过命令行(CLI)让我们得以对Rancher中的每一种环境的应用和服务进行方便的管理的工具。同时,通过rancher-compse.yml文件,Rancher compose还能允许对Rancher工具进行一些其他访问。这是一个纯粹的附加的文件,将不会取代原有的docker-compose.yml文件。在rancher-compose.yml文件中,你可以定义以下内容,比如说: 每种服务的升级策略信息 每种服务的健康检查信息 每种服务的需求规模信息 这些都是Rancher中非常实用的亮点,如果你使用Docker Compose或者Docker daemon,这些内容你都是获取不到的。如果想要查看Rancher Compose能提供的所有特性,你可以查看这个文档 通过将已有的部署工作交给Rancher Compose来替代之前的Ansible工具,我们能够很轻松的将服务迁移并部署为Rancher应用的形式。之后,我们就能够去除DESTINATION参数了,但我们依然保留VERSION参数,因为我们在插入docker-compose.uml文件的时候还要使用它。以下是使用Jenkins部署时,部署逻辑的shell片段: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 exportRANCHER_URL=http: //rancher.abc.net/ exportRANCHER_ACCESS_KEY=… exportRANCHER_SECRET_KEY=… if [-fdocker/docker-compose.yml];then docker_dir=docker elif[-f/opt/abc/dockerfiles/java-service- 1 /docker-compose.yml];then docker_dir=/opt/abc/dockerfiles/java-service- 1 else echo“Nodocker-compose.ymlfound.Can’t continue !” exit 1 fi if ![-f${docker_dir}/rancher-compose.yml];then echo“Norancher-compose.ymlfound.Can’t continue !” exit 1 fi /usr/local/bin/rancher-compose–verbose\ -f${docker_dir}/docker-compose.yml\ -r${docker_dir}/rancher-compose.yml\ up-d–upgrade 阅读完代码段,我们可以发现其主要包括以下内容: 我们定义了以环境变量的方式如何访问我们的Rancher server。 需要找到docker-compose.yml文件,否则将会任务将会报错退出。 需要找到rancher-compose.yml文件,否则任务将会报错退出。 运行Rancher-compose,并告诉它不要block并且使用-d命令输出日志,使用-upgrade命令更新一个已经存在的服务。 也许你已经发现了,在绝大部分,代码的逻辑都是相同的,而最大的区别就是使用rancher-compose代替使用Ansible工具完成部署,并对每一个服务添加了rancher-compose.yml文件。具体到我们的java-service-1应用,docker-compose文件和rancher-compose文件现在是这样的: 1 2 3 4 5 6 7 8 9 10 11 docker-compose.yml java-service- 1 : image:registry.abc.net/java-service- 1 :${VERSION} container_name:java-service- 1 expose: – 8080 ports: – 8080 : 8080 rancher-compose.yml java-service- 1 : scale: 3 在开始部署工作之前,我们先回顾一下部署工作的流程: 开发人员将代码的修改推送至git上 使用Jenkins对代码进行单元测试,在测试工作结束之后触发下游工作 下游工作采用新的代码构建一个docker镜像,并将其推送至我们自己的Docker镜像仓库中 创建包含应用名、版本号、部署环境的deployment ticket 1 2 3 DEPLOY- 111 : App:JavaService1,branch“release/ 1.0 . 1 ” Environment:Production 部署工程师针对应用运行Jenkins的部署工作,运行时需要将版本号作为参数。 Rancher compose开始运行,对于某个环境创建或更新应用,并且当达到所需规模的时候,结束这个工作 部署工程师以及开发工程师分别手动地对服务进行校验 部署工程师在Rancher UI中确认完成升级 关键点 使用Rancher进行我们的服务部署时,我们从Rancher内建的调度、弹性伸缩、还原、升级、和回滚等工具中获得极大的便利,使得我们在部署过程中没有花太大的力气。同时我们发现,在将部署工作从Ansible工具中迁移至Rancher的工作量也是很小的,仅仅需要在原有的基础上增加rancher-compose.yml文件。然而,使用Rancher来处理我们容器的调度意味着我们将难以确认我们的应用到底是在哪台主机上运行的。比方说,之前我们并没有决定java-service-1应用在哪里运行,对于后端,在进行负载均衡相关操作时,该应用就没有一个静态的IP。我们需要找到一种办法,使得我们的各种应用之间能够相互察觉到对方。最终,对于我们的java-service-1应用,我们将明确地将应用容器所在的docker主机的8080端口与应用绑定,不过,如果有其他服务与应用绑定为相同的端口,它将会启动失败。通常负责调度决策的工程师将会对以上的事务进行处理。然而,我们最好将这些信息通知调度器以避免这样的事情发生。 在本教程的最后一个部分,我们将继续探索一些方案来解决在使用亲和性规则、主机标签、服务探索以及智能升级和回滚等特性时出现的问题。 原文来源:Rancher Labs 9月27日,北京海航万豪酒店,容器技术大会Container Day 2017即将举行。 CloudStack之父、海航科技技术总监、华为PaaS部门部长、恒丰银行科技部总经理、阿里云PaaS工程总监、民生保险CIO······均已加入豪华讲师套餐! 11家已容器落地企业,15位真·云计算大咖,13场纯·技术演讲,结合实战场景,聚焦落地经验。免费参会+超高规格,详细议程及注册链接请戳 本文转自 RancherLabs 51CTO博客,原文链接:http://blog.51cto.com/12462495/1958622

优秀的个人博客,低调大师

如何使用Docker、Docker-Compose和Rancher搭建部署Pipeline(四)

在这篇文章中,我们将讨论如何用Rancher实现consul的服务发现。 如果你还没有准备好,推荐你阅读本系列中先前的文章: 第一篇:CI /CD和Docker入门 第二篇:使部署逻辑向使用Docker Compose更进一步 第三篇:借力Rancher完成容器编排 在这构建部署流水线系列的最后一篇文章中,我们将探讨在转换到Rancher进行集群调度时面临的一些挑战。在之前的文章中,我们通过使用Rancher执行调度,让运维人员无须再负责选择每一次容器运行的位置。要使用这个新方案,我们必须让环境的其他部分知道调度程序放置这些服务的位置,以及如何访问它们。我们还将讨论如何使用标签来操作调度程序,以调整容器放置位置,并避免端口绑定冲突。最后,我们将通过利用Rancher的回滚功能优化我们的升级过程。 在引入Rancher之前,我们的环境是一个相当静态的环境。我们总是将容器部署到相同的主机上,而部署到不同的主机则意味着我们需要更新一些配置文件以反映新位置。例如,如果我们要添加'java-service-1'应用程序的一个附加实例,我们还需要更新load balancer以指向附加实例的IP。使用调度器让我们无法预测容器部署的位置,并且我们需要动态配置环境,使其能自动适应变化。为此,我们需要使用服务注册和服务发现。 服务注册表为我们提供了应用程序在环境中的位置的单一来源。和硬编码服务位置不同,我们的应用程序可以通过API查询服务注册表,并在我们的环境发生变化时自动重新配置。Rancher使用Rancher的DNS和元数据服务提供了开箱即用的服务发现。然而,混合使用Docker和非Docker应用程序时,我们不能完全依赖Rancher来处理服务发现。我们需要一个独立的工具来跟踪我们所有服务的位置,consul就符合这个要求。 我们不会详细说明如何在您的环境中设置Consul,但是,我们将简要描述我们在ABC公司使用Consul的方式。在每个环境中,我们都有一个部署为容器的Consul集群。我们在环境中的每个主机上都部署一个Consul代理,如果主机正在运行Docker,我们还会部署一个注册器容器。注册器监视每个守护进程的Docker事件API,并在生命周期事件期间自动更新Consul。例如,在新容器被部署后,注册器会自动在Consul中注册该服务。当容器被删除时,注册器撤销它的注册。 Consul服务列表 在Consul中注册所有服务后,我们可以在负载均衡器中运行consul-template,根据Consul中存储的服务数据动态填充上游列表。对于我们的NGINX负载均衡器,我们可以创建一个模板来填充’java-service-1’应用程序的后端: 1 2 3 4 5 6 #upstreams.conf upstreamjava-service- 1 { {{range_,$element:=service "java-service-1" }} server``.`Address`:``.`Port`; ` else ` server 127.0 . 0.1 : 65535 ;#forcea 502 `end`} 此模板在Consul中查找注册为“java-service-1”的服务的列表。然后它将循环该列表,添加具有该特定应用程序实例的IP地址和端口的服务线。如果在Consul中没有注册任何“java-service-1”应用程序,我们默认抛出502以避免NGINX中的错误。 我们可以在守护进程模式下运行consul-template,使其监控Consul的更改,在发生更改时重新渲染模板,然后重新加载NGINX以应用新配置。 1 2 3 4 TEMPLATE_FILE=/etc/nginx/upstreams.conf.tmpl RELOAD_CMD=/usr/sbin/nginx-sreload consul-template-consulconsul.stage.abc.net: 8500 \ -template "${TEMPLATE_FILE}:${TEMPLATE_FILE//.tmpl/}:${RELOAD_CMD}" 通过使用我们的负载均衡器设置来动态地改变其余的环境变化,我们可以完全依赖Rancher调度器来做出我们的服务应该在哪里运行的复杂的决定。但是,我们的“java-service-1”应用程序在Docker主机上绑定TCP端口8080,如果在同一主机上调度了多个应用程序容器,则会导致端口绑定冲突并最终失败。为了避免这种情况,我们可以通过调度规则来操作调度器。 通过在docker-compose.yml文件中使用容器标签来提出条件,是Rancher给我们的一种操作调度器的方法。条件可以包括亲和规则、否定、至“软”强制(意味着尽可能地避免)。在我们使用'java-service-1'应用程序的情况下,我们知道在给定时间只有一个容器可以在主机上运行,因此我们可以基于容器名称设置反关联性规则。这将使调度程序查找一个未运行名称为“java-service-1”的容器的Docker主机。我们的docker-compose.yml文件看起来像下面这样: 1 2 3 4 5 6 7 java-service- 1 : image:registry.abc.net/java-service- 1 :${VERSION} container_name:java-service- 1 ports: - 8080 : 8080 labels: io.rancher.scheduler.affinity:container_label_ne:io.rancher.stack_service.name=java-service- 1 注意“标签”键的引入。所有调度规则都作为标签被添加。标签可以被添加到Docker主机和容器。当我们在Rancher注册我们的主机时,我们可以将它们与标签关联,以后就可以切断调度部署。例如,如果我们有一组使用SSD驱动器进行存储优化的Docker主机,我们可以添加主机标签storage=ssd。 Rancher主机标签 需要利用优化存储主机的容器可以添加标签来强制调度程序仅在匹配的主机上部署它们。我们将更新我们的“java-service-1”应用程序,以便只部署在存储优化的主机上: 1 2 3 4 5 6 7 8 java-service- 1 : image:registry.abc.net/java-service- 1 :${VERSION} container_name:java-service- 1 ports: - 8080 : 8080 labels: io.rancher.scheduler.affinity:container_label_ne:io.rancher.stack_service.name=java-service- 1 io.rancher.scheduler.affinity:host_label:storage=ssd 通过使用标签,我们可以根据所需的容量,而不是个别主机运行特定的容器集,来精细地调整我们的应用程序部署。切换到Rancher进行集群调度,即使您仍然有必须在特定主机上运行的应用程序。 最后,我们可以利用Rancher的回滚功能优化我们的服务升级。在我们的部署工作流中,通过调用rancher-compose来指示Rancher在该服务堆栈上执行升级以部署服务。升级过程大致如下: 通过拉取一个新的镜像来启动升级 逐一地,现有容器被停止并且新容器被启动 部署程序登录到UI并选择“完成升级”时,升级完成, 已停止的旧服务容器被删除 Rancher升级 当给定服务的部署非常少时,此工作流就好了。但是,当某个服务处于“升级”状态(在部署者选择“完成升级”之前)时,在执行“完成升级”或是“回滚”操作之前,你都不能对它进行任何新的升级”。rancher-compose实用程序让我们可以选择以编程方式选择要执行的操作,以部署程序者的身份执行操作。例如,如果您对服务进行自动测试,则可以在rancher-compose升级返回后调用此类测试。根据这些测试的状态,rancher-compose可以被再次调用,这次我们告诉堆栈“完成升级”或“回滚”。我们部署Jenkins作业的一个原始示例可能如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 # for thefulljob,seepart 3 of this series /usr/local/bin/rancher-compose--verbose\ -f${docker_dir}/docker-compose.yml\ -r${docker_dir}/rancher-compose.yml\ up-d--upgrade JAVA_SERVICE_1_URL=http: //java-service-1.stage.abc.net:8080/api/v1/status if curl-s${JAVA_SERVICE_1_URL}|grep-q "OK" ;then #looksgood,confirmor "finish" theupgrade /usr/local/bin/rancher-compose--verbose\ -f${docker_dir}/docker-compose.yml\ -r${docker_dir}/rancher-compose.yml\ up--confirm-upgrade else #lookslikethere'sanerror,rollbackthecontainers #tothepreviouslydeployedversion /usr/local/bin/rancher-compose--verbose\ -f${docker_dir}/docker-compose.yml\ -r${docker_dir}/rancher-compose.yml\ up--rollback fi 这个逻辑将调用我们的应用程序端点来执行简单的状态检查。如果输出显示的是‘OK’,那么我们完成升级,否则我们需要回滚到以前部署的版本。如果您没有自动测试,另一个选择是简单地总是完成或“确认”升级。 1 2 3 4 5 # for thefulljob,seepart 3 of this series /usr/local/bin/rancher-compose--verbose\ -f${docker_dir}/docker-compose.yml\ -r${docker_dir}/rancher-compose.yml\ up-d--upgrade--confirm-upgrade 如果不久以后,您确定需要回滚,就使用相同的部署作业简单地重新部署以前的版本。这确实不像Rancher的升级和回滚功能那么友好,但它通过使堆栈不处于“升级”的状态来解锁将来的升级。 当服务在Rancher中回滚时,容器将被重新部署到以前的版本。当使用通用标记如“latest”或“master”部署服务时,可能会出现意外的后果。例如,让我们假设'java-service-1'应用程序以前被部署了标签'latest'。对图像进行更改,推送到注册表,Docker标签“latest”被更新为指向此新映像我们使用标签“latest”继续升级,在测试后决定应用程序需要回滚。使用Rancher滚动堆栈仍然会重新部署最新的映像,因为标签“latest”尚未被更新为指向上一个映像。回滚可以在纯技术术语中实现,但是部署最近的工作副本的预期效果完全无法实现。在ABC公司,我们通过始终使用与应用程序版本相关的特定标记来避免这种情况。因此,不要使用标记latest”部署我们的“java-service-1”应用程序,我们可以使用版本标签“1.0.1-22-7e56158”。这保证回滚将始终指向我们的应用程序在环境中的最新工作部署。 我们希望我们分享的经验对你们有所帮助。这有助于我们有条不紊地采用Docker,稳步改进我们的流程,并让我们的团队能熟悉这些概念。对更自动化的部署工作流进行增量更改,使组织能够更快地实现自动化的优势,部署团队可以更加务实地决定他们在流水线中需要什么。我们的经历证明Rancher在可行性、自动化、甚至团队协作方面都是成功的。我们希望分享这些我们在Docker应用过程中获得的经验教训将有助于您自己的应用过程。 欢迎关注Rancher官方微信公众号(RancherLabs),获取第一手技术干货推送;欢迎添加客服微信(RancherLabsChina)为好友,加入Rancher官方技术交流群,获取免费技术支持,与数千Docker/Rancher使用者互动。 原文来源:Rancher Labs 9月27日,北京海航万豪酒店,容器技术大会Container Day 2017即将举行。 CloudStack之父、海航科技技术总监、华为PaaS部门部长、恒丰银行科技部总经理、阿里云PaaS工程总监、民生保险CIO······均已加入豪华讲师套餐! 11家已容器落地企业,15位真·云计算大咖,13场纯·技术演讲,结合实战场景,聚焦落地经验。免费参会+超高规格,详细议程及注册链接请戳 本文转自 RancherLabs 51CTO博客,原文链接:http://blog.51cto.com/12462495/1961896

优秀的个人博客,低调大师

如何使用Docker、Docker-Compose和Rancher搭建部署Pipeline(二)

在这一系列文章的第一篇中,我们分享了只用Docker时我们开发的初步的工作流,如何创建一个基础的构建和部署流水线。容器的部署方式不再是在登陆server的时候从内存中输入Docker命令。我们已经通过Jenkins server实现了镜像的自动化构建。我们使用脚本将Docker命令进行封装,将其存储到GitHub中并且设置版本。目前我们正采取措施,通过逐步改善现有过程来实现持续部署。然而,仍有一些痛点需要我们去解决。在这篇文章中,我们将看看如何使用Docker Compose 和 Ansible来改善此设计。 在部署镜像时,工程师需要登录到服务器,并从shell运行我们的Docker wrapper脚本。这不是很好的解决方法,因为它也需要开发者进行等待。没有任何一方会从在这种方式中获益(作为一个工程师,当你去做某件你很了解并且很容易自动化的事情时,你有多少次被打断了?)由于每一次部署都是通过操作者电脑中的SSH会话来执行的,因此部署过程是不可见的。 如果你对我们的部署脚本还有印象,你会发现它看起来像下面的代码段: 实际上,我们做的是将Docker run命令语句进行抽象,由此工程师将不需要知道每个图像成功运行时所需要的确切的参数。虽然这改善了必须全部记住并且手动输入所有Docker参数的现状,但同时也会带来新的问题: 每个容器的逻辑都存储在同一文件中,这使得对应用程序部署逻辑的更改更难追踪; 当开发者需要测试或者修改参数时,需要被迫理清脚本中的逻辑,而不是能够在某一特定的程序中轻松地阅读和修改参数。 在我们的工作流中,Docker Compose是一个更适合使用的工具,它同样可以将部署参数进行编码,并且在YAML文件中指定,此文件就是docker-compose.yml。Docker Compose不仅帮助我们解决了上面提到的难点,而且也可以使我们从社区未来的工作中获益。下面让我们理清部署脚本,并且为我们的JAVA程序示例创建一个Compose文件。首先,我们需要基于原来的部署逻辑创建一个docker-compose.yml文件: 现在,部署容器只需要在与docker-compose.yml文件相同目录下输入以下命令: 1 docker-composeup 它将根据compose文件中设置的参数启动一个容器。在compose文件中一个重要的变量是${VERSION} 。Docker Compose可以从当前的shell环境中插入compose文件里所列出的参数。我们可以通过简单地运行以下语句来设置参数: 1 VERSION= 1.0 . 0 docker-composeup 它将从我们的私有镜像仓库挑出标记1.0.0的镜像,以此启动java-service-1程序。如果没有设置VERSION变量,Docker Compose将产生一条警告信息,并且用空字符串代替变量值,由此,具有最新版本标签的镜像将会被挑出。因此,正确地设置变量是相当重要的。 作为开发过程的一部分,我们希望开发人员能够在本地建立服务并且测试他们的服务。然而,由于docker-compose.yml指向私有镜像仓库的镜像,运行docker-compose将从最近构建的镜像中开启服务而不是从本地资源中开启。理想情况下,开发者可以通过运行以下代码使用典型的docker-compose工作流: Docker Compose能在不修改docker-compose.yml文件的情况下,让我们做到这一点。我们可以使用多个文件来覆盖我们在本地测试中想要改变的任何参数。在docker-compose.override.yml中,我们指定一个key而不是一个镜像,并且移除了对VERSION变量的需求。由于这是一个覆盖文件,我们不需要复制任何额外的设置,如端口设置: 使用Docker Compose而非部署脚本之后,我们可以: 在源代码中存储每个compose文件,这与Dockerfile类似; 不再需要复杂的部署脚本; 允许开发人员在本地轻松地测试并修改应用程序。 现在我们有了java-service-1程序的compose文件,我们可以将它从我们的部署脚本中删除,因此文件组织与下面的结构类似: 此时,我们仍然没有解决镜像构建和部署之间的问题。在docker-compose.yml文件中包含了所有的部署逻辑,但是它如何在环境中运行直至结束的呢?正好现在我们在运行与UNIX和TPC socket相关的Docker守护进程,是时候讨论一些与安全有关的问题了。 我们的情况是,工程师登录到服务器上,手动运行每个服务器所需容器的部署脚本。默认情况下,当在局部运行Docker命令时,它将使用UNIX socket /var/run/docker.sock连接Docker守护进程;或者让守护进程监听TCP socket,这允许用户远程连接到每个Docker守护进程,使得工程师能够像登录到主机一样运行命令。这为连接方式提供了更大的灵活性,但是没有考虑到一些开销和安全问题: 通过网络连接增加了安全隐患; 增加了对于基于主机或者基于网络的ACLs需求; 保护守护进程需要分布式CA和客户端认证。 另一种可能的方法是不使用基于UNIX socket的方式运行Docker守护进程,而使用SSH来运行命令。已经建立的ACLs将保护SSH端口,并且它只允许通过SSH授权的特定的用户才能使用Docker守护进程。虽然这不是最简洁的方法,但是它有助于保持较低的运行开销,并且使安全隐患降到最低。这点是非常重要的,尤其是对于细粒度的稀疏的任务队列而言。 为了有利于通过SSH运行Docker命令,我们可以使用Ansible——一个流行的编排和配置管理工具。它是无代理的,并且允许通过SSH连接运行“剧本”(服务器任务集合)。一个运行docker-compose命令的简单的剧本如下所示: 如果你对Ansible没有过多了解,你也许可以通过上面的剧本大致了解到我们想做什么。它们按顺序一步步执行,具体如下所示: Ansible将通过SSH连接到目标服务器(允许通过使用DESTINATION变量来指定主机) 在每个服务器中,Ansible会通过执行shell命令登录到公司私有的镜像仓库 Ansible将位于Jenkins(运行ansible剧本的服务器)中的docker-compose.yml文件复制到每个目标服务器中的/tmp/docker-compose.yml下 在每个目标服务器中运行docker-compose命令 通过删除远程的/tmp/docker-compose.yml文件进行清理 一个shell脚本可以被运用在同一个事件中。然而在Ansible中,我们将很容易的使任务并行化并且得到经过良好测试的模块,通过使Ansible与新的部署剧本相结合,我们可以远程启动容器,相较于工程师登录到主机、人工运行命令,这是一个重要的进步。为了在部署过程和状态中提供更大的可视性,我们将建立Jenkins任务来运行Ansible代码。通过使用Jenkins,在未来我们可以轻松地将构建和部署任务集成起来,从而得到额外的好处。 Jenkins任务需要两个参数:目标主机(传递给剧本中的DESTINATION变量)和部署镜像的版本(在docker-compose.yml文件中插入VERSION变量)。大多数任务的构建部分是一个shell构建器,它将试图找到程序中的docker-compose.yml文件,然后通过传递变量(用-e)到剧本中,运行ansible-playbook命令: 虽然看起来我们似乎只对工作流做了微小的变化,但是我们正一步一步地向构建一个持续部署模型迈进: 部署是可以被审查的。我们使用日志来记录输出什么、何时输出、以及哪些主机是目标主机等信息,这一切都归功于Jenkins。 程序部署逻辑已经从一个单一的脚本分散到存储在程序源代码中的单独的docker-compose.yml文件中,这意味着我们可以轻松地通过git更改程序部署逻辑。在程序源文件或者部署文件发生变化时,我们也可以容易地进行构建和部署。 虽然这些改进解决了某些问题,但是它们所带来的新的问题也成为了焦点: 哪个容器的哪个版本会被部署到何地? 容器在被部署后会处于哪种状态? 我们如何确定哪个主机成为程序的目标主机? 在这一系列接下来的文章中,我们将探讨怎样运行Rancher以及使用它的原因,尤其是它如何解决上述的问题。与此同时,我们也讨论它在业务和开发团队中所起到的意想不到的桥梁作用。 原文来源:Rancher Labs 9月27日,北京海航万豪酒店,容器技术大会Container Day 2017即将举行。 CloudStack之父、海航科技技术总监、华为PaaS部门部长、恒丰银行科技部总经理、阿里云PaaS工程总监、民生保险CIO······均已加入豪华讲师套餐! 11家已容器落地企业,15位真·云计算大咖,13场纯·技术演讲,结合实战场景,聚焦落地经验。免费参会+超高规格,详细议程及注册链接请戳 本文转自 RancherLabs 51CTO博客,原文链接:http://blog.51cto.com/12462495/1956623

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册