天天看點

單一Pod上的容器是怎麼共享網絡命名空間的?

作者:平凡人筆記

容器和虛拟機比較

單一Pod上的容器是怎麼共享網絡命名空間的?
  • 虛拟機在基礎架構之上有一個虛拟機監控的程式,在它上面會有不同的作業系統,在不同的作業系統之上再運作獨立的應用程式;
  • 采用容器技術的好處是運作相同的應用程式,使用容器額外開銷比較少,這也是它比較受歡迎的原因;
單一Pod上的容器是怎麼共享網絡命名空間的?

docker有個背景程序使用containerd,它是專門用來管理容器以及容器鏡像的一個應用,當然這個容器鏡像要符合OCI(開放容器标準),它會通過runc進行一個解包的處理,runc是專門用來運作容器中應用的。

容器技術的核心功能

命名空間(Namespace)

Linux命名空間提供了一種核心級别隔離系統資源的方法,通過将系統的全局資源放在不同的Namespace中來實作資源隔離的目的。

  • 檔案系統隔離
  • 程序隔離
  • 網絡資源隔離
  • 使用者和使用者組隔離
  • 主機名和域名隔離
  • 程序間通信隔離

控制組(CGroup)

Linux控制組是一個核心功能,用于限制,記錄和隔離一個或多個程序,對CPU、記憶體、磁盤I/O、以及網絡的使用量及通路。

  • 限制程序組可以使用的資源數量
  • 程序組的優先級控制,比如給特定程序組配置設定特定的CPU使用率
  • 記錄程序組使用的資源數量
  • 程序組控制,比如将程序組挂起和恢複

其實程序和程序之間是運作在同一個作業系統之上的,所謂的隔離是邏輯上的隔離,通過這兩種技術可以起到限制程序使用資源的目的。

單一Pod上的容器是怎麼共享網絡命名空間的?

啟動了一個apache pod。

這是目前k8s叢集裡使用到的容器,其中很多是系統容器不需要管。

容器清單裡面有很多pause這樣的容器鏡像所啟動的容器,所啟動的apache容器和某一個pause容器共享一個網絡命名空間。

單一Pod上的容器是怎麼共享網絡命名空間的?

檢視某個容器的描述,

單一Pod上的容器是怎麼共享網絡命名空間的?

這是程序的相關配置,其中entrypoint.sh是apache的啟動腳本,

單一Pod上的容器是怎麼共享網絡命名空間的?

這個是命名空間配置,隔離apchae所使用的命名空間,pid是apache程序本身在整個程序樹上是根程序,network是apache程序通信的網絡隔離。

網絡命名空間依賴446476這個程序,

單一Pod上的容器是怎麼共享網絡命名空間的?

可以看到apache本身的程序是446531,很明顯apache的網絡是由446476這個程序所影響的,那這個程序是什麼?

單一Pod上的容器是怎麼共享網絡命名空間的?

看下這個程序的狀态,

單一Pod上的容器是怎麼共享網絡命名空間的?

發現這個程序目前處理sleeping狀态,本身不幹活,那麼它存在的意義是什麼?

單一Pod上的容器是怎麼共享網絡命名空間的?

叢集節點上運作着linux作業系統,在上面運作所有的容器在邏輯上是隔離的,是因使用了命名空間和控制組這樣的技術。

單一Pod上的容器是怎麼共享網絡命名空間的?

目前機器本身就是k8s叢集的一個node節點,

單一Pod上的容器是怎麼共享網絡命名空間的?

直接通過ps指令可以看到apache和pause這樣的程序,因為它是運作在本機作業系統上的程序,但是pause程序在啟動的時候,會建立各種各樣的命名空間,進而把pause這個程序隔離起來,進而把它視為運作在一個獨立的作業系統上的一個程序,然後它進入了一個休眠的狀态,它的任務已經完成了。

後面啟動的apache程序在某些命名空間上會attach到這個pause命名空間,2個命名空間關聯起來,apache也可以把自己看作一個獨立在作業系統中的一個程序。

pause建立了命名空間,apache的程序關聯到這個命名空間中。

k8s的pause首先會啟動pause這個程序去建立一個命名空間,然後在k8s的pause裡面,無論有多少個container,都會共享同一個命名空間,比如共享一個網絡命名空間,它有獨立的端口範圍、主機名,路由。

從pod的角度來看它就是一個pod在運作,其實這個pod裡面的所有的容器通過共享命名空間來實作一個獨立的封裝,也就是說封裝在pod裡面的這些程序它們彼此之間都是可以共享同一個命名空間。

首先模拟一下啟動pause這樣一個程序進而建立各種各樣的命名空間,

單一Pod上的容器是怎麼共享網絡命名空間的?

做了一個docker鏡像用來模拟pause容器,

單一Pod上的容器是怎麼共享網絡命名空間的?

把容器裡面的8080端口暴露在主機的80端口上,運作容器了之後,直接删除鏡像,

這個容器本身有它獨立的命名空間,後面就需要一個應用的容器關聯到這個pod上,這裡用了一個python的容器 ,python比較容易啟動web服務,

單一Pod上的容器是怎麼共享網絡命名空間的?

新啟動的python的容器,本身會attach到pause容器上,本身和pause容器共享同一個網絡命名空間,

單一Pod上的容器是怎麼共享網絡命名空間的?
單一Pod上的容器是怎麼共享網絡命名空間的?

python容器把80應用跑起來了,進入python裡面,發現機器名和pause共享同一個機器名,因為在run python的時候并沒有指定host name,而是運作pause的時候指定的,

單一Pod上的容器是怎麼共享網絡命名空間的?

在python容器中啟動一個web服務,

單一Pod上的容器是怎麼共享網絡命名空間的?

當把web server跑在apache容器上,它實際上和pause容器共享了同一個網絡命名空間,

單一Pod上的容器是怎麼共享網絡命名空間的?

再啟動一個python容器,

單一Pod上的容器是怎麼共享網絡命名空間的?

依然使用8080端口,會有端口沖突。

在一個容器裡面生成新檔案,在另外一個容器裡面是沒有這個檔案的,說明檔案系統是獨立的,但是網絡空間卻是共享的。

總結

  • 容器是通過命名空間互相隔離的系統程序
  • K8s pod是一個抽象的概念,使用Pause容器建立命名空間并與使用者程序容器共享
  • 在一個K8s pod中使用者程序容器之間通過網絡命名空間交換網絡資料
  • 在一個K8s Pod中使用者程序容器共享同一主機名、端口範圍、網絡路由
  • 一個node上啟了10個pause,并且每個pause裡面有10個容器,其實本質上來講在作業系統上啟動了100個程序,隻不過通過命名空間的方式把它們進行分組進行隔離。