日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Kubernetes 深入理解 Pod

發(fā)布時(shí)間:2023/12/20 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Kubernetes 深入理解 Pod 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

  • 為什么需要 Pod
  • Pod 的實(shí)現(xiàn)機(jī)制
  • 詳解容器設(shè)計(jì)模式
  • [root@k8s-master ~]# cat pod.yml apiVersion: v1 kind: Pod metadata:name: pod-demonnamespace: defaultlabels:app: myappannotations:create-by: cluster admin spec:containers:- name: myappimage: nginxports:- name: httpcontainerPort: 80- name: httpscontainerPort: 443- name: busyboximage: busyboxcommand: ['sh', '-c', 'echo "Hello, Kubernetes!" && sleep 3600']restartPolicy: OnFailure

    一、為什么需要 Pod


    容器的基本概念

    現(xiàn)在來(lái)看第一個(gè)問(wèn)題:為什么需要 Pod?我們知道 Pod 是 Kubernetes 項(xiàng)目里面一個(gè)非常重要的概念,也是非常重要的一個(gè)原子調(diào)度單位,但是為什么我們會(huì)需要這樣一個(gè)概念呢?我們?cè)谑褂萌萜?Docker 的時(shí)候,也沒(méi)有這個(gè)說(shuō)法。其實(shí)如果要理解 Pod,我們首先要理解容器,所以首先來(lái)回顧一下容器的概念:

    容器的本質(zhì)實(shí)際上是一個(gè)進(jìn)程,是一個(gè)視圖被隔離,資源受限的進(jìn)程。

    容器里面 PID=1 的進(jìn)程就是應(yīng)用本身,這意味著管理虛擬機(jī)等于管理基礎(chǔ)設(shè)施,因?yàn)槲覀兪窃诠芾頇C(jī)器,但管理容器卻等于直接管理應(yīng)用本身。這也是之前說(shuō)過(guò)的不可變基礎(chǔ)設(shè)施的一個(gè)最佳體現(xiàn),這個(gè)時(shí)候,你的應(yīng)用就等于你的基礎(chǔ)設(shè)施,它一定是不可變的。

    在以上面的例子為前提的情況下,Kubernetes 又是什么呢?我們知道,很多人都說(shuō) Kubernetes 是云時(shí)代的操作系統(tǒng),這個(gè)非常有意思,因?yàn)槿绻源祟愅?#xff0c;容器鏡像就是這個(gè)操作系統(tǒng)的軟件安裝包,它們之間是這樣的一個(gè)類比關(guān)系。

    真實(shí)操作系統(tǒng)里的例子

    如果說(shuō) Kubernetes 就是操作系統(tǒng)的話,那么我們不妨看一下真實(shí)的操作系統(tǒng)的例子。

    例子里面有一個(gè)程序叫做 Helloworld,這個(gè) Helloworld 程序?qū)嶋H上是由一組進(jìn)程組成的,需要注意一下,這里說(shuō)的進(jìn)程實(shí)際上等同于 Linux 中的線程。

    因?yàn)?Linux 中的線程是輕量級(jí)進(jìn)程,所以如果從 Linux 系統(tǒng)中去查看 Helloworld 中的 pstree,將會(huì)看到這個(gè) Helloworld 實(shí)際上是由四個(gè)線程組成的,分別是?{api、main、log、compute}。也就是說(shuō),四個(gè)這樣的線程共同協(xié)作,共享 Helloworld 程序的資源,組成了 Helloworld 程序的真實(shí)工作情況。

    這是操作系統(tǒng)里面進(jìn)程組或者線程組中一個(gè)非常真實(shí)的例子,以上就是進(jìn)程組的一個(gè)概念。

    ?那么大家不妨思考一下,在真實(shí)的操作系統(tǒng)里面,一個(gè)程序往往是根據(jù)進(jìn)程組來(lái)進(jìn)行管理的。Kubernetes 把它類比為一個(gè)操作系統(tǒng),比如說(shuō) Linux。針對(duì)于容器我們前面提到可以類比為進(jìn)程,就是前面的 Linux 線程。那么 Pod 又是什么呢?實(shí)際上 Pod 就是我們剛剛提到的進(jìn)程組,也就是 Linux 里的線程組。

    進(jìn)程組概念


    說(shuō)到進(jìn)程組,首先建議大家至少有個(gè)概念上的理解,然后我們?cè)僭敿?xì)的解釋一下。

    還是前面那個(gè)例子:Helloworld 程序由四個(gè)進(jìn)程組成,這些進(jìn)程之間會(huì)共享一些資源和文件。那么現(xiàn)在有一個(gè)問(wèn)題:假如說(shuō)現(xiàn)在把 Helloworld 程序用容器跑起來(lái),你會(huì)怎么去做?

    當(dāng)然,最自然的一個(gè)解法就是,我現(xiàn)在就啟動(dòng)一個(gè) Docker 容器,里面運(yùn)行四個(gè)進(jìn)程。可是這樣會(huì)有一個(gè)問(wèn)題,這種情況下容器里面 PID=1 的進(jìn)程該是誰(shuí)? 比如說(shuō),它應(yīng)該是我的 main 進(jìn)程,那么問(wèn)題來(lái)了,“誰(shuí)”又負(fù)責(zé)去管理剩余的 3 個(gè)進(jìn)程呢?

    這個(gè)核心問(wèn)題在于,容器的設(shè)計(jì)本身是一種“單進(jìn)程”模型,不是說(shuō)容器里只能起一個(gè)進(jìn)程,由于容器的應(yīng)用等于進(jìn)程,所以只能去管理 PID=1 的這個(gè)進(jìn)程,其他再起來(lái)的進(jìn)程其實(shí)是一個(gè)托管狀態(tài)。 所以說(shuō)服務(wù)應(yīng)用進(jìn)程本身就具有“進(jìn)程管理”的能力。

    比如說(shuō) Helloworld 的程序有 system 的能力,或者直接把容器里 PID=1 的進(jìn)程直接改成 systemd,否則這個(gè)應(yīng)用,或者是容器是沒(méi)有辦法去管理很多個(gè)進(jìn)程的。因?yàn)?PID=1 進(jìn)程是應(yīng)用本身,如果現(xiàn)在把這個(gè) PID=1 的進(jìn)程給 kill 了,或者它自己運(yùn)行過(guò)程中死掉了,那么剩下三個(gè)進(jìn)程的資源就沒(méi)有人回收了,這個(gè)是非常非常嚴(yán)重的一個(gè)問(wèn)題。

    而反過(guò)來(lái)真的把這個(gè)應(yīng)用本身改成了 systemd,或者在容器里面運(yùn)行了一個(gè) systemd,將會(huì)導(dǎo)致另外一個(gè)問(wèn)題:使得管理容器,不再是管理應(yīng)用本身了,而等于是管理 systemd,這里的問(wèn)題就非常明顯了。比如說(shuō)我這個(gè)容器里面 run 的程序或者進(jìn)程是 systemd,那么接下來(lái),這個(gè)應(yīng)用是不是退出了?是不是 fail 了?是不是出現(xiàn)異常失敗了?實(shí)際上是沒(méi)辦法直接知道的,因?yàn)槿萜鞴芾淼氖?systemd。這就是為什么在容器里面運(yùn)行一個(gè)復(fù)雜程序往往比較困難的一個(gè)原因。

    這里再幫大家梳理一下:由于容器實(shí)際上是一個(gè)“單進(jìn)程”模型,所以如果你在容器里啟動(dòng)多個(gè)進(jìn)程,只有一個(gè)可以作為 PID=1 的進(jìn)程,而這時(shí)候,如果這個(gè) PID=1 的進(jìn)程掛了,或者說(shuō)失敗退出了,那么其他三個(gè)進(jìn)程就會(huì)自然而然的成為孤兒,沒(méi)有人能夠管理它們,沒(méi)有人能夠回收它們的資源,這是一個(gè)非常不好的情況。

    ?注意:Linux 容器的“單進(jìn)程”模型,指的是容器的生命周期等同于 PID=1 的進(jìn)程(容器應(yīng)用進(jìn)程)的生命周期,而不是說(shuō)容器里不能創(chuàng)建多進(jìn)程。當(dāng)然,一般情況下,容器應(yīng)用進(jìn)程并不具備進(jìn)程管理能力,所以你通過(guò) exec 或者 ssh 在容器里創(chuàng)建的其他進(jìn)程,一旦異常退出(比如 ssh 終止)是很容易變成孤兒進(jìn)程的。

    ?反過(guò)來(lái),其實(shí)可以在容器里面 run 一個(gè) systemd,用它來(lái)管理其他所有的進(jìn)程。這樣會(huì)產(chǎn)生第二個(gè)問(wèn)題:實(shí)際上沒(méi)辦法直接管理我的應(yīng)用了,因?yàn)槲业膽?yīng)用被 systemd 給接管了,那么這個(gè)時(shí)候應(yīng)用狀態(tài)的生命周期就不等于容器生命周期。這個(gè)管理模型實(shí)際上是非常非常復(fù)雜的。

    Pod = “進(jìn)程組”


    在 kubernetes 里面,Pod 實(shí)際上正是 kubernetes 項(xiàng)目為你抽象出來(lái)的一個(gè)可以類比為進(jìn)程組的概念。

    前面提到的,由四個(gè)進(jìn)程共同組成的一個(gè)應(yīng)用 Helloworld,在 Kubernetes 里面,實(shí)際上會(huì)被定義為一個(gè)擁有四個(gè)容器的 Pod,這個(gè)概念大家一定要非常仔細(xì)的理解。

    就是說(shuō)現(xiàn)在有四個(gè)職責(zé)不同、相互協(xié)作的進(jìn)程,需要放在容器里去運(yùn)行,在 Kubernetes 里面并不會(huì)把它們放到一個(gè)容器里,因?yàn)檫@里會(huì)遇到兩個(gè)問(wèn)題。那么在 Kubernetes 里會(huì)怎么去做呢?它會(huì)把四個(gè)獨(dú)立的進(jìn)程分別用四個(gè)獨(dú)立的容器啟動(dòng)起來(lái),然后把它們定義在一個(gè) Pod 里面。

    所以當(dāng) Kubernetes 把 Helloworld 給拉起來(lái)的時(shí)候,你實(shí)際上會(huì)看到四個(gè)容器,它們共享了某些資源,這些資源都屬于 Pod,所以我們說(shuō) Pod 在 Kubernetes 里面只有一個(gè)邏輯單位,沒(méi)有一個(gè)真實(shí)的東西對(duì)應(yīng)說(shuō)這個(gè)就是 Pod,不會(huì)有的。真正起來(lái)在物理上存在的東西,就是四個(gè)容器。這四個(gè)容器,或者說(shuō)是多個(gè)容器的組合就叫做 Pod。并且還有一個(gè)概念一定要非常明確,Pod 是 Kubernetes 分配資源的一個(gè)單位,因?yàn)槔锩娴娜萜饕蚕砟承┵Y源,所以 Pod 也是 Kubernetes 的原子調(diào)度單位。

    上面提到的 Pod 設(shè)計(jì),也不是 Kubernetes 項(xiàng)目自己想出來(lái)的, 而是早在 Google 研發(fā) Borg 的時(shí)候,就已經(jīng)發(fā)現(xiàn)了這樣一個(gè)問(wèn)題。這個(gè)在 Borg paper 里面有非常非常明確的描述。簡(jiǎn)單來(lái)說(shuō) Google 工程師發(fā)現(xiàn)在 Borg 下面部署應(yīng)用時(shí),很多場(chǎng)景下都存在著類似于“進(jìn)程與進(jìn)程組”的關(guān)系。更具體的是,這些應(yīng)用之前往往有著密切的協(xié)作關(guān)系,使得它們必須部署在同一臺(tái)機(jī)器上并且共享某些信息。

    以上就是進(jìn)程組的概念,也是 Pod 的用法。

    為什么 Pod 必須是原子調(diào)度單位?


    可能到這里大家會(huì)有一些問(wèn)題:雖然了解這個(gè)東西是一個(gè)進(jìn)程組,但是為什么要把 Pod 本身作為一個(gè)概念抽象出來(lái)呢?或者說(shuō)能不能通過(guò)調(diào)度把 Pod 這個(gè)事情給解決掉呢?為什么 Pod 必須是 Kubernetes 里面的原子調(diào)度單位?

    下面我們通過(guò)一個(gè)例子來(lái)解釋。

    假如現(xiàn)在有兩個(gè)容器,它們是緊密協(xié)作的,所以它們應(yīng)該被部署在一個(gè) Pod 里面。具體來(lái)說(shuō),第一個(gè)容器叫做 App,就是業(yè)務(wù)容器,它會(huì)寫(xiě)日志文件;第二個(gè)容器叫做 LogCollector,它會(huì)把剛剛 App 容器寫(xiě)的日志文件轉(zhuǎn)發(fā)到后端的 ElasticSearch 中。

    兩個(gè)容器的資源需求是這樣的:App 容器需要 1G 內(nèi)存,LogCollector 需要 0.5G 內(nèi)存,而當(dāng)前集群環(huán)境的可用內(nèi)存是這樣一個(gè)情況:Node_A:1.25G 內(nèi)存,Node_B:2G 內(nèi)存。

    假如說(shuō)現(xiàn)在沒(méi)有 Pod 概念,就只有兩個(gè)容器,這兩個(gè)容器要緊密協(xié)作、運(yùn)行在一臺(tái)機(jī)器上。可是,如果調(diào)度器先把 App 調(diào)度到了 Node_A 上面,接下來(lái)會(huì)怎么樣呢?這時(shí)你會(huì)發(fā)現(xiàn):LogCollector 實(shí)際上是沒(méi)辦法調(diào)度到 Node_A 上的,因?yàn)橘Y源不夠。其實(shí)此時(shí)整個(gè)應(yīng)用本身就已經(jīng)出問(wèn)題了,調(diào)度已經(jīng)失敗了,必須去重新調(diào)度。

    以上就是一個(gè)非常典型的成組調(diào)度失敗的例子。英文叫做:Task co-scheduling 問(wèn)題,這個(gè)問(wèn)題不是說(shuō)不能解,在很多項(xiàng)目里面,這樣的問(wèn)題都有解法。

    比如說(shuō)在 Mesos 里面,它會(huì)做一個(gè)事情,叫做資源囤積(resource hoarding):即當(dāng)所有設(shè)置了 Affinity 約束的任務(wù)都達(dá)到時(shí),才開(kāi)始統(tǒng)一調(diào)度,這是一個(gè)非常典型的成組調(diào)度的解法。

    所以上面提到的“App”和“LogCollector”這兩個(gè)容器,在 Mesos 里面,他們不會(huì)說(shuō)立刻調(diào)度,而是等兩個(gè)容器都提交完成,才開(kāi)始統(tǒng)一調(diào)度。這樣也會(huì)帶來(lái)新的問(wèn)題,首先調(diào)度效率會(huì)損失,因?yàn)樾枰却S捎谛枰冗€會(huì)有外一個(gè)情況會(huì)出現(xiàn),就是產(chǎn)生死鎖,就是互相等待的一個(gè)情況。這些機(jī)制在 Mesos 里都是需要解決的,也帶來(lái)了額外的復(fù)雜度。

    另一種解法是 Google 的解法。它在 Omega 系統(tǒng)(就是 Borg 下一代)里面,做了一個(gè)非常復(fù)雜且非常厲害的解法,叫做樂(lè)觀調(diào)度。比如說(shuō):不管這些沖突的異常情況,先調(diào)度,同時(shí)設(shè)置一個(gè)非常精妙的回滾機(jī)制,這樣經(jīng)過(guò)沖突后,通過(guò)回滾來(lái)解決問(wèn)題。這個(gè)方式相對(duì)來(lái)說(shuō)要更加優(yōu)雅,也更加高效,但是它的實(shí)現(xiàn)機(jī)制是非常復(fù)雜的。這個(gè)有很多人也能理解,就是悲觀鎖的設(shè)置一定比樂(lè)觀鎖要簡(jiǎn)單。

    而像這樣的一個(gè) Task co-scheduling 問(wèn)題,在 Kubernetes 里,就直接通過(guò) Pod 這樣一個(gè)概念去解決了。因?yàn)樵?Kubernetes 里,這樣的一個(gè) App 容器和 LogCollector 容器一定是屬于一個(gè) Pod 的,它們?cè)谡{(diào)度時(shí)必然是以一個(gè) Pod 為單位進(jìn)行調(diào)度,所以這個(gè)問(wèn)題是根本不存在的。

    再次理解 Pod


    在講了前面這些知識(shí)點(diǎn)之后,我們來(lái)再次理解一下 Pod,首先 Pod 里面的容器是“超親密關(guān)系”。

    這里有個(gè)“超”字需要大家理解,正常來(lái)說(shuō),有一種關(guān)系叫做親密關(guān)系,這個(gè)親密關(guān)系是一定可以通過(guò)調(diào)度來(lái)解決的。

    比如說(shuō)現(xiàn)在有兩個(gè) Pod,它們需要運(yùn)行在同一臺(tái)宿主機(jī)上,那這樣就屬于親密關(guān)系,調(diào)度器一定是可以幫助去做的。但是對(duì)于超親密關(guān)系來(lái)說(shuō),有一個(gè)問(wèn)題,即它必須通過(guò) Pod 來(lái)解決。因?yàn)槿绻H密關(guān)系賦予不了,那么整個(gè) Pod 或者說(shuō)是整個(gè)應(yīng)用都無(wú)法啟動(dòng)。

    什么叫做超親密關(guān)系呢?大概分為以下幾類:

    • 比如說(shuō)兩個(gè)進(jìn)程之間會(huì)發(fā)生文件交換,前面提到的例子就是這樣,一個(gè)寫(xiě)日志,一個(gè)讀日志;
    • 兩個(gè)進(jìn)程之間需要通過(guò) localhost 或者說(shuō)是本地的 Socket 去進(jìn)行通信,這種本地通信也是超親密關(guān)系;
    • 這兩個(gè)容器或者是微服務(wù)之間,需要發(fā)生非常頻繁的 RPC 調(diào)用,出于性能的考慮,也希望它們是超親密關(guān)系;
    • 兩個(gè)容器或者是應(yīng)用,它們需要共享某些 Linux Namespace。最簡(jiǎn)單常見(jiàn)的一個(gè)例子,就是我有一個(gè)容器需要加入另一個(gè)容器的 Network Namespace。這樣我就能看到另一個(gè)容器的網(wǎng)絡(luò)設(shè)備,和它的網(wǎng)絡(luò)信息。

    ?二、Pod 的實(shí)現(xiàn)機(jī)制


    Pod 要解決的問(wèn)題

    像 Pod 這樣一個(gè)東西,本身是一個(gè)邏輯概念。那在機(jī)器上,它究竟是怎么實(shí)現(xiàn)的呢?這就是我們要解釋的第二個(gè)問(wèn)題。

    既然說(shuō) Pod 要解決這個(gè)問(wèn)題,核心就在于如何讓一個(gè) Pod 里的多個(gè)容器之間最高效的共享某些資源和數(shù)據(jù)。?

    因?yàn)槿萜髦g原本是被 Linux Namespace 和 cgroups 隔開(kāi)的,所以現(xiàn)在實(shí)際要解決的是怎么去打破這個(gè)隔離,然后共享某些事情和某些信息。這就是 Pod 的設(shè)計(jì)要解決的核心問(wèn)題所在。?

    所以說(shuō)具體的解法分為兩個(gè)部分:網(wǎng)絡(luò)和存儲(chǔ)。?

    1.共享網(wǎng)絡(luò)

    第一個(gè)問(wèn)題是 Pod 里的多個(gè)容器怎么去共享網(wǎng)絡(luò)?下面是個(gè)例子:

    比如說(shuō)現(xiàn)在有一個(gè) Pod,其中包含了一個(gè)容器 A 和一個(gè)容器 B,它們兩個(gè)就要共享 Network Namespace。在 Kubernetes 里的解法是這樣的:它會(huì)在每個(gè) Pod 里,額外起一個(gè) Infra container 小容器來(lái)共享整個(gè) Pod 的? Network Namespace。

    Infra container 是一個(gè)非常小的鏡像,大概 100~200KB 左右,是一個(gè)匯編語(yǔ)言寫(xiě)的、永遠(yuǎn)處于“暫停”狀態(tài)的容器。由于有了這樣一個(gè) Infra container 之后,其他所有容器都會(huì)通過(guò) Join Namespace 的方式加入到 Infra container 的 Network Namespace 中。

    所以說(shuō)一個(gè) Pod 里面的所有容器,它們看到的網(wǎng)絡(luò)視圖是完全一樣的。即:它們看到的網(wǎng)絡(luò)設(shè)備、IP地址、Mac地址等等,跟網(wǎng)絡(luò)相關(guān)的信息,其實(shí)全是一份,這一份都來(lái)自于 Pod 第一次創(chuàng)建的這個(gè) Infra container。這就是 Pod 解決網(wǎng)絡(luò)共享的一個(gè)解法。?

    在 Pod 里面,一定有一個(gè) IP 地址,是這個(gè) Pod 的 Network Namespace 對(duì)應(yīng)的地址,也是這個(gè) Infra container 的 IP 地址。所以大家看到的都是一份,而其他所有網(wǎng)絡(luò)資源,都是一個(gè) Pod 一份,并且被 Pod 中的所有容器共享。這就是 Pod 的網(wǎng)絡(luò)實(shí)現(xiàn)方式。

    由于需要有一個(gè)相當(dāng)于說(shuō)中間的容器存在,所以整個(gè) Pod 里面,必然是 Infra container 第一個(gè)啟動(dòng)。并且整個(gè) Pod 的生命周期是等同于 Infra container 的生命周期的,與容器 A 和 B 是無(wú)關(guān)的。這也是為什么在 Kubernetes 里面,它是允許去單獨(dú)更新 Pod 里的某一個(gè)鏡像的,即:做這個(gè)操作,整個(gè) Pod 不會(huì)重建,也不會(huì)重啟,這是非常重要的一個(gè)設(shè)計(jì)。

    2.共享存儲(chǔ)

    第二問(wèn)題:Pod 怎么去共享存儲(chǔ)?Pod 共享存儲(chǔ)就相對(duì)比較簡(jiǎn)單。

    比如說(shuō)現(xiàn)在有兩個(gè)容器,一個(gè)是 Nginx,另外一個(gè)是非常普通的容器,在 Nginx 里放一些文件,讓我能通過(guò) Nginx 訪問(wèn)到。所以它需要去 share 這個(gè)目錄。我 share 文件或者是 share 目錄在 Pod 里面是非常簡(jiǎn)單的,實(shí)際上就是把 volume 變成了 Pod level。然后所有容器,就是所有同屬于一個(gè) Pod 的容器,他們共享所有的 volume。

    比如說(shuō)上圖的例子,這個(gè) volume 叫做 shared-data,它是屬于 Pod level 的,所以在每一個(gè)容器里可以直接聲明:要掛載 shared-data 這個(gè) volume,只要你聲明了你掛載這個(gè) volume,你在容器里去看這個(gè)目錄,實(shí)際上大家看到的就是同一份。這個(gè)就是 Kubernetes 通過(guò) Pod 來(lái)給容器共享存儲(chǔ)的一個(gè)做法。

    所以在之前的例子中,應(yīng)用容器 App 寫(xiě)了日志,只要這個(gè)日志是寫(xiě)在一個(gè) volume 中,只要聲明掛載了同樣的 volume,這個(gè) volume 就可以立刻被另外一個(gè) LogCollector 容器給看到。以上就是 Pod 實(shí)現(xiàn)存儲(chǔ)的方式。?

    總結(jié)

    以上是生活随笔為你收集整理的Kubernetes 深入理解 Pod的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。