如何系統搭建現代 Web CI/CD

大家好,我是若川。今天分享一篇00后寫的CI/CD直播文字稿。之前發過他的故事:一位00后前端2年經驗的成長歷程。我最近組織了源碼共讀活動,感興趣的加我微信 ruochuan12。


本次直播錄播鏈接:https://live.juejin.cn/4354/595741[1]

開始



歡迎大家來到掘金小冊8月的首場直播,我是本次直播的主講人王圣松

今天給大家帶來的主題是:如何系統搭建CICD。話不多說,咱們就立刻開始

自我介紹


那么在開始之前呢,我先做個自我介紹。我叫 Janlay,目前任職于 Gitee Devops產品前端團隊,是一位前端開發工程師,主要負責參與團隊 Devops 產品的前端開發。曾經主導過 CI/CD 相關產品的前端開發,同時也是掘金小冊《從 0 到 1 實現一套 CI/CD 流程》的作者。

現狀與困境



在開始之前呢,我們先來聊一聊前端的CICD掌握現狀。

現狀


這是我在之前和其他的一個前端開發工程師的聊天。可以看到,前端工程師對于 CI/CD 的方向的興趣還是比較大的。但是也比較焦慮。并且有的大廠面試還會問到相關的問題,里面也有涉及 Kubernetes 相關的技術。

那么大家對此的掌握度又如何呢?

對 162 個前端 CI/CD 工具的掌握度調查



我在去年寫小冊之前,對 162 個中高級前端做了個關于 CI/CD 工具的一個掌握調查。其中有一部分同學已經在大廠,或者已經是一個前端的一個 leader 了。

大家 Docker 的實踐程度以及掌握度是非常非常低的,兩成都不到只有19%。這其中對于 Kubernetes 的掌握程度甚至不到 1%。162 個人里面,僅僅只有一個人實踐過。

對于制品庫這類比較新鮮的概念了解更少了,不了解的人有很多,自研的人也有一部分。構建工具,部署工具,這些大家可能聽的比較多,常見的比較多,掌握程度還算好。但是也有相當一部分同學對這部分還不是很清楚,或者說在采用手動部署。其實不是很適應時代發展和不利于提高效率的。

Devops 工具鏈


這個是某咨詢公司對于 Devops 工具鏈的一個統計圖譜。從全貌上來看呢,這些工具其實還是比較多的。除了持續構建持續部署之外,還有像監控運維,自動化測試,流程管理,容器編排這些內容。

代碼托管 Git 庫就有七種。CI 也不止 Jenkins,Gitlab CI 這幾個。里面還存在著其他的一些工具鏈,其實是比較多比較雜的,這些都是 CI/CD 相關的一個工具生態。有了這些工具生態,我們才能夠將CI/CD的價值完全釋放出來。

那么這樣看來,CICD只是作為自動化工具。那么它的意義有多大呢

為什么要有自動化?



那么為什么要自動化呢?大家可能聽說過一個開發模式,叫做瀑布流。

左上角就是瀑布流開發的方式。傳統瀑布流的開發方式是:把需求的排期給固定住,中間是不允許修改需求的,直到最后完全上線。測試的流程也是比較復雜的,上線流程也是比較復雜的。

我們大家可以看到,在這個圖里面開發和測試之間隔著一堵墻,測試和運維之間也隔著一堵墻。那么在所有的功能開發完畢之后才能交給測試,測試測完所有功能之后才能再交給運維上線。那么這種開發模式在今天的互聯網時代的話,其實已經嚴重脫節了。

互聯網時代的產品需求變動是很頻繁的,瀑布流是根本適應不了的,所以就有了敏捷開發這么一種方式。將原有瀑布流的一大塊的需求,進行了一個拆分,拆成了一個一個迭代。每個迭代里面,有這個迭代相關的需求,一次迭代的需求開發完畢之后,交給測試,原有的一個整個大的流程變成了一個小步快跑的方式。研發做一部分需求測試,測試就測一部分,上線就上一部分。產品在早期的話就可以得到一個市場的快速驗證。

當然需求的頻繁變化,在當今是迫不得已。因為時代發展是比較快的。如果要是說大家都能看到未來的市場走向和用戶需求的話,可能京東淘寶也不會允許拼多多存在。

但是敏捷的劣勢隨即而來了。由于上線的流程不是自動化且是比較復雜的,所以當開發和測試完成了之后,需求依然要等到固定的時間去進行上線。因為發布流程較多且復雜,還是無法把第一時間把需求統一驗證,因為自動化而這道門檻卡在了這里。

于是 Devops 就來了,他把運維和開發測試的墻也打破了。我們上線部署構建的事情。可以去實現一個自動上線,自動構建,自動部署。這樣的話,我們發布的成本就變小了,產品發布的周期也加快了。上線的權利從運維就轉變成了研發,轉變為了業務方。這也就是自動化構建部署的意義,它可以讓需求更快的投入市場驗證。

所以說,自動化不僅是在研發層面提效,更可以影響業務的快速發展迭代。所以從研發同學角度來講,掌握自動化構建和部署比較吃香。

演進歷程


在剛才,我們了解了自動化在業務中的意義。接下來我們就看下 CI/CD 的演進歷程,看下為了盡可能地自動化,技術層面都是如何一步步演進發展的

遠古時代 FTP + Tomcat / Nginx


首先是遠古時代的構建部署。其實說早也不是很早,我在 18 年參加某次技術分享時,與一位后端工程師有聊到這部分,他告訴我就是在使用 FTP 方式進行部署。很多學校教材中甚至還會教學這部分。的確,在早期的網站部署中,FTP 的確比較常見。

首先是在本地將代碼構建。

在 FTP 盛行的年代,Webpack 那個時候可能都沒有,可能只有幾個 JQuery 頁面,或者是靜態頁面,將頁面文件直接扔到服務器。

很多的做法都是和后端的代碼都放一塊兒。比如像 Tomcat、Apache。


隨著時代的發展,FTP 的方式實在是太落后了。我之前有講到:產品需求需要快速投入市場驗證,除了需求要進行拆分之外,上線的流程也要做到自動化,才能實現快速投入的市場的這么一個目標。

沒有自動化的操作,風險也是比較大的。比如說有時候眼花沒有操作好、不小心誤觸、或者不小心刪除了文件,導致服務和系統出現問題。這種情況在歷史上發生了 n 多次。而且自動化也解決了很多重復的一些人力。

一個操作,機器可以自動化去執行,但人去執行,這個對于成本而言就是一個浪費。

自動化序章 Shell + Nginx


于是人們對于自動化最初的探索就是寫 Shell 腳本,可以通過編寫 Shell 腳本來實現自動化操作。首先在腳本里面我們將代碼拉下來,這里面少了一步 git fetch 的命令,上面大家可以腦補一下哈哈。將代碼拉取下來之后,進行一個 npm run build,編譯之后扔到對應的服務目錄。

上圖這個就是有獨立部署服務器,我們可以考慮采用 SCP 的方式將編譯后的壓縮包扔到目標服務器。使用 SSH 命令遠程操控服務器進行一個解壓。比如上面第10行: tar zxvf,將 tar 包解壓后,再 mv 移動到對應目錄。

這就是我們對于自動化最初的一個探索,那么在今天也有相當一部分業務還是在使用這種方式。包括像我們之前的一些內部的、一些小的業務,也是在使用這些方式進行部署。這也側面印證這部分方式的成本還是比較低的。


那么,這方面成本是比較低的,而且不需要額外的服務依賴,不需要多么復雜的操作。也不需要多么復雜的架構。

但是隨著業務增長和團隊人數擴張,就可能變得不是多么很友好。

首先你可以在服務器上執行這個腳本,就說明了你有服務器的權限。那么大家都想去構建的話,密碼公鑰的泄密的風險就加大。人人都可以去訪問服務器,萬一有人想使壞刪庫跑路;或者說不小心刪除了某個文件,不小心誤操作導致了服務模塊,也是一個災難性的問題。

其次,他的操作交互也不是很友好。那么我們是不是可以利用軟件開發的一個思想,將這些真實的操作去做一個上層的封裝呢?提供給用戶一個統一的入口,用戶只能夠執行你給的一個操作范圍,可以在界面上進行一鍵執行。


于是像很多公司,選用了 Jenkins,這個是非常經典的一個構建工具,擁有像可視化操作。而且它是有賬號體系的,你可以根據賬號去分配權限。不同的人看到不同的任務,可以去執行不同的任務。當然他也有豐富的插件也可以進行一個拓展,比如說像 git plugin、node plugin。也有非常開放的 API,可以去做一個自定義拓展。

可視化執行 Jenkins + Nginx


我們用進行一個自動化改造之后呢,一切看起來是比較美好的。在提前寫好 Shell 之后呢,我們一鍵執行就可以完成你想執行的腳本。

甚至 Jenkins,還給你提供給你像定時執行這樣的一個功能。你還可以去搭配 Git 平臺的 Webhook 鉤子,在你提交代碼,或者說合并某個 pull request 的時候,Git 就會利用 Webhook,去調用你 Jenkins 的構建觸發鏈接,對代碼進行一個構建觸發。

大家可以看到上面兩張圖片:左上角就是 Shell 腳本的編寫區域,右邊就是編譯的一個日志,這些都是可以在網頁中進行編寫和實現的。

那么下面就是這個整體的流程。當我們把代碼提交到倉庫時,這時候打開 Jenkins,去點擊這樣的一個構建按鈕,接著就構建完成了。或者說我們直接 push 到倉庫,觸發 Webhook 鉤子,最后直接構建完成。這是更加便捷的一種方式。

可是,有一天服務。不止你們自己用。例如現在很多公司在做 tob,你的服務不只是你自己在用,你要把你的服務拿到客戶那里進行部署。

在這種情況下,如果你的服務需要非常復雜的環境安裝的話,是比較頭疼的。尤其在客戶變多的情況下,安裝環境也是非常的費時費力的,甚至說還會遇到說操作系統不一致的問題。例如在你自己的開發環境上是 Ubuntu,到了客戶那里就變成了 CentOS,有些環境依賴的安裝方式是不兼容的。

版本歸納也是一個大問題。尤其是每次版本包非常大,安裝部署都需要拉去特別重的安裝包,也非常費時間。最理想的情況,是說我拿一個虛擬機一樣的東西,直接到客戶現場直接跑了起來。

Docker 在這個地方就派上用場了。它可以將你的運行環境、服務代碼等之類的東西高度集成為一個鏡像。在你想要的地方,如果那個地方有 Docker 運行環境,我們可以將 Docker 鏡像跑起來,就擁有了全套的一個運行環境體驗。

而且 Docker 的每個鏡像的更新都是增量的,只拿去拉取修改的那一部分,不需要每次都拉取全量的鏡像,也非常省空間省時省力。

容器時代 Jenkins + Docker + Nexus + Nginx 容器


于是我們將原有的服務用 Docker 鏡像跑了起來,然后構建編譯構建包變成了編譯鏡像。在這里還會引入一個新東西 —— 制品庫,右邊這張圖就是制品庫。我們將每次編譯后的產出都被稱為制品,存放這些制品的文件存儲系統就叫制品庫。

右上角這張截圖是 Nexus 的一個制品庫。像Java也有自己的包規范 Maven、Node 的包規范 NPM、Docker 的鏡像,這些 Nexus 都可以去進行一個創建和托管。所以對于一些中小團隊而言,Nexus 還是比較萬能的,也是比較省成本的。有這么一套東西前后端都可以去用。

于是流程就變成了:當我們去構建鏡像的時候,構建完畢,接著就會去 push 鏡像到鏡像庫。原有的構建代碼變成構建鏡像,push 到鏡像庫后告訴遠程服務器你要拉取鏡像。

像左邊這張圖最下面里面有一個 SSH 命令:這時候它就會操作 151 服務器利用 Docker 命令將鏡像拉下來,然后將容器停止掉,刪掉,再跑一個新鏡像。那么這樣的話,我們的服務和它所需要的運行環境是高度集成的,你不需要擔心去分發,也不需要受到操作系統的一個影響。


可是問題也來了。有一天用戶量變大了,你需要加服務器,一臺服務器不夠就要去加。最頭疼的莫過于我要批量對服務器進行新版本更新,或者說要去加新服務器。如果我們加一臺還好,如果加 5 臺、加 10 臺呢?擴展下去的話,總會變得無邊無際。

我們需要一種通用的策略去解決問題,不僅可以批量操作這個服務器,更希望說在我們去添加這個服務器的時候,也可以去變得特別的便捷。就好像寫個配置文件一樣,寫個清單我們就可以寫一個操作。

那么在這里有一個非常知名的工具叫 Ansible。Ansible 是紅帽推出的一個自動化運維工具,它可以去根據你提前預制好的服務器清單,對服務器進行一個批量的操作和部署。

你可以去像寫一個記事本一樣,寫一個 yaml 文件,json 文件一樣去寫入:你的第一個服務器的 IP 多少,賬號密碼多少、第二個服務器賬號密碼是多少....這樣就形成了一個清單。把這個清單交給它后,他就會按照你清單上面寫好的賬號和密碼、服務器地址去對我們遠程服務器去操作腳本執行任務。

本質上還是一個自動化一個運維工具,它是可以自動化幫你去執行命令的一個工具,不僅僅是用來部署。包括像后面我們有提到說 Kubernetes 去安裝 Node 的時候,如果你的 Node 的機器比較多,都需要安裝環境的話,Ansible 是能夠派上用場的,用場還很大。而且這個是 Python 寫的,性能比較快一些。

基于配置清單服務器批量操作 Ansible


那么這個就是 Ansible 操作的 Playbook 腳本集。

右邊這張圖大家可以看到:這是一個樣本文件,里面有一個 task 字段。Ansible,他將你的腳本里面每一條要執行的命令都產生了一條條 task。并且第一條 task,第二條 task 之間還可以去支持異步執行,還可以支持錯誤中斷。比如說我中間的執行出錯退出,我還可以去忽略這個錯誤繼續執行。

整個 Playbook 腳本集還可以根據變量去進行一個實例化。比如我這個地方在用 timestamp 變量,上面可以通過 var 字段去定義一個是 timestamp,后面的 value 就是給它的變量默認值。我在左邊去執行 ansible-playbook 命令的時候,用 -e 這個參數就可以去把 timestamp 變量可以傳進來,每次都會生成一個新的構建的操作實例。

那么在這種情況下,我們對原有的服務器替換鏡像,也變成了去操作 Ansible,讓 Ansible 去操作對應的機器進行一個鏡像的替換。那么大家可以看到:鏡像 push 到鏡像庫之后,接著去操作 Ansible 批量操作服務器,受控的服務器去拉取鏡像,然后再把原有的容器刪除掉,基于新版本運行新容器。



那么,Ansible 幫我們實現了批量操作服務器的夢想,但是它的做法是比較生硬的,因為它只是一個自動化的運維工具。

我們運行的是一個容器,有的時候可能會碰到說負載均衡需要配置 upstream,環境變量的情況。尤其像 toB,大家在做微前端,或者說服務之間有互相引用的地方,都少不了一系列的環境變量。比如這些 nginx upstream 的值其實都是不固定的。

舉個例子,我現在有一個系統,前端頁面我們要訪問 /user 的時候,要去訪問 /user 配置的機器;那么訪問 /a 的時候,要去訪問 /a 的容器。這個時候如果你只有自己用還好,假設到了客戶現場的話,客戶現場的環境是比較復雜的,你根本不知道他會用什么情況去部署。Nginx 的 upstream 那么在這種情況下,你把具體的值寫死,完全不利于后面的部署。這個值真正部署是不固定的,環境的網段和 DNS 都會去影響這個值。

所以我們希望有一個給運容器運行的環境生態,容器高度隔離的一個土壤。容器在自己的生態里面就能去解決這些繁雜的七七八八的一些問題。那么我們再去給客戶部署的時候,只需要帶著這一套環境生態去客戶那里部署,這個環境生態就可以去完美的去實現 1:1 的一個還原。

其實在我們前面去更新容器的時候,都會將原有的容器刪掉,再創建新容器。中間的時間如果用戶去訪問,就是宕機,服務沒有起來就訪問不到。這種情況下,其實相對而言還算是好一些的。如果連你的新版本的容器因為出錯都沒有起來,那么你這個時候問題就大了,就算是一個事故了。回滾也是一個比較麻煩的事情。

所以說我們希望服務發布的時候不要停機。新發布失敗了,還可以自動終止新版本發布,回滾到舊版本。

在保證上面的一個運行生態的時候,還希望去做一個最大化的機器資源利用。比如說我們有多套環境,而且之間都是隔離的,互相不受影響。例如我們日常開發有測試環境,開發環境。希望服務器資源利用最大化,一組高配置的服務器就可以去部署解決這兩套環境。

我們希望去達到這樣一種理想的狀態。在這種情況下,選擇了 Kubernetes,簡稱 k8s。

Kubernetes 是一個容器編排工具,他給你容器提供一個很好的環境生態,就像提供一個完整的家一樣,所以說它叫容器編排工具。在 Kubernetes 里面是以它去管理你要運行容器的服務器,是以集群的方式去管理的。你的每一臺服務器都是一個節點,它可以根據你集群內的節點的一個剩余資源,還有你人工給他的標簽等影響因素,對服務的部署進行了自動的調度,最大化的利用我們的服務器資源。

對于應用更新,也可以采用滾動發布服務的方式,在發布期間不會影響新版和舊版的一個訪問,也就是說不會宕機。這個技術也是比較熱門的,現在很多公司大廠也是在用。

容器集群編排 Jenkins + K8S + Docker + Nginx


那么左上角就是 k8s 運行時的情況。左上角圖是滾動發布,可以看到,k8s 在啟動一個全新的容器之后,他會確保說新容器沒有問題有待殺死原有的一個容器。這樣保證了一個可訪問性,保證不會因為服務重啟而導致宕機。

左下角圖是 k8s 加入一個新節點的方式。可以看到,只需要通過 API 操作一個遠程訪問,就可以加入集群,而且都是服務化。基于密鑰、IP、端口加入就可以。它和集群內的其他節點和集群內的主控制節點其實都是解耦的。想刪除就刪除,想添加就添加,只是把它當成了一個服務。

右邊是 k8s 集成后的一個流程圖。從最下面可以看到,當用戶提交代碼到 Git 了之后,這時候會去觸發 Webhook。或者你手動去觸發 Jenkins。這時候 Jenkins 就構建鏡像,上傳鏡像到了制品庫,接著去調用了 k8s 集群進行一個制品的部署。

這時候告訴 k8s:我的鏡像版本更新了,給你新版本的鏡像地址。這時候 k8s 就把鏡像版本在配置文件中進行一個修改。這個時候就會拿新版本去鏡像庫拉取新鏡像,拉取之后就會對原有的 pod 進行刪除替換。

你可以大致理解為,pod 約等于一個容器,但是它其實不等于容器。k8 s當中的 pod 不只是擁有容器的這個概念,它里面還可以擁有多個容器,他也是 k8s 當中可調度的一個最小節點,也擁有網絡的分配權限,所以它不等于一個容器。

可以看到滾動升級的策略。左邊這個圖原有是 4 個藍色的 pod,我們先把其中 1 個藍色的給下掉,那么下來之后把新的給創建進來,ok 完成;然后剩下三個,再把其中一個給干掉,再上一個新的;再剩下兩個再把其中一個干掉,再上新的,最后完成全部的部署,這就是滾動發布的這么一個方式。

升級完畢之后,k8s 當中還帶來了一種概念 ingress,這個有點類似于 Nginx 的負載均衡。大家可以看到這張圖,瀏覽器去訪問的時候,經過一堆轉發,走到了 k8s 集群;k8s 集群進來之后,首先是走到了 ingress。根據路徑左邊是 path = /,然后去根據路徑走到了 service。右邊這個不僅有 path = /,還有灰度的 cookie。說明他是灰度用戶,給他了灰度的一個服務的訪問。ingress 的作用就是在這里,他可以去做灰度發布,也可以做 path 轉發。

k8s 就給容器去提供了這么一個完整的運行生態。國內大廠基本上都有在使用 k8s 包括像 serverless,也有的通過 k8s 進行一個底層實現。這種編排方式比較省時省力省心的。


當然 k8s 也不是最好的解決方案。未來 Serverless 的部署會更加便捷。

例如左下角的彈性伸縮,按需付費。我們現有k8s的 Node 節點還是需要去手動加入、手動刪除。它并不能根據你的服務的流量情況對節點進行一個自動的增加伸縮。不過在 Serverless 里是可以做到的,因為真正的對物理資源進行一個伸縮的時候,這個時候才會真正達到省錢的目的。無服務器的函數計算,也應對了一部分的一個無狀態的操作和服務,也是比較省錢且快速方便的。當然,他的基礎也是Docker

國內的云服務器廠商也對一些常用的前后端框架進行了一個快速部署的支持。比如像 Next.js、Koa.js、Egg.js 這些都支持實現一個常用框架的快速部署。部署起來會更加的方便。

回到開始


以上是我們的一個演進流程。可以看到,前人為了提升工程效能,想盡了一切辦法來優化提升。

接著讓我們回到主題:為什么要用自動化?

自動化不是為了偷懶,也不是為了做而做,更不是為了刷KPI/OKR。而是為了讓產品和需求可以更快速上線驗證,更加早期地分析用戶信息,需求更加匹配用戶。那么這就是我們要做自動化的一個目標。

現實很殘酷


現實是比較殘酷的。上線實現了自動化,然而需求從開發到上線的時間絲毫沒有一點影響。那么這時候你就要考慮:像測試的時間占了多少?有沒有大量的人工測試?

無法打通上線的最后一公里,就像比較經典的小程序。小程序的上線就不同于以往的開發上線,最后一公里怎么打通?

投入和產出不成正比,本來你的業務不是多么很熱門的業務,一個月部署不了幾次,還有必要去做 CI/CD 嗎?它的意義有多大呢?

對于一些特殊的場景,目前的開源工具依然沒法去打通這么一個構建。最后一公里還是要去手動操作。而且自動化做了,影響有時候也是不大。所以我們就要根據業務進行一個對癥下藥,選擇合適的工具進行一個改造,包括像不限于對現有的工具進行拓展,或者說可以考慮到自研。

做平臺,而不是做工具



那么還是那句話,做平臺而不是做工具。我分別來舉個例子,像 IDE 集成:就小程序 ide 支持的一鍵發布,就是一個很好的例子。它把 IDE 和 CI/CD 進行了一個聯動,包括像很多大廠也在研發 WebIDE,也是出于這方面的一個考慮。還有我們日常任務卡片進行一個關聯和綁定,可以更好的追蹤需求的開發情況。

像自動化測試:我們的上線時間有縮短,但是測試時間沒有變短。大量的人工測試還是比較浪費成本的,這個我們也可以考慮去優化;

根據不同用戶的灰度發布的一個策略:比如說基于用戶畫像的地域,基于其他的一些因素進行灰度發布;還有像服務的一個監控,告警。

像數據度量平臺:比如我們可以統計構建時長、發布時長等等,為了更好地去做優化。甚至非常 nice 的流程可視化的拖動:CI/CD 的流程編排現在也是比較火的。這些都是說 CI/CD 去適應業務的一些例子。

工具是一個比較抽象的平臺,但業務場景是復雜多變的,我們需要使用工具去演變成自己的平臺。之前我們所說的 ?Docker、Jenkins、Nexus、Kubernetes 都有自己的 OpenAPI,你完全可以根據自己的業務需求進行一個自定義的封裝。

持續精進




那么總結一下:自動化是解決問題的手段,而不是一個結果;適當的去做數據度量統計,可以更好的幫助你去對流程的一個改進;要選擇自己合適的工具去做自動化。

Q&A

接下來是問答:

移步至錄播:https://live.juejin.cn/4354/595741[2] 39分53秒

小冊推廣


然后在這里推廣一下我寫的小冊。傳送門:https://juejin.cn/book/6897616008173846543[3]

推薦書籍


這里推薦兩本書。

第一本是 k8s 的進階實戰,個人在查閱相關知識點的時候經常用,不過官網的文檔還要看的

第二本是《Devops 實驗指南》,對于你的一些自動化的流程的建設,Devops 文化的建設,度量平臺建設也是非常有幫助的。

推薦平臺 & 項目


這是一個推薦參考的平臺和項目。這里沒有打廣告,大家如果有自研興趣需求的話,可以參考上面這些平臺的功能設計。

第一個是華為云的 DevCloud。個人感覺他們的 CI/CD 方面做的還比較全的,包括像 CI/CD 可視化拖拽,還支持流水線的中斷執行。我們一條條的任務就可以去組成一個流水線,就像工廠流水線一樣。流水線里面的 task 還可以支持并行執行。

第二個百度效率云。這個維護的頻率比較低,它們的特點是研發數據鏈。比如提交代碼時候,commit 的 message 填入卡片 ID,這時候在卡片里面可以監控到,需求的代碼已經提交到代碼庫里面了。接下來進行構建的時候,也會去和需求卡片進行一個綁定。業務方就可以去清楚的看到需求的一個開發和上線的一個狀態與進度。一個卡片就可以去串聯所有的進度狀態。

第三個 KubeSphere 是針對于 k8s 的一個集群管理。包括對 k8s 的服務監控,CI/CD 的編排。這個是開源的,也是國產的。

Thanks


我的分享就到這里,感謝大家!

參考資料

[1]

https://live.juejin.cn/4354/595741: https://live.juejin.cn/4354/595741

[2]

https://live.juejin.cn/4354/595741: https://live.juejin.cn/4354/595741

[3]

https://juejin.cn/book/6897616008173846543: https://juejin.cn/book/6897616008173846543

最近組建了一個江西人的前端交流群,如果你是江西人可以加我微信?ruochuan12?私信 江西?拉你進群。


推薦閱讀

我在阿里招前端,該怎么幫你(可進面試群)
我讀源碼的經歷

面對 this 指向丟失,尤雨溪在 Vuex 源碼中是怎么處理的
老姚淺談:怎么學JavaScript?

·················?若川簡介?·················

你好,我是若川,畢業于江西高校。現在是一名前端開發“工程師”。寫有《學習源碼整體架構系列》多篇,在知乎、掘金收獲超百萬閱讀。
從2014年起,每年都會寫一篇年度總結,已經寫了7篇,點擊查看年度總結。
同時,活躍在知乎@若川,掘金@若川。致力于分享前端開發經驗,愿景:幫助5年內前端人走向前列。

識別方二維碼加我微信、拉你進源碼共讀

今日話題

略。歡迎分享、收藏、點贊、在看我的公眾號文章~

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/275580.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/275580.shtml
英文地址,請注明出處:http://en.pswp.cn/news/275580.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

sqlserver oracle 數據類型對應關系,SQLSERVER和ORACLE數據類型對應關系詳解和對應表格整理...

Oracle SQLServer 比較 SQLServer 常見的 數據 庫 類型 字符 數據 類型 CHAR CHAR :都是固定長度字符資料但oracle里面最大度為2kb,SQLServer里面最大長度為8kb 變長字符 數據 類型 VARCHAR2 VARCHAR :racle里面最大長度為4kb,SQLServer里面最大長度為8k…

優化算法匯總

interior point block coordinate relaxation Boltzmann machine 求解L1范數最小化 E. Candes, M. B. Wakin, and S. P. Boyd, “Enhancing sparsity by reweighted l1 minimization,” Journalof Fourier Analysis and Applications, vol. 14, pp. 877-905, Dec. 2008.I. Daub…

對接百度地圖API

一、準備工作 百度地圖開發文檔 注冊百度賬號&#xff0c;成為開發人員&#xff0c;同時獲取AK實例代碼&#xff1a;<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content&quo…

ui邊框設計圖_UI設計形狀和對象基礎知識:填充和邊框

ui邊框設計圖第2部分 (Part 2) Welcome to the second part of the UI Design shapes basics. This time we’ll cover two of the most essential properties of a shape — fills and borders. This is also a part of the free chapters from Designing User Interfaces.歡迎…

如何移除項目中無用的 console.log 代碼

大家好&#xff0c;我是若川。早些天時&#xff0c;我看到一個后端公眾號發《辭退了一個前端》&#xff0c;當時還想著現在后端公眾號都開始吊打前端了嘛。其中有個理由就是線上還一堆console.log...我猜很多人都會移除項目中無用的console.log。可以復習一下。前言說起console…

WCF - 服務實例管理模式

WCF 提供了三種實例上下文模式&#xff1a;PreCall、PreSession 以及 Single。開發人員通過 ServiceBehavior.InstanceContextMode 就可以很容易地控制服務對象的實例管理模式。而當 WCF 釋放服務對象時&#xff0c;會檢查該對象是否實現了 IDisposable 接口&#xff0c;并調用…

oracle io lost,磁盤IO故障

測試工作正在如火如荼的進行&#xff0c;突然數據庫就連接不上了。我連接上主機發現數據庫alert_sid日志中有如下信息&#xff1a;KCF: write/open error block0x9a6 online1file2 /oracle_data1/UNDOTBS3.dbferror27072 txt: Linux Error: 5: Input/output errorAdditional in…

易思匯完成近億元B輪融資,信中利投資

3月19日消息&#xff0c;近日&#xff0c;留學生在線付費平臺易思匯宣布已在3月份完成由信中利投資的近億元B輪融資。 易思匯聯合創始人高宇同表示&#xff0c;本輪融資將主要用于留學生信用卡、留學家庭金融商城等新產品布局&#xff0c;以及擴大團隊和市場投入。 易思匯成立…

遠程連接 錯誤 內部錯誤_關于錯誤的性質和原因。 了解錯誤因素

遠程連接 錯誤 內部錯誤Back in 2012, I was a young[er] product designer working in a small tech agency in Valencia, Spain. In parallel, I worked as a freelancer on several side projects for different clients. One day I was contacted by a new health services…

得到鵝廠最新前端開發手冊一份

又逢金九銀十&#xff0c;拿到大廠offer一直是程序員朋友的目標&#xff0c;但是去大廠就得拿出實力來。除了需要積累技術&#xff0c;了解并掌握面試的技巧&#xff0c;熟悉大廠面試流程&#xff0c;也必不可少。這里分享一份最新入職騰訊的前端社招面經&#xff0c;來看看鵝廠…

性能測試分析之帶寬瓶頸的疑惑

第一部分&#xff0c; 測試執行 先看一圖&#xff0c;再看下文 這個當然就是壓力過程中帶寬的使用率了&#xff0c;我們的帶寬是1Gbps的&#xff0c;合計傳輸速率為128MB/s&#xff0c;也正因為這個就讓我越來越疑惑了&#xff0c;不過通過壓力過程中的各項數據我又不得不相信。…

Android 中的LayoutInflater的理解

LayoutInflater與findViewById的區別&#xff1f; 對于一個已經載入的界面&#xff0c;就可以使用findViewById()方法來獲得其中的界面元素。對于一個沒有被載入或者想要動態載入的界面&#xff0c;就需要使用LayoutInflater對象的inflate()方法來載入。findViewById()是查找已…

linux rootfs編譯進內核,九鼎x6818開發板筆記:uboot、kernel、rootfs編譯和燒寫

下面記錄了如何搭建嵌入開發環境&#xff0c;如何編譯uboot、kernel、和文件系統&#xff0c;如何燒寫鏡像以及如何配置uboot環境變量。閱讀注意&#xff1a;記錄中(Base框中的內容)一些操作故意被添加&#xff0c;為了展示文件內容&#xff0c;故意調用cat(Ubuntu)或者type(wi…

figma下載_素描vs Figma困境

figma下載I distinctly remember how much hatred I had in my heart when I lived through my first UI update. The year was 2009; I had just gotten my braces off and I was ready to smash that ‘Like’ button on my high school crush’s status when I logged into …

祝大家七夕快樂,邀你源碼共讀,順帶發點紅包

大家好&#xff0c;我是若川。這是一個普通的周六。只不過又叫七夕節&#xff0c;祝大家七夕節快樂~所以就不更新技術文了。估計還是有很多讀者不知道我。若川名字由來是取自&#xff1a;上善若水&#xff0c;海納百川。順便放兩篇文章。我讀源碼的經歷&#xff0c;跟各位讀者朋…

windows 系統監視器 以及建議閥值

windows 系統監視器 以及建議閥值 計數器的說明可以在添加計數器那邊 資源 對象\計數器建議的閾值注釋磁盤Physical Disk\% Free SpaceLogical Disk\% Free Space15%磁盤Physical Disk\% Disk Time Logical Disk\% Disk Time90%磁盤Physical Disk\Disk Reads/sec、Physical Dis…

前端人員如何在linux服務器上搭建npm私有庫

為什么要搭建npm私有庫&#xff1f; 為了方便下載時&#xff0c;公共包走npmjs,私有包走內部服務器。npm包下載的速度較慢&#xff0c;搭建npm私有庫之后&#xff0c;會先操作私有庫中是否有緩存&#xff0c;有緩存直接走緩存&#xff0c;而不用重新再去請求一遍網絡。哪種方式…

硬幣 假硬幣 天平_小東西叫硬幣

硬幣 假硬幣 天平During the last 1,5 years, I’ve been traveling a lot. Apart from my must-have things like laptop, sketchbook, and power bank, there constantly appears a new one, in a familiar shape but a new look. That’s 在過去的1.5年中&#xff0c;我經常…

Linux創建一個用戶時分配組,useradd和groupadd(Linux創建用戶\用戶組\設置\分配用戶權限)的使用...

前言&#xff1a;man useradd    man groupadd    info useradd    info groupadd 都可以獲取相關命令的用法信息。個人比較喜歡讀英文解釋文檔&#xff0c;沒有你想象的那么complicated&#xff01;&#x1f61c;USERADD(8) System Management Commands USERADD…

尤雨溪發布的Vue 3.2 有哪些新變化?

大家好&#xff0c;我是若川。今天分享一篇 Vue 3.2 版本的文章。查看源碼等系列文章。學習源碼整體架構系列、年度總結、JS基礎系列1前言8.10號凌晨&#xff0c;尤雨溪在微博平臺官宣 Vue 3.2 版本正式發布&#xff1a;此版本包含一系列重要的新功能與性能改進&#xff0c;但并…