Kubernetes 在知名互聯(lián)網(wǎng)公司的落地實(shí)踐_第1頁
Kubernetes 在知名互聯(lián)網(wǎng)公司的落地實(shí)踐_第2頁
Kubernetes 在知名互聯(lián)網(wǎng)公司的落地實(shí)踐_第3頁
Kubernetes 在知名互聯(lián)網(wǎng)公司的落地實(shí)踐_第4頁
已閱讀5頁,還剩6頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、 Kubernetes 在知名互聯(lián)網(wǎng)公司的落地實(shí)踐 容器化背景本來生活網(wǎng)()是一家生鮮電商平臺,公司很早就停止了燒錢模式,開始追求盈利。既然要把利潤最大化,那就要開源節(jié)流,作為技術(shù)可以在省錢的方面想想辦法。我們的生產(chǎn)環(huán)境是由 IDC 機(jī)房的 100 多臺物理機(jī)所組成,占用率高達(dá) 95%,閑置資源比較多,于是我們考慮借助 k8s 來重構(gòu)我們的基礎(chǔ)設(shè)施,提高我們資源的利用率。容器化項(xiàng)目團(tuán)隊(duì)最初加上我就只有三個(gè)人,同時(shí)我們還有各自的工作任務(wù)要做,留給容器化的時(shí)間較少,因此我們要考慮如何快速的搭建容器平臺,避免走全部自研這條路,這對我們來說是個(gè)巨大的挑戰(zhàn)。在經(jīng)歷了一年的容器化之旅后,分享下我們這一年所

2、踩過的坑和獲得的經(jīng)驗(yàn)。面臨的問題在搭建 k8s 集群前,有很多問題擺在我們面前:l人手不足,時(shí)間也不充裕,不能有太多自研的需求l我們目前的發(fā)布是由測試人員完成的,不可能要求他們?nèi)懸粋€(gè) yaml 或執(zhí)行 kubectl 做發(fā)布,這個(gè)學(xué)習(xí)成本太高也容易出錯(cuò),因此我們必須構(gòu)建一個(gè)用戶體驗(yàn)良好的可視化平臺給發(fā)布人員使用l我們有大量的 .NET 項(xiàng)目,而 .NET 環(huán)境又依賴 WindowslConfigMap/Secret 不支持版本控制,同時(shí)用來存業(yè)務(wù)配置也不是很方便lk8s 集群和外部的通信如何打通容器平臺作為小團(tuán)隊(duì)去構(gòu)建一個(gè)容器平臺,自研的工作量太大了。前期我們調(diào)研過很多可視化平臺,比如 k8

3、sdashboard 和 rancher 等等,但是要操作這些平臺得需要專業(yè)的 k8s 運(yùn)維知識,這對我們的測試人員不太友好。后來我們嘗試了 KubeSphere(kubesphere.io)平臺,各方面都比較符合我們的需求,于是決定使用該平臺作為我們?nèi)萜髌脚_的基礎(chǔ),在這之上構(gòu)建我們自己的發(fā)布流程。感興趣的朋友可以去了解下這個(gè)平臺。.NET 項(xiàng)目我們的項(xiàng)目有 Java 也有 .NET 的,.NET 項(xiàng)目占了 80% 以上。要支持.NET 意味著要支持 Windows。在我們?nèi)ツ觊_始啟動項(xiàng)目的時(shí)候,k8s 剛升級到 1.14 版本,是支持Windows 節(jié)點(diǎn)的第一個(gè)版本,同時(shí)功能也比較弱。經(jīng)過實(shí)

4、驗(yàn),我們成功對 .NET Framework 的程序進(jìn)行了容器化,在不改代碼的前提下運(yùn)行在了 Windows 服務(wù)器上,并通過 k8s 進(jìn)行管理。不過我們也遇到了一些比較難處理的問題,使用下來的總結(jié)如下:lKubernetes 版本必須是 1.14 版本或以上l大多數(shù) Linux 容器若不做處理會自動調(diào)度到 Windows 節(jié)點(diǎn)上lWindows 基礎(chǔ)鏡像體積普遍比較大l必須使用 Windows Server 2019 及以上版本lk8s 關(guān)鍵性組件以 Windows 服務(wù)形式運(yùn)行,而非 Podl存儲和網(wǎng)絡(luò)的支持有局限性l部署步驟復(fù)雜,易出錯(cuò)我們調(diào)研了一段時(shí)間后決定放棄使用 Linux 和Wi

5、ndows 的混合集群,因?yàn)檫@些問題會帶來巨大的運(yùn)維成本,而且也無法避免 Windows 的版權(quán)費(fèi)。我們也考慮過把這些項(xiàng)目轉(zhuǎn)換成 Java,但其中包含大量的業(yè)務(wù)邏輯代碼,把這些重構(gòu)為 Java 會消耗巨大的研發(fā)和測試的人力成本,顯然這對我們來說也是不現(xiàn)實(shí)的。那么有沒有一種方案是改動很少的代碼,卻又能支持 Linux 的呢?答案很明顯了,就是把 .NET 轉(zhuǎn) .NET Core。我們采用了這種方案,并且大多數(shù)情況能很順利的轉(zhuǎn)換一個(gè)項(xiàng)目而不需要修改一行業(yè)務(wù)邏輯代碼。當(dāng)然這個(gè)方案也有它的局限性,比如遇到如下情況就需要修改代碼無法直接轉(zhuǎn)換:l項(xiàng)目里使用了依賴 Windows API 的代碼l引用的第三

6、方庫無 .NET Core 版本lWCF 和 Web Forms 的代碼這些修改的成本是可控的,也是我們可以接受的。到目前為止我們已經(jīng)成功轉(zhuǎn)換了許多 .NET 項(xiàng)目,并且已運(yùn)行在 k8s 生產(chǎn)環(huán)境之上。集群暴露由于我們是基于物理機(jī)部署也就是裸金屬(Bare Metal)環(huán)境,所以無論基于什么平臺搭建,最終還是要考慮如何暴露 k8s 集群這個(gè)問題。暴露方式lLoadBalancer, 是 Kubernetes 官方推薦的暴露方式,很可惜官方支持的方式都需要部署在云上。我們公司全部是裸機(jī)環(huán)境部署,無法使用云方案。lNodePort,端口范圍一般是 30000 以上,每個(gè)端口只能對應(yīng)一種服務(wù)。如果應(yīng)

7、用越來越多,那端口可能就不夠用了。它最大的問題是如果你暴露某一個(gè)節(jié)點(diǎn)給外部訪問,那么這個(gè)節(jié)點(diǎn)會成為單點(diǎn)。如果你要做高可用,這幾個(gè)節(jié)點(diǎn)都暴露出去,前面一樣也要加一個(gè)負(fù)載均衡,這樣事情就復(fù)雜了。lIngress,可以解決 NodePort 端口復(fù)用的問題,它一般工作在7層上可以復(fù)用 80 和 443 端口。使用 Ingress 的前提是必須要有 Ingress Controller 配合,而 Ingress Controller 同樣會出現(xiàn)你需要暴露端口并公開的問題。這時(shí)候如果你用 HostNetwork 或 HostPort 把端口暴露在當(dāng)前的節(jié)點(diǎn)上,就存在單點(diǎn)問題;如果你是暴露多個(gè)節(jié)點(diǎn)的話,同

8、樣需要在前面再加一個(gè)LB。lHostNetwork/HostPort,這是更暴力的方式,直接把 Pod 的端口綁定到宿主機(jī)的端口上。這時(shí)候端口沖突會是一個(gè)很大的問題,同時(shí)單點(diǎn)問題依舊存在。裸金屬方案我們分別試用了兩套方案 MetalLB(metallb.universe.tf)和 Porter(/kubesphere/porter),這兩個(gè)都是以 LoadBalancer 方式暴露集群的。我們測試下來都能滿足需求。Porter 是 KubeSphere 的子項(xiàng)目,和 KubeSphere 平臺兼容性更好,但是目前 Porter 沒有如何部署高可用的文檔,我在這里簡單分享下:前置條件l首先你的路

9、由器,必須是三層交換機(jī),需要支持 BGP 協(xié)議?,F(xiàn)在大多數(shù)路由設(shè)備都會支持這個(gè)協(xié)議,所以這個(gè)條件一般都能滿足l其次集群節(jié)點(diǎn)上不能有建立 BGP 通信的其他服務(wù)。舉例來說,當(dāng)使用 Calico 時(shí),開啟了BGP模式。它的 BGP 端口運(yùn)行在每個(gè)集群節(jié)點(diǎn),Calico 和 Porter 同時(shí)啟用BGP 協(xié)議,會有部分節(jié)點(diǎn)同時(shí)運(yùn)行兩個(gè)組件與交換機(jī)建立 BGP 協(xié)議造成沖突。而 KubeSphere 默認(rèn)安裝的 Calico 是 ipip 模式的,所以我們沒有遇到?jīng)_突問題l最后一定要有網(wǎng)絡(luò)運(yùn)維人員支持,配合你完成路由器配置以及了解整個(gè)網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu)。了解網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu)是非常重要的,否則會遇到很多問題配置和

10、部署架構(gòu)和邏輯Porter有兩個(gè)插件:Porter-Manager 和 Porter-AgentPorter-Manager 是使用Deployment 部署到 Master 節(jié)點(diǎn)上的,但默認(rèn)只部署1個(gè)副本,它負(fù)責(zé)同步 BGP 路由到物理交換機(jī)(單向 BGP 路由,只需將 kubernetes 私有路由發(fā)布給交換機(jī)即可,無需學(xué)習(xí)交換機(jī)內(nèi)物理網(wǎng)絡(luò)路由)。還有一個(gè)組件,Porter-Agent,它以 DaemonSet 的形式在所有節(jié)點(diǎn)都部署一個(gè)副本,功能是維護(hù)引流規(guī)則。高可用架構(gòu)部署好后,你可能會有疑問:l單個(gè)路由器掛了怎么辦l單個(gè) porter-manager 掛了怎么辦lporter-man

11、ager 和路由器網(wǎng)絡(luò)斷了怎么辦lEIP 下一跳地址所在的節(jié)點(diǎn)掛了怎么辦l某個(gè) EIP 流量突然飆升,一個(gè)節(jié)點(diǎn)扛不住怎么辦一般路由器或交換機(jī)都會準(zhǔn)備兩臺做 VSU (Virtual Switching Unit) 實(shí)現(xiàn)高可用,這個(gè)是網(wǎng)絡(luò)運(yùn)維擅長的,這里不細(xì)講了。主要說下其他幾點(diǎn)怎么解決l確保一個(gè) EIP 有多條 BGP 路由規(guī)則,交換機(jī)和 Manager 是多對多部署的l確保交換機(jī)開啟等價(jià)路由(ECMP)l要做好故障演練和壓力測試MetalLB 的高可用部署也是類似思路,雖然架構(gòu)稍有不同,比如它和路由器進(jìn)行 BGP 通信的組件是 Speaker,對應(yīng) Porter 的 Manager;它與Po

12、rter 的區(qū)別在于高可用目前做的比較好;但是 Local 引流規(guī)劃不如 Porter,EIP 的下一跳節(jié)點(diǎn)必須是 BGP 對等體(鄰居)。配置中心Kubernetes 的 ConfigMap 和 Secret 在一定程度上解決了配置的問題,我們可以很輕松的使用它們進(jìn)行更改配置而不需要重新生成鏡像,但我們在使用的過程中還是會遇到一些痛點(diǎn):1.不支持版本控制Deployment 和 StatefulSet 都有版本控制,我們可以使用 rollout 把應(yīng)用回滾到老的版本,但是 ConfigMap/Secret 卻沒有版本控制,這會產(chǎn)生一個(gè)問題就是當(dāng)我們的Deployment 要進(jìn)行回滾時(shí),使用的

13、 ConfigMap 還是最新的,我們必須把 ConfigMap 改回上一個(gè) Deployment 版本所使用的 ConfigMap 內(nèi)容,再進(jìn)行回滾,但是這樣的操作是很危險(xiǎn)的,假設(shè)改完 ConfigMap 后有個(gè) Pod 出了問題自動重啟了,又或者 ConfigMap 以文件形式掛載到 Pod 中,都會造成程序讀取到了錯(cuò)誤的配置。一個(gè)折中的做法是每個(gè)版本都關(guān)聯(lián)一個(gè)單獨(dú)的 ConfigMap。2.不太適合管理業(yè)務(wù)配置一個(gè)應(yīng)用有時(shí)候會需要加很多業(yè)務(wù)配置,在維護(hù)大量業(yè)務(wù)配置時(shí),我們可能需要搜索關(guān)鍵字、查看某個(gè) key 的備注、對 value 的格式進(jìn)行校驗(yàn)、批量更新配置等等,但是如果使用了Conf

14、igMap ,我們就不得不再做一些工具來滿足這些需求,而這些需求對于配置的維護(hù)效率是有非常大的影響。3.熱更新我們知道如果 ConfigMap 是以文件形式進(jìn)行掛載,那么當(dāng)修改了 ConfigMap 的值后,過一會所有的 Pod 里相應(yīng)的文件都會變更,可是如果是以環(huán)境變量的方式掛載卻不會更新。為了讓我們的程序支持熱更新,我們需要把 ConfigMap 都掛載成文件,而當(dāng)配置有很多時(shí)麻煩就來了,如果 Key 和文件是一對一掛載,那么 Pod 里會有很多小文件;如果所有 Key 都放到一個(gè)文件里,那么維護(hù)配置就成了噩夢。4.配置大小限制ConfigMap 本身沒有大小限制,但是 etcd 有,默認(rèn)

15、情況下一個(gè) ConfigMap 限制為 1MB,我們估算了下,有個(gè)別應(yīng)用的配置加起來真有可能突破這個(gè)限制,為了繞過這個(gè)大小限制,目前也只有切割成多個(gè) ConfigMap 的方法了。為了解決這些痛點(diǎn),我們綜合考慮了很多方案,最終決定還是使用一套開源的配置中心作為配置的源,先通過Jenkins 把配置的源轉(zhuǎn)換成 ConfigMap,以文件形式掛載到 Pod 中進(jìn)行發(fā)布,這樣以上的問題都可以迎刃而解。我們選擇了攜程的 Apollo(/ctripcorp/apollo)作為配置中心 ,其在用戶體驗(yàn)方面還是比較出色的,能滿足我們?nèi)粘>S護(hù)配置的需求。微服務(wù)在遷移微服務(wù)到 k8s 集群的時(shí)候基本都會遇到一個(gè)

16、問題,服務(wù)注冊的時(shí)候會注冊成 Pod IP,在集群內(nèi)的話沒有問題,在集群外的服務(wù)可就訪問不到了。我們首先考慮了是否要將集群外部與 Pod IP 打通,因?yàn)檫@樣不需要修改任何代碼就能很平滑的把服務(wù)遷移過來,但弊端是這個(gè)一旦放開,未來是很難收回來的,并且集群內(nèi)部的 IP 全部可訪問的話,等于破壞了 k8s 的網(wǎng)絡(luò)設(shè)計(jì),思考再三覺得這不是一個(gè)好的方法。我們最后選擇了結(jié)合集群暴露的方式,把一個(gè)微服務(wù)對應(yīng)的 Service 設(shè)置成 LoadBalancer,這樣得到的一個(gè) EIP 作為服務(wù)注冊后的 IP,手動注冊的服務(wù)只需要加上這個(gè) IP 即可,如果是自動注冊的話就需要修改相關(guān)的代碼。這個(gè)方案有個(gè)小小的

17、問題,因?yàn)橐粋€(gè)微服務(wù)會有多個(gè) Pod,而在遷移的灰度過程中,外部集群也有這個(gè)微服務(wù)的實(shí)例在跑,這時(shí)候服務(wù)調(diào)用的權(quán)重會不均衡,因?yàn)榧簝?nèi)的微服務(wù)只有一個(gè) IP,通常會被看作是一個(gè)實(shí)例。因此如果你的業(yè)務(wù)對負(fù)載均衡比較敏感,那你需要修改這里的邏輯。調(diào)用鏈監(jiān)控我們一直使用的是點(diǎn)評的 CAT(/dianping/cat)作為我們的調(diào)用鏈監(jiān)控,但是要把 CAT 部署到 k8s 上比較困難,官方也無相關(guān)文檔支持??偨Y(jié)部署 CAT 的難點(diǎn)主要有以下幾個(gè):lCAT 每個(gè)實(shí)例都是有狀態(tài)的,并且根據(jù)功能不同,相應(yīng)的配置也會不同,因此每個(gè)實(shí)例的配置是需要不一樣的,不能簡單的掛載 ConfigMap 來解決lCAT 每

18、個(gè)實(shí)例需要綁定一個(gè) IP 給客戶端使用,不能使用 Service 做負(fù)載均衡。lCAT 每個(gè)實(shí)例必須事先知道所有實(shí)例的 IP 地址lCAT 每個(gè)實(shí)例會在代碼層面獲取自己的 IP,這時(shí)候獲取到的是可變的 Pod IP,與綁定的 IP 不一致,這就會導(dǎo)致集群內(nèi)部通信出問題為了把 CAT 部署成一個(gè) StatefulSet 并且支持?jǐn)U容,我們參考了 Kafka 的 Helm 部署方式,做了以下的工作:l我們?yōu)槊總€(gè) Pod 創(chuàng)建了一個(gè) Service,并且啟用 LoadBalancer 模式綁定了 IP,使每個(gè) Pod 都會有一個(gè)獨(dú)立的對外 IP 地址,稱它為 EIP;l我們把所有實(shí)例的信息都保存在配

19、置中心,并且為每個(gè)實(shí)例生成了不同的配置,比如有些實(shí)例是跑 Job,有些實(shí)例是跑監(jiān)控的;l我們會預(yù)先規(guī)劃好 EIP,并把這些 EIP 列表通過動態(tài)生成配置的方式傳給每個(gè)實(shí)例;l最后我們給每個(gè)實(shí)例里塞了一個(gè)特殊的文件,這個(gè)文件里存的是當(dāng)前這個(gè)實(shí)例所綁定的 EIP 地址。接著我們修改了 CAT 的代碼,把所有獲取本地 IP 地址的代碼改成了讀取這個(gè)特定文件里的 IP 地址,以此欺騙每個(gè)實(shí)例認(rèn)為這個(gè) EIP 就是它自己的本地 IP。擴(kuò)容很簡單,只需要在配置中心里添加一條實(shí)例信息,重新部署即可。CI/CD由于 KubeSphere 平臺集成了 Jenkins,因此我們基于 Jenkins 做了很多 CI

20、/CD 的工作。發(fā)布流程起初我們?yōu)槊總€(gè)應(yīng)用都寫了一個(gè) Jenkinsfile,里面的邏輯有拉取代碼、編譯應(yīng)用、上傳鏡像到倉庫和發(fā)布到 k8s 集群等。接著我為了結(jié)合現(xiàn)有的發(fā)布流程,通過 Jenkins 的動態(tài)參數(shù)實(shí)現(xiàn)了完全發(fā)布、制作鏡像、發(fā)布配置、上線應(yīng)用、回滾應(yīng)用這樣五種流程。處理配置由于前面提到了 ConfigMap 不支持版本控制,因此配置中心拉取配置生成 ConfigMap 的事情就由 Jenkins 來實(shí)現(xiàn)了。我們會在 ConfigMap 名稱后加上當(dāng)前應(yīng)用的版本號,將該版本的 ConfigMap 關(guān)聯(lián)到 Deployment 中。這樣在執(zhí)行回滾應(yīng)用時(shí) ConfigMap 也可以一起

21、回滾。同時(shí) ConfigMap 的清理工作也可以在這里完成。復(fù)用代碼隨著應(yīng)用的增多,Jenkinsfile 也越來越多,如果要修改一個(gè)部署邏輯將會修改全部的 Jenkinsfile,這顯然是不可接受的,于是我們開始優(yōu)化 Jenkinsfile。首先我們?yōu)椴煌愋偷膽?yīng)用創(chuàng)建了不同的 yaml 模板,并用模板變量替換了里面的參數(shù)。接著我們使用了 Jenkins Shared Library 來編寫通用的 CI/CD 邏輯,而 Jenkinsfile 里只需要填寫需要執(zhí)行什么邏輯和相應(yīng)的參數(shù)即可。這樣當(dāng)一個(gè)邏輯需要變更時(shí),我們直接修改通用庫里的代碼就全部生效了。數(shù)據(jù)落地隨著越來越多的應(yīng)用接入到容器發(fā)布中,不可避免的要對這些應(yīng)用的發(fā)布及部署上線的發(fā)布效率、失敗率、發(fā)布次數(shù)等指標(biāo)進(jìn)行分析;其次我們當(dāng)前的流程雖然實(shí)現(xiàn)了 CI/CD 的流程代碼復(fù)用,但是很多參數(shù)還是要去改對應(yīng)應(yīng)用的 Jenkinsfile 進(jìn)行調(diào)整,這也很不方便。于是我們決定將所有應(yīng)用的基本信息、發(fā)布信息

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論