一、傳統的運維方式
在瞭解Kubernetes之前,我們有必要先簡單瞭解一下傳統的運維模式。在傳統的項目架構中(單體or微服務),我們一般將項目打包為war或fatJar的方式進行部署。
在部署時,需要人工創建相應的服務器及資源,並搭建項目運行的依賴環境,預估服務需要佔用的內存與CPU,同事還要考慮到高可用的部署環境,在不同配置的服務器上部署相應的服務。當服務意外崩潰或者服務器意外宕機時,需要人工處理。總結一下傳統部署的不足如下:
依賴服務器環境,需要各服務器資源統一。
無法充分利用服務器等資源,使用率一般僅能達到70%。
無法或很難做到容災恢復。
需要人工進行服務擴容,修改服務配置。
服務資源散亂(域名,服務器,負載,數據庫),無法做集中管理。
時間消耗較多,增加運維成本。
需要藉助第三方工具進行資源監控,較為麻煩。
需要對開發、測試、生產環境進行區別管理。
要想解決以上的問題是相對比較麻煩的,特別是現在的項目多為微服務項目,少則幾十,多則上百,極大的增加了運維的難度和成本。
一、Kubernetes是什麼?
官方文檔中描述為:v
Kubernetes一個用於容器集群的自動化部署、擴容以及運維的開源平臺。通過Kubernetes,你可以快速有效地響應用戶需求;快速而有預期地部署你的應用;極速地擴展你的應用;無縫對接新應用功能;節省資源,優化硬件資源的使用。為容器編排管理提供了完整的開源方案。
介紹一下其中提到的幾個詞:
容器
我們現在常說的容器一般是指Docker容器,通過容器隔離的特性和宿主機進行解耦,使我們的服務不需要依賴於宿主機而運行,與宿主機互不影響,Docker容器十分輕量。而kubernetes則負責管理服務中所有的Docker容器,創建、運行、重啟與刪除容器。
快速響應
個人理解為兩個方面。一、新增或者修改需求時,可以快速進行部署測試(CICD);二、kubernetes可以根據不同條件進行動態擴縮容,舉個栗子,用戶訪問量突然由1000人上升到100000人時,現有的服務已經無法支撐,kubernetes會自動將用戶服務模塊增加更多實例以保證當前的系統訪問量。
擴展
在快速響應的特點中已經有所提及,這裡再補充一點: Kubernetes內部有完善的註冊發現機制,當某個服務的實例增加時,kubernetes會自動將其加入服務列表中,免除在傳統運維中需要人工維護服務列表的問題。
對接新應用
kubernetes是一個通用的容器編排框架,支持不同類型的語言,或者是語言無關的,新增加的應用都會以一個新的對象進行接入。
硬件資源
這一點我覺得是kubernetess很基本但是非常重要的一個優點了,kubernetes在部署應用時會自動檢查各個服務器的cpu與內存使用量,同時會根據服務申請的cpu與內存資源,將服務部署到最合適的服務器。(其實這就是容器調度的核心功能了)
小知識: 因kubernetes名字過長,一般簡稱為k8s,因為k與s之間有8個字母,故而稱之。
二、Kubernetes解決了什麼問題?
下面以幾個case進行闡述,便於理解。
服務器環境
kubernetes是使用Docker進行容器管理的,所以天生具備Docker的所有特性,只需要使用相應環境的Docker鏡像就可以運行服務,還需要關心宿主機是redhat、centos還是ubuntu,只要在宿主機上安裝Docker環境即可,相比傳統運維,減少了各種依賴環境的衝突,降低運維成本,也方便整體服務的遷移。
服務器資源管理
對於kubernetes來說,是不關心有幾臺服務器的,每個服務器都是一個資源對象(Node),kubernetes關心的是這個Node上有多少可用的cpu和內存。例如現在有兩臺服務器
server01 (4c16g), 已用(2c7.5G)
server02 (4c16g), 已用(3c13G)
現在有一個服務ServiceA需要部署,ServiceA申明自己運行需要至少3G內存,這時kubernetes會根據調度策略將其部署到server01上,很明顯server01的資源是更加充足的。實際上kubernetes的調度策略要複雜的多,kubernetes會監控整體服務器資源的狀態進行調度,而以前的運維方式只能由人工判斷資源使用。這裡只做簡單示例。
各個服務器節點的狀態
總體集群的資源狀態
服務容災恢復
說簡單點,就是服務掛了之後,能夠自動恢復。例如現在有一個ServiceA,運行在server01上,kubernetes會通過內部的kubelet組件監控ServiceA服務進程的狀態,一旦發現進程丟失(服務本身掛掉或者整個server01的服務器掛掉),就會嘗試換一臺資源充足的服務器重新部署ServiceA並啟動,這樣就可以確保我們的服務一直是可用狀態,而不需要人工維護。
硬件資源利用
前面已經說過,kubernetes會根據節點(Node)的CPU與內存資源的可用量對服務進行部署調度,在調度策略中,可以配置不同的調度策略。例如現在有兩臺服務器:
server01 (4c16g), 已用(3c7.5G)
server02 (4c16g), 已用(1c13G)
需要部署兩個服務
serviceA-Java, 申請2G內存,0.5CPU單位
ServiceB-Nginx, 申請200M內存,申請1CPU單位
這裡kubernetes如果講道理的話,會將ServiceA-Java部署到server01,將serviceB-Nginx部署到server02。這裡server01的內存和server02的CPU資源都得到了充分的利用。經過個人實踐,相比之前的部署方式,kubernetes節省了很多資源,資源利用是非常高效的。
服務資源創建
kubernetes創建服務是非常方便的,分為以下兩個方面:
自有服務
在kubernetes中,進行項目服務部署是十分方便的,只需要構建好相應的鏡像,編寫一個yaml文件即可完成服務的部署。
yaml示例
<code>apiVersion: apps/v1beta1
kind: Deployment
metadata:
# 部署的模塊名稱
name: phantom-server-admin
# 需要部署哪個環境
namespace: develop
spec:
# 部署的實例數量
replicas: 1
template:
metadata:
labels:
# 給這個部署打個標籤,方便之後進行選擇
app: phantom-server-admin
spec:
containers:
# 服務的名稱
- name: phantom-server-admin
# 服務的鏡像
image: phantom-server-admin:v1
ports:
# 服務的端口
- containerPort: 7006
resources:
limits:
# 該服務需要的內存
memory: 1000Mi
/<code>
公共基礎服務
kubernetes開源社區中有一個工具叫helm, 類比的話就像是CentOS中的yum,我們可以通過這個工具進行簡單快速的安裝複雜的應用。阿里雲提供了可視化的創建界面,創建十分方便,相比於傳統運維需要自己進行基礎軟件的安裝的優點是十分突出的,免去了繁瑣的安裝過程,服務的穩定性也有了一定的保障。talk is cheap, show you the below images,
應用商店
可視化管理
在kubernetes中,所有的概念都抽象成不同的對象,而所有的對象都是可以通過圖形化界面進行管理和監控的,當然了,也同時提供了命令行客戶端kubectl進行管理。
對象創建
服務資源監控
各個節點的使用量監控
每個服務的使用量監控
資源整合管理
在之前的運維過程中,對各種資源的管理是十分複雜的,想做到統一管理各種資源更是難上加難,從前到後,我們需要對域名、負載均衡、服務實例、存儲服務進行逐個配置,配置的細節暫且不說,各個資源的關聯關係就錯綜複雜,非專業運維人員是無法進行統一規劃的。
而使用與雲服務整合的kubernetes之後,這些問題都迎刃而解。先看下圖做簡單說明
這是阿里kubernetes的路由配置界面,其中將負載均衡設備與域名和對應的服務進行了綁定,可以很直觀的表述三者之間的關係,同時易於修改排錯。
版本管理與滾動升級
版本管理
kubernetes在部署服務時,會記錄部署服務的版本,我們可以很容易的進行上次版本或跨版本回退。
滾動升級
kubernetes在進行服務升級時,採用的默認策略是先將一部分新的服務啟動,確定服務正常後,停止一部分舊服務,進行新老服務的替換,之後再啟動一些新的服務,停止一部分舊服務,直到舊服務全部停止,即切換完成。滾動省級的過程中,極大的減少了服務切換的間隔時間。
其它
上面所說的是kubernetes的主體功能,kubernetes還有很多其他重要的特性解決了之前運維的痛點,例如DNS解析、自動負載、存儲聲明等等。
三、kubernetes特點
網絡模型
kubernetes採用了三層網絡模型,分為PodIP,ClusterIP,NodeIP。用簡單的話來說,kubernetes在內部使用自己的網絡進行通訊,這樣做一個最直接的好處是我們不用再擔心端口衝突的問題。
舉個栗子: 我們在server01上部署兩個一樣的服務serviceA-1,serviceA-2,兩個服務的端口都是8080,這個時候有一個服務是無法啟動的,因為端口被佔用了,而在kubernetes中,兩個服務在不同的Docker容器中,每個Docker容器都有自己的IP,這時就不會出現端口占用的問題了。
為什麼要有三層網絡有三個IP呢?其實每個IP的作用是不一樣的:
NodeIP
NodeIP是最好理解的,就是每個服務器的IP。例如server01的IP是192.168.1.2,有一個服務實例的IP申明類型為NodeIP,端口申明為30222,那麼我們就可以通過192.168.1.2:30222訪問到這個服務實例。
PodIP
PodIP的作用可以簡單理解為每個服務自己teyoudeIP,就像上面說的可以解決端口衝突的問題,同時也是每個服務的唯一標識。PodIP是無法通過外網訪問的,只能在服務內部進行訪問。
ClusterIP(可以按照下面訪問的進行理解,但實際有所區別)
中文叫集群IP,對集群瞭解的同學應該很容易理解。集群IP可以簡單理解為是對同一個服務的多個實例(每個實例有自己的PodIP)組成的集群的入口IP,換句話說,是對多個實例的負載IP。舉個栗子:
有三個實例:
serviceA-1 172.22.1.2
serviceA-2 172.22.1.3
serviceA-3 172.22.1.4
有一個ClusterIP 172.23.2.23指向了serviceA服務,那麼我們訪問172.23.2.23則會負載轉向到172.22.1.2、172.22.1.3、172.22.1.4中的其中一個服務
對象
在kubernetes中,萬物皆對象。路由(Ingress)、服務(Service)、部署(Deployment)、存儲(Storage/PV/PVC)、容器(Pod)、角色(Role)、賬戶(Accoutn)、配置(ConfigMap)等等。通過管理這些對象來管理整個kubernetes集群。
注意:此處說的服務(Service),不同於上文提到的服務(開發的項目模塊)
聲名式管理
kubernetes採用聲名式進行資源管理,也就是從結果來看問題。舉個栗子,現在需要部署十個ServiceA
面向過程: 部署ServiceA-01,再部署ServiceA02…..ServiceA-10,強調的是過程,用代碼來表示的話就是while(serviceA.count < 10) {serviceA.count++}
面向結果(聲明式):不管是同時部署還是挨個部署,總之要部署十個ServiceA服務。用代碼來表示的話就是kubernetes.addServiceA(10),不用管內部的細節怎麼處理,只要最終的結果。
四、Kubernetes常用相關概念
部署 - Deployment
類似於Docker中的鏡像Image,也就是容器(Pods)實例的模板,容器實例是根據Deploy創建出來的。在Deployment對象中會寫明容器的鏡像,容器的版本,容器要部署的數量等信息。
容器組 - Pods
Pods是Kubernetes中的最小管理單元,Pods和Docker中的容器可以理解為包含關係,在Pods中可以包含有多個Docker容器,例如有ServiceA和ServiceB,ServiceA高度依賴ServiceB(需要共享主機的相同文件),這時就可以將ServiceA與ServiceB放在同一個Pods中,當做一個整體來管理。如果分開部署當然也可以,不過會小號額外的資源或者產生其他不必要的麻煩。
服務 - Service
Service是一個對象,這個對象有自己的IP,也就是ClusterIP,可以理解為就是下層服務的負載均衡。
路由 - Ingress
無論是容器組還是Service,外網都是無法直接訪問的,Ingress就可以通過一個負載IP與Kubernetes集群內部進行通訊,一般會和Service對象進行配合使用。
配置項 - ConfigMap
簡單理解為一個管理配置的對象,可以將項目的配置寫入到ConfgiMap中,項目中的配置使用相應的變量名就可以讀取相應的變量值。
還有很多其它概念,這是就不一一介紹了
五、Kubernetes結構圖
Kubernetes由Master節點和Worker節點組成。master節點是Kubernetes的大腦,而woker節點則是kubernetes中實際運行服務的勞動者。
Master主要由ETCD/Controller Manager/Api Server/Schedular能成,
ETCD
主要負責存儲各個woker節點的狀態和其它相關數據,可以理解為kubernetes的數據庫。
Controller Manager
負責維護集群的狀態,比如故障檢測、自動擴展、滾動更新等
Scheduler
負責資源的調度,按照預定的調度策略將Pod調度到相應的機器上
Worker主要由kubelet和kube-proxy組成,一般還會安裝kube-dns組件。
kubelet
負責維護容器的生命週期,同時也負責Volume(CVI)和網絡(CNI)的管理;
kube-proxy
負責為Service提供cluster內部的服務發現和負載均衡;
kube-dns
負責為整個集群提供DNS服務,通過Service名稱訪問相應的服務
六、總結
Kubernetes在容器編排可謂是做到了淋漓盡致,解決了之前的種種痛點,但是學習成本也相對較高,需要結合一定的實踐,踩一定的坑才能形成自己的理解。
JAVA進階架構程序員福利:我這裡還總結整理了比較全面的JAVA相關的面試資料,都已經整理成了
PDF版,這些都可以分享給大家,關注私信我:【806】,免費領取!
閱讀更多 欣然1013 的文章