1. 程式人生 > >git+python+管理機實現配置文件版本控制

git+python+管理機實現配置文件版本控制

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+管理機實現配置文件版本控制