查看原文獲得更好閱讀體驗震嫉。
剛開始接觸K8s的同學(xué)可能都會覺得有一定的學(xué)習(xí)難度,撲面而來的各種概念到底是什么牡属。比如票堵,如何提供一個服務(wù)給別人,我是應(yīng)該用Pod還是用Deployment來運(yùn)行我的應(yīng)用等逮栅,在接下來的文章中悴势,希望能夠解答你的這些疑惑。
Kubernetes可以看做云原生時代的操作系統(tǒng)措伐,統(tǒng)一管理下層的基礎(chǔ)設(shè)施特纤,如計算資源、網(wǎng)絡(luò)資源废士、存儲資源等等叫潦。將集群中存在的各種復(fù)雜關(guān)系抽象成各種API資源,以統(tǒng)一的方式暴露出各種接口官硝,也便于未來的擴(kuò)展以及開發(fā)團(tuán)隊根據(jù)自己的需要定制矗蕊。因此,我們可以看到在K8s中Docker僅僅是容器運(yùn)行時的一個實現(xiàn)而已氢架,只要遵守它的約定傻咖,實際上是可以替換為適合的其他容器技術(shù)的♂校基于這樣的設(shè)計思路卿操,理清各種API對象的作用和關(guān)系就變得很重要了,只有理解了才能正確地使用K8s孙援,接下來我們就通過一張關(guān)系圖一點點的來說明害淤。
通過Pod終結(jié)單容器的蠻荒時代
在接觸K8s之前,大多人首先要接觸到的就是Docker拓售。我們得到一個容器的鏡像之后窥摄,要把應(yīng)用運(yùn)行起來最簡單的方式就是
docker run
的命令。然而在實際的生產(chǎn)環(huán)境中础淤,很少僅靠一個單容器就能夠滿足崭放。比如哨苛,一個Web前端的應(yīng)用,可能還得依賴后端的一個容器服務(wù)币砂;后端的容器可能需要數(shù)據(jù)庫服務(wù)建峭;后端的服務(wù)需要多副本等等場景。在這些假想的場景中决摧,比較真實的需求就是這些容器應(yīng)用需要共享同一個網(wǎng)絡(luò)棧亿蒸,同一個存儲卷等,還有它們的生命周期如何管理調(diào)度蜜徽。這個時候祝懂,僅僅依靠容器無法解決這個問題,我們第一個選手Pod就閃亮登場了拘鞋。
Pod 內(nèi)共享配置
有了Pod之后砚蓬,同一個Pod內(nèi)的容器可以共享很多信息,也可能需要讀取同一份配置盆色。比如Pod內(nèi)有兩個容器需要訪問同一個數(shù)據(jù)庫灰蛙,那么我們可以把相關(guān)的配置信息寫到ConfigMap里。那如果還有一些比較敏感的信息的話隔躲,就需要放到Secret對象中摩梧,它其實是一個保存在 Etcd 里的鍵值對數(shù)據(jù)。這樣宣旱,你把 Credential 信息以 Secret 的方式存在 Etcd 里仅父,Kubernetes 就會在你指定的 Pod(比如,Web 應(yīng)用的 Pod)啟動時浑吟,自動把 Secret 里的數(shù)據(jù)以 Volume 的方式掛載到容器里笙纤。
任務(wù)和定時任務(wù)
有了Pod之后,事情就變得更清晰了组力。在集群內(nèi)省容,我們可能會有多種形式的要求。比如燎字,我們可能希望一個應(yīng)用每天固定時間運(yùn)行或者只允許運(yùn)行一次腥椒,可能希望某個應(yīng)用以守護(hù)進(jìn)程的方式運(yùn)行。在K8s里候衍,自然也有方案來解決這些問題笼蛛。
首先來看定時任務(wù)的需求,假設(shè)我的系統(tǒng)內(nèi)有一個全網(wǎng)信息排行榜展示蛉鹿,要求每天需要在凌晨0點的時候更新一次伐弹。這個需求在K8s里就可以用CronJob來搞定。而如果僅僅需要執(zhí)行一次的任務(wù)榨为,那就直接使用Job對象就可以了惨好。
默默工作的DaemonSet
再接下來,可能需要以守護(hù)進(jìn)程的方式運(yùn)行一個應(yīng)用随闺。比如日川,我想要在后臺進(jìn)行日志的收集。這個時候DaemonSet就派上了用場矩乐,它會保證在所有的目標(biāo)節(jié)點上運(yùn)行一個Pod的副本龄句。在這期間,如果有新的Node加入到K8s集群中的話散罕,它也會自動完成調(diào)度分歇,在新的機(jī)器上運(yùn)行一個Pod副本。因此欧漱,前面說的監(jiān)控职抡、日志等任務(wù)很適合用DaemonSet的方式執(zhí)
Deployment管理Pod
說完DaemonSet,下一個重點Deployment來了误甚。前面說過容器之間的關(guān)聯(lián)關(guān)系缚甩、共享資源等問題需要處理,從而引入了Pod窑邦。對于Pod擅威,也是同樣的問題需要解決,只不過高了一個抽象層次罷了冈钦。因為面臨Pod的生命周期管理郊丛、調(diào)度、多副本等問題需要解決瞧筛,聰明的設(shè)計者引入了Deployment厉熟。它可以根據(jù)我們的需求(比如通過標(biāo)簽)將Pod調(diào)度到目標(biāo)機(jī)器上,調(diào)度完成之后驾窟,它還會繼續(xù)幫我們繼續(xù)監(jiān)控容器是否在正確運(yùn)行庆猫,一旦出現(xiàn)問題,會立刻告訴我們Pod的運(yùn)行不正常以及尋找可能的解決方案绅络,比如目標(biāo)節(jié)點不可用的時候它可以快速地調(diào)度到別的機(jī)器上去月培。另外,如果需要對應(yīng)用擴(kuò)容提升響應(yīng)能力的時候恩急,通過Deployment可以快速地進(jìn)行擴(kuò)展杉畜。
在實際的工作中,Deployment并不是直接控制著Pod的衷恭,中間實際上還有一個ReplicaSet此叠,但是在這里為了簡化理解過程,可以先忽略随珠。
提供容器服務(wù)
前面的內(nèi)容主要是圍繞著Pod自身的運(yùn)行調(diào)度管理灭袁,下面面臨的問題是解決如何將服務(wù)提供給第三方的問題猬错。
- 對內(nèi)提供服務(wù)
首先要解決的是將服務(wù)提供給同一個集群內(nèi)的其他服務(wù)使用∪灼纾可能剛?cè)腴T的同學(xué)會問為什么我們不能直接使用Pod的IP呢倦炒?原因是這樣,前面也說過Pod是會被管理調(diào)度的软瞎,可能被調(diào)度到不同的機(jī)器上逢唤,同時生命周期也可能會發(fā)生變化。這導(dǎo)致一個應(yīng)用的IP可能會隨時發(fā)生變化涤浇,那么直接使用Pod的IP自然是不合理的鳖藕。
針對這個問題K8s提供了Service對象來解決。
但是只锭,并不是說Service就有一個固定的IP著恩。而且,它和Pod IP還有很不一樣的地方纹烹。Pod的網(wǎng)絡(luò)是K8s在物理機(jī)上建立了一層Overlay Network實現(xiàn)的页滚,而且在網(wǎng)卡上能夠看到這個網(wǎng)絡(luò)的地址。但是Service是一個完全虛擬的網(wǎng)絡(luò)層铺呵,并不會存在于任何網(wǎng)絡(luò)設(shè)備上裹驰。它通過修改集群內(nèi)部的路由規(guī)則,僅對集群內(nèi)部有效片挂。Deploment創(chuàng)建好應(yīng)用之后幻林,再為它生成一個Service對象。接下來就可以通過Service的域名訪問到服務(wù)音念,形式是
<Service Name>.<NameSpace>
沪饺,比如你有為Deployment的應(yīng)用創(chuàng)建了一個名為portal的Service在默認(rèn)的命名空間,那么集群內(nèi)想要通過Http訪問這個應(yīng)用闷愤,就可以使用http://portal.default整葡。這個域名僅在集群內(nèi)有效,因為是內(nèi)部的一個DNS負(fù)責(zé)解析讥脐。
- 對外提供服務(wù)
說完如何給內(nèi)部提供服務(wù)以后遭居,剩下的就是如何給外部提供服務(wù)了。在K8s里把這個叫做Ingress旬渠,正如其名俱萍,它是集群的入口。比如我們的集群Web應(yīng)用想要讓用戶能夠訪問告丢,那必然要在Ingress入口上增加一條解析記錄枪蘑。這一點,熟悉像Nginx的朋友應(yīng)該比較容易理解,事實上Nginx Ingress也是K8s生態(tài)中的一個成員岳颇。
關(guān)于Ingress的使用照捡,在之前我曾寫過一篇使用Traefik作為Ingress的文章,我們可以通過Traefik實現(xiàn)為需要暴露的服務(wù)提供負(fù)載均衡赦役、自動簽發(fā)Https證書麻敌、限流等很多功能,如果有興趣可以點擊查看掂摔。