日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

持续部署编排的另类选择:使用Node-RED进行容器化部署

發(fā)布時(shí)間:2023/12/15 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 持续部署编排的另类选择:使用Node-RED进行容器化部署 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.


Node-RED是在2013年IBM開源的應(yīng)用于物聯(lián)網(wǎng)的流編排引擎,但是也不僅限于物聯(lián)網(wǎng),這篇文章選取容器化應(yīng)用持續(xù)交付的一個(gè)示例來進(jìn)行說明Node-RED的使用方式。

場(chǎng)景說明

持續(xù)集成執(zhí)行完畢之后,容器化的應(yīng)用已經(jīng)存儲(chǔ)在Harbor鏡像私庫中,持續(xù)部署的時(shí)候需要拉取鏡像、啟動(dòng)容器,這本來是非常簡單的事情,但是需要考慮到主要是各種異常的分支的對(duì)應(yīng)方法,比如:

  • 拉取鏡像:鏡像私庫連接失敗和成功的處理
  • 啟動(dòng)容器:確認(rèn)是否存在容器,如果不存在使用docker run生成,如果存在,首先停止此容器,然后刪除,停止失敗和刪除失敗都需要進(jìn)行異常處理,停止并刪除成功之后啟動(dòng)容器
  • 結(jié)果確認(rèn): 確認(rèn)容器是否啟動(dòng),根據(jù)結(jié)果輸出成功或失敗信息

持續(xù)部署的邏輯流程

普通邏輯下,這個(gè)示例流程可能是這樣的:

Created with Rapha?l 2.2.0開始拉取鏡像鏡像拉取成功?容器已經(jīng)存在?容器已經(jīng)停止?刪除容器容器已刪除?啟動(dòng)容器容器成功啟動(dòng)?顯示容器啟動(dòng)成功信息顯示容器啟動(dòng)失敗信息顯示容器刪除失敗信息停止運(yùn)行中的容器容器成功停止?顯示容器停止失敗信息顯示鏡像拉取失敗信息yesnoyesnoyesnoyesnoyesnoyesno

當(dāng)然,在實(shí)際的使用中有很多種方法會(huì)將上述這個(gè)流程變得非常簡化,比如簡化這個(gè)過程,如果不需要對(duì)中間結(jié)果進(jìn)行確認(rèn)的話,可以將所有的條件全部去除,直接上來先強(qiáng)制停止->強(qiáng)制刪除之前的容器和鏡像->強(qiáng)制拉取->強(qiáng)制啟動(dòng),或者使用kubernetes提供的滾動(dòng)升級(jí)的機(jī)制都會(huì)非常簡單,但是這里主要是用于檢驗(yàn)持續(xù)部署引擎中流水線可視化編排的能力,是否能夠很輕松和簡單地實(shí)現(xiàn)這個(gè)流程是需要確認(rèn)的。

Jenkins vs Node-RED

實(shí)際上這并不是可以進(jìn)行比較的兩個(gè)東西,但是僅限于本文中示例說明的這個(gè)場(chǎng)景,似乎還真有可對(duì)比的地方。Jenkins提供可以DSL語言支持的流水線,代碼及流水線,如果把流水線也看作“流”的表現(xiàn)形式和結(jié)果,在這個(gè)角度上是有類似的地方的,在本文指定的場(chǎng)景中實(shí)際上只有一個(gè)流編排引擎的能力:條件分支。

Jenkins的編排能力

Jenkins的DSL里面支持基于Stage的條件分支和并行的編排需求,但是可視化編排引擎能力稍差,比如BlueOcean插件可以在很簡單地程度上進(jìn)行可視化編排,但是目前還達(dá)不到易用的程度,但是毫無疑問,條件分支的支持在Jenkins中沒有任何問題,比如下圖為使用Jenkins中的when語句進(jìn)行條件分支的示例流水線的執(zhí)行情況:

注:詳細(xì)可參看https://blog.csdn.net/liumiaocn/article/details/92817179
更多Jenkins相關(guān)的使用技巧:點(diǎn)擊此處

Node-RED的編排能力

條件分支

  • 可以根據(jù)需要進(jìn)行分支處理

    詳細(xì)可參看:https://liumiaocn.blog.csdn.net/article/details/104745053
  • 也可以使用多路輸入進(jìn)行統(tǒng)一處理

    詳細(xì)可參看:https://liumiaocn.blog.csdn.net/article/details/104740766

更多Node-RED相關(guān)的使用技巧:點(diǎn)擊此處

使用Node-RED進(jìn)行編排

與Docker的結(jié)合

可以使用Node-RED的插件或者直接拷貝docker客戶端至Node-RED容器中即可對(duì)容器進(jìn)行操作,這里使用后一種方式,詳細(xì)的方法可參看下文:

  • https://blog.csdn.net/liumiaocn/article/details/104965769

環(huán)境準(zhǔn)備

  • Node-RED
    以容器方式啟動(dòng)Node-RED服務(wù),啟動(dòng)命令如下所示:

啟動(dòng)命令:docker run -it -p 1880:1880 -v $PWD/data:/data -e DOCKER_HOST=tcp://192.168.31.242:2375 -e TZ=Asia/Shanghai --name nodered -d nodered/node-red:1.0.4

注:DOCKER_HOST環(huán)境變量的設(shè)定請(qǐng)根據(jù)自己機(jī)器的配置進(jìn)行設(shè)定

示例實(shí)現(xiàn)

參照前面一些Node-RED系列的文章可以非常容易的實(shí)現(xiàn)如下的可視化編排, 拉取鏡像也直接拉取一個(gè)nginx的版本,這里已1.13為例進(jìn)行拉取和啟動(dòng):

這里為了簡單演示,直接在命令行中硬編碼的方式實(shí)現(xiàn)容器名稱和映射端口號(hào),啟動(dòng)容器的設(shè)定如下所示:

JSON格式的flow

如下JSON格式的flow,導(dǎo)入之后即可即可使用。

[{"id":"d9908e57.2efd4","type":"inject","z":"c205d2ff.b4322","name":"觸發(fā)器","topic":"","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":150,"y":60,"wires":[["4af508a3.75bed8"]]},{"id":"4af508a3.75bed8","type":"exec","z":"c205d2ff.b4322","command":"docker pull nginx:1.13","addpay":true,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"拉取鏡像","x":340,"y":60,"wires":[[],[],["8e27643a.f72f68"]]},{"id":"8e27643a.f72f68","type":"switch","z":"c205d2ff.b4322","name":"拉取鏡像成功?","property":"payload.code","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"str"},{"t":"neq","v":"0","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":540,"y":60,"wires":[["fbc7e47e.300d68","3f88a226.a0e27e"],["d6bf6546.e90028"]]},{"id":"fbc7e47e.300d68","type":"debug","z":"c205d2ff.b4322","name":"拉取鏡像成功結(jié)果顯示","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":760,"y":20,"wires":[]},{"id":"d6bf6546.e90028","type":"debug","z":"c205d2ff.b4322","name":"拉取鏡像失敗結(jié)果顯示","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":760,"y":100,"wires":[]},{"id":"3f88a226.a0e27e","type":"exec","z":"c205d2ff.b4322","command":"docker ps -a |grep nginx","addpay":false,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"容器存在性確認(rèn)","x":160,"y":220,"wires":[[],[],["f04db033.03b9d"]]},{"id":"f04db033.03b9d","type":"switch","z":"c205d2ff.b4322","name":"容器已經(jīng)存在?","property":"payload.code","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"str"},{"t":"neq","v":"0","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":360,"y":220,"wires":[["41de4ca4.2bc304"],["370847f2.635c28","de314625.b32708"]]},{"id":"370847f2.635c28","type":"exec","z":"c205d2ff.b4322","command":"docker run -p 8088:80 --name=nginx -d nginx:1.13","addpay":false,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"啟動(dòng)容器","x":600,"y":200,"wires":[[],[],["fc7c7676.7747b8"]]},{"id":"fc7c7676.7747b8","type":"switch","z":"c205d2ff.b4322","name":"結(jié)果判斷","property":"payload.code","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"str"},{"t":"neq","v":"0","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":800,"y":200,"wires":[["e7f38a59.27c928"],["594e0886.2aa498"]]},{"id":"e7f38a59.27c928","type":"debug","z":"c205d2ff.b4322","name":"顯示容器正常啟動(dòng)信息","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":1000,"y":180,"wires":[]},{"id":"594e0886.2aa498","type":"debug","z":"c205d2ff.b4322","name":"顯示容器啟動(dòng)失敗信息","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":1000,"y":220,"wires":[]},{"id":"de314625.b32708","type":"debug","z":"c205d2ff.b4322","name":"容器不存在","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":610,"y":280,"wires":[]},{"id":"f4e42833.ee4448","type":"exec","z":"c205d2ff.b4322","command":"docker stop nginx;","addpay":false,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"停止容器","x":160,"y":540,"wires":[[],[],["3e4a962a.01903a"]]},{"id":"3e4a962a.01903a","type":"switch","z":"c205d2ff.b4322","name":"容器停止成功?","property":"payload.code","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"str"},{"t":"neq","v":"0","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":340,"y":540,"wires":[["e5baa05e.433b9","84ae2749.94ee28"],["f5d2345c.4f0d98"]]},{"id":"e5baa05e.433b9","type":"debug","z":"c205d2ff.b4322","name":"顯示容器停止成功信息","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":580,"y":500,"wires":[]},{"id":"f5d2345c.4f0d98","type":"debug","z":"c205d2ff.b4322","name":"顯示容器停止失敗信息","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":580,"y":580,"wires":[]},{"id":"41de4ca4.2bc304","type":"exec","z":"c205d2ff.b4322","command":"docker ps |grep nginx","addpay":false,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"容器停止?fàn)顟B(tài)確認(rèn)","x":170,"y":380,"wires":[[],[],["827bee6d.6d1d1"]]},{"id":"827bee6d.6d1d1","type":"switch","z":"c205d2ff.b4322","name":"容器已停止?","property":"payload.code","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"str"},{"t":"neq","v":"0","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":360,"y":380,"wires":[["db3dca72.6a5d98","f4e42833.ee4448"],["370847f2.635c28","eb12796d.538858"]]},{"id":"db3dca72.6a5d98","type":"debug","z":"c205d2ff.b4322","name":"存在啟動(dòng)的容器需要停止","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":630,"y":340,"wires":[]},{"id":"eb12796d.538858","type":"debug","z":"c205d2ff.b4322","name":"沒有啟動(dòng)的容器需要停止","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":630,"y":420,"wires":[]},{"id":"84ae2749.94ee28","type":"exec","z":"c205d2ff.b4322","command":"docker rm nginx;","addpay":false,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"刪除容器","x":140,"y":720,"wires":[[],[],["8515b044.05477"]]},{"id":"8515b044.05477","type":"switch","z":"c205d2ff.b4322","name":"容器刪除成功?","property":"payload.code","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"str"},{"t":"neq","v":"0","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":320,"y":720,"wires":[["61927cc0.f243e4","370847f2.635c28"],["9b26c2ff.a7d18"]]},{"id":"61927cc0.f243e4","type":"debug","z":"c205d2ff.b4322","name":"顯示容器刪除成功信息","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":560,"y":680,"wires":[]},{"id":"9b26c2ff.a7d18","type":"debug","z":"c205d2ff.b4322","name":"顯示容器刪除失敗信息","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":560,"y":760,"wires":[]}]

結(jié)果確認(rèn)

  • 執(zhí)行前確認(rèn)
liumiaocn:~ liumiao$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e290de2ccd69 nodered/node-red:1.0.4 "npm start -- --user…" 11 minutes ago Up 11 minutes (healthy) 0.0.0.0:1880->1880/tcp nodered liumiaocn:~ liumiao$
  • 第一次執(zhí)行

    說明:這里出現(xiàn)了一個(gè)很顯眼的錯(cuò)誤信息,這是因?yàn)槭褂胐okcer ps |grep nginx確認(rèn)是否有nginx為名稱的容器在運(yùn)行中的命令執(zhí)行的時(shí)候沒有發(fā)現(xiàn)這樣的容器所產(chǎn)生的,所以這并不是一個(gè)問題,exec組件會(huì)根據(jù)返回值進(jìn)行狀態(tài)顯示而已,結(jié)合docker ps命令在宿主機(jī)器上可以看到名為nginx的容器已經(jīng)啟動(dòng)起來了
liumiaocn:~ liumiao$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4728e76addcf nginx:1.13 "nginx -g 'daemon of…" 11 seconds ago Up 10 seconds 0.0.0.0:8088->80/tcp nginx e290de2ccd69 nodered/node-red:1.0.4 "npm start -- --user…" 44 minutes ago Up 44 minutes (healthy) 0.0.0.0:1880->1880/tcp nodered liumiaocn:~ liumiao$
  • 第二次執(zhí)行

    結(jié)合docker ps命令在宿主機(jī)器上可以看到nginx容器是啟動(dòng)狀態(tài),但是Container ID已經(jīng)發(fā)生了變化,說明原有的的nginx容器已經(jīng)被停止和刪除,然后重新啟動(dòng)的nginx容器。
liumiaocn:~ liumiao$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 122c01aa206d nginx:1.13 "nginx -g 'daemon of…" 22 seconds ago Up 20 seconds 0.0.0.0:8088->80/tcp nginx e290de2ccd69 nodered/node-red:1.0.4 "npm start -- --user…" 46 minutes ago Up 46 minutes (healthy) 0.0.0.0:1880->1880/tcp nodered liumiaocn:~ liumiao$

總結(jié)

這篇文章使用了一個(gè)簡單地示例對(duì)Node-RED的編排進(jìn)行了說明,當(dāng)然在使用的過程中還有很多需要注意的,比如參數(shù)的傳入方法,比如異常的處理機(jī)制,但是相信這樣一個(gè)簡單的示例就能夠說明流編排引擎在持續(xù)集成和部署中的作用,鑒于Jenkins目前的可視化編排功能較弱,所以很多平臺(tái)都是基于此進(jìn)行強(qiáng)化,但是后續(xù)的CDF時(shí)候能夠提供一種標(biāo)準(zhǔn)的DSL的編排標(biāo)準(zhǔn)或者接入現(xiàn)在主流的工具還需要進(jìn)一步地觀察,這些都是我們?cè)诔掷m(xù)集成和部署實(shí)踐中需要注意的。

總結(jié)

以上是生活随笔為你收集整理的持续部署编排的另类选择:使用Node-RED进行容器化部署的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。