当前位置: 首页 > news >正文

探秘varian:优雅的发布部署程序

为什么80%的码农都做不了架构师?>>>   hot3.png

上一篇文章《记一次诡异的故障排查经历》中有介绍到我们的部署程序varian,文章发布后有小伙伴对varian很感兴趣,今天就简单的介绍一下我们的varian,揭开她神秘的面纱~

什么是varian

varian是我们基于Python3编写的一套部署程序,处在整个部署系统的中心,与CMDB、Jenkins、SVN/Git、镜像仓库Harbor、Kubernetes API、通知系统等都有交互,负责将源代码经过一系列的处理后打包成Docker镜像,并发布到各个环境,然后通知相关人员。简化后的varian架构如下:

varian架构图

项目环境介绍

  • 项目数量:50+
  • 开发语言:php、java、nodejs
  • 代码版本管理工具:svn、git
  • 编译方式:maven、grunt、yarn
  • 通知方式:email、sms、im

varian能解决我们哪些问题

说到解决的问题,要先聊一下部署系统经历的几个迭代版本:

  1. 最早项目比较少,所用架构及技术也比较单一,每个项目都单独维护了一个shell脚本做部署,脚本里配置了项目的所有信息,包含服务器列表、代码路径等项目特有信息和通知类型等公共信息,各项目脚本之间互不干涉。这样做的好处是每个项目部署发布逻辑都比较简单,修改任何一个项目都对其他项目无影响;但缺点也很明显,各个项目脚本分散,任何项目信息变更都需要取改这个脚本,且一些公共功能的修改就需要所有项目脚本都改一遍,难免不出问题。

  2. 后来随着项目、服务器数量的增多,引入了CMDB来管理项目和主机的基本信息,纯shell的脚本也升级为了python+shell的脚本来维护编译部署,把一部分公共模块例如去CMDB拉取项目下的主机列表、邮件通知等从shell脚本中单独抽出来用python重构,并用python实现了一个主入口,所有项目部署都通过这个主入口进入,然后调用python或shell脚本来实现部署发布整过程,这样解决了脚本分散和公共模块更新所有项目脚本都要跟着修改的问题,但是添加一个新项目还是要手动更新一堆的脚本文件,效率低且易出错,各个项目处理逻辑各不相同,对需要熟悉她的新人很不友好。

  3. 现在线上项目数量已经超过50+,且还在不断增多,微服务、容器化等新技术也不断加入,每天进行数十上百次的部署更新,对部署系统的健壮性,扩展性有了更高的要求。基于之前一步步的探索,采用微服务的设计理念,我们实现了现在这一套部署程序varian,效率高、易扩展、出错率大大降低且对新人友好,解决了以上遇到的所有问题。

varian究竟长何种模样

说了这么多,那varian究竟是个什么样子呢?

设计思路

Lego积木,就是那种各个不同的小模块能拼装成各种各样的建筑的玩具。设计的思路也主要采用了lego的方式,把所有的功能都拆分成一个一个的python类,部署项目时就组装不同的类,例如一个最简单的纯静态web项目,组装了“拉代码模块”+“JS/CSS合并压缩模块”+“分发API模块”+“邮件通知模块”,如果是一个纯java api项目呢?组装“拉代码模块”+“maven编译模块”+“分发API模块”+“邮件通知模块”即可,从上边的例子可以就可以看出这种组装模块的优势。

lego拼装模块

所有模块可复用,来了一个新项目根据项目架构、开发语言等因素去判断目前的模块是否能够满足,如果可以满足就直接组装使用吧,如果确认过眼神,实在满足不了呢?那就新加一个模块,模块编写遵循简单可复用原则,需考虑到后续有类似功能可以直接使用此模块。

可能会有疑问?那些各个项目不同的配置怎么办?例如代码路径。这里采用了逻辑(模块)跟配置拆分的设计方式,所有处理逻辑不涉及任何一个项目特有的属性,项目特有的属性都单独配置,我们采用CMDB来配置,CMDB里有一张deploy的表,表关联project,记录了项目的特殊属性,例如通知邮件列表等等,逻辑模块会调用CMDB API自动取出所需配置信息。

实现方法

  • 目录结构如下:
varian/
|-- main.py #入口主函数
|-- module
|   |-- __init__.py
|   |-- notify.py
|   |-- check.py
|   |-- ...更多模块
|-- project
    |-- website #项目名
    |   |-- cache   #存放log等内容
    |   |-- docker  #打包docker镜像目录
    |   |-- svn     #svn源代码目录
  • 简化过的主函数main.py如下(代码随机删除。。意思对就行吧)
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import argparse,sys
from module import build,public

parser=argparse.ArgumentParser(description='deploys duang!!!')

parser.add_argument(dest='pro_name',type=str)
parser.add_argument(dest='env_name',type=str)
parser.add_argument(dest='parameters',nargs='*')

args=parser.parse_args()

class M(object):
    def __init__(self):
        self.pro_name = args.pro_name
        self.env_name = args.env_name
        self.parameters = args.parameters

        self.build_ob = build.BUILD(self.pro_name,self.env_name)
        self.public_ob = public.PUBLIC(self.pro_name,self.env_name)
        
        self.maps = {
            "7":"self.build_ob.Maven_Build",
            
            "14":"self.public_ob.Remove_Cache",
        }

    def main(self):
        self.arg_list = self.parameters
       
        if self.env_name not in ("dev","qa","hidden","product"):
            print("\n环境参数错误.\n")
            sys.exit()

        for self.every_arg in self.arg_list:
            self.func = self.maps[self.every_arg]
            self.func_ob = str("%s()" % self.func)
            exec(self.func_ob)

if __name__ == '__main__':
    m = M()
    m.main()
  • modele下的模块函数,以maven编译模块为例
class BUILD(object):
    def __init__(self,pro_name,env_name):
        self.pro_name = pro_name
        self.env_name = env_name

        self.svn_path = ("%s/project/%s/svn" % (sys.path[0],self.pro_name))

    def Maven_Build(self):
        self.command = str("cd %s; mvn clean package -P%s -Dmaven.test.skip=true" % (
            self.svn_path, self.env_name)
        )

        try:
            print("\nStart maven build in webapp.\n")
            self.result = os.system(self.command)
            assert self.result == 0
        except AssertionError:
            print("\nMvn build error!\n")
            sys.exit()  # 异常退出,这个再模块中非常重要

使用方法

  • 控制台使用:
python main.py static qa 1 3 6 8

# 第一个参数为项目名
# 第二个参数为部署环境
# 后边的参数就是要构建的模块组合
  • Jenkins使用:

只需要将控制台命令贴到jenkins的构建步骤中当做shell执行即可

总结

  1. 简单即是美
  2. 适合自己的就是最好的

扫码关注公众号查看更多实用文章

转载于:https://my.oschina.net/37Y37/blog/1923582

相关文章:

  • 论“小猪佩奇如何从营销到吸金一路开挂前行”!
  • 使用mysqldump 备份 恢复从库报错解决方案(ERROR 1872)
  • Jquery mobiscroll 移动设备(手机)wap日期时间选择插件以及滑动、滚动插件
  • 动画小记——点击头像逐渐放大
  • Tuxera NTFS for Mac 拼团仅需¥99!再见原价¥298!
  • 什么样的项目适合自动化测试
  • leetcode-27. Remove Element
  • Spark进阶之路-Spark提交Jar包执行
  • 算法与数据结构1800题 数组和广义表(一)
  • JavaScript 函数式编程(二)
  • volatile 可见性的模拟分析示例
  • 管理微服务中的数据
  • bzoj 2002 弹飞绵羊 lct裸题
  • 【c学习-3】
  • BZOJ 4589 Hard Nim
  • ES6语法详解(一)
  • JavaWeb(学习笔记二)
  • MySQL常见的两种存储引擎:MyISAM与InnoDB的爱恨情仇
  • Netty+SpringBoot+FastDFS+Html5实现聊天App(六)
  • Sass Day-01
  • SegmentFault 技术周刊 Vol.27 - Git 学习宝典:程序员走江湖必备
  • SpringCloud(第 039 篇)链接Mysql数据库,通过JpaRepository编写数据库访问
  • vue+element后台管理系统,从后端获取路由表,并正常渲染
  • Wamp集成环境 添加PHP的新版本
  • 从零开始学习部署
  • 基于 Ueditor 的现代化编辑器 Neditor 1.5.4 发布
  • 快速体验 Sentinel 集群限流功能,只需简单几步
  • 马上搞懂 GeoJSON
  • 前端临床手札——文件上传
  • 前端知识点整理(待续)
  • 如何正确配置 Ubuntu 14.04 服务器?
  • 什么是Javascript函数节流?
  • 《天龙八部3D》Unity技术方案揭秘
  • mysql 慢查询分析工具:pt-query-digest 在mac 上的安装使用 ...
  • RDS-Mysql 物理备份恢复到本地数据库上
  • 哈罗单车融资几十亿元,蚂蚁金服与春华资本加持 ...
  • # Maven错误Error executing Maven
  • (09)Hive——CTE 公共表达式
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (Mac上)使用Python进行matplotlib 画图时,中文显示不出来
  • (Matalb分类预测)GA-BP遗传算法优化BP神经网络的多维分类预测
  • (附源码)spring boot公选课在线选课系统 毕业设计 142011
  • (附源码)ssm考试题库管理系统 毕业设计 069043
  • (五) 一起学 Unix 环境高级编程 (APUE) 之 进程环境
  • (五)MySQL的备份及恢复
  • *p++,*(p++),*++p,(*p)++区别?
  • .NET Core日志内容详解,详解不同日志级别的区别和有关日志记录的实用工具和第三方库详解与示例
  • .NET 编写一个可以异步等待循环中任何一个部分的 Awaiter
  • .NET设计模式(11):组合模式(Composite Pattern)
  • /dev下添加设备节点的方法步骤(通过device_create)
  • @DependsOn:解析 Spring 中的依赖关系之艺术
  • [ vulhub漏洞复现篇 ] Jetty WEB-INF 文件读取复现CVE-2021-34429
  • [\u4e00-\u9fa5] //匹配中文字符
  • []使用 Tortoise SVN 创建 Externals 外部引用目录
  • [<死锁专题>]