1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        手把手教你搭建一個(gè)灰度發(fā)布環(huán)境

        共 7890字,需瀏覽 16分鐘

         ·

        2020-10-01 16:07







        ?作者:?DevUI團(tuán)隊(duì)

        https://segmentfault.com/a/1190000022612488

        引言

        灰度發(fā)布,又稱(chēng)金絲雀發(fā)布。

        金絲雀發(fā)布這一術(shù)語(yǔ)源于煤礦工人把籠養(yǎng)的金絲雀帶入礦井的傳統(tǒng)。礦工通過(guò)金絲雀來(lái)了解礦井中一氧化碳的濃度,如果一氧化碳的濃度過(guò)高,金絲雀就會(huì)中毒,從而使礦工知道應(yīng)該立刻撤離?!禗evOps實(shí)踐指南》

        對(duì)應(yīng)到軟件開(kāi)中,則是指在發(fā)布新的產(chǎn)品特性時(shí)通過(guò)少量的用戶(hù)試點(diǎn)確認(rèn)新特性沒(méi)有問(wèn)題,確保無(wú)誤后推廣到更大的用戶(hù)使用群體。

        集成灰度發(fā)布的流水線在DevOps中是一個(gè)非常重要的工具和高效的實(shí)踐,然而筆者在入職以前對(duì)流水線和灰度發(fā)布知之甚少。在了解一個(gè)新東西時(shí),先從邏輯上打通所有的關(guān)鍵環(huán)節(jié),然后再完成一個(gè)最簡(jiǎn)單的Demo,對(duì)于我們來(lái)說(shuō)是比較有意思的學(xué)習(xí)路徑,因此便有了這篇文章。

        本文理論內(nèi)容較少,主要是從零到一的搭建流程實(shí)踐,適合對(duì)工程化感興趣的初級(jí)前端開(kāi)發(fā)者。

        01 服務(wù)器準(zhǔn)備

        獲取服務(wù)器

        上面提到,灰度發(fā)布是通過(guò)少量的用戶(hù)試點(diǎn)來(lái)驗(yàn)證新功能有沒(méi)有問(wèn)題。所以要保證有兩批用戶(hù)能在同一時(shí)間體驗(yàn)到不同的功能。這就要求我們準(zhǔn)備兩臺(tái)服務(wù)器,分別部署不同的代碼版本。

        如果你已經(jīng)有了一臺(tái)服務(wù)器,也可以通過(guò)在不同端口部署服務(wù)的方式來(lái)模擬兩臺(tái)服務(wù)器。如果你還一臺(tái)服務(wù)器都沒(méi)有,那么可以參考這個(gè)過(guò)程購(gòu)買(mǎi)兩臺(tái)云服務(wù)器,如果是按需購(gòu)買(mǎi),完成本文的Demo,大概要花費(fèi)20塊錢(qián)。

        獲取云服務(wù)器教程:github.com/TerminatorS…

        工具安裝

        Git

        首先,確保你的服務(wù)器上已經(jīng)安裝了git,如果沒(méi)有的話使用以下命令進(jìn)行安裝,安裝好了以后生成ssh 公鑰,放到你的github 里,后面拉取代碼的時(shí)候會(huì)用到。

        yum?install?git

        Nginx

        如果你的服務(wù)器沒(méi)有Nginx,先按照以下操作進(jìn)行安裝,Linux 下安裝Nginx非常簡(jiǎn)單:

        sudo?yum?install?nginx

        安裝完了,在終端輸入nginx -t檢查一下是否安裝成功。如果安裝成功,它會(huì)顯示Nginx 配置文件的狀態(tài),以及位置。

        此時(shí)nginx還沒(méi)有啟動(dòng),在終端中輸入nginxnginx \-s reload 命令即可啟動(dòng),此時(shí)看到的nginx相關(guān)進(jìn)程如下,表明已經(jīng)啟動(dòng)成功。

        在瀏覽器里訪問(wèn)你的服務(wù)器公網(wǎng)IP,如果能看到下面的頁(yè)面說(shuō)明Nginx 可以正常工作。

        Jenkins (耗時(shí)比較久)

        第一次接觸Jenkins 可能會(huì)有很多疑問(wèn),Jenkins 是什么?能完成什么事情?我為什么要使用Jenkins 等諸如此類(lèi)。很難講清楚Jenkins 是什么東西,所以這里簡(jiǎn)單介紹一下Jenkins 可以做什么。簡(jiǎn)單來(lái)講,你在任何一臺(tái)服務(wù)器上進(jìn)行的任何操作命令,Jenkins 都可以幫你完成,只要你提前在Jenkins上創(chuàng)建好任務(wù),指定任務(wù)內(nèi)容和觸發(fā)時(shí)機(jī),比如定時(shí)觸發(fā)或者在特定的情況下觸發(fā)。

        (1)安裝

        Jenkins穩(wěn)定版本list:pkg.jenkins-ci.org/redhat-stab…

        //?科學(xué)上網(wǎng)會(huì)快一些,記得留意網(wǎng)站上java和jenkins版本匹配信息,別下錯(cuò)了
        wget?http://pkg.jenkins-ci.org/redhat-stable/jenkins-2.204.5-1.1.noarch.rpm
        rpm?-ivh?jenkins-2.204.5-1.1.noarch.rpm

        修改Jenkins端口,不沖突可不修改

        //?line?56?JENKINS_PORT
        vi?/etc/sysconfig/jenkins

        (2)啟動(dòng)

        啟動(dòng)jenkins

        service?jenkins?start/stop/restart
        //?密碼位置
        /var/lib/jenkins/secrets/initialAdminPassword

        (3)訪問(wèn)

        訪問(wèn)服務(wù)器的8080端口,輸入從上述位置獲取的密碼,點(diǎn)擊繼續(xù)

        創(chuàng)建一個(gè)賬戶(hù)然后登錄

        看到Jenkins 已就緒的頁(yè)面表示安裝已經(jīng)完成,服務(wù)器準(zhǔn)備工作到此結(jié)束。

        02 代碼準(zhǔn)備

        準(zhǔn)備兩份代碼

        因?yàn)橐龌叶炔渴穑孕枰獪?zhǔn)備兩份不一樣的代碼,以驗(yàn)證我們實(shí)施的灰度操作是否生效。這里選擇使用Angular 的Angular-CLI 來(lái)創(chuàng)建代碼。創(chuàng)建的項(xiàng)目并不簡(jiǎn)潔,但是勝在操作簡(jiǎn)單。我們一次性把兩份代碼準(zhǔn)備好,簡(jiǎn)化開(kāi)發(fā)側(cè)工作。

        //?安裝angular-cli,前提是已經(jīng)安裝了node,如果沒(méi)有node真的要去自行百度了...
        npm?install?-g?@angular/cli
        //?快速創(chuàng)建一個(gè)新項(xiàng)目,一路回車(chē)
        ng?new?canaryDemocd?canaryDemo
        //?運(yùn)行完這個(gè)命令后訪問(wèn)http://localhost:4200?查看頁(yè)面信息
        ng?serve

        訪問(wèn)localhost 的4200 端口查看頁(yè)面,然后把項(xiàng)目根目錄下src 中的index.html 的title 改成A-CanaryDemo,可以看到頁(yè)面會(huì)進(jìn)行實(shí)時(shí)地刷新。在這個(gè)例子中,我們用title 來(lái)標(biāo)識(shí)灰度發(fā)布過(guò)程中兩邊不同的服務(wù)需要部署的代碼。

        接下來(lái),我們進(jìn)行兩次打包,兩次打包的title 分別為A-CanaryDemo 和 B-CanaryDemo, 把這兩個(gè)文件夾放好備用,作為一會(huì)灰度發(fā)布的新老代碼。

        ng?build?--prod

        配置Nginx

        在上述完成Nginx 的安裝操作時(shí),我們?cè)L問(wèn)服務(wù)器的IP 看到的是Nginx 的頁(yè)面,現(xiàn)在我們想訪問(wèn)到自己的頁(yè)面,首先把上面打包得到的A-CanaryDemo 發(fā)送到兩臺(tái)服務(wù)器上任意位置,這里我們把它放到/var/canaryDemo。

        //?將A-CanaryDemo?文件夾復(fù)制到你的公網(wǎng)服務(wù)器上,xx部分是你的服務(wù)器公網(wǎng)ip
        scp?-r?./dist/[email protected]:/var/canaryDemo

        去服務(wù)器上/var 的位置上看一下,是否已經(jīng)有了這個(gè)文件,如果有了的話,接著到下一步。即修改Nginx 配置把訪問(wèn)該服務(wù)器IP 的請(qǐng)求轉(zhuǎn)發(fā)到我們剛剛上傳上來(lái)的頁(yè)面上。上面提到過(guò)可以通過(guò)nginx -t 這個(gè)命令來(lái)查看Nginx 配置文件的位置,在這一步,我們要去編輯那個(gè)文件。

        vi?/etc/nginx/nginx.conf

        修改47-50行添加下圖相關(guān)的內(nèi)容,即將訪問(wèn)到該服務(wù)器IP 的流量轉(zhuǎn)發(fā)到/var/canaryDemo 下的index.html.

        修改完畢,保存退出,重啟一下nginx

        nginx?-s?reload

        這時(shí)候去訪問(wèn)我們服務(wù)器的IP 地址可以看到頁(yè)面已經(jīng)變成了剛剛我們?cè)诒镜馗牡捻?yè)面,而且title 確實(shí)是A-CanaryDemo。兩臺(tái)服務(wù)器都操作完成后,兩邊都可以訪問(wèn)到title 為A-CanaryDemo 的頁(yè)面。此時(shí)的狀態(tài)相當(dāng)于生產(chǎn)環(huán)境已經(jīng)在提供穩(wěn)定服務(wù)的兩臺(tái)機(jī)器。

        03 定義灰度策略

        接下來(lái),我們要開(kāi)始進(jìn)行灰度發(fā)布的部分,在進(jìn)行相關(guān)操作之前,我們需要定義一個(gè)灰度策略,即滿(mǎn)足什么情況下的流量會(huì)走到灰度邊,而其他流量走向正常邊。這里為了簡(jiǎn)單起見(jiàn),我們使用名字為canary 的cookie 來(lái)區(qū)分,如果檢測(cè)到這個(gè)cookie 的值為devui,就訪問(wèn)灰度邊機(jī)器,否則就訪問(wèn)正常邊機(jī)器。按照此規(guī)則配置Nginx 結(jié)果如下,此處分別使用11.11.11.11和22.22.22.22代表兩臺(tái)服務(wù)器的IP地址:

        #?Canary?Deployment
        map?$COOKIE_canary?$group?{
        ??#?canary?account
        ??~*devui$?server_canary;
        ??default?server_default;
        }

        upstream?server_canary?{
        ??#?兩臺(tái)機(jī)器的IP,第一臺(tái)設(shè)置端口號(hào)8000是為了防止nginx轉(zhuǎn)發(fā)出現(xiàn)死循環(huán)導(dǎo)致頁(yè)面報(bào)錯(cuò)
        ??server?11.11.11.11:8000?weight=1?max_fails=1?fail_timeout=30s;
        ??server?22.22.22.22?weight=1?max_fails=1?fail_timeout=30s;
        }

        upstream?server_default?{
        ??server?11.11.11.11:8000?weight=2?max_fails=1?fail_timeout=30s;
        ??server?22.22.22.22?weight=2?max_fails=1?fail_timeout=30s;
        }

        #?相應(yīng)地,要配置8000端口的轉(zhuǎn)發(fā)規(guī)則,8000端口默認(rèn)不開(kāi)啟訪問(wèn),需要去云服務(wù)器控制臺(tái)安全組新增8000
        server?{
        ??listen?8000;
        ??server_name?_;
        ??root?/var/canaryDemo;

        ??#?Load?configuration?files?for?the?default?server?block.
        ??include?/etc/nginx/default.d/*.conf;

        ??location?/?{
        ????root?/var/canaryDemo;
        ????index?index.html;
        ??}
        }

        server?{
        ??listen?80?default_server;
        ??listen?[::]:80?default_server;
        ??server_name?_;
        ??#?root?/usr/share/nginx/html;
        ??root?/var/canaryDemo;

        ??#?Load?configuration?files?for?the?default?server?block.
        ??include?/etc/nginx/default.d/*.conf;

        ??location?/?{
        ????proxy_pass?http://$group;
        ????#?root?/var/canaryDemo;
        ????#?index?index.html;
        ??}

        ??error_page?404?/404.html;
        ????location?=?/40x.html?{
        ??}

        ??error_page?500?502?503?504?/50x.html;
        ??location?=?/50x.h
        }

        此時(shí),灰度流量和正常流量都會(huì)隨機(jī)分配到AB兩邊的機(jī)器。下面,我們通過(guò)建立Jenkins 任務(wù)執(zhí)行Nginx 文件修改的方式實(shí)現(xiàn)灰度發(fā)布。

        04 實(shí)現(xiàn)灰度發(fā)布

        流程梳理

        在創(chuàng)建用于實(shí)現(xiàn)灰度發(fā)布的Jenkins任務(wù)之前我們先梳理一下要達(dá)到灰度發(fā)布的目標(biāo)需要哪幾個(gè)任務(wù),以及每個(gè)任務(wù)負(fù)責(zé)完成什么事情。灰度發(fā)布一般遵循這樣的流程(假設(shè)我們有AB兩臺(tái)服務(wù)器用于提供生產(chǎn)環(huán)境的服務(wù),我們稱(chēng)之為AB邊):

        (1)新代碼部署到A邊

        (2)符合灰度策略的小部分流量切到A邊,剩余大部分流量仍去往B邊

        (3)手動(dòng)驗(yàn)證A邊功能是否正??捎?/p>

        (4)驗(yàn)證無(wú)誤后,大部分流量轉(zhuǎn)到A邊,灰度流量去往B邊

        (5)手動(dòng)驗(yàn)證B邊功能是否正??捎?/p>

        (6)驗(yàn)證無(wú)誤后,流量像往常一樣均分到AB邊

        任務(wù)拆解

        通過(guò)上述的拆解,我們得出灰度發(fā)布的6個(gè)步驟,其中(3)和(5)是需要手動(dòng)驗(yàn)證的環(huán)節(jié),所以我們以這兩個(gè)任務(wù)為分割點(diǎn),建立三個(gè)Jenkins 任務(wù)(Jenkins 任務(wù)建立在A 邊機(jī)器上)如下:

        (1)Canary_A(灰度測(cè)試A),這個(gè)任務(wù)又包含兩個(gè)部分,更新A邊的代碼,然后修改流量分發(fā)策略使得灰度流量到達(dá)A,其他流量到達(dá)B

        (2)Canary_AB(上線A灰度測(cè)試B),更新B邊代碼,灰度流量達(dá)到B,其他流量到達(dá)A

        (3)Canary_B(上線B),所有流量均分到AB

        創(chuàng)建任務(wù)

        先按照任務(wù)拆解部分的設(shè)定創(chuàng)建三個(gè)FreeStyle 類(lèi)型的Jenkins 任務(wù),記得使用英文名字,中文名字后面建文件夾比較麻煩。任務(wù)詳情信息可以不填,直接保存就好,下一步我們?cè)賮?lái)配置每個(gè)任務(wù)的具體信息。

        配置任務(wù)

        現(xiàn)在已經(jīng)創(chuàng)建好了三個(gè)任務(wù),先點(diǎn)擊進(jìn)入每一個(gè)任務(wù)進(jìn)行一次空的構(gòu)建(否則后面可能導(dǎo)致修改后的構(gòu)建任務(wù)無(wú)法啟動(dòng)),然后我們來(lái)對(duì)每個(gè)任務(wù)進(jìn)行詳細(xì)的配置。

        現(xiàn)代前端項(xiàng)目都要進(jìn)行構(gòu)建打包這一步。但是廉價(jià)的云服務(wù)器在完成構(gòu)建方面有些力不從心,CPU 經(jīng)常爆表。所以我們?cè)谶@里把打包出得出的生產(chǎn)包納入git 管理,每次的代碼更新會(huì)同步最新的生產(chǎn)包到github,因此Jenkins 任務(wù)把生產(chǎn)包拉下來(lái),放在指定位置即可完成一次新代碼的部署。

        這一步操作,其實(shí)我們?cè)谥熬鸵呀?jīng)完成了,我們?cè)谏厦娲蛄藘煞輙ilte 不一樣的生產(chǎn)包,此時(shí)可以派上用場(chǎng)了。

        首先來(lái)配置灰度測(cè)試A,這個(gè)任務(wù)內(nèi)容上面也基本講清楚了,首先要關(guān)聯(lián)該任務(wù)到遠(yuǎn)程的github 倉(cāng)庫(kù)(需要手動(dòng)創(chuàng)建一個(gè),存放上面打包的B-CanaryDemo,并命名為dist)讓它知道可以去哪里拉取最新代碼。

        執(zhí)行一次構(gòu)建任務(wù)(在git fetch 那一步耗時(shí)不穩(wěn)定,有時(shí)比較久),然后點(diǎn)擊本次構(gòu)建進(jìn)去查看Console Output,可以確定執(zhí)行Jenkins 任務(wù)的位置是位于服務(wù)器上的/var/lib/jenkins/workspace/Canary_A

        繼續(xù)編輯灰度測(cè)試A 任務(wù),添加build shell,也就是每次任務(wù)執(zhí)行時(shí)要執(zhí)行的命令:

        (1)先拉取最新的代碼

        (2)把代碼根目錄下的dist目錄復(fù)制到部署代碼的位置,這里我們指定的位置是/var/canaryDemo

        (3)修改Nginx 配置使灰度流量到達(dá)A邊

        就步驟(3)而言,修改灰度流量的方式其實(shí)就是選擇性注釋Nginx 配置文件中的內(nèi)容,注釋方式如下即可實(shí)現(xiàn)灰度測(cè)試A。

        upstream?server_canary?{
        ??#?灰度流量訪問(wèn)A?邊
        ??server?11.11.11.11:8080?weight=1?max_fails=1?fail_timeout=30s;
        ??#?server?22.22.22.22?weight=1?max_fails=1?fail_timeout=30s;
        }
        upstream?server_default?{
        ??#?正常流量訪問(wèn)B?邊,為了在修改文件的時(shí)候把這段的配置和上面的server_canary?區(qū)分開(kāi),我們把這里的weight?設(shè)為2
        ??#?server?11.11.11.11:8080?weight=2?max_fails=1?fail_timeout=30s;
        ??server?22.22.22.22?weight=2?max_fails=1?fail_timeout=30s;
        }

        這一步填寫(xiě)的shell 命令在使用jenkins 用戶(hù)執(zhí)行時(shí)可能會(huì)遇到權(quán)限問(wèn)題,可以先用root 用戶(hù)登錄,把/var 目錄的歸屬改為jenkins 用戶(hù),/etc/nginx/ngix.conf也需要新增可寫(xiě)權(quán)限。由此,最終得到的shell 命令如下:

        git?pull
        rm?-rf?/var/canaryDemo
        scp?-r?dist?/var/canaryDemo
        sed?-i?'s/server?22.22.22.22?weight=1/#?server?22.22.22.22?weight=1/'?/etc/nginx/nginx.conf
        sed?-i?'s/server?11.11.11.11:8000?weight=2/#?server?11.11.11.11:8000?weight=2/'?/etc/nginx/nginx.conf
        nginx?-s?reload

        灰度測(cè)試A 任務(wù)內(nèi)容配置完成,接下來(lái)依次配置上線A 灰度測(cè)試B 和上線B。

        灰度測(cè)試B 的要執(zhí)行的任務(wù)是把最新的代碼拉到A 邊(因?yàn)槲覀兊腏enkins 任務(wù)都是建立在A 邊的),復(fù)制dist 下的代碼到B 邊Nginx 指定訪問(wèn)位置,然后修改A 邊Nginx 配置,使灰度流量到達(dá)B 邊。

        git?pull
        rm?-rf?canaryDemo
        mv?dist?canaryDemo
        [email protected]:/var
        sed?-i?'s/#?server?22.22.22.22?weight=1/server?22.22.22.22?weight=1/'?/etc/nginx/nginx.conf
        sed?-i?'s/#?server?11.11.11.11:8000?weight=2/server?11.11.11.11:8000?weight=2/'?/etc/nginx/nginx.conf
        sed?-i?'s/server?22.22.22.22?weight=2/#?server?22.22.22.22?weight=2/'?/etc/nginx/nginx.conf
        sed?-i?'s/server?11.11.11.11:8000?weight=1/#?server?11.11.11.11:8000?weight=1/'?/etc/nginx/nginx.conf
        nginx?-s?reload

        這一步的任務(wù)內(nèi)容涉及到從A 邊服務(wù)器向B 邊服務(wù)器發(fā)送代碼,這個(gè)過(guò)程一般來(lái)說(shuō)需要輸入B 邊服務(wù)器的密碼。我們想要做到免密發(fā)送,因此要通過(guò)把A 邊機(jī)器~/.ssh/id_rsa.pub 中的內(nèi)容添加到B 邊服務(wù)器~/.ssh/authorized_keys 中使得A 獲得免密像B 發(fā)送文件的權(quán)限。

        上線B 則是通過(guò)取消對(duì)A 邊Nginx 配置的注釋使所有流量均分到AB 邊.

        sed?-i?'s/#?server?22.22.22.22?weight=2/server?22.22.22.22?weight=2/'?/etc/nginx/nginx.conf
        sed?-i?'s/#?server?11.11.11.11:8000?weight=1/server?11.11.11.11:8000?weight=1/'?/etc/nginx/nginx.conf
        nginx?-s?reload

        至此,我們就從零到一搭建了一個(gè)灰度發(fā)布環(huán)境。在代碼更新后,通過(guò)手動(dòng)執(zhí)行Jenkins 任務(wù)的方式實(shí)現(xiàn)灰度部署和手工測(cè)試,保證新功能平滑上線。

        總結(jié)

        本文從服務(wù)器準(zhǔn)備、代碼準(zhǔn)備、灰度策略制定和實(shí)現(xiàn)灰度發(fā)布四個(gè)方面介紹了從零搭建一個(gè)灰度發(fā)布環(huán)境的必備流程?;叶劝l(fā)布的核心其實(shí)就是通過(guò)對(duì)Nginx 文件的修改實(shí)現(xiàn)流量的定向分發(fā)。內(nèi)容頗為簡(jiǎn)單,但是從零到一的整個(gè)流程操作下來(lái)還是比較繁瑣,希望各位看官能夠有所收獲。

        另外,這只是一個(gè)最簡(jiǎn)易的Demo,在真正的DevOps 開(kāi)發(fā)過(guò)程中,還需要集成編譯構(gòu)建、代碼檢查、安全掃描和自動(dòng)化測(cè)試用例等其他操作,期待后續(xù)團(tuán)隊(duì)的其他成員進(jìn)行更多的專(zhuān)項(xiàng)擴(kuò)展!

        ??愛(ài)心三連擊

        1.看到這里了就點(diǎn)個(gè)在看支持下吧,你的點(diǎn)贊,在看是我創(chuàng)作的動(dòng)力。

        2.關(guān)注公眾號(hào)程序員成長(zhǎng)指北,回復(fù)「1」加入Node進(jìn)階交流群!「在這里有好多 Node 開(kāi)發(fā)者,會(huì)討論 Node 知識(shí),互相學(xué)習(xí)」!

        3.也可添加微信【ikoala520】,一起成長(zhǎng)。


        “在看轉(zhuǎn)發(fā)”是最大的支持

        瀏覽 52
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            一级黄色性交 | 女上男下做爰免费观看视频 | 大香蕉久久伊人网 | 囯产精品久久久久久久久久久免费 | 加勒比色老久久爱综合网 | 国产性爱综合 | 中文字幕亚洲视频 | 一级毛片AAAAAA免费看小说 | 99热这里只有精品66 | 啊啊啊快高潮了短片 |