git+python+管理机实现配置文件版本控制

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了git+python+管理机实现配置文件版本控制相关的知识,希望对你有一定的参考价值。

随着公司业务越来越多,业务的分组也越来越多,像nginx,haproxy,lvs等也会区分出多组配置,所以想着自己写一套简单的支持多人操作/版本控制/快速回滚的一套管理方案。
简单描述一下我的设计思路
通过单一的跳板机来git pull拉取每个业务的nginx配置文件,在通过跳板机修改后执行脚本实现语法测试,测试通过直接更新线上,如更新后发现bug实现快速回滚,一切的操作通过脚本执行,运维感知不到git的存在

现就上面的目的写出目前实现的效果
技术分享图片

A:10.0.4.12 配置管理中心
B:10.5.8.19 线上tengine(可以为多个)

1,登陆配置文件管理服务器,用户以个人用户登陆进行修改配置操作
2,更新最新的配置文件
技术分享图片

会把配置下载到自己的家目录,以防多人同时操作出现问题
这里贴出脚本内容

#!/bin/sh
PID=`ps ef | grep commit.sh| grep -v grep | wc -l`
if [ $PID -eq 2 ]
then
    continue
else
    echo -e "\033[41;37;1m already someone usering  \033[0m"
    exit 4
fi
parameter1=`echo "$1" |sed  s/[[:space:]]//g`
parameter2=`echo "$2" |sed  s/[[:space:]]//g`

if [ $# -eq 1 ]
then
    if [ $parameter1 == ‘pull‘ ]
    then
        cd /home/`whoami`/deploy/
        git fetch --all >/dev/null 2>&1
        git reset --hard origin/master >/dev/null 2>&1
        git pull
        exit 3
    fi
fi

if [ $# -ne 2 ]
then
    echo -e "\033[41;37;1m update configs ----->\c\033[0m"
    echo -e "\033[32;1m commit.sh pull \033[0m"
    echo -e "\033[41;37;1m delete file ----->\c\033[0m"
    echo -e "\033[32;1m commit.sh rm FILENAME \033[0m"
    echo -e "\033[41;37;1m commit configs ----->\c\033[0m"
    echo -e "\033[32;1m commit.sh CHANGEINF APPNAME \033[0m"
    echo -e "\033[41;37;1m stop action ----->\c\033[0m"
    echo -e "\033[32;1m commit.sh APPNAME stop \033[0m"
    exit 2
fi

if [ $parameter2 == ‘stop‘ ]
then
    sudo python /data/config/change_run.py -s $parameter1 -a stop
    exit 7
fi

git config --global user.email `whoami`@meicai.cn 
git config --global user.name `whoami`

cd /home/`whoami`/deploy/ 
git add .
git status
git diff master
if [ $parameter1 == ‘rm‘ ]
then
    cd /home/`whoami`/deploy
    git rm $parameter2
    if [ $? -eq 0 ]
    then
        echo -e "\033[32;1m delete is complated \033[0m"
        exit 2
    else
        echo -e "\033[41;37;1m delete error \033[0m"
        exit 3
    fi
fi

echo -e "\033[32;1m please confirm your change Y(commit) or N(interrupt): \033[0m"
read -p "" YN
if [ $YN == "Y" -o $YN == "y" ]
then
    sudo rsync -av --delete --progress --exclude .git/  /home/`whoami`/deploy/  /data/config/deploy/
    if [ $? -eq 0 ]
    then
        sudo python /data/config/sync.py -s $parameter2
        return_status=$?
        if [ $return_status -eq 0 ]
        then
            git commit -m $parameter1
            git push
            if [ $? -eq 0 ]
            then
                echo -e "\033[32;1m $parameter1 push git server is complate \033[0m"
            else
                echo -e "\033[41;37;1m push error \033[0m"
            fi
        elif [ $return_status -eq 3 ];then
            exit 7
        else
            echo -e "\033[41;37;1m reload error \033[0m"
            echo -e "\033[41;37;1m already roll-back \033[0m"
            exit 6
        fi
    else
        echo -e "\033[41;37;1m sync error \033[0m"
        exit 5
    fi
else
    exit 3
fi

python /data/config/change_run.py -s $parameter2 -a start

3,通过vim等工具进行修改配置文件,这里注意如果有删除的文件,在rm后还要执行,commit.sh rm FILENAME(相对路径)
4,修改完后提交最新配置
sh commit.sh CHANGEINFO PRODUCTNAME
这里的两个参数做下介绍
CHANGEINFO:这次操作你修改了什么
PRODUCTNAME:你修改了哪个项目的配置
技术分享图片
这里脚本其实会调用sync.py这么一个同步脚本
这里贴出具体内容

# -*- coding: utf-8 -*-

import os
import argparse
import ConfigParser
import ansible.runner
import json
import sys
import time
import getpass  

parser = argparse.ArgumentParser(description="USEAGE: python sync.py -s APPNAME")
parser.add_argument(‘-s‘, help="Service name", required=True)

def Sync():
    runner_sync = ansible.runner.Runner(
        module_name=‘synchronize‘,
        module_args="delete=yes" + ‘ ‘ + "src=" + app_src + ‘ ‘ + "dest=" + app_dest + " " + "dest_port=" + dest_port,
        pattern=args.s,
        forks=10
        )

    datastructure = runner_sync.run()
    data = datastructure.get(‘contacted‘)
    return data
def Tar_zcvf():
    runner_command = ansible.runner.Runner(
        module_name=‘shell‘,
        module_args="tar -zcvf" + ‘ ‘ + "/tmp/" + args.s + ".tar.gz" + ‘ ‘ + app_dest,
        pattern=args.s,
        forks=10
        )   
    command_runner = runner_command.run()
    return command_runner

def Command():
    runner_command = ansible.runner.Runner(
        module_name=‘shell‘,
        module_args=res_service,
        pattern=args.s,
        forks=10
        )
    command_runner = runner_command.run()
    return command_runner
def Roll_back():
    runner_command = ansible.runner.Runner(
        module_name=‘shell‘,
        module_args="cd /" + ";" + "rm -rf" + " " + app_dest + ";" + "tar -xvf" + ‘ ‘ + "/tmp/" +  args.s + ".tar.gz" + ‘ ‘ + "-C" + "/",
        pattern=args.s,
        forks=10
        )   
    command_runner = runner_command.run()
    return command_runner
if __name__ == "__main__":
    config=ConfigParser.ConfigParser()
    config.read(u‘/data/config/app_dir.conf‘)
    args = parser.parse_args()

    try:
        app_src = config.get(args.s,‘src‘)
        app_dest = config.get(args.s,‘dest‘)
        res_service = config.get(args.s,‘res_service‘)
        dest_port = config.get(args.s,‘dest_port‘)
        running = config.get(args.s,‘running‘)
        current_user = config.get(args.s,‘current_user‘)
    except ConfigParser.NoSectionError:
        print ‘Without this app‘
        sys.exit(5)
    if int(running) == 0:
        Tar_zcvf()
        for k,v in Sync().items():
            if v.get(‘failed‘):
                print k,v.get(‘msg‘)
                exit(6)
            else:
                if v.get(‘changed‘) == False:
                    print(‘\033[1;31;40m‘)
                    print k + ": is not changed"
                    print(‘\033[0m‘)
                else:
                    print(‘\033[1;32;40m‘)
                    print k + ": change complated"
                    print(‘\033[0m‘)
                  #time.sleep(5)
                    cmd = Command().get(‘contacted‘).get(k).get(‘cmd‘)
                    stdout = Command().get(‘contacted‘).get(k).get(‘stdout‘)
                    stderr = Command().get(‘contacted‘).get(k).get(‘stderr‘)
                    if stdout:
                        print(‘\033[1;32;40m‘)
                        print "cmd:" + cmd
                        print stdout
                        print(‘\033[0m‘)
                    else:
                        print stderr
                        Roll_back()
                        sys.exit(1)
    else:
        print(‘\033[1;32;40m‘)
        print current_user + " " + "userd"
        print(‘\033[0m‘)
        sys.exit(3)

随便添加了个文件 这里我通过hostname的命令来获取配置的语法正确(直接拿线上的进行测试就不用nginx -t啦)
技术分享图片
最后也会有输出显示已经把最新配置上传到git服务器

5,待完成后执行commit.sh tengine_mall stop结束此次操作,方便其他人再做修改,因为我这里做了操作保护,一旦有1个人正在执行修改的时候,其他人是禁止操作的
最后贴出配置文件的格式
/data/config/app_dir.conf
[tengine_mall]
src = /data/config/deploy/tengine/tengine_mall/nginx
dest = /tmp/test
res_service = "hostname"
dest_port = 50022
running = 0
current_user = zhangsan

以上是关于git+python+管理机实现配置文件版本控制的主要内容,如果未能解决你的问题,请参考以下文章

Git配置版本控制与分支管理

Git和SVN,代码管理哪个更好

——Git版本控制工具安装和配置

python后端面试第六部分:git版本控制--长期维护

Git与SVN对比

Git原理架构详解