Git實現自動化部署案例實戰

通過以上的學習,我們已經對git非常熟悉了,可以設計一個自動化部署腳本:

q  約定:

1.已經有一個可以上線的代碼在git倉庫。

2.我們現在要做10個集羣節點的一鍵部署,秒級回滾。

3.所有的web服務,都應該使用普通用戶。(強烈建議)

4.所有的web服務都不應該監聽80端口,除了負載均衡。

q  自動化部署思路大綱:

1.獲取最新代碼

2.編譯(可選)

3.配置文件(軟連接或者拷貝)

4.打包(tar,加速傳輸)

5.文件分發(Scp Rsync Salt(不需要密碼驗證)

6.將目標服務器移除集羣(註釋配置文件)

7.解壓

8.防止webroot站點目錄

9.scp差異文件(可能有一個節點配置文件不一樣)

10.重啓Web服務

11.測試

12.正常回退實踐

13.緊急回退實踐

q  1.環境說明

我這裏使用1臺負載均衡兩臺web來演示(salstack批量管理會有相關章節)

主機名

IP地址

描述

部署服務

git-node

192.168.56.11

部署機兼git倉庫

Gitlab

lb-node1

192.168.56.100

負載均衡服務

Nginx

pre-node1

192.168.56.12

Web測試節點

Nginx+PHP

Web-node1

192.168.56.13

Web節點node1

Nginx+PHP

Web-node2

192.168.56.14

Web節點node2

Nginx+PHP

q  2.創建相關用戶(部署機以及web節點都需要操作)

useradd www &&  echo "123"|passwd --stdin www

q  3.部署機能登陸到web節點任意一臺機器(部署機操作)

[www@git-node1 ~]$ ssh-keygen

Generating public/private rsa key pair.

Enter file in which to save the key (/home/www/.ssh/id_rsa):

Created directory '/home/www/.ssh'.

Enter passphrase (empty for no passphrase):

Enter same passphrase again:

Your identification has been saved in /home/www/.ssh/id_rsa.

Your public key has been saved in /home/www/.ssh/id_rsa.pub.

The key fingerprint is:

fc:75:01:96:47:27:d5:d4:e3:16:e7:15:3a:b1:a4:87 www@web-node1

The key's randomart image is:

+--[ RSA 2048]----+

|            o=o+B|

|           .=.===|

|           E *o.=|

|       .. .+.|

|        S. o  |

|         . . .|

|          .|

|                 |

|                 |

+-----------------+

//分發各個web節點,會提示輸入密碼

[www@git-node1 ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]

[www@git-node1 ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]

[www@git-node1 ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]

[www@git-node1 ~]# ssh 192.168.56.13  //測試一臺

Last login: Mon Nov  7 03:45:08 2016 from 192.168.56.11

[www@web-node1 ~]$

q  4.gitlab服務部署(部署機操作)

安裝配置依賴項

 [root@git-node1 ~]# yum install curl openssh-server postfix

[root@git-node1 ~]# systemctl enable sshd postfix

[root@git-node1 ~]# systemctl start sshd postfix

[root@git-node1 ~]# firewall-cmd --permanent --add-service=http

[root@git-node1 ~]# systemctl reload firewalld

添加GitLab倉庫,並安裝到服務器上

[root@git-node1 ~]# curl -sS http://packages.gitlab.cc/install/gitlab-ce/script.rpm.sh | sudo bash

[root@git-node1 ~]# yum install gitlab-ce

啓動GitLab

gitlab-ctl reconfigure

瀏覽到主機名和登錄Browse to the hostname and login

首次訪問GitLab,系統會讓你重新設置管理員的密碼,設置成功後會返回登錄界面.

默認的管理員賬號是root,如果你想更改默認管理員賬號,請輸入上面設置的新密碼登錄系統後修改帳號名.

q  5.創建項目相關目錄(部署機操作)

項目代碼倉庫

mkdir -p /deploy/code/rainbow_pro

項目源代碼倉庫

mkdir -p /deploy/source/rainbow_pro

存放配置文件

mkdir -p /deploy/config/rainbow_pro/config

存放管理配置文件

mkdir -p /deploy/config/rainbow_pro/admin_config

mkdir -p /deploy/tmp

mkdir -p /deploy/logs

授權www用戶

chown -R www:www /deploy

chown -R www:www /home/www/

查看目錄結構

tree /deploy/

/deploy/

├── code

   └── rainbow_pro

├── config

   └── rainbow_pro

       ├── admin_config

       └── config

├── logs

├── source

   └── rainbow_pro

└── tmp

q  6.web節點需要創建的項目目錄(rainbow_pro是項目名稱,如果修改了就需要修改腳本)

mkdir –p /deploy/tmp

mkdir –p /deploy/code/rainbow_pro

schown -R www.www /deploy/

q  7.負載均衡服務器配置

安裝nginx

[root@lb-node1 ~]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

[root@lb-node1 ~]# yum install -y nginx

配置nginx

[root@lb-node1 ~]# egrep -v '#|^$' /etc/nginx/nginx.conf.default  > /etc/nginx/nginx.conf

[root@lb-node1 ~]# cat /etc/nginx/nginx.conf

worker_processes  1;

events {

    worker_connections  1024;

}

http {

    include       mime.types;

    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;

    upstream web_server {

    server 192.168.56.13:8888;

    server 192.168.56.14:8888;

    }

    server {

        listen       80;

        server_name  linux.git.com;

        location / {

            root   html;

            index  index.html index.htm;

    proxy_pass http://web_server;

        }

        error_page   500 502 503 504  /50x.html;

        location = /50x.html {

            root   html;

        }

    }

}

啓動負載均衡Nginx服務

[root@lb-node1 ~]# systemctl start nginx

q  8.sudo授權(所有web操作)

sed -i '98a www     ALL=(ALL)       NOPASSWD:ALL' /etc/sudoers

sed -i 's@Defaultsrequiretty@\#Defaultsrequiretty@g' /etc/sudoers

q  9.配置nginx(所有web操作)

安裝nginxphpphp-fpm

[root@web-node1 ~]#wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

[root@web-node1 ~]# yum install -y nginx php php-fpm

配置nginx

[root@web-node1 ~]# egrep -v '#|^$' /etc/nginx/nginx.conf.default  > /etc/nginx/nginx.conf

[root@web-node1 ~]# cat /etc/nginx/nginx.conf

user www www;

worker_processes  1;

events {

    worker_connections  1024;

}

http {

    include       mime.types;

    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;

    server {

        listen       8888;

        server_name  192.168.56.13;  #不同節點更改爲不同節點IP

        location / {

            root   /home/www/rainbow_pro;

            index  index.html index.htm;

        }

        error_page   500 502 503 504  /50x.html;

 location = /50x.html {

            root   html;

        }

    }

}

啓動所有web節點Nginx+PHP

[root@web-node1 ~]# systemctl start nginx

[root@web-node1 ~]# systemctl start php-fpm

q  10.部署機切換www用戶,添加遠程項目,執行如下腳本(注意:如無法pull,請添加www用戶keygitlab)

[root@git-node1 ~]# echo "192.168.56.11 git-node1" >> /etc/hosts

[root@git-node1 ~]# su – www

 

//首次使用需要執行如下步驟

[www@git-node1 ~]$ cd /deploy/source/rainbow_pro/

[www@git-node1 rainbow_pro]$ git init

初始化空的 Git 版本庫於 /deploy/source/rainbow_pro/.git/

[www@git-node1 rainbow_pro]$ git remote add origin git@git-node1:root/git_demo.git

[www@git-node1 rainbow_pro]$ git pull origin master

 

 

[www@git-node1 ~]$ cat deploy.sh

#!/bin/bash

 

#!/bin/bash

 

添加www用戶,並且做好相關機器的sshkey認證(部署機能登陸到web節點任意一臺機器)

# Nginx 權限必須讓www用戶可訪問

 

#項目代碼倉庫

# mkdir -p /deploy/code/rainbow_pro

 

#項目源代碼倉庫

# mkdir -p /deploy/source/rainbow_pro

 

#存放配置文件

# mkdir -p /deploy/config/rainbow_pro/config

 

#存放管理配置文件

# mkdir -p /deploy/config/rainbow_pro/admin_config 

 

# mkdir -p /deploy/tmp

 

# mkdir -p /deploy/logs

 

# web站點存放目錄

# mkdir -p /home/www/

 

#授權www用戶

# chown -R www:www /deploy

# chown -R www:www /home/www/

 

 

MSG(){

  if [ $? -eq 0 ];then

    echo "$1 OK"

    else

    echo "$1 FAIL"

    shell_unlock;

    exit 1

  fi

}

 

 

定義代碼變量

PRO_NAME="rainbow_pro"

CODE_DIR="/deploy/code/$PRO_NAME"

SOURCE_DIR="/deploy/source/$PRO_NAME"

CONFIG_DIR="/deploy/config/$PRO_NAME"

WEB_DIR="/home/www"

TMP_DIR="/deploy/tmp"

 

 

# web節點列表信息

PRE_LIST="192.168.56.12"

GROUP1_LIST="192.168.56.13 192.168.56.14"

ROLLBACK_LIST="192.168.90.13 192.168.56.14"

 

 

# Date/Time Veriables

CTIME=$(date "+%F-%H-%M")

 

# Shell Env

SHELL_NAME="deploy.sh"

SHELL_DIR="/home/www"

 

 

#日誌定義

LOG_FILE="${SHELL_DIR}/${SHELL_NAME}".log

LOCK_FILE="/tmp/deploy.lock"

 

腳本鎖

shell_lock(){

    touch ${LOCK_FILE}

}

 

shell_unlock(){

    rm -f ${LOCK_FILE}

}

 

 

測試URL

url_test(){

    URL=$1

    curl -s --head $URL |egrep '200|301|302'

}

 

日誌記錄

writelog(){

    LOGINFO=$1

    [ -f ${LOG_FILE} ] || touch ${LOG_FILE}

    echo "${CTIME}: ${SHELL_NAME} : ${LOGINFO}" >> ${LOG_FILE}

}

 

 

獲取代碼

code_get(){

    writelog "code_get"

    cd $SOURCE_DIR && git pull origin $DEPLOY_METHOD

    GIT_CID=$(git log|awk 'NR==1{print $2}'|cut -c 1-6)

    PKG_VER="${CTIME}_${GIT_CID}"

    PKG_NAME="${PRO_NAME}_${PKG_VER}"

    cp -r ${SOURCE_DIR} ${TMP_DIR}/${PKG_NAME}

}

 

#代碼編譯過程(php沒有編譯過程)

code_bulid(){

    echo code_bulid

}

 

#代碼配置文件

code_config(){

    writelog "code_config"

    /bin/cp -r ${CONFIG_DIR}/config.php ${TMP_DIR}/${PKG_NAME}/config.php

}

 

#打包代碼並去除.git目錄

code_tar(){

    writelog "code_tar"

    cd ${TMP_DIR} && tar czf ${PKG_NAME}_tar.gz ${PKG_NAME} --exclude=.git --exclude=.gitignore

    writelog "${PKG_NAME}_tar.gz"

}

 

 

#代碼發送至各個節點

code_scp(){

    writelog "code_scp"

    for node in $PRE_LIST;do

            scp ${TMP_DIR}/${PKG_NAME}_tar.gz $node:${TMP_DIR}/

    done

 

    for node in $GROUP1_LIST;do

            scp ${TMP_DIR}/${PKG_NAME}_tar.gz $node:${TMP_DIR}/

    done

 

}

 

#部署預生產環境代碼

pre_deploy(){

    writelog "Pre "$node" deploy code"

    for node in ${PRE_LIST};do

            ssh ${node} "cd ${TMP_DIR} && tar xf ${PKG_NAME}_tar.gz -C ${CODE_DIR}/"

            ssh ${node} "rm -f $WEB_DIR/${PRO_NAME} && ln -s ${CODE_DIR}/${PKG_NAME} $WEB_DIR/${PRO_NAME}"

                   MSG "Pre "$node" deploy code"

    done

}

 

#測試預生產環境代碼

pre_test(){

    for node in ${PRE_LIST};do

             url_test "http://${node}:8888/index.html" >/dev/null

                   MSG "Pre "$node" Test_URL"

    done

}

 

 

#分組部署代碼

group1_deploy(){

        writelog "Pro "$node" deploy code"

    for node in $GROUP1_LIST;do

             ssh $node "cd ${TMP_DIR} && tar xf ${PKG_NAME}_tar.gz -C ${CODE_DIR}/"

             ssh $node "rm -f $WEB_DIR/${PRO_NAME} && ln -s ${CODE_DIR}/${PKG_NAME} $WEB_DIR/${PRO_NAME}"

                   MSG "Pro "$node" deploy code"

    done

}

 

 

#分組測試代碼

group1_test(){

    for node in ${GROUP1_LIST};do

        url_test "http://${node}:8888/index.html" >/dev/null

            MSG "Pro "$node" Test_URL"

    done

}

 

 

#重啓php清理opcode緩存

code_reload(){

    for node in $GROUP1_LIST;do

            ssh $node "sudo  systemctl restart php-fpm"

                   MSG "Pro "$node" php_fpm reload"

    done

}

 

 

#列出web節點最近2天部署最新代碼

rollback_list(){

  for node in $GROUP1_LIST;do

    ssh $node /usr/sbin/ifconfig eth0|awk 'NR==2 {print $2}'|sed -r 's#(.*)# echo "\=\=\=\1\=\=\="#g'|bash

        ssh $node ls -l "$WEB_DIR"|grep "$PRO_NAME" &&\

        ssh $node find "$CODE_DIR/" -maxdepth 1 -mtime -5|sed 1d|awk -F '/' '{print $5}'

        ssh $node find "$CODE_DIR" -type d -name "$PRO_NAME*" -mtime +30|xargs rm -fr

  done

}

 

 

rollback_fun(){

  if [ -z $ROOLBACK ];then

    shell_unlock;

    echo "Please input rollback version" && exit;

else

    for node in $ROLLBACK_LIST;do

    ssh $node rm -f $WEB_DIR/${PRO_NAME} && \

    ssh $node ln -s ${CODE_DIR}/$ROOLBACK $WEB_DIR/${PRO_NAME}

    done

fi

}

 

 

main(){

  if [ -f "$LOCK_FILE" ];then

    echo "Deploy is Running" && exit;

  fi

 

  DEPLOY_METHOD="$1"

  ROOLBACK="$2"

  case $DEPLOY_METHOD in

    deploy|master|dev)   #可寫多個分支

            shell_lock;

            code_get;

            code_bulid;

            code_config;

            code_tar;

            code_scp;

            pre_deploy;

            pre_test;

            group1_deploy;

            group1_test;

            shell_unlock;

            code_reload;

            ;;

    list)

    rollback_list;

            ;;

    rollback)

            shell_lock;

            rollback_fun $ROLLBACK;

            shell_unlock;

            code_reload;

            ;;

    *)

            echo "$Usage:$0 [ branch | list | rollback ]"

    esac

}

 

main $1 $2

部署master分支代碼

[www@web-node1 ~]$ sh deploy.sh master

來自 git-node1:root/git_demo

 * branch            master     -> FETCH_HEAD

Already up-to-date.

code_bulid

rainbow_pro_2016-11-07-03-27_194199_tar.gz            100%  2700.3KB/s   00:00   

rainbow_pro_2016-11-07-03-27_194199_tar.gz            100%270     0.3KB/s   00:00

rainbow_pro_2016-11-07-03-27_194199_tar.gz            100%  2700.3KB/s   00:00   

Pre 192.168.56.12 deploy code OK

Pre 192.168.56.12 Test_URL OK

Pro 192.168.56.13 deploy code OK

Pro 192.168.56.14 deploy code OK

Pro 192.168.56.13 Test_URL OK

Pro 192.168.56.14 Test_URL OK

Pro 192.168.56.13 php_fpm reload OK

Pro 192.168.56.14 php_fpm reload OK

查看當前版本

[www@web-node1 ~]$ sh deploy.sh list

===192.168.56.13===

lrwxrwxrwx 1 www www   60 11  7 03:40 rainbow_pro -> /deploy/code/rainbow_pro/rainbow_pro_2016-11-07-03-40_194199

rainbow_pro_2016-11-07-04-10_194199

===192.168.56.14===

lrwxrwxrwx 1 www www 60 11  7 05:09 rainbow_pro -> /deploy/code/rainbow_pro/rainbow_pro_2016-11-07-03-40_194199

rainbow_pro_2016-11-07-04-10_194199

測試訪問服務器

[root@linux-node1 ~]# #echo "192.168.56.100 linux.git.com" >> /etc/hosts

[root@linux-node1 ~]# curl http://linux.git.com

hello boss

boos  doubi

更新代碼重新部署

[root@git-node1 demo]# echo "git + nginx + php" > index.html

[root@git-node1 demo]# git add index.html

[root@git-node1 demo]# git commit -m "new file"

[master 75c7d1f] new file

[root@git-node1 demo]# git push origin master

Counting objects: 10, done.

Compressing objects: 100% (4/4), done.

Writing objects: 100% (6/6), 575 bytes | 0 bytes/s, done.

Total 6 (delta 0), reused 0 (delta 0)

To git@git-node1:root/git_demo.git

   1941990..75c7d1f  master -> master

 

//重新部署

[www@web-node1 ~]$ sh deploy.sh master 

 

//重新測試

[root@linux-node1 ~]# curl http://linux.git.com

git + nginx + php

執行回滾操作,回退上一個版本

[www@linux-node1 ~]$ sh deploy.sh rollback  //不允許直接執行

Please input rollback version

 

//首先使用list查看想要回退的版本

[www@web-node1 ~]$ sh deploy.sh list

===192.168.56.11===

lrwxrwxrwx 1 www www   60 11  7 04:17 rainbow_pro -> /deploy/code/rainbow_pro/rainbow_pro_2016-11-07-04-17_75c7d1

rainbow_pro_2016-11-07-04-10_194199

rainbow_pro_2016-11-07-04-17_75c7d1

===192.168.56.12===

lrwxrwxrwx 1 www www 60 11  7 05:46 rainbow_pro -> /deploy/code/rainbow_pro/rainbow_pro_2016-11-07-04-17_75c7d1

rainbow_pro_2016-11-07-04-10_194199

rainbow_pro_2016-11-07-04-17_75c7d1

 

 

//回退至上一個版本

[www@web-node1 ~]$ sh deploy.sh rollback rainbow_pro_2016-11-07-04-10_194199

Pro 192.168.56.11 php_fpm reload OK

Pro 192.168.56.12 php_fpm reload OK

 

//再次查看,已經回退上一個版本

[root@linux-node1 ~]# curl http://linux.git.com

hello boss

boos  doubi

查看代碼部署日誌

[www@web-node1 ~]$ cat deploy.sh.log

2016-11-07-04-10: deploy.sh : code_get

2016-11-07-04-10: deploy.sh : code_config

2016-11-07-04-10: deploy.sh : code_tar

2016-11-07-04-10: deploy.sh : rainbow_pro_2016-11-07-04-10_194199_tar.gz

2016-11-07-04-10: deploy.sh : code_scp

2016-11-07-04-10: deploy.sh : Pre 192.168.56.12 deploy code

2016-11-07-04-17: deploy.sh : Pro 192.168.56.13 deploy code

2016-11-07-04-10: deploy.sh : Pro 192.168.56.14 deploy code

2016-11-07-04-17: deploy.sh : code_get

2016-11-07-04-17: deploy.sh : code_config

2016-11-07-04-17: deploy.sh : code_tar

2016-11-07-04-17: deploy.sh : rainbow_pro_2016-11-07-04-17_75c7d1_tar.gz

2016-11-07-04-17: deploy.sh : code_scp

2016-11-07-04-17: deploy.sh : Pre 192.168.56.12 deploy code

2016-11-07-04-17: deploy.sh : Pro 192.168.56.13 deploy code

2016-11-07-04-17: deploy.sh : Pro 192.168.56.14 deploy code



徐亮偉, 江湖人稱標杆徐。多年互聯網運維工作經驗,曾負責過大規模集羣架構自動化運維管理工作。擅長Web集羣架構與自動化運維,曾負責國內某大型電商運維工作。

個人博客"[徐亮偉架構師之路](http://www.xuliangwei.com)"累計受益數萬人。

筆者Q:552408925、572891887 

架構師羣:471443208

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章