为什么 K8s 在阿里能成功?| 问底中国 IT 技术演进

alicloudnative阅读(258)评论(0)

作者:
曾凡松 阿里云云原生应用平台高级技术专家
张振 阿里云云原生应用平台高级技术专家

导读:本文描述了阿里巴巴在容器管理领域的技术演进历程,解读了为什么 K8s 最终能够大获成功的原因,以及到今年 双11 阿里巴巴内部的 K8s 应用情况。内容着重描述了阿里巴巴基于 K8s 的云原生改造实践过程的三大能力升级,在对应能力升级过程中沉淀的技术解决方案,以及通过这些能力升级所取得的业务价值。

从 2015 年 Google 牵头成立 CNCF 以来,云原生技术开始进入公众的视线并取得快速的发展,到 2018 年包括 Google、AWS、Azure、Alibaba Cloud 等大型云计算供应商都加入了 CNCF,云原生技术也从原来的应用容器化发展出包括容器、Service Mesh、微服务、不可变基础设施、Serverless、FaaS 等众多技术方向,CFCF 旗下也囊括了越来多的开源项目。

Kubernetes 作为 CNCF 的第一个项目从诞生之初就就令人瞩目,Kubernetes 由 Google 工程师基于 Google 内部多年集群管理系统 Borg 的设计经验,结合云计算时代的基础设施特点重新设计而得,旨在帮助企业解决大规模 IT 基础设施的应用容器编排难题。

Google 在 2014 年 6 月开源 Kubernetes 以后,在 Redhat、Microsoft、Alibaba 等厂商和众多开源爱好者共同的努力下,成长为如今容器编排领域的事实标准,极大的推动了云原生领域的发展。

今天为大家分享来自阿里云的 Kubernetes 大规模实践经验,展现阿里云如何基于 Kubernetes 推动阿里巴巴应用运维技术栈走向云原生,如何推动 Kubernetes自身的技术进步,充分挖掘云原生时代的红利助力阿里巴巴大幅降低 双11 的 IT 成本。

容器在阿里巴巴的发展历程

1.png

在 2011 年之前,阿里巴巴使用 VM 虚拟化技术将一个物理机切分为 3 个虚拟机,用于部署淘宝服务,而随着淘宝业务的飞速发展,基于 VM 的技术方案在灵活性上跟不上业务的步伐。

因此,阿里巴巴在 2011 年就开始探索基于 Linux lxc 的容器技术,用于替代传统基于 VM 的应用部署方案,到 2013 年,研发了基于 Linux lxc 的 T4 容器和 AI 容器编排系统。这在当时已是非常领先的技术方案,但自己研发的容器技术与基于 VM 时代的运维系统始终存在一些兼容性问题。

在 2013 年随着 Docker 容器镜像方案的出现,阿里巴巴技术人员立即看到了基于容器 + Docker 镜像技术的未来,开始大力投入到这一领域的研究当中,到 2015 年 Aliswarm、Zeus、Hippo 等容器编排系统蓬勃发展,各自开疆扩土服务了阿里巴巴经济体的一部分业务。诸多的系统在解决了业务运维成本的同时,也带来了一定的重复建设成本,同时也导致了阿里巴巴内部的资源分布比较分散,无法统一调度多样的业务类型发挥出不同业务错峰使用资源的优势。

正是在这样的背景下,Sigma 系统应运而出并在 2017 年统一了阿里巴巴的资源池,统一调度阿里巴巴所有的核心业务,并第一次支持将在线服务与离线作业运行在同一个物理机上,大幅提高数据中心的资源利用效率并降低了阿里巴巴的 IT 成本。

随着云原生技术的高速发展,阿里巴巴也看到了云原生技术的潜力,以及未来企业 IT 全面上云的必然趋势,从 2018 年开始转型到 Kubernetes 技术,通过 Kubernetes 扩展能力将 Sigma 积累多年的调度能力通过 Kubernetes 的方式提供出来。

在 2019 年阿里巴巴宣布全面上云,阿里巴巴开始全面拥抱 Kubernetes,并将 Sigma 调度系统全面的迁移到基于 Kubernetes 的调度系统,该系统也正是支持了今年最大规模 双11 电商交易系统的底层基础设施,稳定的支持了大促前后数百次的应用变更并提供极速的应用发布与扩容体验,为 双11 的顺畅的购物体验立下悍马功劳。

为什么 K8s 在阿里能成功

Kubernetes 在众多的技术中脱颖而出,概括起来可以归纳为以下三个方面。

2.png

  • 首先是其在诞生之初就为云时代而生,拥有超前的眼光和先进的设计理念,加之最初由天才的 Google 工程师基于其内部 Borg 多年的经验设计而来,诞生之后就飞速发展;

后来随着 RedHat、IBM、微软、Vmware、阿里云等来自全球的优秀工程师大力投入,打造了繁荣的社区和生态系统,成为企业容器编排系统的首选。

阿里巴巴经济体拥有众多的子公司,这些子公司在加入阿里巴巴大家庭时或多或少都会有一套自有的容器编排系统,在融入阿里巴巴的基础设施过程中,Kubernetes 是最标准也最容易被经济体内外的客户所接受的一个方案。

  • 其次,Kubernetes 倡导的申明式 API 的设计理念,也贴合了阿里巴巴在应用运维领域的经验与教训;

传统的运维系统通常是基于过程式的设计,而过程式的运维系统在较长的系统调用链路下,通常会出现因异常处理复杂而导致的系统效率低下。

在大规模应用运维系统中复杂又繁多的状态处理也是一个大难题,基于过程式的系统设计很难确保系统的一致性,针对这些边界异常的处理通常又导致运维系统变得非常复杂,最终为异常兜底的只能依赖运维人员的人工操作。基本上可以认为基于过程式的运维系统难以应对超大规模的应用管理,而 Kubernetes 提供的申明式 API 却是解决应用运维状态轮转的一剂良药,是提高运维技术栈整体链路效率的最佳实践原则。

  • 第三,Kubernetes 模块化、可扩展的架构设计,满足阿里巴巴的定制化改造以支持众多业务运维场景的需求。

在阿里巴巴内部,即有大量的无状态核心电商系统,也有大量的缓存、消息队列等中间件有状态系统,也包括大量带有倒排索引数据的检索系统,还有大量的 AI 计算任务,不用的应用类型对底层容器管理平台的要求也有所不同。

因此,一个模块化方便迁入自定义应用管理策略、易于扩展调度模型的设计显得至关重要,是能够服务阿里内部众多应用形态、提供统一容器管理基础设施的关键,Kubernetes 基本上提供了这些关键基础能力,虽然在实际应用过程中仍然会遇到非常多的实际问题。

阿里巴巴的 K8s 应用情况

3.png

在 2019 年 双11,阿里巴巴内部核心业务主要运行在神龙、ECS、ECI 三种资源类型的基础设施之上,而这些不同类型的基础设施资源均通过 Kubernetes 统一管理,以容器的形态提供给上层应用使用,完成了核心业务的支撑。

有别于以往的 双11,今年核心电商业务应用大规模部署在神龙裸金属服务器上。如果有关注过阿里云技术的发展,应该不会对神龙服务器感到陌生,它是阿里云自主研发的新一代云服务器,通过“软硬一体”的技术开创性的将云计算的虚拟化开销分摊到低价硬件板卡上,彻底的释放 CPU 的计算能力,第一次真正的做到了云计算虚拟化的“零”开销。

容器也是一种轻量级的虚拟化方案,神龙+容器+Kubernetes 的结合正是云原生时代的最佳拍档,支撑了今年最大规模的 双11,也将是未来的主流技术形态。

阿里巴巴也在继续使用 ECS 作为 Kubernetes 的底层资源供给,ECS 作为传统的云计算虚拟化方式支撑了部门集团内部业务,同时结合灵活性更好的弹性容器实例 ECI 用于应对业务突发的流量峰值,为业务带来了云计算的弹性价值,真正实现了按需申请、释放资源的极致弹性能力,降低了业务需要提前规划资源所带来的成本。

这些分布在海内外的数十万个节点的资源,被数十个 Kubernetes 集群托管,运行着阿里巴巴上万个应用,共计超过百万的容器,其规模之大前所未有。在今年的 双11 中,阿里巴巴内部最大的 Kubernetes 集群规模达到万级;当然这并不是Kubernetes 的技术极限,而是我们考虑数据中心资源效率与基础设施容灾能力之间所取的平衡,在将来如果有需要这个数字也可能变得更大。

基于 K8s 的云原生改造实践

Kubernetes 作为云原生技术的代表,已经成为了容器编排领域的事实标准,阿里巴巴自 2017 年开始探索,到 2018 年确认技术转型到使用 Kubernetes 来管理生产的容器。

在落地 K8s 的过程中,我们主要面临着两大难题:

4.png

  • 其一,上层多样的业务运维平台;

为了支撑阿里巴巴内部多样的业务形态,在内部发展出来了多个典型的业务运维平台,每一个运维平台的基础设施、流程控制、应用发布策或多或少都会存在一些差别,缺少一个统一的应用运维标准。在调度与集群管理的技术演进过程中,如何牵引整个运维体系升级的同时并保持多个业务的平台及其上业务的稳定性,这是一个巨大的工程。

  • 其二,随着阿里巴巴经济体全面上云战略的实施,整个底层基础设施包括存储、网络、基础运维软件的技术演进也非常迅速。调度与集群管理需要在支持好基础设施快速演进的同时,迭代自身的技术架构,并同时保证业务的稳定性。

基于 K8s 的云原生技术改造正是在这样的背景下诞生,发展到 2019 年 Kubernetes 在内部已大规模部署,所有的核心业务也都已经运行在 K8s 集群管理中。但在这几年的实践过程中,有一个问题始终萦绕在工程师头脑中,在阿里巴巴这么大体量、这么复杂的业务下,遗留了大量传统的运维习惯以及支撑这些习惯的运维体系,在这样的背景下落地Kubernetes (内部一个形象的比喻叫做给高速飞行的飞机更换发动机)到底是在坚持什么,哪些地方可以妥协,哪些地方必须改变?

这一章节, 将为大家分享我们这几年对这个问题的一些思考,特别是经过了今年的 双11 考验后,这个问题的答案基本上得到了工程师群里的集体认可。

负责顶层设计的架构师终于可以喘一口气:拥抱 Kubernetes 本身并不是目的,而通过拥抱 Kubernetes 翘动业务的云原生改造,通过 Kubernetes 的能力治理传统运维体系下的沉疴顽疾,真正释放云的弹性能力,为业务的应用交付解绑提速,才是这次技术变革的最大价值所在。

5.png

面向终态升级

在传统的运维体系下,应用的变更都是运维通过创建操作工单发起工作流,继而对容器平台发起一个个的变更来完成的。比如升级一个服务下的 3000 个实例,工单会被提前计算并生成出多个批次的子任务,并逐个的调用容器平台的接口完成变更应用的变更。

为了确保应用发布工单的顺利执行,在每一个子工单内部,每一个容器的发布也是一个工作流,包括监控开管、镜像拉取、容器启停、服务注册、配置推送等等,如果一切正常该流程会按预期有序的进行。

6.png

在大规模应用发布的场景中,诸如宿主机宕机、磁盘异常、IO 异常、网络异常、内核异常等几乎是必然存在的,如果发布流程中的某一个步骤出现了错误,通常情况下需要运维平台按照一定的策略来重试,直到超过该批次的超时阈值,这将会带来三个问题,下面逐一展开。

  • 其一是重试带来的效率问题;

每一个子任务的执行时间将被任务内的长尾发布所拖累,假设将 3000 个容器分为 30 批次每批 100 个(仅为示意并非最佳实践),每一批次内出现一个容器发布异常时,该批次的发布时间将被重试拉长。

  • 其二是失败带来的一致性问题;

对于发布异常的容器,在工单结束之后通常只能通过外围链路巡检的方式来治理,而事实上通常的巡检是依赖运维人员手工操作的,带来了极大的人工成本和不确定性。

  • 第三是应用并发变更冲突问题。

如果在应用发布的过程中,同时提交了应用扩容的请求,由 3000 扩容到 3200 个实例,扩容的 200 个实例应该采用旧版本还是新版本,采用旧版本扩容将面临的问题是谁最终负责这 200 个旧版本实例的升级,采用新版本扩容将面临的是稳定性问题,如果新版本存在问题新扩容的实例将产生较大的影响。

正是因为这些复杂的问题导致多数运维系统拒绝了并发的应用变更,导致并发操作效率非常底下。

K8s 为应用管理所提供的申明式 API 的设计理念同时解决了解决了这三个问题,用户只需要描述期望的最终状态以及达成期望状态的过程中需要遵守的限制条件,达成终态所需要执行的复杂操作全部交由 K8s 的来完成。

在应用发布过程中,通常情况下 K8s 通过控制并发度及最大不可用实例数来约束应用发布对服务的影响,对于发布过程中失败的实例通过最终一致的方式在系统内部解决。正是基于这一设计,用户发起服务变更时只是更新了应用的预期状态,并不需要等待任何任务的结束,一并解决了应用发布效率、线上配置的一致性和并发变更冲突效率的问题。

7.png

基于面向终态的理念管理应用,我们开发 Advanced StatefulSet 的应用管理工作模型,顾名思义它基于 Kubernetes 官方的 StatefulSet 扩展而来。

在官方的工作模型中,应用通过滚动的方式完成版本升级,也就是创建新的 Pod 同时删除旧版本的 Pod,直到整个应用切换为新的版本。

这种方式简单直接,但存在效率的问题,比如所有应用的 Pod 需要重新的调度,这在大规模应用发布场景将给调度器带来很大的压力;同时,因为新版本 Pod 为全新创建,需要重新分配 IP 并挂载远程卷,这对云计算网络、存储基础设施也将是很大的挑战;再者,因为容器是被全新调度出来的,在机器上需要重新下载新的应用镜像,这将大幅降低应用发布的效率。

为了提高应用发布的效率和资源的确定性,开发了这一工作负载模型,它支持原地发布应用,应用发布前后应用所在的位置保持不变,同时支持了并发更新、容错暂停等丰富的发布策略,高效的满足了阿里巴巴内部电商应用的发布需求。因为应用发布前后位置不变,因此我们可以在灰度发布的过程中预先下载并解压即将要发布的容器镜像,从而大幅提高应用发布的效率。

8.png

在面向终态的应用管理中,复杂的运维过程被 K8s 内部所实现,K8s根据用户的期望及现状计算出需要执行的动作,并逐步的变更直到终态。面向终态带来了卓越的运维效率提升,但同时也为系统工程架构提出了更高的要求。

我们知道在 K8s 内部是一个模块化、分布式的系统,通往终态的运维决策分散在内部的多个模块中,这些模块都有可能对容器发起一些运维动作,比如控制器、运维 Operator、重调度器甚至是 kubelet。在高度自动化的系统中,一旦出现预期外的异常,其杀伤力可能会对其上运行的业务造成灾难性的后果,加之 K8s 中决策分散在众多的模块中,所带来的问题是系统风险的控制变得更加困难,对这个系统设计的质量有很高的要求。

为了控制整个系统的风险,如上图所示,我们在 K8s 系统的关键位置对关键行为行为进行了埋点,针对性的制定了限流及熔断的策略,使得整个系统即使在出现极端错误的场景下,也能够最大化的保护其上运行的业务。

自愈能力升级

9.png

在阿里巴巴传统的运维体系下,容器平台仅生产资源,应用的启动以及服务发现是在容器启动后由运维平台系统来完成的,这种分层的方法给了运维系统最大的自由度,也在容器化后促进了阿里巴巴的容器生态繁荣。

但是这种方式有一个严重的问题,因为容器调度平台无法自主地去触发容器的扩缩容,而需要和一个个运维平台来做复杂的联动,上层运维系统也因为需要感知到底层基础设施的信息,从而导致进行了很多重复建设的工作。

在工程实践上,这些复杂性使得即使经过了细心的设计与大量的投入其工作效率也不高,严重妨碍宿主机发生故障、重启,容器中进程发生崩溃、卡住等异常时的自愈修复效率,同时也让应用弹性伸缩的实现变得非常的复杂和低效。

10.png

我们解决这一问题的思路是通过 K8s 中提供了容器命令以及生命周期钩子,将启动应用以及检查应用启动状态这一正个流程内置到 pod 中,包括与监控、VIP、服务中心、配置中心等基础设施的交互,通过 Pod 实现容器与应用实例的生命周期统一。

容器平台不再是仅生产资源,而是交付可以直接为业务使用的服务,从而使得可以在 K8s 系统内部完成故障自愈闭环,极大地简化了应用故障自愈以及自动弹性扩缩容能力的建设。提高系统自愈的效率,实际上也是帮助业务获得更好的运行时稳定性和应用运维效率。

11.png

在完成了容器与应用实例的生命周期统一之后,我们正在打造一个统一控制器编程框架:Operator Platform。

Operator Platform 由中心的控制组件与一个 sidecar 框架容器以及客户端代码组成,通过对通用的控制器能力的抽象,包括:事件通知、灰度管理、版本控制、缓存、命令管道等能力的封装集成,支持多语言编写operator,使得开发者无需要理解 K8s 的众多的接口细节及错误处理,从而降低了基于 operator 的自动化运维能力的开发难度,使得越来越多的运维能力通过operator 的方式沉淀到 K8s 生态体系中来,让更多的有状态应用能够自动化地部署,提高整个运维体系的运转效率。

通过这种方式,构建了整个机器故障自愈的体系,高效的串联起包括机器锁定、应用驱逐、机器线下、异常修复等流程,确保了集群宿主机的在线率以及业务的可用性。未来,我们期望通过将 operator 编写标准化的方式去推动多个运维平台的基础运维能力能够被最大化的复用,减少重复建设的成本。

不可变基础设施

12.png

第三个重要的能力升级是对不可变基础设施的升级。

我知道 Docker 提供了一种统一的应用交付的形式,通过把应用的二进制、配置、依赖文件在构建过程中打到一个镜像中,从而确保了应用被一次构建出来之后在多个环境中交付的确定性,避免了环境不一致带来的诸多问题。

而 K8s 更进一步,通过将不同用途的 Docker 容器组装在一起成为一个 pod,通常情况下在升级 pod 时需要整个的销毁重建,从而确保应用镜像、卷、资源规格的一致性。在落地 K8s 的过程中,坚持了不可变基础设施的设计理念,通过 K8s pod 将原本运行在一个富容器中的应用与运维基础组件分离到不同的容器中,并通过升级容器镜像的方式完成应用的升级。

这里有一个概念需要澄清,并不是使用 K8s 就等于践行了不可变基础设施的理念,而是必须要确保应用运维通过镜像升级而不是动态发布文件的方式完成,而事实上因为一些历史原因,这一用法在行业中普遍存在。

13.png

当然,与 K8s 有所不同的是,我们并未强制坚持 pod 的不可变而是取了一个折中的方式,即坚持容器不可变。

原因是我们将应用容器与运维基础设施容器分离之后,运维容器作为应用容器的 sidecar 容器,其拥有着不同的版本迭代策略。应用容器由应用运维人员负责发布,其策略因应用的不同而不同,比如电商应用使用 StatefulSet 而本地生活使用 Deployment 来管理应用,而基础设施容器则由基础设施运维负责,其发布策略与应用本身也存在一些差别。

为了解决这个问题,我们开发了一个叫做 SidecarSet 的基础设施容器管理模型,它使用同一个集合统一管理多个应用的运维容器,将基础设施的变更与应用容器的变更进行分离,从而支持基础设施的快速演进。将基础设施容器定义从应用 pod 中抽离出来后,应用管理员不再关心基础容器的启动参数,而是交由基础设施运维人员通过配置 SidecarSet 自动为应用注入运维容器,简化了应用运维的复杂性。

可以看到,这种关注点分离的设计,同时简化了应用运维与基础设施运维的负担。

总结与展望

阿里云通过落地 K8s 推动阿里巴巴运维体系走向云原生,在应用容器发布管理效率、服务稳定性以及企业 IT 成本方面取得了很大的突破。

我们一直在思考,通过什么样的方式能够将阿里巴巴的应用管理经验输出到更多的场景,解决更多客户面临的应用管理难题,在企业全面云化这样的趋势下,如何解决企业在公有云、私有云、混合云以及多云场景的应用管理复杂性。

14.png

正是在这样的背景下,阿里云与微软在 2019 年 11 月联合推出了一款用于构建和交付云原生应用的标准规范,即 Open Application Model(简称 OAM)

OAM 提出了一种通用的模型,让各平台可以在统一的高层抽象上透出应用部署和运维能力,解决跨平台的应用交付问题。同时,OAM 以标准化的方式沟通和连接应用开发者、运维人员、应用基础设施,让云原生应用交付和管理流程更加连贯、一致。

15.png

通过应用交付标准化的方法,我们期望未来在云上部署一个应用,就像手机在应用商店中安装一个淘宝一样便捷与高效。

最后,本文提到的阿里巴巴在云原生改造上完成的相关能力升级,我们都已经或者即将开源到OpenKruise 项目中,欢迎大家关注与交流!

参与方式:

  • 钉钉扫码进入 OAM 项目中文讨论群

16.png
(钉钉扫码加入交流群)

云原生实践峰会即将开幕

17.png

阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的技术圈。”

Saas 应用12个架构规范

JFrogchina阅读(183)评论(0)

一、引言

如今,软件通常会作为一种服务来交付,它们被称为网络应用程序,或软件即服务(SaaS)。12-Factor 为构建如下的 SaaS 应用提供了方法论:

  • 使用标准化流程自动配置,从而使新的开发者花费最少的学习成本加入这个项目。
  • 和操作系统之间尽可能的划清界限,在各个系统中提供最大的可移植性
  • 适合部署在现代的云计算平台,从而在服务器和系统管理方面节省资源。
  • 将开发环境和生产环境的差异降至最低,并使用持续交付实施敏捷开发。
  • 可以在工具、架构和开发流程不发生明显变化的前提下实现扩展

这套理论适用于任意语言和后端服务(数据库、消息队列、缓存等)开发的应用程序。

二、特别声明

本文转自国外一篇文章,由Adam Wiggins所著,原文地址:https://12factor.net/

在此文基础上增加个人的理解以及部分图解。

 

三、12个架构规范

1. 统一源代码管理系统

一份基准代码(Codebase),多份部署(deploy)

在类似 SVN 这样的集中式版本控制系统中,基准代码 就是指控制系统中的这一份代码库;而在 Git 那样的分布式版本控制系统中,基准代码 则是指最上游的那份代码库。

基准代码和应用之间总是保持一一对应的关系:

  • 一旦有多个基准代码,就不能称为一个应用,而是一个分布式系统。分布式系统中的每一个组件都是一个应用,每一个应用可以分别使用 12-Factor 进行开发。
  • 多个应用共享一份基准代码是有悖于 12-Factor 原则的。解决方案是将共享的代码拆分为独立的类库,然后使用 依赖管理 策略去加载它们。

 

2. 依赖管理

显式声明依赖

 

大多数编程语言都会提供一个打包系统,用来为各个类库提供打包服务,就像 Perl 的 CPAN 或是 Ruby 的 Rubygems 。通过打包系统安装的类库可以是系统级的(称之为 “site packages”),或仅供某个应用程序使用,部署在相应的目录中(称之为 “vendoring” 或 “bunding”)

 

12-Factor规则下的应用程序不会隐式依赖系统级的类库。 它一定通过 依赖清单 ,确切地声明所有依赖项。此外,在运行过程中通过 依赖隔离 工具来确保程序不会调用系统中存在但清单中未声明的依赖项。这一做法会统一应用到生产和开发环境。

 

显式声明依赖的优点之一是为新进开发者简化了环境配置流程。新的开发者可以检出应用程序的基准代码,安装编程语言环境和它对应的依赖管理工具,只需通过一个 构建命令 来安装所有的依赖项,即可开始工作,如Maven,Pip,Npm等

 

12-Factor 应用同样不会隐式依赖某些系统工具,如 ImageMagick 或是curl。即使这些工具存在于几乎所有系统,但终究无法保证所有未来的系统都能支持应用顺利运行,或是能够和应用兼容。如果应用必须使用到某些系统工具,那么这些工具应该被包含在应用之中。

 

3. 配置管理

在环境中存储配置

 

通常,应用的 配置 在不同 部署 (预发布、生产环境、开发环境等等)间会有很大差异。这其中包括:

  • 数据库,Memcached,以及其他后端服务的配置
  • 第三方服务的证书,凭证,如 Amazon S3、Twitter 等
  • 每份部署特有的配置,如域名等

 

应用程序不允许将配置存储为代码中的常量,这需要严格地将配置与代码分离。配置在部署之间差异很大,代码则没有。另外,“config”的这个定义不包括内部应用程序配置,这种类型的配置在部署之间不会有所不同,因此最好在代码中保存

 

提示:对应用程序是否在代码中正确分配了所有配置的试金石是,代码库是否可以随时变为开源,而不用担心泄漏任何敏感凭据。

 

 

应用程序应将配置存储在环境变量中(通常缩写为env varsenv)。在不更改任何代码的情况下,可以在部署之间轻松更改Env变量; 与配置文件不同,它们几乎没有机会被意外地检入代码仓库; 与自定义配置文件或其他配置机制(如Java系统属性)不同,它们是与语言和操作系统无关的标准。

 

 

 

 

4. 后端服务

把后端服务(backing services)当作附加资源

 

后端服务是指程序运行所需要的通过网络调用的各种服务,如数据库(MySQLCouchDB),消息/队列系统(RabbitMQBeanstalkd),SMTP 邮件发送服务(Postfix),以及缓存系统(Memcached)。

 

类似数据库的后端服务,通常由部署应用程序的系统管理员一起管理。除了本地服务之外,应用程序有可能使用了第三方发布和管理的服务。示例包括 SMTP(例如 Postmark),数据收集服务(例如 New Relic 或 Loggly),数据存储服务(如 Amazon S3),以及使用 API 访问的服务(例如 TwitterGoogle MapsLast.fm)。

 

12-Factor 应用不会区别对待本地或第三方服务。 对应用程序而言,两种都是附加资源,通过一个 url 或是其他存储在 配置 中的服务定位/服务证书来获取数据。12-Factor 应用的任意 部署 ,都应该可以在不进行任何代码改动的情况下,将本地 MySQL 数据库换成第三方服务(例如 Amazon RDS)。类似的,本地 SMTP 服务应该也可以和第三方 SMTP 服务(例如 Postmark )互换。上述 2 个例子中,仅需修改配置中的资源地址。

12-Factor 应用将这些都视作 附加资源 ,这些资源和它们附属的部署保持松耦合。

 

 

5. 构建,发布,运行

严格分离构建和运行

 

基准代码 转化为一份部署(非开发环境)需要以下三个阶段:

  • 构建阶段 是指将代码仓库转化为可执行包的过程。构建时会使用指定版本的代码,获取和打包 依赖项,编译成二进制文件和资源文件。
  • 发布阶段 会将构建的结果和当前部署所需 配置 相结合,并能够立刻在运行环境中投入使用。
  • 运行阶段 (或者说“运行时”)是指针对选定的发布版本,在执行环境中启动一系列应用程序 进程

12-factor 应用严格区分构建,发布,运行这三个步骤。 举例来说,直接修改处于运行状态的代码是非常不可取的做法,因为这些修改很难再同步回构建步骤。

每一个发布版本必须对应一个唯一的发布 ID,例如可以使用发布时的时间戳(2011-04-06-20:32:17),亦或是一个增长的数字(v100)。发布的版本就像一本只能追加的账本,一旦发布就不可修改,任何的变动都应该产生一个新的发布版本。这样也便于回退到任意历史版本,而不需要冒风险重新构建。

 

新的代码在部署之前,需要开发人员触发构建操作。但是,运行阶段不一定需要人为触发,而是可以自动进行。如服务器重启,或是进程管理器重启了一个崩溃的进程。因此,运行阶段应该保持尽可能少的模块,这样假设半夜发生系统故障而开发人员又捉襟见肘也不会引起太大问题。构建阶段是可以相对复杂一些的,因为错误信息能够立刻展示在开发人员面前,从而得到妥善处理。

 

 

6. 进程

以一个或多个无状态进程运行应用

 

运行环境中,应用程序通常是以一个和多个 进程 运行的。

 

12-Factor 应用的进程必须无状态且 无共享  任何需要持久化的数据都要存储在 后端服务 内,比如数据库。

内存区域或磁盘空间可以作为进程在做某种事务型操作时的缓存,例如下载一个很大的文件,对其操作并将结果写入数据库的过程。12-Factor应用根本不用考虑这些缓存的内容是不是可以保留给之后的请求来使用,这是因为应用启动了多种类型的进程,将来的请求多半会由其他进程来服务。即使在只有一个进程的情形下,先前保存的数据(内存或文件系统中)也会因为重启(如代码部署、配置更改、或运行环境将进程调度至另一个物理区域执行)而丢失。

 

一些系统依赖于 “粘性 session”, 这是指将用户 session 中的数据缓存至某进程的内存中,并将同一用户的后续请求路由到同一个进程。粘性 session 是 12-Factor 极力反对的。Session 中的数据应该保存在诸如 Memcached 或 Redis 这样的带有过期时间的缓存中。

 

7. 端口绑定

通过端口绑定(Port binding)来提供服务

 

应用有时会运行于服务器的容器之中。例如 PHP 经常作为 Apache HTTPD 的一个模块来运行,正如 Java 运行于 Tomcat 。

12-Factor 应用完全自我加载 而不依赖于任何网络服务器就可以创建一个面向网络的服务。互联网应用 通过端口绑定来提供服务 ,并监听发送至该端口的请求。

还要指出的是,端口绑定这种方式也意味着一个应用可以成为另外一个应用的 后端服务 ,调用方将服务方提供的相应 URL 当作资源存入 配置 以备将来调用。

 

 

8. 并发

通过进程模型进行扩展

 

在 12-factor 应用中,进程是一等公民。12-Factor 应用的进程主要借鉴于 unix 守护进程模型 。开发人员可以运用这个模型去设计应用架构,将不同的工作分配给不同的 进程类型 。例如,HTTP 请求可以交给 web 进程来处理,而常驻的后台工作则交由 worker 进程负责。

 

上述进程模型会在系统急需扩展时大放异彩。 12-Factor 应用的进程所具备的无共享,水平分区的特性 意味着添加并发会变得简单而稳妥。这些进程的类型以及每个类型中进程的数量就被称作 进程构成 。

 

 

9. 易处理

快速启动和优雅终止可最大化健壮性

 

12-Factor 应用的 进程 是 易处理(disposable的,意思是说它们可以瞬间开启或停止。 这有利于快速、弹性的伸缩应用,迅速部署变化的 代码 或 配置 ,稳健的部署应用。

 

进程应当追求 最小启动时间 。 理想状态下,进程从敲下命令到真正启动并等待请求的时间应该只需很短的时间。更少的启动时间提供了更敏捷的 发布 以及扩展过程,此外还增加了健壮性,因为进程管理器可以在授权情形下容易的将进程搬到新的物理机器上。

 

另外进程 一旦接收 终止信号(SIGTERM 就会优雅的终止 。就网络进程而言,优雅终止是指停止监听服务的端口,即拒绝所有新的请求,并继续执行当前已接收的请求,然后退出。此类型的进程所隐含的要求是HTTP请求大多都很短(不会超过几秒钟),而在长时间轮询中,客户端在丢失连接后应该马上尝试重连;对于 worker 进程来说,优雅终止是指将当前任务退回队列。

 

 

10. 开发环境与线上环境一致

尽可能的保持开发,预发布,线上环境相同

 

开发环境(即开发人员的本地 部署)和线上环境(外部用户访问的真实部署)之间存在着很多差异。这些差异表现在以下三个方面:

  • 时间差异: 开发人员正在编写的代码可能需要几天,几周,甚至几个月才会上线。
  • 人员差异: 开发人员编写代码,运维人员部署代码。
  • 工具差异: 开发人员或许使用 Nginx,SQLite,OS X,而线上环境使用 Apache,MySQL 以及 Linux。

12-Factor 应用想要做到 持续部署 就必须缩小本地与线上差异。 再回头看上面所描述的三个差异:

  • 缩小时间差异:开发人员可以几小时,甚至几分钟就部署代码。
  • 缩小人员差异:开发人员不只要编写代码,更应该密切参与部署过程以及代码在线上的表现。
  • 缩小工具差异:尽量保证开发环境以及线上环境的一致性。

将上述总结变为一个表格如下:

12-Factor 应用的开发人员应该反对在不同环境间使用不同的后端服务 ,即使适配器已经可以几乎消除使用上的差异。这是因为,不同的后端服务意味着会突然出现的不兼容,从而导致测试、预发布都正常的代码在线上出现问题。这些错误会给持续部署带来阻力。从应用程序的生命周期来看,消除这种阻力需要花费很大的代价。

 

 

11. 日志

把日志当作事件流

 

日志 使得应用程序运行的动作变得透明。在基于服务器的环境中,日志通常被写在硬盘的一个文件里,但这只是一种输出格式。

 

12-factor应用本身从不考虑存储自己的输出流。 不应该试图去写或者管理日志文件。相反,每一个运行的进程都会直接的标准输出(stdout)事件流。开发环境中,开发人员可以通过这些数据流,实时在终端看到应用的活动。

在预发布或线上部署中,每个进程的输出流由运行环境截获,并将其他输出流整理在一起,然后一并发送给一个或多个最终的处理程序,用于查看或是长期存档。这些存档路径对于应用来说不可见也不可配置,而是完全交给程序的运行环境管理。类似 Logplex 和 Fluentd 的开源工具可以达到这个目的。

 

这些事件流可以输出至文件,或者在终端实时观察。最重要的,输出流可以发送到 Splunk 这样的日志索引及分析系统,或 Hadoop/Hive 这样的通用数据存储系统。这些系统为查看应用的历史活动提供了强大而灵活的功能,包括:

  • 找出过去一段时间特殊的事件。
  • 图形化一个大规模的趋势,比如每分钟的请求量。
  • 根据用户定义的条件实时触发警报,比如每分钟的报错超过某个警戒线。

 

 

12. 管理进程

后台管理任务当作一次性进程运行

 

进程构成(process formation)是指用来处理应用的常规业务(比如处理 web 请求)的一组进程。与此不同,开发人员经常希望执行一些管理或维护应用的一次性任务,例如:

  • 运行数据移植(Django 中的 manage.py migrate, Rails 中的 rake db:migrate)。
  • 运行一个控制台(也被称为 REPL shell),来执行一些代码或是针对线上数据库做一些检查。大多数语言都通过解释器提供了一个 REPL 工具(python 或 perl) ,或是其他命令(Ruby 使用 irb, Rails 使用 rails console)。
  • 运行一些提交到代码仓库的一次性脚本。

一次性管理进程应该和正常的 常驻进程 使用同样的环境。这些管理进程和任何其他的进程一样使用相同的 代码 和 配置 ,基于某个 发布版本 运行。后台管理代码应该随其他    应用程序代码一起发布,从而避免同步问题。

如何熟悉一个系统?(内含知识大图)

alicloudnative阅读(248)评论(0)

作者 | 唐志龙(鲲龙)  阿里巴巴高级开发工程师

导读:本文总结了熟悉系统主要分三部分:业务学习、技术学习、实战。每部分会梳理一些在学习过程中需要解答的问题,这些问题随着经验的积累需要逐步补充完善。

前言

开发人员经常会面临下面一些场景:

  • 新人入职,需要学习已有系统,作为 landing 的一部分,如何学习?
  • 被拉过去参与一个陌生系统的迭代开发或者系统维护(bugfix),如何快速上手?
  • 同事离职或转岗,需要把系统交接给你,怎么去接? 内心 os:这是一口锅吗?

1.png

这样的场景多了,就需要去梳理常见问题以及应对方法,方便后续遇到类似场景可以快速应对。本文总结熟悉系统主要分三部分:业务学习、技术学习、实战。每部分会梳理一些在学习过程中需要解答的问题,这些问题随着经验的积累需要逐步补充完善。

业务学习

业务学习就是从业务角度去学习系统,我们需要了解系统的客户是谁、使用人是谁、带来了什么价值,系统提供了哪些功能等。不清楚业务,就等于不知道系统在干什么。技术是为业务落地而服务,清楚了业务才知道怎样用技术更好地服务业务,所以业务学习是熟悉一个系统的首要任务。这块主要的学习方式有跟产品、运营、开发沟通,学习产品设计文档文档、PRD、自己使用系统,还有一些常见图,如产品功能架构图、业务流程图、功能树,用例图等。

常见问题:

  • 系统所在行业的情况是怎样?
  • 系统的目标用户是谁?比如是给公司高层做决策用?给运营或客服用?还是互联网用户用?
  • 平均有多少人在使用?高峰期有多少人在用?
  • 系统有什么业务价值?有哪些指标可以衡量系统业务价值?
  • 系统有哪些功能模块?
  • 系统有哪些领域概念?梳理下系统的领域模型;
  • 系统的关键业务流程有哪些?关键业务流程是怎样?
  • 系统的非功能性需求有哪些?如性能、质量、扩展性、安全性等;
  • 系统未来的发展规划是怎样?

技术学习

技术学习主要学习系统的架构、如何实现、系统的运维等。描述一个系统的架构有五视图方法论。

五视图分别是:

  • 逻辑架构
  • 开发架构
  • 运行架构
  • 物理架构
  • 数据架构

逻辑架构

逻辑架构着重考虑功能需求,系统应当向用户提供什么样的服务,关注点主要是行为或职责的划分。常用表达图形,静态图有包图、类图、对象图;动态图有序列图、协作图、状态图、活动图。逻辑架构的核心设计任务是模块划分、接口定义、领域模型细化。

常见问题:

  • 有哪些子系统或模块?系统之间是什么样的关系?
  • 对外上下游接口有哪些?对接人是谁?
  • 关键业务流程怎么实现的?用类图、序列图等方式表达出来。

开发架构

开发架构关主要关注系统源代码、第三方 SDK、使用的框架、中间件、工具包。

常见问题:

  • 代码在哪?
  • 包怎么划分的?怎么分层?如 mvc、controller-service-dao;
  • 用了什么框架,如 ssh、dubbo;
  • 用了哪些工具包?如 apache commons、guava;
  • 用了哪些中间件?如 metaq、tair、schedulerX、Diamond;
  • 依赖哪些平台?如权限平台、流程引擎等。

运行架构

运行架构的着重考虑运行期质量属性,关注点是系统的并发、同步、通信等问题,这势必涉及到进程、线程、对象等运行时概念,以及相关的并发、同步、通信等。

常见问题:

  • 系统能支撑多少 qps?峰值 qps 多少?
  • 与上下游系统怎么交互的?rpc?http?同步还是异步?

物理架构

物理架构的设计着重考虑安装和部署需求,关注点是目标程序及其依赖的运行库和系统软件最终如何安装或部署到物理机器,以及如何部署机器和网络来配合软件系统的可靠性、可伸缩性、持续可用性、性能和安全性等要求。

常见问题:

  • 系统如何发布部署?有哪些部署环境?
  • 系统有多少台机器?
  • 系统部署怎么部署的?关注接入层,部署方式,如集群部署、分布式部署等
  • 有没有容器化?
  • 有没有多机房部署?

数据架构

数据架构的设计着重考虑数据需求,关注点是持久化数据的存储方案,不仅包括实体及实体关系数据存储格式,还可能包括数据传递、数据复制、数据同步等策略。

常见问题:

  • 数据存储在哪?用了什么数据库,如 oracle、mysql;
  • 梳理 E-R 图;
  • 数据量有多少?是否有分库分表?
  • 用了哪些 nosql 库?
  • 有哪些数据同步任务?
  • 大数据框架的使用情况如何?

系统运维

系统运维重点关注什么时候会出问题,出了问题怎么解决。

常见问题:

  • 什么时间容易出问题?比如电商 双11,对系统的压力很大,这时候很容易出问题;
  • 对关键功能是否有监控?需要看系统有配置了哪些报警项,监控了哪些方面;
  • 出了问题怎么解决?日志在哪?是否有全链路跟踪?是否有一些紧急操作,比如开关配置、降级、限流配置;
  • 系统有哪些坑?找开发同学回顾历史问题,以免踩坑。通过同事总结的 case,或者与负责的产品、运营、技术与了解。系统总会有一些坑,需要把这些坑填上。历史代码经过多次迭代总会导致复杂度高(分支、嵌套、循环很多),存在设计漏洞,性能隐患等,很难维护,这些就需要我们去重构了。记住有一句话:填的坑越大,能力越大;
  • 运营、客服反馈的常见问题有哪些?

实践

熟悉了系统的业务和技术后,就要实战了,通过实战进一步加深对系统的熟悉程度。实践可以通过做需求、修 bug、重构等方式,亲自动手编码、调试、测试、上线。

总结

已有系统通常经历了从 0 到 N 的建设过程,熟悉系统其实是一个逆向推导过程,也是一个学习架构、阅读源码的过程。在学习的过程中最好能带上思考,比如为什么要这么设计?为什么要用这个中间件?是否有更好的编码方式?哪些地方可以优化等,以此达到一个深入熟悉的过程。

附:总结图

2(1).jpg

云原生实践峰会即将开幕

3.png

阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的技术圈。”

2020,最关注企业级云原生实践落地的大会来了!

alicloudnative阅读(309)评论(0)

过去的 2019 年,云原生关注度依然居高不下,更多开发者热衷使用云原生技术,更多企业开始探索云原生架构转型落地。尽管云原生技术已经被广泛接受,其在企业技术栈的落地仍然面临挑战。

在与各行业头部企业深度合作和交流中,我们发现国内云原生实践已累积了诸多宝贵经验。云原生技术带来的资源成本降低、研发运维效率提升等巨大价值,已经驱动企业主动迎接这些挑战。可以预见通过云原生上云最大化使用云的能力,高效的社会分工,使企业聚焦于自身业务发展,将成为企业的共识。

2020,站在一个全新十年的节点上,我们期望在以开放创新为支撑的云原生领域发声,邀请来自国内外 IT 公司的一线云原生技术专家们,碰撞思想、共话实践。全方位洞悉云原生技术趋势,分享企业云原生落地实践痛点及经验,共同探索中国企业的云原生化转型的新路径。

2020 年 2 月 29 日,阿里云主办首届云原生实践峰会即将亮相北京!

拉至底部获取赠票福利

1.png

大会官网链接https://developer.aliyun.com/topic/cloudnative2020#/

2.png

主论坛

云原生技术正在快速开拓新的技术边疆,支持新的应用范式,承载新的计算价值。在大会主论坛将分享云原生技术趋势下,我们的洞察和判断;并邀请多位行业领袖分享企业级云原生转型经验。

议题(部分)

  • 云原生和可见的云未来
  • 从 IDC 到全面上云,申通云原生演进之路
  • 阿里巴巴云原生开源探索
  • 云原生在金融场景的实践
  • Apache Flink on K8s 的云原生发展
  • 企业级云原生数据库
  • 云原生生态合作伙伴计划重磅发布

主题演讲嘉宾(部分)

3.png

丁宇(花名:叔同)2010 年加入阿里,云原生应用平台负责人;10 次参与 双11 作战,推动和参与了 双11 几代技术架构的演进升级。

4.png

李响,阿里云智能资深技术专家,负责阿里巴巴大规模集群调度与管理系统,帮助阿里巴巴通过云原生技术初步完成了基础架构的转型,实现了资源利用率与软件的开发和部署效率的大幅提升,并同步支撑了云产品的技术演进。CNCF 技术监督委员会代表,etcd 作者。

5.png

杨海悌(花名:齐风) 蚂蚁金服资深技术专家,具备多年的中间件、PaaS、网络接入、云原生工作经验,目前负责蚂蚁金服资源调度、网络服务、SOFAMOSN、监控等领域,参与并主导蚂蚁 LDC 弹性服务、容器化、Mesh 化等架构演进和云原生技术在蚂蚁规模化应用。

6.png

叶正盛(花名:斗佛)阿里云智能资深技术专家。20 年 IT 领域工作经验。曾带领团队构建阿里巴巴 & 蚂蚁金服集团数据库业务研发体系,创立了全球领先的云计算数据传输、数据管理、数据库云备份、数据库自动驾驶服务的行业产品标杆。目前负责阿里云数据库产品线整体规划工作,包括 PolarDB、AnalyticDB、RDS、NoSQL 等数据库产品,致力于打造全球领先的数据库云计算服务。

7.png

宁晓民(花名:灭道)阿里云云原生合作伙伴负责人。具有 10 多年企业架构(EA)、分布式架构、云原生架构的深度实践经验。2013 年加入阿里巴巴集团,曾负责淘宝共享业务平台技术架构设计,见证与实践了阿里云云原生技术演进及商业化进程,负责多个阿里云战略客户上云架构升级。目前负责云原生合作伙伴业务线。

8.png

任春德(花名:瓦力)阿里云智能高级技术专家。10 年的 Hadoop 相关的大数据计算平台研发经验,目前在计算平台事业部负责 Flink on YARN/K8s 的资源调度管理的研发,致力于为大数据计算提供大规模、高效、稳定的运行平台。

分论坛

分论坛 1: 微服务架构与 Service Mesh 专场

微服务是数字化转型的关键技术架构,而 Service Mesh 已成为云原生堆栈的重要组成部分,本论坛将通过大量企业云原生技术应用案例,深入探讨微服务架构与 Service Mesh 的落地经验及未来发展趋势。

议题(部分)

  • 云原生时代的微服务:架构演进与趋势
  • 双 11 洗礼下的最佳实践,云原生微服务治理与监管控一体解决方案
  • 使用 ASM 重新定义云原生应用通信基础设施
  • 深耕微服务,拥抱云原生,基于 EDAS 的微服务最佳实践及案例分享
  • Serverless 应用引擎如何落地企业级生产应用
  • 云原生时代的“必备品”:可观测 Prometheus + 链路跟踪最佳实践

演讲嘉宾(部分)

9.png

分论坛 2: 容器云专场

微服务是数字化转型的关键技术架构,而 Service Mesh 已成为云原生堆栈的重要组成部分,本论坛将通过大量企业云原生技术应用案例,深入探讨微服务架构与 Service Mesh 的落地经验及未来发展趋势。

议题(部分)

  • 创见未来 – 云原生构建数字经济时代新基石
  • 进击的小玩 – 云原生应用在玩吧的落地与实践
  • 云原生的容器安全
  • Kubernetes 集群智能诊断实践下的 AIOps 演进
  • 专有云的云原生最佳实践 —— 阿里云敏捷 PaaS 容器服务

演讲嘉宾(部分)

10.png

开发者 Workshop

本次大会将设置 6 场开发者 Workshop,聚焦 Kubernetes、微服务、消息、Serverless、函数计算以及 Service Mesh。帮助开发者快速上手云原生技术,共同实操、探讨云原生在企业级落地实践中的难点及解决方法。

议题

  • Kubernetets Workshop
  • 微服务 Workshop
  • 消息 Workshop
  • Serverless Workshop
  • 函数计算 Workshop
  • Service Mesh Workshop

演讲嘉宾(部分)

11.png

报名参与

  • 早鸟票

RMB 98 元(2 月 15 日恢复原价 196 元) 含大会限量礼包,Workshop 席位有限,先到先得!

  • VIP 票

RMB 688元 含晚宴及大会限量礼包,Workshop 席位有限,先到先得!

12.png

扫描二维码,购买 5 折早鸟票

阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”

生产环境容器落地最佳实践 – JFrog 内部K8s落地旅程

JFrogchina阅读(308)评论(0)

引言

Kubernetes已经成为市场上事实上领先的编配工具,不仅对技术公司如此,对所有公司都是如此,因为它允许您快速且可预测地部署应用程序、动态地伸缩应用程序、无缝地推出新特性,同时有效地利用硬件资源。

 

本期我们将回顾采用Kubernetes作为容器编排工具的公司所面临的复杂性和挑战。我们希望我们提供的经验教训、最佳实践和技巧将帮助您在前往K8s旅途中起步并继续前进。

 

 

本期将介绍关于在Kubernetes生产环境的最佳实践,包括::

  • 为上K8s容器云准备好应用程序
  • 在Kubernetes中获得灵活性和通用性
  • 为所有应用程序使用单一、可信和可靠的源
  • 自动部署到Kubernetes
  • 在Kubernetes中构建可靠且可伸缩的环境
  • 可见性和安全性:在Kubernetes中保护您的应用程序
  • 在Kubernetes中记录、监视和调试您的微服务
  • 将应用程序部署到Kubernetes的生产环境中

 

背景

JFrog与Kubernetes的旅程始于我们寻找一个合适的容器编排解决方案,以便为内部目的创建一个功能齐全的环境。我们的开发人员需要测试我们非常复杂的环境,包括JFrog Artifactory和其他产品。与此同时,我们需要为程序和产品经理提供一个完整的功能环境,以便向我们的客户演示平台。

 

为了满足我们的需求,每个产品都需要一个独立的CI/CD开发环境,以便在测试各个分支之间的交互时独立地测试各个分支。

 

随着我们对Kubernetes越来越有信心,我们认识到将JFrog产品分发到Kubernetes的价值,能够跨不同的阶段、开发和生产环境运行应用程序。Kubernetes还允许我们更好地利用我们的资源,因为我们不再需要为单独部署每个产品而启动单个VM。下面我们将回顾落地过程中的主要挑战(6大挑战),同时分享我们的最佳实践、技巧,和在将您的容器应用程序一路带到生产环境中所获得的经验教训。

 

                                                                                           图1 – 应用分发到K8 的6大挑战

 

Kubernetes 介绍

Kubernetes允许您创建容器化的应用程序,并将它们并行的部署,而不必担心各种服务和组件之间的兼容性。将应用程序容器化运行在Kubernetes中的好处是,您可以在一个充满活力的社区中开发产品,从而更容易创建可伸缩的微服务应用程序。这样做的缺点是,当整个团队都在处理各种组件时,情况会很快变得非常复杂。此外,容器化的应用程序可以包含多种组件类型,这取决于您使用的操作系统、语言和框架。

 

 

让我们从使用Kubernetes运行应用程序所需的三个基本组件开始:

 

Ø  容器云集群

Kubernetes集群是您的容器化应用程序运行的编排基础设施。您需要决定是否要自己管理它,以及是否要使用云提供商托管它。此组件不在文档的此范围内讨论。

 

Ø  CI/CD 流水线

CI/CD流水线在Kubernetes中运行,并使流程自动化,从源代码和外部依赖包开始,一直到将应用程序部署到Kubernetes集群中。Kubernetes流水线是“应用程序感知的”(面向应用),这意味着它们天生能够动态地提供一个完整的容器化应用程序堆栈(通常由多个service、deployments, replica sets, secrets, configmap等组成)。对应用程序上下文的每次更改,无论是代码、、镜像还是配置更改,都将触发流水线。

Ø  Kubernetes Registry

您的生产集群应该使用一个单独的、受管理的和可信的真实源,该源存储和记录应用程序和其依赖组件。使用Kubernetes Registry,您可以在一个pod中并行运行多个应用程序堆栈,而不产生冲突,也不需要关心每个应用程序的内部依赖关系。这将维护正在运行的集群、向上和向下扩容应用程序、开发新版本和调试应用程序具体问题分隔开来。

 

 

上K8s容器云前准备好你的应用程序

应用程序是服务/解决方案的核心。在Kubernetes中运行应用程序之前,需要计划和准备应用程序。

Ø  问卷清单:为K8S准备应用程序

下表显示了在准备Kubernetes应用程序之前必须询问的与应用程序相关的任务和问题。

 

有关将构建软件的基础知识,请参见软件12因素。https://12factor.net/

 

 

在Kubernetes中获得灵活性和通用性

多语言编程和多种不同的工具和技术提供了多种可能性。您可以选择最适合您的业务需求的技术,但是每种技术可能有不同的接口、REST API和自己的包格式。支持这些工具的唯一方法是做到在制品从创建到部署的生命周期的管理中实现通用。

 

 

Ø  部署Artifactory作为您的Kubernetes Registry

通过使用Artifactory作为“Kubernetes Registry”,您可以获得灵活性和通用性,作为可信的单一来源,它允许您深入了解代码到应用集群的过程,同时关联每个应用程序的每一层(layer)。Artifactory在一个系统中支持超过25种不同的技术栈,具有一个元数据模型、一个升级流和强大的制品依赖关系。

 

 

Artifactory允许您将容器化的微服务部署到Kubernetes集群,因为它作为一个通用存储库管理平台来满足您的所有CI/CD需求,而不管它们在您的组织中何处运行。登记应用程序包后,可以继续传播和执行构建、测试、升级,最后部署到Kubernetes。为了方便地将Artifactory(和其他JFrog产品)部署到Kubernetes,请参考我们在helm hub中的官方JFrog Helm Charts(https://hub.helm.sh/charts/jfrog)。

 

 

自动化部署到Kubernetes

在CI/CD流水线的每个阶段中不需要人工干预的情况下可靠地大规模部署应用程序是的协调的主要原因。但是如何以一种可重复、可靠的方式将代码发布到集群中呢?如何确保只有正确版本的应用程序才能投入生产?

 

 

为此,我们建议将Artifactory部署为存储库管理平台,通过抹平开发和操作之间的差距在CI/CD流水线中扮演重要角色。

 

Ø  将Artifactory部署为Helm Charts仓库

Artifactory原生支持Helm存储库,使您能够完全控制Kubernetes的部署过程。它提供安全的、私有的、本地的Helm存储库,通过细粒度的访问控制在您的组织中共享Helm Charts。使用远程存储库代理和缓存公共Helm Charts资源,并将本地和远程资源聚合到单个虚拟Helm存储库下,从而从单个URL访问所有Helm Charts。

 

 

K8S 专家建议:

当使用Artifactory作为您的Helm 存储库时,我们建议:

  • 分离您的稳定存储库和开发阶段存储库(基于成熟度)。
  • 在Charts中使用SemVer version 2版本。
  • 定期重新计算索引。

 

Ø  在CI/CD流水线中部署应用程序的最佳实践

在CI/CD流水线中部署应用程序时,我们建议:

 

  • 使用相同的Helm Chart进行本地、分段、测试和生产,同时每个环境使用不同的yaml 文件。每个yaml都需要包含特定的环境配置值。例如:values-stg..yaml,,value-prod.yaml。
  • 在VCS源代码管理系统中管理应用自定义值。
  • 默认配置值yaml应该是针对开发人员或本地的,这样开发人员就可以轻松地在本地使用它。
  • 对依赖项使用外部charts。使用社区已经完成的工作!
  • 出于安全目的:将您的迷药从Charts中分离出来,并将它们作为外部Charts引用。

 

升级发布可靠和可伸缩的应用到Kubernetes环境

在Kubernetes集群中并行运行多个应用程序需要建立对工件(Docker镜像)的持续访问,同时支持零停机的高负载服务。

 

 

Ø  在Kubernetes部署Artifactory 高可用

通过在Kubernetes集群中部署Artifactory HA(高可用),在集群中,您将体验到零宕机服务,如果一个pod被回收或崩溃,或者节点意外停机,容器集群将自动调度恢复对应服务的Pod。

 

在Kubernetes部署Artifactory HA的好处是:

 

  • 在不影响性能的情况下,支持更高的负载兵法。
  • 提供水平服务器可伸缩性,允许您在组织增长时轻松地增加容量以满足任何负载需求。
  • 支持在没有系统停机的情况下执行大多数维护任务。
  • 通过使用零停机时间替换应用程序的各个实例,可以在实例上安装更新版本,从而支持滚动升级。

在下例中,使用三个节点部署了一个Artifactory HA集群:一个主节点和两个成员节点。因为负载均衡只在成员节点上执行。这使得主节点可以自由地处理作业和任务,不会被入站流量中断。

Ø  Kubernetes集群的存储和可伸缩性

Artifactory HA允许您在Kubernetes中突破应用程序的限制,因为它支持大量存储替代方案。有关更多信息,请参见配置文件存储库。

https://www.jfrog.com/confluence/display/RTF/Configuring+the+Filestore

 

 

可见性和安全性:在Kubernetes中保护您的应用程序

像Docker和Kubernetes这样的云本地技术提供了更大的攻击面,为恶意数据挖掘、勒索软件和数据盗窃提供了更多潜在的入口点。在Kubernetes集群中运行的服务并不是完全独立的,它们可以访问集群中的其他区域。

 

 

正是出于这个原因,集群的可见性非常重要,尤其是从安全性的角度来看。您需要知道容器中运行的是什么,因为您的应用程序很少包含单个组件,而是包含外部依赖项,如OS包、OSS libs和第三方流程。这就引出了一个不可避免的问题——它们安全吗?它们是否包含安全漏洞?他们是否遵守自由/开源软件许可?

 

Ø  获的k8s中容器的可见性

Artifactory通过提供可审核性来深入了解整个CI/CD流程,因为它捕获了整个CI/CD流程中产生的大量有价值的元数据。您可以跟踪负责生成Docker镜像层的应用层的CI作业。它还可以通过允许比较两个构建来显示构建差异,从而很容易地跟踪Docker镜像基于哪个层生成的,到哪个构建产生的,从而跟踪到提交。

 

k8专家提示:

推荐阅读:每个人都必须遵循9个Kubernetes安全最佳实践。

(https://www.cncf.io/blog/2019/01/14/9-kubernetes-security-best-practices-everyone-must-follow/

 

Ø  扫描和检测容器中的漏洞

JFrog Xray与Artifactory协作,在应用程序生命周期的任何阶段执行二进制软件工件的通用分析。它对容器中的所有层执行递归扫描,并通过扫描和分析工件及其元数据(递归地遍历任何级别的依赖关系)来帮助识别所有层中的漏洞。可以在Xray中设置策略,根据Xray扫描发现的风险级别限制或阻止容器镜像部署到Kubernetes。通过这种方式,可以阻止脆弱或不兼容的应用程序运行,或者限制它们在启动时可以做什么。

 

Ø  在K8S中保护您的开源项目

大多数应用程序严重依赖于包管理器和开源存储库,因此很容易受到来自这些源的恶意或不安全代码的攻击。作为我们支持和贡献开源社区计划的一部分,JFrog开发了KubeXray,这是一个开源项目,它将Xray的安全性扩展到Kubernetes pod中运行(或即将运行)的应用程序。使用Xray通过扫描容器映像生成的元数据,KubeXray可以对已经部署的内容执行策略。

 

KubeXray监控您所有的活动Kubernetes Pod,以帮助您:

 

  • 捕获当前在所有Kubernetes Pod中运行的应用程序中最新的风险或漏洞。
  • 对正在运行的应用程序强制执行当前策略,即使您已经更改了这些策略。
  • 对未被Xray扫描且风险未知的正在运行的应用程序执行策略。

 

Ø  使用Helm 2防止未经授权的访问

Helm 2包含一个名为“Tiller”的服务器端组件。Tiller是一个集群内的服务器,它与Helm客户端交互,并与Kubernetes API服务器交互。

 

 

Tiller 绝对是很酷的,但重要的是要知道有安全问题。这是因为Helm客户端负责管理Charts,而服务器负责管理发布。这带来了很大的风险,因为Tiller使用root权限运行,有人可能会未经授权访问您的服务器。

 

Rimas Mocevicius是JFrog公司的一名员工,也是Helm公司的联合创始人,他提出了一种创新的方法来解决这种情况,即在工作站上或CI/CD管道上运行Helm和Tiller,而不将Tiller安装到Kubernetes集群中。您可以下载并安装无Tiller 的Helm v2插件。

 

Ø  使用用RBAC管理Kubernetes

必须将RBAC(基于角色的访问控制)设置为Kubernetes的管理功能,因为它允许您定义哪个用户可以管理集群及其粒度。除了定义可以列出哪些用户和应用程序之外,还可以获取、创建或删除pods和其他Kubernetes对象。一个好的实践是通过在为应用程序创建的服务帐户中设置“automountServiceAccountToken: false”来禁用对API的访问。

 

如果没有指定服务帐户,它会自动将相同名称空间中的“默认”服务帐户分配给pod。我们建议不要使用名称空间附带的默认值。始终为应用程序创建服务帐户,因为它允许您设置应用程序的限制,包括名称空间或集群范围的操作,并完全禁用对Kubernetes API的访问。

 

 

在K8S中记录日志、监视和调试应用程序

微服务的数量随着复杂性的增加而增加,问题是如何跟踪和监视它们,以及应该监视什么。当涉及到微服务时,您需要收集以下数据微服务:

 

  • 意外事件:例如,在数据库容器中执行的所有权更改
  • 微服务宕机。
  • 不正确的文件选择在生产造成混乱。
  • 不允许使用特定的基本OS版本。

 

Ø  在Kubernetes中应用程序记录日志的最佳实践

应用程序和系统日志对于排除Kubernetes集群活动的故障非常重要。

 

在Kubernetes中应用程序记录日志时,请遵循以下最佳实践::

  • 限制对日志的直接访问。
  • 在使用Kubernetes仪表板(不推荐用于生产环境)时,将仪表板设置为具有访问权限的只读。您可以允许其他成员执行故障排除,但不要完全访问仪表板,因为它可能会对Kubernetes集群造成损害。
  • 确保您的日志是实时可访问的,并且可以在稍后的阶段进行分析。
  • 使用ELK/EFK技术栈等日志收集工具(ElasticSearch、Logstash/Fluentd和Kibana)收集和索引来自系统和应用程序的所有日志。
  • 考虑将日志保存在单独的集群中,以便在稍后阶段使用日志。如果集群宕机,允许您访问日志

 

Ø  持续监控K8S中的微服务

持续监视系统和应用程序健康状况非常重要。

 

对于实时监视Kubernetes集群和其中运行的应用程序,有许多免费的和商业的解决方案。其中一个流行的解决方案是Prometheus ,Grafana的结合,提供实时监控,可以与报警工具相结合。

 

 

将应用程序部署到K8S生产环境中

Ø  在K8S顺利开始旅程的10个技巧

  1. 对于初学者,我们建议从阅读Kubernetes的艰难方式开始!

(https://github.com/kelseyhightower/kubernetes-the-hard-way/blob/master/README.md)

  1. 从小事做起。从示例中学习,从一个小应用程序(nginx)开始,使用现有的演示,并尝试在Docker的Skin Kubernetes中部署应用程序。

 

  1. 在进入K8S之前准备好你的应用程序。

(https://docs.google.com/document/d/1YS_jICIEPZLle7KcpEoLjuKCZ_TkgNzb9LajPU4AhsI/edit#heading=h.81oh8o1kpi75)

 

  1. 为使应用程序在k8s中运行,设置一个最小的目标。
  2. 使用托管的k8S来解放您的工作,例如:AKS、ESK或GKE,它们为您抽象了许多复杂性。
  3. 每个Pod有一个主容器。
  4. 我们建尝试GKE 托管管理Kubernetes。
  5. 确定在Kubernetes集群内或集群外存储数据库的位置。这一点非常重要,因为您需要在集群崩溃时计划集群恢复。考虑以下:

 

-当K8S在prem上运行时:在Kubernetes中将现有的数据库作为无状态应用程序使用。

 

-在云上运行K8S时:,选择一个如PostgreSQL或MySQL 的 operator ,其知道如何在Kubernetes节点宕机时恢复的持久化数据库。

 

  1. 部署到容器云时,请将对应集群分开,运行CI/CD流水线,以及从外部CI/CD流水线部署应用到Kubernetes集群。

 

  1. 与社区合作

 

总结

正如本篇文章所描述的,我们展示了Kubernetes和JFrog Artifactory是如何让您可靠地、可预测地部署应用程序、动态地伸缩应用程序、无缝地推出新特性并有效地利用硬件资源的。

 

本篇文章旨在回顾希望采用Kubernetes作为容器编排工具的公司所面临的复杂性和挑战。我们希望我们分享的经验教训、最佳实践和技巧将帮助您在前往K8s的旅途中起步并继续前进。

你的应用有漏洞吗?使用第三方依赖需谨慎

JFrogchina阅读(268)评论(0)

引言

开源对软件的发展可以说具有深远的意义,它帮助我们共享成果,重复使用其他人开发的软件库,让我们能够专注于我们自己的创新,它推进了技术的快速发展。据不完全统计78% 的企业都在使用开源,但是其中有多少企业关注第三方开园依赖的安全呢?其中仅有13% 将安全作为第一考虑因素。可喜的是仍然有50% 的企业将安全列为第二或第三位考虑因素,越来越多的公司开始重视第三方依赖的安全性。
 

为什么要关住第三方依赖的安全性

想象我们交付的软件 Application 是一张饼,我们自己开发的代码仅占其中很小一部分,见下图:

而开源依赖并不等于是安全的,当然也不等于不安全,自2000年,仅有几家大厂贡献开源,其中有Apache, Linux, IBM, OpenSSL等,而到了2015年之后,任何人都在贡献开源社区,下图是主流软件库的发展 ,数量庞大

而我们在使用这些依赖的时候,一定要意识到:

  1. 开源依赖往往很少有进行安全性测试的
  2. 开源软件开发人源对安全意识普遍不高
  3. 开源软件提供方没有多余的预算进行安全性测试
  4. 黑客的主要攻击目标是开源,因为攻击一个,影响范围很大

 

让我们一起看几组第三方依赖安全的调查数据:

 

 

 

如何管理第三方依赖安全

我们看到第三方依赖是存在非常大的安全隐患的,那我们应该如何做呢?不使用第三方依赖显然是不现实的,我们总结了四个步骤

  1. 了解你都使用了哪些依赖
  2. 删除你不需要的依赖
  3. 查找并修复当前已知的漏洞
  4. 持续监听新发现的漏洞,重复前三个步骤

依赖分析

相对简单,我们使用目前的依赖管理工具可以轻松做到,如maven的dependency tree

删除不需要的依赖

我们发现很对开发人员在维护依赖的时候,即使该依赖已经不适用,但不会删除,这显然会扩大黑客的攻击范围,因此我们需要定期检查删除不需要的依赖

发现并修复漏洞

第三步开始较为复杂,所幸已有很多开源组织提供了免费的漏洞库,如US-CERT,NVD,OSVDB等漏洞广播源,该类组织集中维护发现的已知漏洞,对外提供表述漏洞数据描述以及漏洞广播,为开源社区安全提供数据支持,有了漏洞数据源之后,判断我们的依赖中是否有依赖就简单了,我们仅需要根据我们的依赖包与漏洞数据库进行对比,就可以发现我们发布的应用中是否包含已知的漏洞,甚至有些开源组织会在漏洞库的基础上提供关于漏洞的修复建议,如 Synk.io,JFrog 和 Sync 合作贡献了一个漏洞数据源(JXray),其中包含主流漏洞数据源,包括刚才提到的几个,这样我们就可以对我们包含对漏洞进行漏洞升级。

JXray 漏洞数据源

 

持续监听新的漏洞

我们知道漏洞是持续增长的,近几年每年平均都有900左右的新漏洞,我们需要持续监听这些新产生的漏洞,并与我们内部软件生命周期集成,与DevOps有机结合(DevSecOps),这显然需要一套平台或系统帮助我们系统的管理第三方漏洞安全,下面我们整理了一个漏洞扫描平台技术需求设计

 

 

漏洞扫描平台技术需求设计

能力分类 技术指标 指标需求描述 价值描述
扫描能力 多语言支持 支持主流语言漏洞扫描能力,如war,jar,docker,npm,python,debian,rpm等 统一监管企业各种技术栈的开发,漏洞风险与License合规分析,全面避免漏洞上线到生产环境
深度扫描能力 对二进制包深入逐层进行漏洞扫描,如war包中包含jar包 细粒度,深层次发现可能的漏洞,处理混合式软件发布体系,如Docker镜像,rpm等
分析能力 正向依赖分析 能够分析定位出扫描目标漏洞包所在位置,标出具体哪个依赖出现漏洞 为企业快速定位问题及恢复提供数据依据
反向依赖分析 能够自动化分析出漏洞包的影响范围 快速分析漏洞问题的影响范围,加速线上漏洞的恢复,最大程度降低企业风险

以及评估风险成本

漏洞库 开源漏洞数据集成 集成NVD等漏洞数据中心 针对第三方依赖包,对外部依赖包进行统一监管
商业漏洞数据集成 集成第三方商业漏洞工具能力,如

BlackDuck,

WhiteSource等

丰富漏洞数据库,最大程度降低第三方依赖漏洞风险
本地漏洞数据中心 对第三方依赖或企业自研件添加自定义漏洞,如与Jira等缺陷管理系统的集成 针对企业内部构建的软件监管,避免团队内部漏洞包进一步扩散到其他团队
其他漏洞扫描工具集成 通过API,自定义扩展对接第三方漏洞数据库,如病毒扫描工具集成 进一步丰富漏洞扫描范围,加强漏洞扫描能力,如木马病毒等
告警 自定义告警规则 不同项目管理人员可以监听各自项目或软件制品 同时提供全局监管与分级监管机制,提高项目团队自主安全意识
告警通知,自动化 邮件通知及webhook支持,

发现漏洞可以与自动化任务集成,如高危漏洞触发回滚任务

提高企业漏洞快速相应能力,甚至漏洞自修复能力,降低企业风险
生态,CI/CD 作为CI/CD软件交付质量关卡 可以在软件交付流水线中集成,根据扫描结果,继续或阻止流水线运行 多维度加强软件交付质量,增加流水线质量关卡,保证软件交付质量
RestAPI支持 提供RestFul方式对接漏洞扫描平台 方便企业与内部工具链集成
可视化 漏洞分析报表 漏洞扫描趋势图

漏洞频率top图

可视化漏洞监管能力

提供决策依据

License报表 License分布图

License兼容性分析图

可视化企业在用License

提供决策依据

 

 

 

JFrog Xray 介绍

JFrog Xray 是一个通用的漏洞扫描平台,可以满足我们对第三方漏洞安全管理的所有需求,其主要有以下几个特性

支持多语言漏洞扫描

Java,Docker,Npm,Python,Ruby Gems,Nuget,Rpm,Debian等主流语言漏洞扫描,统一对所有开发技术栈进行安全管理

深入扫描能力

我们会深入分析软件的依赖及其传递依赖,甚至是Docker 镜像中的操作系统层,如Docker 镜像中ubuntu操作系统Layer中某一个debian包存在漏洞。下图是一个Docker 镜像中包含的一个基础maven jar包含漏洞的分析图

影响范围分析

当我们监听到一个新的漏洞后,我们往往很难定为其被哪些项目依赖并试用,极为耗时,且总会有遗漏的情况出现,提高了企业损失的几率。

JFrog Xray 会根据所有收集到的依赖拓扑,进行反向依赖性分析,逐层找到所有包含漏洞包的上层应用。快速分析漏洞的影响范围,评估漏洞上线风险,指导企业进行漏洞修复

开放式集成

可以扩展与其他第三方漏洞数据平台集成,如Whitesource,Blackduck等,通过Xray 平台提供的Rest Api,甚至可以与企业自己漏洞数据源进行集成,形成企业安全的统一管理闭环。

 

DevOps 集成能力(DevSecOps)

我们可以在软件持续交付流水线中集成漏洞扫描能力,将安全机制集成进来,作为企业软件质量关卡中的一部分,当发现漏洞的时候,阻止漏洞包交付到生产环境,如下图

 

 

 

JFrog Xray 架构介绍

JFrog Xray 采用微服务架构设计,其中主要包含以下几个微服务,

  • Server,主服务,UI
  • Indexer,索引层,进行软件包索引
  • Persist,持久层,存储漏洞及扫描结果
  • Analysis,分析层,分析依赖拓扑及反向依赖,发现漏洞并告警

JFrog Xray同时支持高可用集群方式,针对企业级安全管理,提高漏洞扫描的效率及稳定性,并且与 JFrog Artifactory 通用二进制包管理系统原生集成,共同组成制品管理统一管理方案。

 

微服务数据流

 

 

 

总结

本次分享,介绍了在使用第三方依赖时的安全隐患,以及针对该类问题,我们应该如何管理第三方依赖的安全,同时介绍了JFrog Xray 的安全管理特性,帮助企业轻松管理第三方漏洞,降低企业安全风险,避免含有漏洞的包上线到生产环境或客户环境中。

优秀的DevOps工程师必须具备的软技能

JFrogchina阅读(423)评论(0)

年末将至,大批攻城狮与程序猿早已蠢蠢欲动,开始了跳槽涨薪之旅,虽然受社会大形势影响,IT行业虽然无法和前几年的突飞猛进的势头相比,但是对DevOps的热度却只增不减,工程效能团队的普及率正在迅速增长,对DevOps工程师需求量也是呈指数式增加。转型做DevOps工程师、DevOps教练也是逐渐成为IT圈的时尚。那么如何在大量的DevOps工程师中脱颖而出,打破开发与运维之间的隔阂,成为团队内首屈一指的DevOps专家呢?

首先,DevOps没有初级工程师的说法,只要你了解这个领域,就会知道,需求、开发、构建、测试、安全、发布、部署等都是DevOps工程师必备的能力,为此我们查看所有招聘软件,DevOps工程师的招聘JD中,都会要求候选人了解git、jenkins、sonarqube、ansible、zabbix、docker、k8s、saltstack、java、python、shell、nginx、F5、mysql、redis等等等。如果这些工具、语言全部都了解,怕是初级工程师很难做到。所以一旦进入了这个领域,已经成为一位高级工程师,并且有足够的能力能Hold上述开源工具及语言了。这些都是DevOps工程师应该具备的硬实力,如果感觉自己在DevOps这个领域没有进步空间,请打开招聘软件随便看一个岗位需求,自然就会知道自己欠缺的技能。

DevOps工程师只具备上述技能点就能完美匹配职责么,为什么每次我们看到业界大拿每次在运维峰会上侃侃而谈,而自己却只能坐在工位上配置ansible、编写流水线?所以仅仅靠技术是无法成为DevOps专家的,工具及语言只是用来解决问题的手段,为此我们还需要具备下述软技能来突破瓶颈或提升个人能力:

 

  1. 敏捷及项目管理能力

DevOps与敏捷有着千丝万缕的联系,为了实现DevOps的首要目标:增强客户体验、提高创新能力、更快实现价值,那么作为一位DevOps工程师,你是否了解客户的需求、产品的目标、用户的体验、业界的发展方向等?如果不了解,请你去参与业务组的每日站会。可以通过站会了解到,需求是如何拆解的,迭代周期为什么设计为双周,发布频率、功能的使用群体等。有这样的经验积累,才能开发出更贴合业务需求的DevOps平台,业务部门也可以放心的将整个持续交付流程运行在你所开发的平台中。更好的做法是,DevOps工程师可以带领业务团队实践敏捷,结合开发的平台,设计最佳的项目管理及敏捷方案,并把方案落实到实际的项目中,最终通过交付流水线来落地,实现真正的DevOps持续交付。

 

  1. 技术布道能力

作为DevOps工程师,无论是落地了某些强大的工具链、还是引入了哪种前沿的开发理念,如果没有人去使用,依然是毫无价值。

技术布道从性质上说更靠近市场推广、而从行为细节更贴近技术。DevOps工程师首要的工作就是技术及工具链选型。选择更适合业务发展的技术方案和架构带来的工程效能的提升不是一点点的,所以对新技术的敏感性是DevOps工程师的一个核心技能。一味的适应过去的开发模式,不去尝试改变,是无法实践DevOps的。所以新的开发模式、前沿的技术理念如何在整个组织内推广就是DevOps工程师的职责了。在工具链维护、DevOps平台开发的工作之余,做好技术推广、写好技术文章、处理好与开发团队运维团队的关系,给使用者一个好的体验和目标,DevOps的转型自然会得到团队的支持。

 

  1. 成本控制能力(赚钱与花钱的能力)

站在巨人的肩膀上,我们可以看的更远,所以在DevOps建设过程中我们使用了大量的开源工具,避免自己造轮子。但是开源工具是需要维护成本和二次开发的,稳定性和安全性都是我们在使用过程中的巨大的挑战。一个DevOps工程师的成本算上社保、公积金、工资、奖金等一年不会低于500K,但是500K可以购买的商业软件确比比皆是。如果用一个工程师一年的成本去购买一个商业软件,可以节省掉3个工程师的维护和二次开发的时间,并且提高了产品的稳定性和易用性,这笔买卖不值么?用省下来的钱给工程师发奖金,不香么(当然省下来的钱也大概率不会打到员工的工资卡上)。

所以,不是全部用开源的就省钱,这个时代最贵的是人才!所以DevOps工程师要有成本控制的思维,无论在硬件还是在软件的选型上,都要精打细算,毕竟DevOps团队是个花钱的团队,花掉的钱一定要产生价值,虽然业务价值不好评估,我们可以评估节省的成本来体现DevOps的重要性。

 

  1. PPT

PPT一直是程序员的痛处,甚至一度有一些有趣的声音,比如某公司年会上对PPT的吐槽,PPT做得好会变相的认为该员工没有实际的能力,只能靠PPT汇报的精彩就得以晋升,所以流传着一句话“累死累活干不过做 PPT 的”。这种声音是错误的,,PPT 是 DOC文档的精华本,一般大多数时候通过图文图表等方式展示你要表达的重点。没有哪位专家是拿着github地址来分享代码如何构思巧妙,逻辑如何精彩的。ppt是用于人与人交流的介质,DevOps工程师可以通过吸引人的PPT帮助其他开发者理解你所推广的开发理念,接受统一的持续集成工具链。

 

  1. 演讲能力

综上,具备了项目管理能力、敏捷能力、对新技术敏感性、具备了技术布道能力,PPT能力,接下来就是演讲能力了。为什么需要演讲能力?公司内的开发人员、测试人员、运维人员都相当于你的客户,给客户演示你的DevOps平台,介绍前沿的DevOps理念,都是需要站台的,这是一个体现演讲能力最常见的场景了。所以,DevOps工程师一定不要只知道盯着屏幕撸代码,只有与其他团队加强沟通,才能慢慢消除掉彼此间的不信任,消除运维与开发之间的隔阂。推广DevOps的不只有技术,文化依然是关键的一个环节。

 

DevOps是开发运维一体化、更是工具和文化的集合体,作为一名优秀的DevOps工程师,具备全面技术能力是基础,自身软技能的积累则是决定因素。

kubernetes-部署RabbitMQ

Daniel_Ji阅读(941)评论(0)

1、RabbitMQ简介

RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件)。RabbitMQ服务器是用Erlang语言编写的,而集群和故障转移是构建在开放电信平台框架上的。AMQP:Advanced Message Queue,高级消息队列协议。它是应用层协议的一个开放标准,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言灯条件的限制。AMQP具有如下的特性:

  • 可靠性(Reliablity):使用了一些机制来保证可靠性,比如持久化、传输确认、发布确认。
  • 灵活的路由(Flexible Routing):在消息进入队列之前,通过Exchange来路由消息。对于典型的路由功能,Rabbit已经提供了一些内置的Exchange来实现。针对更复杂的路由功能,可以将多个Exchange绑定在一起,也通过插件机制实现自己的Exchange。
  • 消息集群(Clustering):多个RabbitMQ服务器可以组成一个集群,形成一个逻辑Broker。
  • 高可用(Highly Avaliable Queues):队列可以在集群中的机器上进行镜像,使得在部分节点出问题的情况下队列仍然可用。
  • 多种协议(Multi-protocol):支持多种消息队列协议,如STOMP、MQTT等。
  • 多种语言客户端(Many Clients):几乎支持所有常用语言,比如Java、.NET、Ruby等。
  • 管理界面(Management UI):提供了易用的用户界面,使得用户可以监控和管理消息Broker的许多方面。
  • 跟踪机制(Tracing):如果消息异常,RabbitMQ提供了消息的跟踪机制,使用者可以找出发生了什么。
  • 插件机制(Plugin System):提供了许多插件,来从多方面进行扩展,也可以编辑自己的插件。

RabbitMQ中的消息都只能存储在Queue中,生产者(下图中的P)生产消息并最终投递到Queue中,消费者(下图中的C)可以从Queue中获取消息并消费。

2、RabbitMQ部署

下面是RabbitMQ部署的定义代码,此代码由两部分组成,即RabbitMQ部署的部署以及其代理服务。镜像使用的是bitnami/rabbitmq:latest。通过NodePort模式对外暴露了15672和5672端口,并通过nfs文件系统对RabbitMQ的数据进行持久化。

#-------------定义RabbitMQ部署-----------------
apiVersion: apps/v1beta2
kind: Deployment
metadata:
 name: rabbit
spec:
 replicas: 1
 selector:
   matchLabels:
     app: rabbit
 strategy:
   rollingUpdate:
     maxSurge: 25%
     maxUnavailable: 25%
   type: RollingUpdate
 template:
   metadata:
     labels:
       app: rabbit
   spec:
     containers:
     - image: bitnami/rabbitmq:latest
       imagePullPolicy: IfNotPresent
       name: rabbit
       ports:
       - containerPort: 15672
         name: rabbit15672
         protocol: TCP
       - containerPort: 5672 
         name: rabbit5672 
         protocol: TCP
       resources: {}
       volumeMounts:
       - mountPath: /bitnami
         name: rabbit-persistent-storage
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
      volumes:
      - name: rabbit-persistent-storage
        nfs:
         path: /home/nfs-share/rabbit
         server: 10.0.33.201

#-----------------定义rabbit的代理服务--------------
apiVersion: v1
kind: Service
metadata:
 name: rabbit-service
spec:
 ports:
 - name: rabbit15672
   nodePort: 31199
   port: 15672
   protocol: TCP
   targetPort: 15672
 - name: rabbit15672 
   nodePort: 305672 
   port: 5672 
   protocol: TCP 
   targetPort: 5672
 selector:
   app: rabbit
 type: NodePort

通过kubectl,执行下面的命令在Kubernetes集群中部署Oracle数据库。

$ kubectl create -f rabbitmq.yaml --namespace=kube-public

在部署完成后,通过下面的命令可以查看RabbitMQ暴露的端口:

$ kubectl get svc --namespace=kube-public

3、部署验证

在浏览器中输入:http://10.0.33.203:31199/,访问部署好的RabbitMQ。在登录页面输入用户名和密码(此处初始user/bitnami),系统将会进入RabbitMQ的主页。

4、运行环境配置

在部署时,可以通过设置下面的环境变量来改变容器的运行时:

  • RABBITMQ_USERNAME: 用户名,默认值为user
  • RABBITMQ_PASSWORD: 密码,默认值为bitnami
  • RABBITMQ_HASHED_PASSWORD: 哈希密码
  • RABBITMQ_VHOST: 安装后启动创建的虚拟主机,默认值为 /
  • RABBITMQ_ERL_COOKIE: Erlang cookie用于确定不同的节点之间是否允许行互相通信。
  • RABBITMQ_NODE_TYPE: 节点类型,有限制: statsqueue-ram or queue-disc。 默认值为stats
  • RABBITMQ_NODE_NAME: 节点名称和主机,例如: node@hostnamenode 。默认值为rabbit@localhost。
  • RABBITMQ_NODE_PORT_NUMBER: 节点端口,默认值为5672
  • RABBITMQ_CLUSTER_NODE_NAME: 集群名称,例如:clusternode@hostname
  • RABBITMQ_CLUSTER_PARTITION_HANDLING: 集群分区恢复机制,默认值为: ignore
  • RABBITMQ_MANAGER_PORT_NUMBER: 管理端口,默认值为15672
  • RABBITMQ_DISK_FREE_LIMIT: Rabbitmq存储数据的可用空间限制,当低于该值的时候,将触发流量限制。默认值为 {mem_relative, 1.0}
  • RABBITMQ_ULIMIT_NOFILES: 资源限制, 打开文件描述符的最大数目,默认值为65536

作者简介:

季向远,北京神舟航天软件技术有限公司。本文版权归原作者所有。

“云”端的语雀:用 JavaScript 全栈打造商业级应用

alicloudnative阅读(249)评论(0)

作者|  不四(死马)蚂蚁金服 语雀产品技术负责人

语雀是什么?

语雀是一个专业的云端知识库,面向个人和团队,提供与众不同的知识管理,打造轻松流畅的工作协同,它提供各种格式的在线文档(富文本、表格、设计稿等)编辑能力,支持实时在线多人协同编辑,数据云端保存不丢失。而语雀与其他文档工具最大的不同是,它通过知识库来对文档进行组织,让知识创作者更好的管理知识。

1.png

语雀技术架构演进

原型阶段

语雀诞生于 2016 年,当时蚂蚁金融云需要一个工具来承载它的文档。当时负责的技术同学利用业余时间,开始搭建这个文档工具。项目的初期,没有任何人员和资源支持,同时也为了快速验证原型,技术选型上选择了最低成本的方案。

底层服务完全基于体验技术部内部提供的 BaaS 服务和容器托管平台:

  • Object 服务:一个类 MongoDB 的数据存储服务;
  • File 服务:阿里云 OSS 的基础上封装的一个文件存储服务;
  • DockerLab:一个容器托管平台;

这些服务和平台都是基于 Node.js 实现,专门给内部创新型应用使用,也正是由于有这些降低创新成本的内部服务,才给工程师们提供了更好的创新环境。

应用层服务端自然而然的选用了体验技术部开源的 Node.js Web 框架 Egg(蚂蚁内部的封装 Chair),通过一个单体 Web 应用实现服务端。应用层客户端也选用了 React 技术栈,结合内部的 antd,并采用 CodeMirror 实现了一个功能强大、体验优雅的 markdown 在线编辑器。

2.png

这时可以算作语雀的“原型阶段”,它仅仅是一个工程师的业余项目,采用内部专为创新应用提供的 BaaS 服务和一系列的开源技术解决方案,验证了在线文档工具这个产品原型。

PS:当时我还不在语雀团队,但是巧的是我却在给语雀提供 Object、File 等 BaaS 服务和 Egg.js Web 框架的支持。

内部服务阶段

随着在线文档工具得到了团队内部的认可,语雀的目标已经不仅仅是金融云的文档工具,而是志在替代 confluence 等竞品,成为阿里内部十万员工的知识管理平台。语雀要面向知识创作者,只提供 Markdown 编辑器肯定无法让非技术人员更高效的使用语雀。尽管有不少真爱粉因为语雀开始学习甚至爱上了 Markdown,但是我们仍然义无反顾的踏入了富文本编辑器领域的深坑。同时和 Word 等富文本编辑器不同,我们选择了更“Web”的路线,在富文本编辑器中加入了公式、文本绘图、思维导图等特色功能。而随着语雀在知识管理领域的不断探索,知识管理的三层结构(团队、知识库、文档)开始成型。在此之上的协作、分享、搜索与消息动态等功能越来越复杂单纯的依靠 BaaS 服务已经无法满足语雀的业务需求了。

为了应对业务发展带来的挑战,我们主要从下面几个点进行改造:

  • BaaS 服务虽然使用简单成本低,但是它们提供的功能不足以满足语雀业务的发展,同时稳定性上也有不足。所以我们将底层服务由 BaaS 替换成了内部的 IaaS 服务(MySQL、OSS、缓存、搜索等服务)。
  • Web 层仍然采用了 Node.js 与 Egg 框架,但是业务层借鉴 rails 社区的实践开始变成了一个大型单体应用,通过引入 ORM 构建数据模型层,让代码的分层更清晰;
  • 前端编辑器从 codeMirror 迁移到 Slate。为了更好的实现语雀编辑器的功能,我们内部 fork 了 Slate 进行深入开发,同时也自定义了一个独立的内容存储格式,以提供更高效的数据处理和更好的兼容性。

3.png

在内部服务阶段,语雀已经成为了一个正式的产品,和蚂蚁的其他项目没有什么区别了,通过在阿里内部的磨炼,语雀的产品形态基本定型。

商业化阶段

随着语雀的内部影响力越来越大,一些离职出去创业的阿里校友们开始找到玉伯:“语雀挺好用的,有没有考虑商业化之后让外面的公司也能够用起来?” 经过小半年的酝酿和重构,18 年初,语雀开始正式对外提供服务,进行商业化。

当一个应用走出公司内到商业化环境中,面临的技术挑战一下子就变大了。最核心的知识创作管理部分的功能越来越复杂,表格、思维导图等新格式的加入,多人实时协同的需求对编辑器技术提出了更高的挑战。而为了更好的服务企业用户与个人用户, 语雀在企业服务、会员服务等方面也投入了很大精力。在业务快速发展的同时,服务商业化对质量、安全和稳定性也提出了更高的要求。

为了应对业务发展,语雀的架构也随之发生了演进:

我们将底层的依赖完全上云,全部迁移到了阿里云上,阿里云不仅仅提供了基础的存储、计算能力,同时也提供了更丰富的高级服务,同时在稳定性上也有保障。

  • 丰富的云计算基础服务,保障语雀的服务端可以选用最适合语雀业务的的存储、队列、搜索引擎等基础服务;
  • 更多人工智能服务给语雀的产品带来了更多的可能性,包括 OCR 识图、智能翻译等服务,最终都直接转化成为了语雀的特色服务;

而在应用层,语雀的服务端依然还是以一个基于 Egg 框架的大型的 Node.js web 应用为主。但是随着功能越来越多,也开始将一些相对比较独立的服务从主服务中拆出去,可以把这些服务分成几类:

  • 微服务类:例如多人实时协同服务,由于它相对独立,且长连接服务不适合频繁发布,所以我们将其拆成了一个独立的微服务,保持其稳定性;
  • 任务服务类:像语雀提供的大量本地文件预览服务,会产生一些任务比较消耗资源、依赖复杂。我们将其从主服务中剥离,可以避免不可控的依赖和资源消耗对主服务造成影响;
  • 函数计算类:类似 plantuml 预览、mermaid 预览等任务,对响应时间的敏感度不高,且依赖可以打包到阿里云函数计算中,我们会将其放到函数计算中运行,既省钱又安全;

随着编辑器越来越复杂,在 slate 的基础上进行开发遇到的问题越来越多。最终语雀还是走上了自研编辑器的道路,基于浏览器的 contenteditable 实现了富文本编辑器,通过 canvas 实现了表格编辑器,通过 SVG 实现了思维导图编辑器。

语雀富文本编辑器相关的介绍,可以看看 Lake Editor 之父隆昊的分享:富文本编辑器的技术演进

4.png

语雀的这个阶段(也是现在所处的阶段)是商业化阶段,但是我们仍然保持了一个很小的团队,通过 JavaScript 全栈进行研发。底层的服务全面上云,借力云服务打造语雀的特色功能。同时为企业级用户和个人知识工作者者提供知识创作和管理工具。

JavaScript 全栈

5.png

在社交网络上,大家好像对 JavaScript 全栈的看法都比较负面,“样样通,样样松”可能是大家听到全栈工程师这个名词后的第一印象。那为什么语雀选择了 JavaScript 全栈的方向呢?

JavaScript 全栈与产品工程师

在语雀,我们并不将用 JavaScript 全栈进行开发的工程师定义为全栈工程师,而是“一专多能”型的产品工程师

  • 他们是产品的“技术合伙人”,他们对产品有 owner 感,和产品经理一起参与产品讨论设计,从技术的角度上对产品设计方案提出建议,独立的完成产品功能的全栈研发,并跟踪发布后的产品结果。
  • 同时他们也是某一个技术领域的领域专家,例如有人可能是服务端领域的专家、测试领域的专家、前端构建领域的专家、CSS 领域的专家。他们可以用自己的专业领域知识来优化团队研发工具链,提升产品研发效率。

6.png

在语雀,产品工程师们的产品研发流程是这样的:

  • 在产品设计阶段,产品工程师就会参与进去进行讨论,最终会产出一份 final design 的产品设计稿。由于前期产品工程师参与充分讨论,一般此处定下的产品设计稿到后期的研发过程中不会遇到技术上的问题;
  • 随后会在语雀上进行文档化的系统分析设计。会在语雀上发起异步的评审。一些大的技术方案会有其他的领域专家加入进来一起进行评审,确保将所有的技术难点都梳理清楚;
  • 系统设计清晰后,进入研发阶段;
  • 对所有的代码,都需要有自动化测试覆盖。对所有新增代码和修改的业务逻辑都需要有完全覆盖的单元测试,对关键链路的功能同时也要提供端到端测试。编写完自动化测试是进入代码评审前的必备流程。
  • 阶段性的功能研发完成、测试编写完善后会发起异步的代码评审。会邀请相关业务的负责人和对应的一些领域专家来进行代码评审。从业务逻辑的正确性,安全性,可维护性等多个角度来进行代码评审。
  • 最终在发布上线时,必须遵循三板斧原则:可灰度、可应急、可监控。避免功能变更可能带来的 bug 影响到大量用户。

7.png

语雀是如何进行全栈 JavaScript 测试的呢?感兴趣的同学可以看看语雀团队大前端自动化测试大牛达峰老师的分享:大前端测试的思考和在语雀的实践

通过 JavaScript 全栈,语雀团队可以更高效、高质量的的完成产品研发:

  • 从代码层面上来说,有大量的代码可以复用,以编辑器举例,它不仅仅可以在 Web 端使用,也可以在桌面端使用。同时许多数据处理的能力还可以在服务端使用。
  • 从产品研发效率上来说,全栈研发减少了大量沟通成本,在语雀当前的阶段是非常高效的。而 JavaScript 全栈避免了开发者在不同的语言中进行切换,不用考虑前端使用的 lodash / moment 等工具类在其他语言中应该用什么,大大提升全栈的研发效率。
  • 最后从工程师角度来看,全栈研发让工程师有机会深度参与到产品研发的整个流程中,大家会自发的去思考产品有什么优化点,从技术上能帮助产品做什么。例如语雀最近新上的 OCR 搜图功能,就是语雀的全栈工程师自发从技术预研到产品落地完成整个产品优化的。

8.gif

JavaScript 全栈与 Node.js

说到 JavaScript 全栈,有一个绕不过去的技术就是 Node.js。作为一个与前端结合紧密的服务端运行时,基本上就成为了全栈的代言人。那 Node.js 是不是真的是一个适合大型商业化项目的语言呢?大家对它都有颇多质疑:

9.png

其实随着 JS 语言的发展,许多问题已经得到了解决,例如 Async Function 的出现,可以让开发者以同步的方式编写异步代码,理解起来更简单,异常处理也变简单了。同时随着社区的进一步完善,大量高质量的工具模块、框架涌现出来。语雀的服务端部分基于 Egg 框架,已经集成了大量 Web 开发需要的模块和服务,同时基于 Async Function 编程模型也更加简单。TypeScript 的出现也打消了许多人对 JavaScript 进行大型项目开发的疑虑。除此之外,语雀还有一些其他的方式来保障代码质量和可维护性(语雀甚至是一个纯 JavaScript 项目,没有一行 TypeScript 代码)。

语雀做的第一件事情就是确定核心系统和外部系统的边界。通过六边形架构(也叫做端口适配器架构),我们把语雀核心系统和外界系统和用户之间的交互固定下来。通过“端口”的形式,来确定输入和输出。外部系统通过“适配器”来将系统对接到语雀暴露的端口之上,只需要按照“端口”定义来实现,外部系统可以自由替换。

10.png

在这个模型下,Controller 就是语雀暴露给用户接口的 HTTP 适配器。在 Controller 中,我们对用户请求参数进行格式校验和转换,检查用户权限,并格式化输出。

11.png

我们定义好语雀与第三方平台和服务之间的交互方式(一般是一系列方法),通过适配器,将不同环境的不同服务封装成统一的方法,并在调用时记录好调用日志。

12.png

数据模型层即是数据层的 Model,以 Doc 模型举例,它的 meta 信息数据被存储在了 MySQL 中,而文档正文数据被加密后存储在 OSS 中。对于语雀核心的业务逻辑来说,完全不感知底层的存储在哪里。更进一步来说,只要语雀是使用 SQL 和数据库进行交互,底层数据可以无缝迁移到 OceanBase 等其他支持完整 SQL 语法的数据库中,即使有少量修改也可以在 Model 层封装掉。

13.png

最终以一次文档发布举例,用户通过调用 HTTP 接口与语雀进行交互,数据会通过 Model 层写入到存储中,包括 MySQL 和 OSS,更新文档缓存。同时出发异步消息给其他系统,触发钉钉的 WebHook,并将数据同步到搜索引擎中。这些和外界系统的交互通过适配器封装之后各司其职,参数转换、权限校验、日志记录,不仅确保核心逻辑的精简,也让系统调用链路跟踪更加简单。

14.png

混合应用架构

当系统发展到一定程度后,到底是应该继续在大单体应用上加功能,还是拆分成微服务呢?这两种架构既然存在,肯定有各自的优劣,具体选择那种架构形式,应该是与当前的业务规模和团队分布决定的。所以语雀的技术架构随着语雀的业务形态也变成了一个混合式的技术架构。

15.png

语雀的主服务是一个大型的 Node.js 服务,集中了所有的应用业务逻辑。而在主服务之外,还有一些不同形态的其他服务。

  • 微服务:一些独立而稳定的功能模块,或者有额外部署架构需求的服务,会通过微服务的形式独立部署,系统间暂时通过 HTTP 接口进行交互。例如实时协同服务,由于其自身比较独立稳定,而且是长连接服务,不能频繁发布重启,所以将其部署成了一个独立的微服务。
  • 任务集群:一些 CPU 密集型的任务,或者依赖了一些复杂的第三方依赖的服务,会放到一个独立的任务集群中。例如各种文件预览服务,可能依赖到了其他服务,且需要消耗大量计算成本,放到任务集群通过队列消除并发后最为合适。
  • 函数计算:一些对响应时间比较高且可以函数化的服务,我们会尽量迁移到阿里云的函数计算,例如plantuml、mermaid 等文本绘图服务。

16.png

以 mermaid 的渲染举例。用户输入一段 mermaid 代码调用语雀,语雀调用一个部署在阿里云函数计算的函数,在函数中运行 puppeteer 渲染成 svg 返回。

17.png

为什么要特别把 Serverless 单独拿出来说呢?还记得之前说 Node.js 是单线程,不适合 CPU 密集型任务么?由于 Serverless 的出现,我们可以将这些存在安全风险的,消耗大量 CPU 计算的任务都迁移到函数计算上。它运行在沙箱环境中,不用担心用户的恶意代码造成安全风险,同时将这些 CPU 密集型的任务从主服务中剥离,避免出现并发时阻塞主服务。按需付费的方式也可以大大节约成本,不需要为低频功能场景部署一个常驻服务。所以我们会尽量的把这类服务都迁移到 Serverless 上(如阿里云函数计算)。

语言之外的通用领域

除了语言之外,任何的商业化系统还有更多需要考虑的方面,其中最重要的两点可能就是安全性和稳定性了。
18.png

一个系统从前端、服务端到底层的依赖都存在着各种各样的安全风险:

  • 前端安全风险:XSS、跳转钓鱼、跨站请求等
  • 服务端安全风险:水平权限问题、未授权访问、敏感信息泄露、SSRF、SQL 注入等
  • 云服务的安全风险:短信/邮件轰炸、数据泄露风险、内容安全等

这些安全问题想要解决基本都没有银弹,只能一个个单独处理,但是有一些基本的原则:

  • 不要信任用户的任何输入
    • 任何渲染富文本的地方都需要防范 XSS,内容也可能并不是通过 IDE 输入的;
    • 要在服务端执行用户的代码一定要放在沙箱中;
    • 要从服务端请求用户传递的资源,一定要经过 SSRF 过滤;
  • 沉淀标准的编码范式来处理安全风险,且需要在 Code Review 中重点关注
    • 所有接口都必须有权限校验;
    • 响应序列化方法过滤敏感信息;
    • 不允许拼接 SQL;

语雀从商业化一开始就和安全团队通力协作,从内部的安全意识培训、内部安全团队测试,到内部的红蓝攻防、外部的白帽子渗透测试,安全是一场持久战。

19.png

为了保障语雀的稳定性,我们从前端到服务端和云服务上都做了许多工作,和安全一样,稳定性也是一个从前到后的长期工程。语雀的稳定性保障主要在两个维度:

  • 保障服务可用性:从架构设计上要杜绝单点,底层的数据都需要进行容灾和备份,服务需要多单元、可用区部署。同时避免引入不必要的强依赖;
  • 异常可监控和追溯:从前端的业务埋点日志、异常日志监控,到服务端的全链路日志跟踪和采集,系统性能监控和分析。最终我们可以达到异常可及时感知和追溯,性能问题可以定位分析;

什么叫做避免引入不必要的强依赖呢?以语雀的场景举例,MySQL 就是一个无法去除的强依赖,而缓存不应该是一个强依赖,但是最早语雀的 session 是存储在缓存(Redis)中的,一旦 Redis 集群出问题,用户资料无法获取就导致用户无法登录。这就把缓存变成了一个强依赖。所以我们将 session 存储放到了 MySQL 中,Redis 就变成了一个弱依赖,它挂了系统还能正常运行。另一个例子,语雀前段时间上线了多人实时协同编辑的功能,而在这个功能上线之前,是通过文档加锁的方式避免多个人同时编辑同一篇文档的。然而多人实时协同引入了另一个服务,一旦实时协同服务挂了,用户就无法编辑文档了,它又变成了语雀系统的一个强依赖,为了解决他,我们在用户连接协同服务失败的时候,自动切换到老的锁模式。这样协同服务也变成了语雀的一个弱依赖。

语雀如何选择技术栈

20.png

语雀这几年一步步发展过来,背后的技术一直在演进,但是始终遵循了几条原则:

  1. 技术栈选型要匹配产品发展阶段。产品在不同的阶段对技术提出的要求是不一样的,越前期,对迭代效率的要求越高,商业化规模化之后,对稳定性、性能的要求就会变高。不需要一上来就用最先进的技术方案,而是需要和产品阶段一起考虑和权衡。
  2. 技术栈选型要结合团队成员的技术背景。语雀选择 JavaScript 全栈的原因是孵化语雀的团队,大部分都是 JavaScript 背景的程序员,同时 Node.js 在蚂蚁也算是一等公民,配套的设施相对完善。
  3. 最重要的一点是,不论选择什么技术栈,安全、稳定、可维护(扩展)都是要考虑清楚的。用什么语言、用什么服务会变化,但是这些基础的安全意识、稳定性意识,如何编写可维护的代码,都是决定项目能否长期发展下去的重要因素。

阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的技术圈。”

基于Saltstack、Artifactory打造传统模式下持续部署平台

JFrogchina阅读(243)评论(0)

一、持续部署

1.现状

由于没有建立标准的持续部署流程,导致了版本管理混乱,制品管理混乱,上线持续时间长,上线测试覆盖不全面,业务流量上升后故障较多,排查复杂。运维、测试、开发人员每次版本迭代的时候,都要可能需要经历一次通宵的历练,并且这种在上线的第二天依然会出现很多线上故障。

2. 痛点

  • 自动化发布体系覆盖率低。
  • 无标准化发布的流程。

a.只注重敏捷、忽视质量问题;

b.变更频繁导致故障率增加;

c.开发语言种类多,发布制品管理混乱,发布方式复杂;

  • 安全问题容易被忽视。

二、工具介绍

1.Saltstack

基于ZeroMQ的开源的配置管理工具。笔者之所以选型使用saltstack,而放弃了ansible,原因是由于ansible基于ssh通信,在管控主机超过五百台之后,基于消息队列的命令下发方式无论在稳定性还是速度上都优于ssh协议。笔直另外选在saltstack的原因是,在服务的开发团队中存在着不同的技术栈并行的状况,尤其是java和.net并存的情况下,saltstack对于windows的支持明显要优于ansible。更容易作为多平台的底层发布工具。

而基于SaltStack打造自动化部署平台主要是用grains、pillar、state三个特性,grains用于获取默认环境配置信息、pillar用于定义环境信息、state用于编排发布文件进行发布。

2. Artifactory

全语言制品仓库管理软件,有开源版及企业版两种。开源版支持maven制品管理;企业版支持全语言制品管理,支持元数据管理功能,提供高可用部署方式、匹配nvd及vulnDB数据库,提供漏洞扫描能力。

 

三、针对上述痛点解决方案

1. 自动化发布覆盖率低

通过搭建兼容多平台部署统一发布工具,替换掉传统的shell脚本拷贝的方式实现发布工具标准化。通过SaltStack的state特性,实现跨平台的基础服务发布、服务启停、文件发布、配置发布、远程主机管理等90%以上手动操作。使用SaltStack的state编排文件,执行远程命令,通过Artifactory获取制品及配置,将需要的版本发布到线上。

主要方案在部署平台中,通过json格式描述发布流程,通过yaml.dump(sls_json)将json文件转换成yaml各位的配置文件,最终通过平台调度saltstack执行编排好的任务。

转换后的yaml文件格式如下:

2. 标准化发布流程

  • 备份

发布任务编排的第一步就是备份,备份需采用本地备份加异地备份两种机制,本地备份用于快速回滚,异地备份用于环境重建。

  • 切流量(蓝绿部署)

对于服务,尤其是有状态的服务,需要在注册中心中进行节点下线,确保本节点所有处理结束后,再进行部署。

对于页面,需要在负载均衡上将节点注销,对没有流量的web页面进行部署操作。

  • 部署

通过saltstack的sls特性,编排部署文件,对多个部署任务进行统一进行发布。

部署时我们希望可以在部署页面查看到类似下述信息,如:部署包对应的需求id、部署包对应代码的提交信息、部署包自动化测试的通过率、部署包的代码扫描结果、部署包的安全扫描结果、部署包人工测试的结果等等。运维人员需要在发布过程中看到此类信息,来明确包是否通过了所有质量关卡、具备了上线条件,从而判断此次上线是否可以继续进行。这里我们使用了Artifactory的元数据功能,用于记录软件包诞生的整个生命周期的信息,并通过api方式对接到发布平台。给运维人员一个完整的包的信息记录。

  • 自动化测试

此处自动化测试主要可以理解为检测服务端口通信是否正常、回归线上功能是否可用、缺陷是否被修复、新特性是否部署完成等。同时此处需要预热服务及站点,通过自动化的测试打通业务流程。

  • 流量回归(金丝雀)

部分真实流量切换到已经部署完成的应用上,通过全链路日志追踪或监控指标反馈来初步判断新上线应用是否健康运行,并将此结果作为后续发布或回退的依据。

  • 部署补全(滚动发布)

在使用低谷时间将流量牵引到已部署完成的应用上,同时将其余应用升级。

  • 变更管理通告。

上线成功后需要及时的通知大家线上版本已变更,产品经理需要及时更新文档,运营人员需要及时对用户进行告知。

  • 回滚

任何发布都需要考虑回滚方案,对于单个应用需要回滚到一个指定版本;对于多个应用,需要明确一个回滚集,通过发布时的编排任务指定回滚的编排任务。对于数据库等更新,如果回顾复杂,则需要在升级方案制定前就明确回滚方案或在业务中做好版本兼容。

3. 建立统一的制品管理仓库

大多互联网公司已经对源码仓库有了统一的管理,但对于制品依然处于一个原始的管理状况,比如使用ftp以及每种语言开源的管理仓库。这里遇到的问题是,运维人员需要投入大量的精力维护不同的包管理平台(如ftp、maven、nuget、pypi、docker镜像中心等)。浪费掉大量运维团队的人力成本之外,也极度复杂了发布流程。发布人员需要在不同的平台获取上线的包,导致发布流程混乱,发布平台配置混乱。并且大多数开源组件均不提供高可用能力,一旦硬件或软件出现故障,都将严重的影响发布效率。

为了解决这种问题,我们采用Artifactory来管理所有语言的制品仓库。与统一gitlab一个道理,我们把整个公司的制品统一管理,成为对接发布平台的唯一包来源,从而规范了发布流程。

4. 漏洞扫描

目前安全团队扫描大多是在服务部署上线后进行,这种情况下和容易造成由于版本有安全漏洞导致的整个迭代废弃,所有包需要重新编译,重新经过测试流程以及上线过程,浪费掉大量的时间,降低迭代的速度。

解决办法是将漏洞扫描步骤前置,在制品包构造编译的时候,乃至开发人员code代码的时候就对外部引用、内部公共库进行漏洞扫描,一旦匹配到高危漏洞,直接把提交或构建终端。如果一定要继续构建,那么可以将扫描结果记录到制品的元数据中,供测试人员,运维人员查看。目前JFrog Xray等安全扫描故居提供此类能力。也可以使用开源软件,如cvechecker,在编译流水线中对包进行扫描,防止由于安全漏洞造成的整个迭代失败。

 

四、后期完善

1. 设置度量体系,提升发布质量

敏捷开发模式下,开发人员和测试人员往往是汇报给同一位管理人员,出于快速迭代线上功能,往往有些团队会投机取巧、将没有测试完整的包发布到线上进行测试。该种问题的直接表现是,为了解决一个bug,可能多时间多次对同一个应用或页面进行hotfix或发布新版本。这样做是十分危险的,置线上业务稳定于不顾。为了避免此类情况发生、我们可以采用一些措施或规范来约束开发团队。例如:

上线后触发新bug数量

短时间内对相同问题发布次数

由于上线原因造成的P5-P0级别故障的数量

上线后故障恢复时间

上线后回滚的次数

非上线时间内紧急上线数量

通过收集上述数据,每月或固定周期对各个团队进行考核。并对发布状态复盘,通过制定规约,评估团队的交付质量及交付能力,挖掘团队中的发布问题及痛点,从而提高发布质量,减少线上故障率。

2. 制定度量标准,进行发布质量考核

每团队初始分为100分,每月重置,每月用此分作为迭代质量的一项标准,分数不挂钩kpi考核,只用来驱动开发团队去提高效率。

评判为两个维度:项目组发布稳定性得分、服务(站点、app、微服务等)发布质量得分

  • 非上线时间发布hotfix(项目组减1分,服务减1分)
  • 代码类hotfix,同一项目每天发布超过3次(项目组减1分,服务减2分)
  • hotfix发布失败或回滚(项目组减2分,服务减2分),发布是否失败,由运维团队认定。
  • 数据库等脚本异常或执行失败(项目组减1分)
  • 每月服务发布数量(取top5,服务按排序减5到1分)
  • 由于hotfix原因造成P2级以上的线上事故,项目组减5分,相关服务减5分
  • 项目组本月hotfix量如超过前3月平均值的30%,减10分

3. 变更管理

在google的SRE体系中,变更管理是DevOps体系中最为重要的一个部分。根据以往的经验,90%的线上故障是由于线上变更导致的,该变更原因包括软件、硬件、环境等所有因素。建设变更管理体系目的就是为了快速定位线上问题,止损由于变更造成的线上故障,及时通知相关人员做好故障预防工作。所以,变更管理体系也是需要我们重点去建设以及完善的。

落地方式包括但不限于下述几点:

  • 运维人员、对应的开发及测试人员、产品经理等微信通知
  • 大屏滚动播放最近的变更记录
  • 变更记录同步到监控系统

五、总结

总结为一句话,虽然在敏捷开发模式下、产品、开发、测试团队都在小步快跑,但运维必须有自己的原则,一定要对整个上线流程制定规范、对DevOps工具链进行统一管理。

线上稳定大于一切!

kubernetes-部署Oracle数据库

Daniel_Ji阅读(935)评论(0)

1、Oracle数据库

Oracle Database,又名Oracle RDBMS,或简称Oracle。是甲骨文公司的一款关系数据库管理系统。它是在数据库领域一直处于领先地位的产品。可以说Oracle数据库系统是目前世界上流行的关系数据库管理系统,系统可移植性好、使用方便、功能强,适用于各类大、中、小、微机环境。它是一种高效率、可靠性好的、适应高吞吐量的数据库方案。

2、Oracle部署

下面是Oracle部署的定义代码,此代码由两部分组成,即Oracle部署的部署以及其代理服务。此处部署的Oracle数据库为11g  r2,镜像使用的是mybook2019/oracle-ee-11g:v1.0。通过NodePort模式对外暴露了1521和1158这两个端口,并通过nfs文件系统对Oracle的数据进行持久化。

#-------------定义oralce代理服务--------------------
apiVersion: v1
kind: Service
metadata:
  name: oralce-svc
  labels:
    app: oralce
spec:
  type: NodePort
  ports:
  - port: 1521
    targetPort: 1521
    name: oracle1521
  - port: 8080
    targetPort: 8080
    name: oralce8080
  selector:
    app: oralce
---

#-------------定义oralce部署--------------------
apiVersion: apps/v1
kind: Deployment
metadata:
  name: oralce
spec:
  replicas: 1
  selector:
    matchLabels:
      app: oralce
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: oralce
    spec:
      containers:
      - image: mybook2019/oracle-ee-11g:v1.0
        name: oralce
        - containerPort: 1521
          name: oralce1521
        - containerPort: 8080
          name: oralce8080
        volumeMounts:
        - name: oralce-data
          mountPath: /u01/app/oracle
      volumes:
      - name: oralce-data
        nfs:
          path: /home/sharenfs/oracle
          server: 192.168.8.132

通过kubectl,执行下面的命令在Kubernetes集群中部署Oracle数据库。

$ kubectl create -f oracle11g-en.yaml --namespace=kube-public

在部署完成后,通过下面的命令可以查看oracle暴露的端口(此处的端口为1521和32175):

$ kubectl get svc --namespace=kube-public

3、部署验证

在此处,部署好Oracle以后。

1)在Kubernetes集群内的应用,连接数据库的相关信息如下:

hostname: oracle-svc.kube-public
port: 1521
sid: EE
service name: EE.oracle.docker
username: system
password: oracle

对于在oracle客户端所在机器上,执行下面的命令连接到数据库。

$ sqlplus system/oracle@//oracle-svc.kube-public:1521/EE.oracle.docker

2)在Kubernetes集群外的应用,连接数据库的所使用的相关信息如下:

hostname: 10.0.32.165
port: 32175
sid: EE
service name: EE.oracle.docker
username: system
password: oracle

对于在oracle客户端所在机器上,执行下面的命令连接到数据库。

$ sqlplus system/oracle@//10.0.32.165:32175/EE.oracle.docker

DevOps is Hard、DevSecOps is Even Harder — Enterprise Holdings.

JFrogchina阅读(184)评论(0)

Enterprise Holdings. 的IT团队超过2000人,在2018年的演讲中介绍了Enterprise Holdings的DevOps是如何转型的。我们通过打造一个不只包涵了pipeline的CI/CD平台,将其称之为SDLC。在最开始的200+个应用中,我们挑选出5个来作为试点。当时的情况证明这次DevOps转型计划是成功的,我们的团队有4+位工程师和两位架构师,从2年半前就开始了整个平台的开发工作,根据业务需求确保平台可以适配各种云服务、也要适配已有的中间件,我们也在不断对CI/CD平台进行改进,以适应所有业务场景。其的目标是让开发人员更专注于具体的项目开发,让工具去解决一些通用性的问题。为了达到目前的效果,我们做了很多关于平台的需求收集及问题反馈相关的运营工作,所以在过去的一年里,我们已经将此套平台服务于70%的应用中,并且这个数字还在持续的增加。

在DevOps转型过程中,我们的角色并不是软件的开发者,但我们支撑了应用开发团队和他们所开发的应用,我们的服务工作介于应用程序与基础设施之间。在我们的角度来看,应用程序的开发应该是这样的:

  • 开发人员在本地开发
  • 在仓库中检查源码
  • 在构建服务器上构建应用
  • 运行安全扫描
  • 打包发布到JFrog的Artifactory
  • 发布应用到不同的环境测试
  • 所有测试结束后,发布到生产环境

这个模式很简单,但是也很高效,但是为了实现这个流程做了非常多的事,我们开发了一些被称之为共享库的模版,并将此和打包程序、自动化脚本、ansible脚本等一起存储到源码仓库中进行版本管理,同时提供给应用团队去使用。为了支撑我们的应用团队按上述流程实践,我们使用了很多工具。

持续集成工具链包括:git、maven、gradle、Artifactory、Bitbucket、BlackDuck、jenkins

持续交付工具包括:Ansible、jenkins、Bitbucket、Artifactory、Oracle、Tomcat等

工具使用简单,所以就会有人告诉你DevOps是简单的,但这种说法是不负责任的,不能认为使用了某个工具,我们就实践了整个DevOps理念。我们公司的it团队由超过2000人组成,这些人开发了大量的应用程序,我们要保证整个团队都能正常的工作。虽然每个团队使用的技术栈不同,使用的平台不同,但我们需要找到这些人的共同点,以便在我们的DevOps平台上更好的适配所有团队和开发者以及超过200个的应用。我们需要保证所有人都能应用我们的平台,并且保障平台实时可用,为此我们在jenkins的上面使用groovy开发了很多pipeline模版、自动化脚本、jenkinsfile等供其他团队使用。这样我们就能引导开发人员使用工具的时候是按照我们指引的方式去使用的,并且在这个过程中我们设置了很多关卡,明确告诉了开发人员如果进行这些校验、他们的应用程序是无法正常的被构建的。这样的结果就是,开发人员使用我们定义好的模版,自动进行安全扫描,收集元数据,并把应用包上传到Artifactory中统一管理。之后我们的团队就可以通过这些元数据所收集的结果,去反查到你的应用程序包括什么。我们在模版中维护了一个json串,告诉你这个模版会做什么事、收集什么数据。

上面都是说的CI的内容,接下来我们讨论下CD。很遗憾,到目前为止我们仍然没有办法将所有的CD流程自动化,我们有太多的开发场景和平台,有大量复杂的工作等着我们去做。在我们的CD体系中ansible负责了大量的工作,我们使用jenkins去管理我们的发布流程、并通过ansible去执行发布任务,最重要的是,我们收集了部署中的数据(如发布的环境、发布的时间、测试的结果等等),并把这些数据以元数据的方式回写到Artifactory中。在这个过程中你需要定制开发一些自动化的测试脚本,并把他们应用到pipeline中。

我们的构建任务运行在一个jenkins中、测试任务运行在另一个jenkins里,这样的方式保证我们的应用有一点点安全性。

在部署过程中我们存在的最大的一个问题就是,每次部署不仅仅部署一个应用,可能会涉及到很多应用同时发布,我们为了处理这个问题,让应用运维团队去梳理了应用程序间的依赖关系,以及部署的顺序。并且维护了一个清单来对整个发布进行说明。Jenkins会按照这些事先定义好的清单来进行发布 ,并收集到过程中的问题、哪个stage失败、是否影响到了其他的任务等等。并把这些问题同步到pipeline中以及Artifactory的元数据上。我们给了所有开发者对jenkins的只读权限,这样可以确保所有的相关开发者都可以看到这些问题,并及时对问题进行修复。我们通过这种方式,把一次发布由4小时缩减到1小时。

那么接下来,我们要保障的就是每个人都按照这个标准去执行就可以了

接下来我们谈论一些安全的话题

安全是我们组织中非常重要的一部分,实施起来也有很多困难。在我们缺乏安全意识的时候,我们都使用普通用户。这些普通用户,实际上拥有这些流程运行的权限。应用程序的团队甚至可以随意去使用有漏洞的组件,每当我们检查到这些问题的时候,往往这些问题已经被引入到测试环境和生产环境了,我们需要使用到很多开源软件,但是引入这些开源软件需要花费至少一个月的时间去评估它的安全问题是否会对我们的应用程序带来影响,这样的流程是与敏捷开发模式不符合的。

每一天都有非常多的漏洞被提交到公网上,所以我们希望我们的安全问题不应该仅仅由安全团队负责,开发、测试、运维团队的所有工程师都应该对安全重视起来,所以我们选择把安全扫描放到我们的CI/CD流水线里。我们强制所有应用流水线中必须增加安全扫描,如果没有这个stage,那么这条流水线是无法通过的。虽然开始的时候大家不愿意接受,但是过了一段时间,开发人员发现安全团队找他们修复漏洞的这种事变得越来越少,大家也就慢慢常态化了安全扫描这个步骤。这样安全团队也将专心的把时间花费在研究漏洞对应用程序的影响上,减少了与开发团队测试团队的沟通成本。另外我们制定了流水线安全的SLA,来定义一个构建的所有依赖是否满足上线需求。在这个过程也不是完全顺利的,我们发现每条流水线里都进行安全扫描非常花费时间和资源,所以我们改进了方案,每次扫描只扫描一些新的依赖、组件以及新的漏洞特征,这样也大大的提高了安全扫描的效率。

未来工作中,我们会继续与我们所有支持的团队保持持续的沟通,我们要随时了解支持的团队的所有想法和产品,结合实际情况,向他们展示我们的CICD平台是如何给他们带来收益的,确保最终每个团队都可以采用我们的最佳实践,主动来接入我们的平台。总结来说,你所知道完整的CI CD应该是这样的,它不仅是开发,不仅是安全,更是运维、测试。所以pipeline基本等同于一切。我们真的想确保我们所有的过程的设计是安全的,这是我们团队每个人的目标,我们真正专注于在基础设施团队内部全面整合。整合内容包括服务器环境、网络、技术栈等等,而实际上这些整合都是依赖于我们的CICD平台建设的。

 

 

 

更多技术分享请关注    JFrog杰蛙在线课堂

1月14日在线课堂:《JFrog免费社区版容器镜像仓库JCR—功能介绍及实践》

课堂收益:

  1. 了解JCR的优良特性和强大能力
  2. 通过示例演示,掌握如何利用JCR更好地支持微服务及Kubernetes应用的开发和部署

 

报名链接:https://www.bagevent.com/event/6334008

 

抽奖活动:

课堂结束前五分钟,进行抽奖活动

第一名:小爱音箱

第二名:JFrog杰蛙新版T恤

第三名:JFrog杰蛙新版T恤