Kubernetes在企業級架構中的實踐分享_Kubernetes中文社群
本文是9月24日時速雲技術沙龍大連站的演講乾貨分享,內容源自時速雲聯合創始人兼技術總監楊樂的現場演講錄音整理。
以下為主要內容:
演講提綱
1、Docker與容器技術
Docker跟VM的區別:VM每次起一個例項,實際上包括三層,整個作業系統、中間層內部以及其他應用,全部都包括從OS kernel到應用態的全部,容器技術把kernel層共享給所有的例項。
容器例項僅僅是應用態各不相同,而底層的作業系統核心是共享的,這樣就帶來一個好處: 所有執行的應用,都是程序粒度,輕量級,採用Namespace、Cgroup等隔離技術,同時 Docker所定義的標準映象模式,讓我們可以對容器和映象進行非常快速的遷移。
Docker容器可以 build once、run anywhere,一次構建,可以隨意執行。
2、Kubernetes架構及特性
Kubernetes是容器叢集編排系統。例如10臺機器都裝了Docker,我們可以用Kubernetes把這些機器都編排起來,統一成一個叢集來處理。
這種生產系統已經是生產級別的了,kubernetes最早的技術理念是源於谷歌的borg系統,而這種borg系統已經在谷歌內部穩定執行很多年了。
Kubernetes是2014年6月開源的,採用Golang的語言開發,每一個元件互相之間使用的是Master API的方式,Kubernetes的架構模式是用Master-slave模式,並且支援多種的聯機網路,支援多種的分散式的儲存架構。
Master的核心元件是API server,對外提供REST API服務介面。kubernetes所有的資訊都儲存在ETCD. Scheduler是kubernetes的排程器,用於排程叢集的主機資源。Controller用於管理節點註冊以及容器的副本個數等控制功能。
在Node上的核心元件是kubelet,它是任務的執行者,它會跟apiserver進行互動,獲取資源排程資訊。 kubelet會根據資源和任務的資訊和排程狀態與Docker去互動,呼叫Docker的API, 建立,刪除與管理容器,而kube-Proxy可以根據從API裡獲取的資訊以及整體的Pod架構狀態組成虛擬NAT網路。
Pod 是Kubernetes可排程的最小單元,一個Pod裡面可以有多個容器,容器與容器之間可以用Local host的方式去溝通,共享網路共享儲存,也就是實現在pod內的資源共享。
Replication Controller 是Pod的一個控制,可以控制Pod副本和狀態,就可以做手動的彈性伸縮.也可以利用hpa去通過CPU,或者是記憶體, 設定閾值去彈性伸縮。label是對Pod或其他的資源像Node, Service打標籤,通過標籤使不同層次的元件發生聯絡。可以用一個選擇器把想要的資源選擇出來,然後對他們進行操作。
Service 定義了服務虛擬IP與容器例項間的影射關係,同時定義了服務暴露給使用者的方式。
Daemon Set 可以給每一個節點去分發應用容器,並以守護程序的方式執行,比如希望在每個節點上有一個元件,這個元件可以監控我的節點的健康狀態,可以用Daemon set的方式來部署執行。
Config Map 可以做非常靈活的配置管理,容器本身執行過程中,不建議去更改裡邊的檔案,不建議去開SSH登陸埠,但是程式執行起來以後需要知道如何去連線資料庫,如何去訪問配置檔案。可以去把配置檔案定義到Kubernetes的Config Map中,然後它會幫去分發配置到相應的容器,即在Pod裡面掛載到指定的位置,應用僅僅是需要去已知路徑獲取。
3、Kubernetes應用實踐
這部分主要介紹在實際生產或在企業落地過程中,企業使用者比較關注的問題。
在部署或要執行時,關鍵節點需要具備高可用性,排出單點故障問題。在kubernetes 中給Master設定多個例項,所有例項通過loadbalancer 對外提供apiserver 的服務。Salve 在連線時,只與loadbalancer對應。Podmaster 可以保證在同一時刻,僅有一對controller和scheduler存在在叢集內。當其中一個master節點出現問題時,其它的節點通過loadbalancer依然可用,如果controller或scheduler出現故障,也會在其它可用的master節點上啟動新的controller或scheduler.
◆ Network
Docker原生的網路是bridge的方式,原理在主機上面去建立一個docker0的bridge,相當於虛擬交換機,每一個容器會在該bridge上掛接一個埠,並與容器網絡卡聯通。但在kubernetes 中跨主機網路一般採用flannel工具來搭建 vxlan,即疊加的隧道網路。
對與企業內部典型的三層網路,即每個區域限定不同的使用目的,相鄰的網路區域間由防火牆隔離。 採用vxlan的方式可以輕鬆跨越網路區域和防火牆,flannel對外的開發埠時8285(或其它可選),網路IP包在流出該埠前會被flannel 加封一層IP包頭,作為vxlan的包頭協議,在穿越防火牆後,進入目的主機時會被flannel拆解掉包頭並還原,這樣多層區域的主機可以被打通成叢集資源使用。這種使用方法的前提是對防火牆的規則並不嚴格。
對於隔離要求較高的場景需求,採用calico是比較合適的選擇。calico會幫助容器在主機間搭建純二層的網路,在每個主機上維護一個路由表,用來獲取目標容器所在主機的可達路徑,以及本機容器的路有項。利用iptables的防火牆機制去做隔離。
容器之間跨主機進行互動時,IP包從容器出發,經過本地路有表選路,通過目標網段所在主機的路有項,到達目標主機,然後在目標主機內,進入路有選路前,先經由iptables隔離規則(如果設定過的話)進行判斷決定是否丟棄或返回,然後再經路有選路到目標容器,最終到達目標容器。整個過程沒有任何封包解包的過程,傳輸效率較高。
隔離規則可以設定在同一使用者名稱下的哪些容器可以被隔離成一組,被隔離的容器間可通訊,而與其它容器不可通訊。或者設定規則來組成更加豐富的隔離效果。
◆ Storage
Kubernetes儲存介面可以支援多種的儲存,在使用場景角度,可以分為可共享儲存和非共享儲存。舉例來說,多個容器之間可能需要共同讀寫檔案,可以將相同的儲存卷掛載到不同的容器上,比如使用nfs。對於非共享儲存,比如mysql, 資料庫程序在啟動後,會對庫檔案加鎖,以免其它資料庫程序進行讀取時產生同步操作問題,這種互斥排他的資源可以採用非共享儲存的方式,比如rdb.
在對分散式儲存卷的外掛支援上, kubernetes 的介面形式上很簡化,首先在kubelet/app/plugins.go中註冊自定義外掛的引用。並在實現程式碼中繼承相應的interface介面。定義如何初始化Init, 如何啟動或掛載SetUp, 如何去關閉Teardown,定義支援標誌CanSupport.
CI/CD持續部署可以加快企業內部的開發測試以及部署的生產整個交付流程,在企業使用場景中,開發人員首先提交程式碼到程式碼庫,例如gitlab,svn等,在專案編譯之前,可以進行程式碼掃描。比如利用SonaQube來進行分析, 獲取專案程式碼UT的覆蓋率。
在編譯完成專案之後,獲得檔案輸出,並可分享到不同的整合映象中。當通過Dockerfile構建成映象後,可以將映象推送到Dev-Docker registry。然後在測試環境中,可以用手動或者自動的方式部署到雲環境。當映象通過測試團隊的測試以及相關稽核之後,可以同步到指定的生產環境的映象中心,通過部署服務把映象部署到生產或者對已有的服務進行滾動升級。
這個是一個CI/CD的一個實踐例子。CMDB是做企業的資產管理的,onecmdb是開源的一個元件。在眾多子專案中,其中的一個專案只有Dockerfile, 沒有程式碼檔案,它要做的工作是將程式碼檔案構建到容器映象中。其它的幾個專案是onecmdb的程式碼檔案,但沒有Dockerfile。這樣在做持續整合時,擁有程式碼檔案的專案通過關聯構建的方式,將編譯號的war包共享給Dockerfile 的專案,而Dockerfile 的工作僅僅是構建映象。
◆ Configrate management
當服務執行在容器中時,有時需要訪問外部的變數,或者需要根據環境的不同更改配置檔案,比如,DB以傳統的方式執行在容器雲之外,當服務啟動時,需要初始化包含DB資訊的配置檔案。當需要切換db時,就需要更改配置檔案, 當容器中有服務在執行時, 並不推薦登陸到容器內進行檔案配置更改。合理的方式是利用kubernetes的配置管理,將配置資訊寫入到ConfigMap, 並掛載到對應的pod中。 服務在pod容器內只需要讀取固定位置的配置檔案, 當配置需要改變時, 更新ConfigMap並重新分發到pod內,這樣重啟容器後,容器內所掛載的配置也會相應更新。當需要pod容器同時使用一個ConfigMap 時,更新ConfigMap內容的同時,可以批量更新容器的配置。
4、Kubernetes管理與運維
◆ 監控與報警
監控與報警是雲平臺在企業執行過程中比較重要的環節,運維人員需要實時獲知系統是否執行正常,Apiserver是否健康,節點應用是否出現問題,服務的QPS是否過載等等。例如在kubernetes中,Node Problem Detector可以探測到主機的健康狀況並以事件的方式傳送到Apiserver中,這個detector 元件可以採用Deamon set的方式來推送到每個節點上。 報警系統如果發現服務出現異常將以郵件和頁面列表兩種方式通知使用者。
◆ 操作
對於運維操作來說,kubectl是一個很便利的命令列工具,首先可以對各種資源進行操作,比如新增、獲取、刪除,通過更多命令引數得到指定的資訊。
當需要對節點進行操作時,比如由於配置升級需要對節點主機進行重啟。首先將節點主機設定成不可排程模式,kubectl cordon[nodeid], 然後需要將主機上的正在執行的容器驅趕到其它可用節點,使用命令kubectl drain [nodeid], 當容器遷移完畢後,運維人員可以對該主機進行操作,配置升級性能引數調優等等。
當對主機的維護操作完畢後, 再將主機設定成可排程模式,kubectl uncordon [nodeid], 這樣新建立的容器即可以分配到該主機。可以通過kubectl patch 對資源物件進行實時修改,比如為service增加埠,為pod修改容器映象版本。Annotation 可以幫助使用者更好的設定kubernete自定義外掛。
使用者可以在自建元件中獲取資源中對應的annotation以此進行操作。通過kubectl label可以方便的對資源打標籤,比如對node打標籤,然後容器排程時可指定分配到對應標籤的主機。
◆ 升級
最後一個問題時系統升級,kubernetes的版本定義分為產品版本和API版本,產品版本是常用的格式[major.minor.patch] ,由於在kubernetes版本迭代過程中經歷了API版本的變動,比如v1beta3到v1, 當跨越API版本號升級時,需要先將版本的kubernets升級到API相容的版本,然後再升級到高版本。
比如v0.17.x版本的API是v1beta3,而v1.x的API是v1版本,此時直接升級會造成資料的混亂和丟失,需要經歷相容版本的升級,比如v0.19.x可以同時支援API v1beta3和API v1,因此先將v0.17.x升級到v0.19.x,當資料正常升級後,再從v0.19.x升級到v1.x.