基于 Orbit 的云原生应用交付基础原则与良好实践

news2024/11/25 14:49:31

img


本文作者:何文强——腾讯云 CODING 高级架构师。
负责 CODING DevOps产品解决方案架构设计和技术产品布道以及 CODING 云原生技术研究与落地实践。在多个技术大会担任演讲嘉宾,腾讯云 CODING DevOps 课程认证出品人,腾讯云云原生训练营核心初创成员。

精通敏捷精益、DevOps 和云原生领域,技术扎实,视野开阔,格局前瞻;在泛互、教育、工业、政务、金融等多个行业拥有数字化落地规划和实战经验;多年技术开发和团队管理经验,目前专注于一站式研发效能平台的建设和推广,聚焦于“以应用为中心“的云原生的落地与实践,致力于中国软件工程能力的提升和改进。

良好的实践需要遵循一定的原则,通过原则指导的实践才能行稳致远。在云原生应用交付中,可通过 The Twelve-Factor App(应用 12 因素)原则作为云原生应用交付实践的指南。

img
图5-1

应用 12 因素(图5-1)主要包括:#1基准代码;#2依赖;#3配置;#4后端服务;#5构建、发布、运行;#6进程;#7端口绑定;#8并发;#9易处理;#10开发环境与线上环境等价;#11日志;#12进程管理。接下来我们将详细介绍基于这 12 个原则的良好实践。

基准代码:一份基准代码,多份部署

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

● 一旦有多个基准代码,就不能称为一个应用,而是一个分布式系统。分布式系统中的每一个组件都是一个应用,每一个应用可以分别使用 12-Factor 进行开发。

● 多个应用共享一份基准代码是有悖于 12-Factor 原则的。解决方案是将共享的代码拆分为独立的类库,然后使用 依赖管理 策略去加载它们。

在“一份基准代码,多份部署”的良好实践中(图5-2),为一个应用的每个模块创建一个代码仓库,选择 Master 分支作为基线,并以 Master 分支构建镜像, Master 分支构建出来的镜像部署在不同的环境中,即所有环境共享由 master 分支构建出来的镜像,如 dev 环境、pre-production 环境、production 环境共享同一镜像。在基准代码实践中,不同环境使用的镜像是同一份,但是不同环境的配置信息不一致,通过镜像与配置信息实现不同环境的部署。

img

依赖:显示声明依赖

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

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

在“显示声明依赖”的良好实践中(图5-3),Python 通过 requirements.txt 显示声明所需要的第三方类库和组件,并记录这些类库和组件的所有依赖和精确的版本号;Gradle 通过 build.gradle(Maven 通过 pom.xml)的 dependencies 显示声明所需要的第三方类库和组件的所有依赖和版本号。通过显示声明依赖,可以有效减少因错误的依赖版本导致的缺陷,提升软件供应链的可见性。

img
图5-3

配置:在环境中存储配置

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

● 数据库,Memcached,以及其他后端服务的配置;

● 第三方服务的证书,如 Amazon S3、企业微信等;

● 每份部署特有的配置,如域名等。

有些应用在代码中使用常量保存配置,这与 12-Factor 所要求的代码和配置严格分离显然大相径庭。配置文件在各部署间存在大幅差异,代码却完全一致。

在“在环境中存储配置”的良好实践中(图5-4),将配置管理信息存储在 Git 仓库中,对配置进行版本化管理,不同环境的配置通过不同分支进行区分和管理,如 reviews 模块中,每个环境创建一个配置管理分支,如 test-folder-ref 分支存储 dev 环境的配置信息、test-base 分支存储 pre-production 环境的配置信息、master 分支存储 production 环境的配置信息,实现应用配置与运行环境的对应。

img*
图5-4*

在“在环境中存储配置”的良好实践中(图5-4),应将应用的配置存储于环境变量中。在 Kubernetes 应用中,可通过 ConfigMap 和 Secret 对象的 Key-Value 存储配置信息,为不同环境创建不同的 ConfigMap 和 Secret,不同环境的 ConfigMap 和 Secret 的 Key 相同,但是 Value 不同;在容器环境变量中引用 ConfigMap 和 Secret 的 Key,实现不同环境不同 Value 的注入,并在应用启动时,加载注入到容器环境的 Key,获取到对应环境的 Value。通过将应用的配置存储于环境变量中,可以有效管理不同环境的配置。

后端服务:把后端服务当做附加资源

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

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

在“把后端资源当做附加资源”的良好实践中(图5-5),Review 服务所依赖的 MySQL 服务和 Redis 服务都是独立部署的,应用服务和附属的后端服务保持松耦合,通过协议的方式进行访问(MySQL 通过 MySQL 协议,Redis 通过 Redis 协议)。通过“把后端服务当做附加资源”,部署可以按需加载或卸载资源,如 MySQL 服务异常,可从备份中快速恢复,卸载当前数据库,然后加载新的数据库,而不需要修改代码。

img
图5-5

构建、发布、运行:严格分离构建和运行

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

● 构建阶段 是指将代码仓库转化为可执行包的过程。构建时会使用指定版本的代码,获取和打包 依赖项,编译成二进制文件和资源文件。

● 发布阶段 会将构建的结果和当前部署所需配置相结合,并能够立刻在运行环境中投入使用。

● 运行阶段 (或者说“运行时”)是指针对选定的发布版本,在执行环境中启动一系列应用程序 进程。

img
图5-6-1

在“严格分离构建和运行”的良好实践中(图5-6-2),代码提交到 CODING 代码库后,通过 CODING 持续集成将源代码打包构建为二进制文件,将二进制文件存储在 CODING 制品库中,二进制文件和配置信息组成发布包,通过 CODING 持续部署选择指定发布包进行程序发布。通过“严格分离构建和运行”,可以更好的实现职责和关注点的分离,同时将代码打包成二进制文件是一种不可变基础设施的体现,禁止通过 patch 等方式修改运行时的代码,有利于代码的同步和二进制文件的一致性和完整性。

img
图5-6-2

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

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

无状态应用程序是一种应用程序,它不会保存在一个会话中生成的客户端数据,以便在与该客户端的下一个会话中使用。每个会话都像第一次一样进行,响应不依赖于前一个会话的数据。相反,有状态应用程序保存有关每个客户端会话的数据,并在客户端下次发出请求时使用该数据。

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

在“以一个或多个无状态进程运行应用”的良好实践中(图5-7),在应用设计时需要将应用设计为无状态应用程序,同时在 Kubernetes 中采用 Deployment 对象进行声明式部署。

img
图5-7

端口绑定:通过端口绑定提供服务

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

将网络服务器类库通过依赖声明载入应用。例如,Python 的 Tornado, Ruby 的Thin , Java 以及其他基于 JVM 语言的 Jetty。完全由用户端 ,确切的说应该是应用的代码发起请求和运行环境约定好绑定的端口即可处理这些请求。

在“通过端口绑定提供服务”的良好实践中,应在 Dockerfile 中指定端口,该端口与应用绑定的端口一致,在镜像构建时,会将 Dockerfile 中指定的端口进行暴露和通信。应用访问可直接通过 Dockerfile 构建的镜像暴露的端口进行访问。在云原生环境下,可在 Kubernetes 的 yaml 文件中的 containerPort 绑定 Dockerfile 中暴露的端口,实现 Kubernetes 资源与 Docker 镜像端口的绑定。端口绑定这种方式也意味着一个应用可以成为另外一个应用的 后端服务 ,调用方将服务方提供的相应 URL 当作资源存入配置以备将来调用

img
图5-8

并发:通过进程模型进行扩展

任何计算机程序,一旦启动,就会生成一个或多个进程(图5-9-1)。互联网应用采用多种进程运行方式。

在 12-factor 应用中,进程是一等公民。12-Factor 应用的进程主要借鉴于 unix 守护进程模。12-Factor 应用的进程所具备的无共享,水平分区的特性 意味着添加并发会变得简单而稳妥。这些进程的类型以及每个类型中进程的数量就被称作进程构成

img
图5-9-1

在“通过进程模型进行扩展”的良好实践中(图5-9-2),面对并发,提倡通过水平扩展进程的数量(增加应用的副本数量,即部署多个相同资源的进程),而非垂直扩展进程的容量(如增加单一进程的CPU、内存等资源)。在云原生应用中,可充分利用Kubernetes的水平缩扩容的能力。通过设置repilcas的值来调整副本的数量,这种水平(横向)扩展进程的方式让并发变得简单、高效和安全。

img
图5-9-2

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

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

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

进程一旦接收终止信号(SIGTERM) 就会优雅的终止 。就网络进程而言,优雅终止是指停止监听服务的端口,即拒绝所有新的请求,并继续执行当前已接收的请求,然后退出。

快速启动良好实践

在“快速启动”的良好实践中(图5-10),采用 Docker 镜像方式进行应用打包,Docker 镜像中包含应用本身及其所有的运行时依赖,能够快速复制到新环境中,并能够快速进行应用的部署。同时,Docker 镜像具备强大的跨平台和可移植性,可以快速将进程迁移到新的服务器上。

优雅终止良好实践

在“优雅停机”良好实践中(图5-10),有两个层面可进行设置,第一个层面是应用层面,若采用 Springboot 框架开发的应用,可在 Springboot 中进行优雅停机参数配置,通过设置 shutdown: graceful 即可实现应用的优雅终止。第二个层面是 Kubernetes 层面,在 Kubernetes yaml 配置中,可以通过 lifecycle 生命周期的 preStop 钩子,设置 terminationGracePeriodSeconds,即可实现容器镜像的优雅终止。通过在应用配置层面和 Kubernetes yaml 中的镜像层面进行优雅终止设置,可实现应用优雅停机。

img
图5-10

开发环境与线上环境等价:尽可能保持开发环境,预发布环境,线上环境相同。

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

时间差异: 开发人员正在编写的代码可能需要几天,几周,甚至几个月才会上线。

人员差异: 开发人员编写代码,运维人员部署代码。

工具差异: 开发人员或许使用 Nginx,SQLite,OS X,而线上环境使用 Apache,MySQL 以及 Linux。

12-Factor 应用想要做到 持续部署 就必须缩小本地与线上差异

传统应用12-factor 应用
每次部署间隔数周几小时
开发人员 vs 运维人员不同的人相同的人
开发环境 vs 线上环境不同尽量接近

在“尽可能保持开发环境,预发环境,线上环境相同”的良好实践中(图5-11)。在时间差异上,通过 CODING CI/CD 流水线缩短部署实践,并且可以采用自动化的方式,加速应用的交付速度,降低每次部署间隔实践;在人员差异上,采用谁开发,谁构建,谁运行原则,通过设置开发、构建、发布运行权限,实现开发运维一体化,授权团队具备端到端交付能力;在工具差异上,反对在不同环境中使用不同的后端服务,尽最大努力消除使用上的差异,同时使用 IaC(基础设施即代码)工具(如Terraform)进行各类环境资源的创建和维护,并将 IaC 配置信息存储到代码库中,在 CI/CD 根据 IaC 配置自动创建环境资源,实现各类环境的等价。

img
图5-11

日志:把日志当做事件流

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

日志应该是事件流的汇总,将所有运行中进程和后端服务的输出流按照时间顺序收集起来。尽管在回溯问题时可能需要看很多行,日志最原始的格式确实是一个事件一行。日志没有确定开始和结束,但随着应用在运行会持续的增加。

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

在“把日志当做事件流”的良好实践中(图5-12),应该使用 logstash 或 Loki 等工具以事件流的方式对日志进行输出,并将输出的事件流发送到 Splunk,ElasticSeach 等日志索引及分析系统中,统一对日志进行存储和检索(图5-12的良好实践)。日志信息不应该以文件的形式存储在运行节点的磁盘上(图5-12的不良实践)。

img
图5-12

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

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

● 运行数据移植,如数据库定期备份。

● 运行一个控制台 ,或是其他命令,如定期线上数据库状态检查。

● 运行一些提交到代码仓库的一次性脚本。如应用部署前运行数据库脚本

在“后台管理任务当做一次性进行运行”的良好实践中,应充分利用 Kubernetes 的 Job 和 CornJob 对象(图5-13)。对于只执行一次的后台管理任务,如应用部署前进行数据库表结构和表数据的导入,可以使用 Kubernetes Job 对象进行一次性进程的管理;对于重复性的后台管理任务,如每日凌晨两点对数据库进行备份,可以使用 Kubernetes CronJob 对象进行重复性进程的管理,通过设置 CrobJob 中的 schedule 的 Cron 表达式,即可实现重复性后台管理任务的执行。

img
图5-13

点击这里,前往 CODING 体验

img

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/770566.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

上市公司Git分支管理规范

Git分支管理策略 主分支Master 首先,代码库应该有一个、且仅有一个主分支。所有提供给用户使用的正式版本,都在这个主分支上发布。 Git主分支的名字,默认叫做Master。它是自动建立的,版本库初始化以后,默认就是在主…

ASEMI快恢复二极管MUR20100CT尺寸, MUR20100CT体积

编辑-Z MUR20100CT参数描述: 型号:MUR20100CT 最大峰值反向电压(VRRM):1000V 最大RMS电压(VRMS):700V 最大直流阻断电压(VDC):1000V 平均整流正向电流(IF):20A 非重复峰值浪涌电流(IFSM)&#xff1a…

Revit中墙体的问题,门窗洞口及柱断梁墙

一、如何同时开两道相邻墙的门窗洞口 做外墙装饰的时候,我们很经常为了方便、简洁在已经绘制好的墙体外围再绘制一面墙体,并且添加上材质作为外饰面,提高工作效率;但是遇到有门窗洞口的墙体时,外饰面墙体却没办法直接被门窗剪切&a…

LeetCode142.环形链表II

142.环形链表II 目录 142.环形链表II一、哈希表二、双指针 一、哈希表 和141题.判断链表是否有环类似,区别在于141题只要求判断链表中是否有环,该题则要求我们返回入环节点 一个非常直观的思路:遍历链表中的每个节点,并将它们记…

【论文】基于GANs的图像文字擦除 ——2010.EraseNet: End-to-End Text Removal in the Wild(已开源)

pytorch官方代码:https://github.com/lcy0604/EraseNet 论文:2010.EraseNet: End-to-End Text Removal in the Wild 网盘提取码:0719 一、图片文字去除效果 图10 SCUT-EnsText 真实数据集的去除 第一列原图带文字、第二列为去除后的标签&a…

【数据结构常见七大排序(三)上】—交换排序篇【冒泡排序】And【快速排序】

目录 前言 1.冒泡排序 1.1冒泡排序动图 1.2冒泡排序源代码 1.3冒泡排序的特性总结 2.快速排序👑 2.1hoare版本实现思想 排序前 排序中 排序后 2.2hoare版本快排源代码 2.3分析先走 情况1🥇 情况2🥈 前言 交换类排序两个常见的排…

7月31日起,这类产品将禁止在亚马逊美国站销售!

亚马逊美国站发布公告称由于口腔胶带(睡眠胶带)在睡觉时存在潜在危险,出于对消费者的安全考虑,任何睡眠胶带产品的listing将在亚马逊商店下架,以下是公告内容: 自2023年7月31日起,口腔胶带&…

Docker 应用容器引擎

Docker 应用容器引擎 一、Docker是什么二、Docker安装和查看1、docker安装2、docker版本信息查看3、docker信息查看 三、镜像操作四、容器操作1、容器创建2、创建并启动容器3、容器的进入4、复制5、容器的导入和导出6、删除容器 一、Docker是什么 是一个开源的应用容器引擎&…

Java遍历集合方法分析(实现原理、算法性能、适用场合)

Java遍历集合方法分析(实现原理、算法性能、适用场合) 概述 java语言中,提供了一套数据集合框架,其中定义了一些诸如List、Set等抽象数据类型,每个抽象数据类型的各个具体实现,底层又采用了不同的实现方式…

56 # 实现 pipe 方法进行拷贝

pipe 是异步的,可以实现读一点写一点,管道的优势:不会淹没可用内存,但是在导入的过程中无法获取到内容 const fs require("fs"); const path require("path");fs.createReadStream(path.resolve(__dirname…

电脑记事本笔记误删如何找回?恢复删除的笔记方法

电脑上有很多好用的记事本软件。以Windows电脑为例,比较经典的有txt记事本,每个记事本可以单独的文件形式保存,误删某个记事本文件后可通过回收站找回,还原恢复。而如果正编辑笔记的时候误删了笔记,还未保存的情况下可…

2023 年第四次工业革命(工业4.0)指南

全球工业4.0市场在2019年估计为70亿美元,预计到2026年将达到210亿美元,因为越来越多的制造企业正在优化其数字化转型战略。工业4.0,也被称为第四次工业革命,旨在创建智能制造机器和系统,这些机器和系统经过连接&#x…

随手笔记——如何手写高斯牛顿法

随手笔记——如何手写高斯牛顿法 说明源代码 说明 将演示如何手写高斯牛顿法 源代码 #include <iostream> #include <chrono> #include <opencv2/opencv.hpp> #include <Eigen/Core> #include <Eigen/Dense>using namespace std; using names…

IIS 日志分析

Microsoft互联网信息服务&#xff08;IIS&#xff09;服务器&#xff0c;包括Web和FTP&#xff0c;已成为企业必不可少的。但是&#xff0c;IT 安全管理员的工作并不仅仅局限于部署 IIS 服务器。部署后&#xff0c;管理员必须采取安全措施来保护这些服务器。监视 IIS 服务器安全…

MacOS上安装Portainer

Portainer介绍 Portainer 是一个很方便的 Docker 可视化管理工具。主要的功能包括: 管理 Docker 主机,可以添加和删除 Docker 主机管理容器,可以启动、停止、删除等容器管理镜像,可以搜索、拉取、删除镜像管理卷,可以查看、删除卷管理网络,可以创建 Docker 网络管理用户和角色…

【Web安全】小白怎么快速挖到第一个漏洞,src漏洞挖掘经验分享,绝对干货!

src漏洞挖掘经验分享 – 掌控安全以恒 一、公益src 公益src是一个白帽子提交随机发现的漏洞的品台&#xff0c;我们可以把我们随机发现或者是主动寻找到的漏洞在漏洞盒子进行提交。 在挖掘src的时候不能越红线&#xff0c;一般情况下遇到SQL注入 只获取数据库名字以证明漏洞的…

蓝牙资讯|三星和日企合作开发智能戒指,将与苹果直接竞争

三星提交了一系列关于可穿戴设备的商标申请&#xff0c;其中包括与智能戒指有关的商标。近日有媒体爆出&#xff0c;三星已经开始与日本印刷电路板企业Meiko合作开发一款智能戒指。据称这款戒指可能会采用Galaxy品牌&#xff0c;或上周申请的智能戒指商标。 目前这一项目处于前…

对Element DatePicker时间组件的封装,时间组件开始时间和结束时间绑定

背景 我们时常有时间范围选择&#xff0c;需要选择一个开始时间和一个结束时间给后端&#xff0c;但我们给后端的是两个字段&#xff0c; 分别是开始时间和结束时间&#xff0c;现在使用element绑定的值是一个数组&#xff0c;我们还要来回处理&#xff0c;很麻烦列表也的查询…

Linux6.1 Docker 基本管理

文章目录 计算机系统5G云计算第四章 LINUX Docker 基本管理一、Docker 概述1.概述2.Docker与虚拟机的区别3.容器在内核中支持2种重要技术4.Docker核心概念1&#xff09;镜像2&#xff09;容器3&#xff09;仓库 二、安装 Docker三、Docker 镜像操作四、Docker 容器操作 计算机系…

vue注意点:$attrs、$slots!插槽

$attrs 当父组件给子组件传值&#xff0c;子组件并没有接收数据时&#xff0c;此时数据在$attrs中可以拿到&#xff0c;并且如果子组件不需要使用数据&#xff0c;而孙组件需要&#xff0c;则可以直接v-bind"$attrs"传给孙。 <-- 父组件 --> <div><…