開發(fā)也需了解的運維知識之Kubernetes
本文轉(zhuǎn)載自微信公眾號「 Java藝術(shù)」,轉(zhuǎn)載本文請聯(lián)系 Java藝術(shù)公眾號。
Docker與Kubernetes是什么關(guān)系?這可能是我們剛接觸Kubernetes時都有的一個疑問。那么Kubernetes是什么?
Kubernetes是一個容器集群編排管理系統(tǒng),用于實現(xiàn)容器集群的自動化部署、自動擴縮容等功能。Docker提供用于運行應(yīng)用程序的容器技術(shù),而Kubernetes本身并不提供用于運行應(yīng)用程序的容器,而是負責(zé)管理容器。
了解Docker與Kubernetes的關(guān)系之后,就能理解為什么我們要先學(xué)習(xí)Docker再學(xué)習(xí)Kubernetes,這與先學(xué)習(xí)Spring框架才能更好地學(xué)習(xí)Spring Boot、Spring Cloud是一樣的。如果還不了解Docker可以先看下上一篇《開發(fā)也需了解的運維知識之Docker》。
作為開發(fā),我們?yōu)槭裁匆私馊萜骷夹g(shù),這不是運維該學(xué)習(xí)的嗎?作為開發(fā)者,只有足夠了解容器技術(shù),才能做好技術(shù)選型,以及開發(fā)部署在Kubernetes容器服務(wù)之上的應(yīng)用應(yīng)該要注意哪些問題。如果運維不了解代碼,開發(fā)也不了解Kubernetes,誰能解決將服務(wù)遷移到Kubernetes上遇到的各種問題呢?
關(guān)于Kubernetes
學(xué)習(xí)Kubernetes首先要了解Kubernetes的架構(gòu),了解一些“概念”,再了解配置文件。配置文件這塊對初學(xué)者來說是最難理解的,因此推薦大家閱讀《Kubernetes in Action中文版》這本書,跟著例子一步步掌握一些配置文件中每種kind的作用,每個配置項的作用是什么。
Kubernetes管理所有可用的物理機,以阿里云容器服務(wù)Kubernetes為例,Kubernetes負責(zé)管理一堆ECS實例,這需要我們在創(chuàng)建Kubernetes集群時,購買足夠的ECS實例,至少兩臺。后續(xù)也可將新購買的ECS實例加到Kubernetes集群,由Kubernetes管理。
開發(fā)者和運維都不需要知道一個應(yīng)用程序部署在哪個ECS實例上,只需要指定運行應(yīng)用程序所需要的cpu、內(nèi)存等資源,Kubernetes會根據(jù)要求計算出滿足條件的節(jié)點(ECS),并在節(jié)點(ECS)上從鏡像倉庫拉取應(yīng)用程序的鏡像創(chuàng)建容器并運行容器,并且監(jiān)控容器的整個生命周期。我們可以把Kubernetes管理的所有節(jié)點(ECS)看成一個大的物理機,這臺大的物理機的cpu、內(nèi)存是所有節(jié)點(ECS)的總和。
(圖片來之《Kubernetes in Action》)
如上圖所示,開發(fā)者只需要將應(yīng)用構(gòu)造成鏡像,并將鏡像push到遠程鏡像倉庫,然后編寫一個配置文件,在配置文件中描述應(yīng)用程序鏡像運行所需要的資源、鏡像從哪拉取等,使用kubectl調(diào)用Kubernetes提供的API就能將應(yīng)用程序部署到Kubernetes。
Kubernetes由兩種類型的節(jié)點組成。
(圖片來自《Kubernetes in Action》)
一種是主節(jié)點Master,負責(zé)控制和管理整個集群,為實現(xiàn)高可用,主節(jié)點也要求部署集群。主節(jié)點上會部署一些組件,這些組件可以運行在單個主節(jié)點上,或者通過副本分別部署在多個主節(jié)點上,實現(xiàn)高可用。如基于Reft協(xié)議實現(xiàn)的數(shù)據(jù)強一致性存儲服務(wù)etcd、提供給我們使用的Kubernetes API服務(wù)、調(diào)度應(yīng)用部署的Scheculer組件、執(zhí)行集群功能的Controller Manager組件。這些組件我們可以先這么簡單了解,暫時不用過于深究。
另一種是工作節(jié)點,運行用戶實際部署的應(yīng)用。
假設(shè)我們在阿里云購買了托管的Kubernetes服務(wù),那么主節(jié)點就由阿里云托管,而工作節(jié)點就是我們購買的ECS實例,一個集群中有多少個ECS實例就是有多少個工作節(jié)點。
工作節(jié)點就是運行容器的機器,除了運行用于運行我們部署的應(yīng)用程序的容器外,每個工作節(jié)點上還會運行一些組件,這些組件負責(zé)運行、監(jiān)控和管理應(yīng)用服務(wù)。如Docker、Kubelet、Kube-proxy。Docker我們已經(jīng)很熟悉了;Kubelet負責(zé)與主節(jié)點的Kubernetes API服務(wù)通信,并管理它所在的工作節(jié)點的容器;Kube-proxy負責(zé)組件之間的負載均衡網(wǎng)絡(luò)流量。
上圖是根據(jù)到目前為止我們對Kubernetes的了解所畫出的一個應(yīng)用部署流程圖。
- 1、開發(fā)者在本地機器構(gòu)建應(yīng)用程序鏡像;
- 2、開發(fā)者將本地應(yīng)用程序鏡像psuh到鏡像倉庫;
- 3、開發(fā)者為運行應(yīng)用程序編寫描述文件(yaml配置文件);
- 4、開發(fā)者使用kubectl調(diào)用Kubernetes API將應(yīng)用程序描述文件提交給Kubernetes;
- 5、Scheduler組件根據(jù)描述文件調(diào)度工作節(jié)點部署應(yīng)用程序;
- 6、在工作節(jié)點上由Container runtime負責(zé)從鏡像倉庫拉取鏡像、創(chuàng)建容器并運行容器;
在實際項目部署時,我們可能最關(guān)系也最難理解就是網(wǎng)絡(luò)和容器這部分內(nèi)容。比如,在不使用Kubernetes時,我們部署一個需要SSD資源的應(yīng)用程序時,先購買SSD掛載在該服務(wù)器上,而使用Kubernetes時,我們要告訴Kubernetes只在具有SSD的節(jié)點中選擇節(jié)點部署應(yīng)用。網(wǎng)絡(luò)和容器卷的內(nèi)容還是很多很復(fù)雜的,本篇就不過多介紹,后續(xù)文章中再介紹,當(dāng)然也只是簡單的理解和怎么去用,因為筆者目前理解的也不多。
需要了解的一些概念
namespaces:用于區(qū)分不同的資源,如測試環(huán)境資源、生產(chǎn)環(huán)境資源;當(dāng)然也可以使用labels區(qū)分。不指定namespaces則默認(rèn)使用default,如果使用非defalut名稱空間,則在使用kubectl創(chuàng)建secret、創(chuàng)建ServiceAccount等都需要明確指定namespaces。
節(jié)點(Node):節(jié)點就是實際的機器或者虛擬機,例如阿里云ECS。
Pod:Pod是Kubernetes創(chuàng)建或部署的最小基本單位,一個Pod封裝一個或多個應(yīng)用容器,存儲資源、一個獨立的網(wǎng)絡(luò)IP以及管理控制容器運行方式的策略選項。
(圖片來自《Kubernetes in Action》)
如上圖所示,當(dāng)一個Pod包含多個容器時,這些容器總是運行于同一個工作節(jié)點上,不會跨越多個工作節(jié)點。例如我們部署一個java程序,可以在一個Pod中運行多個該java程序的容器。Pod可以封裝緊密耦合的應(yīng)用,它們需要由多個容器組成,它們之間能夠共享資源,例如前后端部署在一起(這個例子不恰當(dāng))。而對于我們開發(fā)java微服務(wù)應(yīng)用來說,一般一個Pod只會運行一個容器,因此初學(xué)時可以不用過多去糾結(jié)這些概念。
Service:Service抽象的概念,是Pod的邏輯分組,這一組Pod能夠被Service訪問到,通常是通過Label、Selector實現(xiàn)。例如:
- apiVersion: v1
- kind: Service
- metadata:
- name: demo-srv-service
- namespace: sit
- spec:
- selector:
- app: demo-srv
- env: sit
- ports:
- - protocol: TCP
- port: 80
- targetPort: 8080
通過selector匹配app為demo-srv、env為sit的一組Pod,這組Pod對應(yīng)demo-srv-service這個Service。更簡單一點理解,假設(shè)我們部署一個java程序,一個Pod只啟動一個該java程序的容器,那么啟動多個該java程序就對應(yīng)多個Pod,而這組Pod對應(yīng)同一個Service。
ReplicationController:ReplicationController(簡稱RC)是確保用戶定義的Pod副本數(shù)保持不變。在用戶定義范圍內(nèi),如指定一個java程序部署的集群數(shù)量為3,如果Pod超過3(例如手動啟動),則RC會終止額外的Pod,如果少于3(例如內(nèi)存溢出導(dǎo)致),RC會創(chuàng)建新的Pod,始終保持在定義范圍。
ReplicaSet:ReplicaSet簡稱RS,是RC的升級版本。RS和RC之間的唯一區(qū)別是對選擇器(Selector)的支持,這里不做過多介紹。
Deployments:Deployment為Pod和ReplicaSet提供聲明式更新。你只需要在Deployment中描述你想要的目標(biāo)狀態(tài)是什么,Deployment Controller就會幫你將Pod和ReplicaSet的實際狀態(tài)改變到你的目標(biāo)狀態(tài)。
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- name: demo-srv-deployment
- namespace: sit
- spec:
- # 副本數(shù),運行多少個`Pod`
- replicas: 3
- # 選擇器,使用標(biāo)簽匹配
- selector:
- matchLabels:
- app: demo-srv
- template:
- metadata:
- # 標(biāo)簽
- labels:
- app: demo-srv
- env: sit
- spec:
- # 容器,指定多個容器就會在一個`Pod`內(nèi)運行多個容器
- containers:
- - name: demo-srv
- image: registry.cn-shenzhen.aliyuncs.com/wujiuye/demo-srv
DaemonSet:確保每個節(jié)點(物理機器或者虛擬機)上只運行一個該應(yīng)用的Pod。如阿里云的實現(xiàn)的日記收集,就是在每個節(jié)點上運行一個用于收集日記的應(yīng)用程序容器,對應(yīng)一個Pod。
網(wǎng)絡(luò)通信
Pod之間的網(wǎng)絡(luò)通信:
Kubernetes集群中的所有Pod都在同一個共享網(wǎng)絡(luò)地址空間中,這意味著每個Pod都可以通過其他Pod的IP地址來實現(xiàn)相互訪問。這也表示它們之間沒有NAT網(wǎng)關(guān)。當(dāng)兩個Pod彼此之間發(fā)送網(wǎng)絡(luò)數(shù)據(jù)包時,它們都會將對方的實際IP地址看作數(shù)據(jù)包中的源IP。
無論是將兩個Pod安排在單一的還是不同的工作節(jié)點上,同時不管實際節(jié)點間的網(wǎng)絡(luò)拓撲結(jié)構(gòu)如何,這些Pod內(nèi)的容器都能夠像在局域網(wǎng)上的計算機一樣通信。
Service之間的網(wǎng)絡(luò)通信:
Kubernetes service為一組功能相同的Pod提供單一不變的接入點。當(dāng)服務(wù)存在時,它的IP地址和端口不會改變??蛻舳送ㄟ^IP地址和端口號建立連接,這些連接會被路由到提供該服務(wù)的任意一個Pod上,會實現(xiàn)負載均衡。通過這種方式,客戶端不需要知道每個單獨的提供服務(wù)的Pod的地址,這樣這些Pod就可以在集群中隨時被創(chuàng)建或移除。
假設(shè)現(xiàn)有一個項目,該項目有兩個微服務(wù),分別是demo-srv、demo-cap?,F(xiàn)在將這兩個服務(wù)部署到阿里云容器服務(wù)Kubernetes上,在控制臺的服務(wù)列表頁可以看到,這兩個服務(wù)都有一個集群IP,不管這個兩個服務(wù)部署多少個Pod,也不管Pod怎么變,其它服務(wù)都可以通過這個集群IP訪問背后的Pod,當(dāng)然訪問背后Pod也是實現(xiàn)負載均衡的。
也是因為如此,我們開發(fā)微服務(wù)實現(xiàn)的服務(wù)發(fā)現(xiàn)都是基于Service的,那么在應(yīng)用程序中實現(xiàn)負載均衡就顯得多余了。
類型:
- ClusterIP:通過集群的內(nèi)部IP暴露服務(wù),選擇該值,服務(wù)只能夠在Kubernetes集群內(nèi)部可以訪問。
- NodePort:通過每個Node上的IP和靜態(tài)端口(NodePort)暴露服務(wù)。NodePort服務(wù)會路由到ClusterIP服務(wù),這個ClusterIP服務(wù)會自動創(chuàng)建。通過請求
: ,可以從集群的外部訪問一個NodePort服務(wù)。 - LoadBalancer:如使用阿里云提供的負載均衡器,可以向外部暴露服務(wù)。外部的負載均衡器可以路由到NodePort服務(wù)和ClusterIP服務(wù)。
本篇就介紹到這,Kubernetes要學(xué)的知識點很多,但作為開發(fā),我們可能不會去過多的關(guān)注一些細節(jié),本篇介紹的知識點是筆者認(rèn)為作為開發(fā)應(yīng)掌握的知識的。網(wǎng)絡(luò)、容器卷這部署建議多了解一些,網(wǎng)絡(luò)有關(guān)服務(wù)間的調(diào)用,而容器卷有關(guān)日記的打印、文件存儲,如果使用阿里云容器服務(wù),那么日記這塊我們可以不輸出到文件,使用阿里提供的日記服務(wù)收集日記。但如果需要持久化存儲的服務(wù),就必須要了解容器卷Volume。
不懂的概念可以查閱官方文檔:http://docs.kubernetes.org.cn
想要深入學(xué)習(xí)還是推薦閱讀《Kubernetes in Action》中文版