开发管理的乐趣(2) -- 最小化DevOps自动化流程(Golang)

  • Why?

为什么要做自动化流程?

在开发过程中,我们在本地机器上做开发,完成一次功能迭代之后,如何发布到远程产品服务器一直是个很头疼的问题。最通常的做法就是使用(S)FTP把代码(或者代码压缩包)覆盖到服务器上。这样的做法虽然“直截了当”,但是容易出错,而且全程需要人为干预。(笔者亲历过其他项目部门的负责人过来求助,说发布时拷贝代码到服务器的过程中,服务器突然宕机没有反应。)所以我们需要一种方式帮助我们完成代码发布的整个过程。有非常多的第三方工具帮助我们实现流程自动化的目的。
我们要完成的目标是:1,无人干预;2,缩短发布时间,减少发布时期存在的风险;3,增加项目迭代效率。

  • What?

用什么工具来做自动化流程?

git, github(gitlab)

  • When?

在什么时机下创建自动化流程?

理论上是在第一次发布项目到服务器之前就需要做自动化流程。但是根据迭代开发的思想,我们在创建项目的时候就应该开始着手创建自动化流程。

  • How?

如何创建一个最小化的自动化流程?

我们通过三部实现开发部署流程自动化。

  1. 创建版本仓库

笔者使用Gitlab创建一个名为DevOps的私有仓库.
new gitlab repo

接着clone 远程仓库到本地开发机器.
如果你还没有创建任何项目代码文件。此时可以使用命令:

git clone git@gitlab.com:EdisonLeung/devops.git
cd devops
touch README.md
git add README.md
git commit -m "add README"
git push -u origin master 

如果您已经开始了本地机器上的编码工作,此时可以在项目目录下使用命令:

git init
git remote add origin git@gitlab.com:EdisonLeung/devops.git
git add .
git commit -m "Initial commit"
git push -u origin master

如果您不光在本地开始了编码工作,同时在本地已经创建了git仓库.此时可以在项目目录下使用命令:

git remote rename origin old-origin
git remote add origin git@gitlab.com:EdisonLeung/devops.git
git push -u origin --all
git push -u origin --tags

最后在服务器clone我们的版本仓库(记得添加服务器SSH Key到Gitlab):

cd ~/www
git clone git@gitlab.com:EdisonLeung/devops.git

clone完成:

root@aliyun:~/www# git clone git@gitlab.com:EdisonLeung/devops.git
Cloning into 'devops'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (3/3), done.

目前我们从项目开发到项目部署有三个动作要手动做:
a) 本地机器git push到远程仓库
b) 远程服务器git pull拉去远程仓库版本
c) 重启webserver服务
第二步我们就要将这三个动作自动化。

  1. 创建自动化部署脚本

创建deploy目录,并创建两个文件,main.go和deploy.sh:


目录结构

deploy.go

package main

import (
    "io"
    "log"
    "net/http"
    "os/exec"
)

func relaunching() {
    cmd := exec.Command("sh", "./deploy.sh")
    err := cmd.Start()
    if err != nil {
        log.Fatal(err)
    }
    err = cmd.Wait()
}

func restart(w http.ResponseWriter, r *http.Request) {
    io.WriteString(w, "<h1>deploy server: restarting webserver...</h1>")
    relaunching()
    io.WriteString(w, "<h1>deploy server: webserver restarted!</h1>")
}

func main() {
    http.HandleFunc("/", restart)
    http.ListenAndServe(":5000", nil)
}

当服务器5000端口被访问时,http.HandleFunc会创建路由调用restart函数relaunching函数,调用过程中在浏览器输出启动过程.
最终relaunching函数调用命令行deploy.sh来重启webserver.
deploy.sh脚本内容如下:

#! /bin/sh

kill -9 $(pgrep webserver)
cd ~/www/devops
git pull git@gitlab.com:EdisonLeung/devops.git
./webserver &

再创建一个main.go来启动一个最小web页面:


webserver main.go

代码示例如下:

package main

import (
    "io"
    "net/http"
)

func index(w http.ResponseWriter, r *http.Request) {
    io.WriteString(w, "<h1>This is Index Page!</h1>")
}

func main() {
    http.HandleFunc("/", index)
    http.ListenAndServe(":8080", nil)
}

注意:这里的http监听端口号要与deploy.go内的端口号区别开,不能是相同端口号,不然会有端口冲突造成服务不能启动!

这时的代码架构就完成了,下面我们来编译发布代码:
因为我们在本地机器环境编译代码,所以对于异构系统来说,go语言为我们提供了相应的参数来针对不同的操作系统和架构进行代码的编译:
因为服务器所采用的是linux amd64的系统,所以编译命令的环境变量如下:
main.go编译生成webserver

env GOOS=linux GOARCH=amd64 go build -o webserver

进入deploy目录编译生成deploy

env GOOS=linux GOARCH=amd64 go build

输出的文件如图:


编辑结果

下面我们提交项目:
进入DevOps根目录

git add .
git commit -m "basic automatic publishing feature."
git push origin master

提交结果:

Counting objects: 8, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (8/8), done.
Writing objects: 100% (8/8), 5.03 MiB | 1.21 MiB/s, done.
Total 8 (delta 1), reused 0 (delta 0)
To gitlab.com:EdisonLeung/devops.git
   91e5396..c9c087f  master -> master

接下来就要进入服务器拉去最新版本代码并发布。
登录远程服务器拉取代码:

root@aliyun:~/www/devops# git pull
remote: Enumerating objects: 9, done.
remote: Counting objects: 100% (9/9), done.
remote: Compressing objects: 100% (8/8), done.
remote: Total 8 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (8/8), done.
From gitlab.com:EdisonLeung/devops
   91e5396..c9c087f  master     -> origin/master
Updating 91e5396..c9c087f
Fast-forward
 deploy/deploy    | Bin 0 -> 6594124 bytes
 deploy/deploy.go |  28 ++++++++++++++++++++++++++++
 deploy/deploy.sh |   6 ++++++
 main.go          |  15 +++++++++++++++
 webserver        | Bin 0 -> 6498848 bytes
 5 files changed, 49 insertions(+)
 create mode 100755 deploy/deploy
 create mode 100644 deploy/deploy.go
 create mode 100644 deploy/deploy.sh
 create mode 100644 main.go
 create mode 100755 webserver

将deploy目录拷贝至用户根目录:
cp -r ~/www/devops/deploy/* ~/
启动webserver和deploy service:

cd ~
./www/devops/webserver &
./deploy &

打开浏览器查看结果显示:


webserver result
deploy service result

两个服务均启动成功了!
注意1.两个服务启动前,先用以下命令查看是否有相同服务正在运行,如果有,先将其kill掉:
$ps aux | grep webserver
$kill [pid]
注意2.使用chmod命令给服务程序和脚本提权:
chmod a+x webserver

  1. 自动获取版本推送事件webhook

我们将部署触发的地址添加到远程版本仓库的webhook中,如图:

webhook

webhook添加完成:
webhook

下面我们验证一下这个简单的自动化流程的效果。
我们把显示的文本改为"This is the Index Page2".
change code

然后编译提交
编译提交

查看结果:
发布迭代成功

文章中提到的做法仅仅是抛砖引玉,实现使用Golang是因为语言结构上简短精悍,更容易理解流程,如果您使用其他语言,例如python,php等都可以用相同的方式实现。同时流程上仅关注自动化的过程,开发编译的整个过程都在本地进行,服务端没有提到任何反向代理的服务及运行环境、虚拟环境的配置,因为在虚拟化环境下这些做法会有很多变化,很多情况下完全没有必要做,或者很少去做。更没有必要像目前这样自己去实现自动化流程。如果没有虚拟化实现自动化流程的经验,直接上手虚拟化,还没有很深入理解的情况下,在虚拟化环境下做DevOps及微服务架构,会给自己带来很大的困惑。具体这些将会在后续的文章中提到。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,100评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,308评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,718评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,275评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,376评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,454评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,464评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,248评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,686评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,974评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,150评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,817评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,484评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,140评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,374评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,012评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,041评论 2 351

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,644评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,945评论 25 707
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,709评论 2 59
  • (三 又见蔺硕) 这几天厂里没有原料,不能上班,又能做点儿什么呢?姜然心里揣摩。“不如叫上秀芳一起去蔡企民那里报个...
    宝宝蛋儿阅读 320评论 0 0
  • 引言:P2P解决的是供需关系的对接,人工智能是大数据分析加智能化的集合,通过大数据筛选智能匹配,保证借贷人和出借人...
    2ee6980a78cf阅读 181评论 0 0