美文网首页程序员
开发管理的乐趣(2) -- 最小化DevOps自动化流程(Gol

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

作者: 拼命三郎OL | 来源:发表于2018-11-17 06:57 被阅读0次
    • 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及微服务架构,会给自己带来很大的困惑。具体这些将会在后续的文章中提到。

    相关文章

      网友评论

        本文标题:开发管理的乐趣(2) -- 最小化DevOps自动化流程(Gol

        本文链接:https://www.haomeiwen.com/subject/cggbzxtx.html