缺點:

效率: 發布方式一單一服務器上線沒問題,多服務器分發效率下降。如果網內是統一入口登錄(即堡壘機為單一入口時),發布工作將變得極為困難。

安全風險:發布方式二的SSH賬號密碼必須存在Jenkins上,雖然不是明文,但…..同樣也面臨這服務器的22口要對Jenkins開放,安全是問題。

采用系統方案:YUM

我當時的思路:公司是等保三級的單位,在當初我制定內網規則的時候,強烈建議SSH登錄范圍必須限定,統一的入口可以極大的減少被***跳板式***的可能,所以我想到了是用YUM更新的方式:

發布:把代碼從SVN上遷出后,打成RPM包(強烈推介FPM)

更新:通過YUM的特性,更新的程序包每次保持版本號 1,例如test-519-1.x86_64(519就是Jenkins的發布版本號),服務器每次只需要執行以下2條命令即可。

bash
yum clean all
yum install test

批量操作:通過Saltstack去通知每臺服務器去進行Yum的動作啦。。。

回退: 就更簡單了,粗暴點在YUM服務器直接 mv test-518-1.x86_64 test-520-1.x86_64即可,斯文點當然還是回調Jenkins的接口,使用TAG回滾。

具體邏輯及實施

那么下面先來解決打RPM包,更新YUM源的問題(我的Jenkins就是我們內網的YUM源):

配置Jenkins

首先我們需要打開Jenkins中的batch tasks(批處理,其實就是腳本),不會用Jenkins自己百度吧。

點擊Add post-build action-選擇Invoke batch tasks

Batch tasks里填入腳本

bash
mkdir -p /home/release/$JOB_NAME && \\\\
fpm -s dir -t rpm -n $JOB_NAME -v $BUILD_NUMBER --prefix /home/www/bbs -C /var/lib/jenkins/workspace/$JOB_NAME -p /home/release/$JOB_NAME ./ && \\\\
createrepo --update /home/release/$JOB_NAME/ && \\\\
curl -d job_id=$JOB_NAME http://salt master IP/cmdb/salt_jenkins_post/

這段Jenkins腳本的大體意思:

創建/home/release/$JOB_NAME目錄

然后把/var/lib/jenkins/workspace/$JOB_NAME(Jenkins項目工作區)的代碼打成一個以$JOB_NAME命名,版本號為$JOB_NAME的RPM包,其存放在/home/release/$JOB_NAME這個目錄里,其解壓后會解壓到/home/www/bbs目錄。

然后createrepo --update /home/release/$JOB_NAME/ 通知更新更新YUM源.

最后就是回調我的Salt接口(此接口的作用其實就是根據這個項目反查對應的哪幾臺發布主機,然后在這些主機上執行yum install命令,是不是很無腦~)

Saltstack接口(saltjenkinspost)

由于我的平臺和Salt master是同一臺(主要是省事),省去了調用API,直接調用了本地Saltstack已經封裝的一些yum install 之類的命令。

upgradeavailable 驗證yum源是否更新

install 安裝

modrepo 創建yum源

getrepo 驗證yum源是否存在

intro 執行更新后的一些命令

我在接口處理的每一步后都會驗證返回的主機是否跟數據庫預設的項目主機一樣,只有一樣了才會進行下一步(比如接口只返回了一臺服務器通過salt執行的結果,而數據庫里該項目是兩臺服務器,我會認為這個發布有問題,而進行中斷)這樣也是為了避免有的主機更新成功了,有的主機沒更新成功,導致線上用戶體驗不好(目前已經成功從深信服公司要到了負載均衡的API)后面要做的就是采用灰度發布,從負載上摘除一個然后就更新一個,更新完畢再加回負載。

import json
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt

try:
    import salt.client
except:
    pass
from cmdb.models import *

class Salt_jenkins:
    def __init__(self, host_list, job):
        self.client = salt.client.LocalClient()
        self.host_list = host_list
        self.type = type
        self.job = job


    def upgradeavailable(self):
        檢測目標主機組項目在yum上是否有新版本更新,返回可以更新的主機
        ret = self.client.cmd(\\\'%s\\\'% self.host_list, \\\'pkg.upgrade_available\\\', [\\\'%s\\\'% self.job],expr_form=\\\'list\\\',ret=\\\'return_Redis\\\')
        true_hostlist = []
        for host in ret.keys():
            if ret[\\\'%s\\\' % host]:
                true_hostlist.append(host)
            else:
                pass
        return true_hostlist

    def install(self):
        YUM安裝項目RPM包
        ret = self.client.cmd(\\\'%s\\\'% self.host_list, \\\'pkg.install\\\', [\\\'%s\\\'% self.job],expr_form=\\\'list\\\',ret=\\\'return_redis\\\')
        true_hostlist = []
        for host in ret.keys():
            if ret[\\\'%s\\\' % host] != {}:
                install_ret = ret[\\\'%s\\\' % host][\\\'%s\\\' % self.job]
                if install_ret != \\\'\\\':
                    true_hostlist.append(host)
                else:
                    pass
            else:
                pass
        return true_hostlist

    def modrepo(self):
        創建項目YUM源
        ret = self.client.cmd(\\\'%s\\\'% self.host_list, \\\'pkg.mod_repo\\\',[\\\'repo=%s\\\'% self.job,\\\'baseurl=http://172.18.11.98/release/%s\\\'% self.job,\\\'enabled=1\\\',\\\'gpgcheck=0\\\',\\\'name=%s\\\'% self.job,\\\'priority=10\\\'],expr_form=\\\'list\\\',ret=\\\'return_redis\\\')
        true_hostlist = []
        for host in ret.keys():
            if type(ret[\\\'%s\\\' % host]) == dict:
               true_hostlist.append(host)
            else:
                pass
        return  true_hostlist

    def getrepo(self):
        驗證項目YUM源是否存在
        ret = self.client.cmd(\\\'%s\\\'% self.host_list, \\\'pkg.get_repo\\\', [\\\'repo=%s\\\'% self.job],expr_form=\\\'list\\\',ret=\\\'return_redis\\\')
        true_hostlist = []
        for host in ret.keys():
            if ret[\\\'%s\\\' % host] != {}:
               true_hostlist.append(host)
            else:
                pass
        return  true_hostlist

    def intro(self):
        執行svn_intro內命令
        command = Svn.objects.get(svn_name = self.job).svn_intro
        ret = self.client.cmd(\\\'%s\\\'% self.host_list, \\\'cmd.run\\\', [\\\'%s\\\'% command],expr_form=\\\'list\\\',ret=\\\'return_redis\\\')
        return ret


@csrf_exempt    
def salt_jenkins_post(request):
    if request.method == \\\'POST\\\':     
        ip = request.META.get(REMOTE_ADDR, None)
        if ip == \\\'172.18.11.98\\\':   
            job =  request.POST.get(\\\'job_id\\\')
            job_hosts =  Svn.objects.get(svn_name=job).svn_hosts
            if job ==\\\'cms_template.youth.cn\\\' or job ==\\\'cms_assets.youth.cn\\\':
                pass
            else:
                初始化Salt_jenkins
                salt_jenkins = Salt_jenkins(job_hosts, job)

                目標主機檢查YUM源是否存在
                if sorted(salt_jenkins.getrepo()) == sorted(str(job_hosts).split(\\\',\\\')):
                    pass
                else:
                    不存在就創建YUM源
                    salt_jenkins.modrepo()
                目標主機檢查YUM源是否更新
                if sorted(salt_jenkins.upgradeavailable()) == sorted(str(job_hosts).split(\\\',\\\')):
                    if sorted(salt_jenkins.install()) == sorted(str(job_hosts).split(\\\',\\\')):
                        目標主機執行命令
                        salt_jenkins.install()
                        目標主機執行命令
                        salt_jenkins.intro()
                        return HttpResponse(\\\'install success\\\')
                    else:
                        return HttpResponse(\\\'install fail\\\')
                else:
                    return HttpResponse(\\\'upgradeavailable fail\\\')
        else:
            return HttpResponse(\\\'ip deny\\\')
    else:
        return HttpResponse(\\\'get deny\\\')

后續會介紹發布的狀態返回,也就是Saltstack的MasterEvent及通過Jenkins結合Saltstack創新發布項目。

更多關于云服務器域名注冊,虛擬主機的問題,請訪問三五互聯官網:www.shinetop.cn

贊(0)
聲明:本網站發布的內容(圖片、視頻和文字)以原創、轉載和分享網絡內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。郵箱:3140448839@qq.com。本站原創內容未經允許不得轉載,或轉載時需注明出處:三五互聯知識庫 » 授之以漁-運維平臺發布模塊一(Jenkins篇)

登錄

找回密碼

注冊

主站蜘蛛池模板: 日韩精品成人区中文字幕| 亚洲永久精品免费在线看| 男人扒女人添高潮视频| 亚洲综合网一区中文字幕| 少妇上班人妻精品偷人| 国产精品剧情亚洲二区| 国产成人8X人网站视频| 宅男噜噜噜66网站高清| 韩国三级网一区二区三区| 亚洲精品乱码久久久久久中文字幕| 国产农村乱人伦精品视频| 人人爽人人爽人人爽| 视频专区熟女人妻第二页| 夜夜躁日日躁狠狠久久av| 中文字幕人成乱码熟女| 久久综合免费一区二区三区| 日韩精品无码区免费专区| 麻豆国产AV剧情偷闻女邻居内裤| 四虎国产精品免费久久| 亚洲精品成人片在线观看精品字幕 | 家庭乱码伦区中文字幕在线| 久久亚洲精品11p| 99国产精品99久久久久久| 日韩本精品一区二区三区| 国产喷水1区2区3区咪咪爱AV| 亚洲an日韩专区在线| 日韩人妻一区二区三区蜜桃视频| 色综合久久天天综线观看| 漂亮人妻中文字幕丝袜| 韩国V欧美V亚洲V日本V| 亚洲精品久久国产高清小说| 亚洲伊人久久综合成人| 国产精品国产三级国产午| 国产999久久高清免费观看| 高清中文字幕国产精品| 欧美精欧美乱码一二三四区 | 秋霞电影网| 亚洲中文字幕精品一区二区三区| 亚洲中文字幕精品第一页| 亚洲精品一区二区妖精| 337P日本欧洲亚洲大胆精品555588|