k8s學習記錄

SeriousSnow_發表於2020-12-14

直接複製排版不好。。可以去有道雲筆記看:http://note.youdao.com/noteshare?id=6cd1a4fd404e8f92fb8d610090e876e9&sub=237CA78BEE39435F8A548121BE41C32E

0x0 前言

什麼是K8S?要明白這個問題,需要首先了解一些基礎

 

0x1 並行

0x1.1 物理並行

放眼現在,大家使用電腦一邊聽歌一邊玩遊戲一邊看直播哪都不是事。那麼當年比如30年前,還在使用dos系統的時候(沒仔細考究dos是否真的不支援非同步多執行緒等。。如果說錯一笑而過),系統同一個時間只能同事執行一個程式,這時候你想一遍聽歌一邊玩遊戲怎麼辦呢?解決方案就是多加一臺電腦。當然這個方案現在來看肯定不夠好。那現在怎麼解決的,為啥我們可以一次性執行多個程式?

0x1.2 程式

對於程式是啥網上都有解釋,雖然我感覺那個解釋對一個正常人都不是太好理解。用java的說法有點類似於,程式就是你的一個類,程式就是你的那個類的例項化物件。。然後有個問題兩個程式是如何做到隔離的。原因是保護模式,由於保護模式每個程式都有獨立的4G虛擬記憶體空間,程式都是用的虛擬記憶體而非直接使用實體記憶體。(這也能解釋為啥一個程式吃記憶體有上限,瀏覽器吃記憶體是因為每個標籤每個擴充套件都是一個程式),那麼還有個最重要的問題,如何做到多個程式一起執行呢?現在只是解決了兩個程式如果一起執行了,由於記憶體隔離不會衝突。答案就是他們其實並沒一起執行。只是你看起來好像一起執行。原理就是,每個程式會有時間很短時間片,然後每次執行一個程式時間片走完就掛起,然後執行下一個程式,這樣一直迴圈,只要時間片夠短我們看起來就好像好多程式是一起在執行。但是由於時間片分法策略不是簡單的程式平均,所以有時候一個程式卡死了,你會發現整個系統都卡了。總結一下,cpu使用時間片使得進場看起來並行,作業系統使用保護模式做到程式之間記憶體隔離。

0x2 虛擬化

0x2.1 為啥要虛擬化

這個原因網上也好多,不是很想多說,我簡單說幾點。第一大家用虛擬機器不?為啥要用?理由不用我多說了。再比如就前文所說的程式無法做到資源按我所需分配。虛擬化可以。

0x2.2 什麼是虛擬化

最簡單一個例子來解釋虛擬化就是。cpu不是有時間片麼,全給虛擬機器了,然後一共分到100個,然後你再虛擬機器裡執行程式,每個程式最多給25個時間片。那麼就算你只執行了一個程式,其他75個時間片輪到了也啥都不幹,是不是就相當於把cpu虛擬成了4個邏輯cpu,然後那個程式只用了一個。具體下文介紹,這裡先介紹一些基本知識

0x2.2.1 作業系統分層

應用程式

API

 

核心

驅動

 

HAL

硬體

0x2.2.1 ring0 ring3

還是前文所說的程式的例子,作業系統因為保護模式使得程式內部直接讀寫記憶體的程式碼不會衝突,那麼如果程式碼裡直接寫讀取實體記憶體的程式碼怎麼辦?答案是CPU不允許這麼幹。所有的應用程式都是執行在ring3,ring3的程式碼會受到CPU的檢查,很多事情不能幹,比如不能直接訪問硬體,不能無限制訪問記憶體,比如高2G記憶體(linux為高1G)這部分記憶體是核心記憶體所有程式共享

0x2.3 虛擬化分類

0x2.3.1 全虛擬化

為啥先講這個呢?因為大家最熟悉的VMware 就是屬於全虛擬化。全虛擬化的意思就是不需要對客戶機系統做修改,所以吧對客戶機來說不知道自己是個虛擬機器(當然了還是有辦法知道的)。

0x2.3.1.1 軟體全虛擬化

應用程式

ring3

Guest OS

VMM

Host OS

ring0

硬體

軟體全虛擬化就是,通過VMM把Host OS所有能操作的CPU、記憶體等抽象成虛擬CPU、記憶體(CPU虛擬化簡單邏輯前文有說)。然後有Guest OS來使用這些虛擬裝置

但是這種方法不考慮別的,單純可行性方面就需要解決兩個問題。

1.特權指令

說人話就是,有一些指令只能在ring0執行,比如io裝置的,讀取特殊暫存器的。但是吧你Guest OS肯定得要用。所以解決方案就是,Guest OS要執行特權指令,往下走,到Host OS觸發異常,被VMM捕獲,通過VMM把Guest OS的特權指令用一些可以在ring3執行的的指令來模擬出一個只針對Guest OS的特權指令,這樣就可以把Guest OS的特權指令的特權解除,這叫做特權解除

2.敏感指令

這個說人話就是,比如關機。Guest OS要關機,下發關機指令到Host OS,它怎麼知道是Guest OS要關機還是Host OS要關機。所以吧這時候VMM就要在下發之前先判斷,是不是敏感指令,是就和特權指令一樣直接模擬了。這玩意叫陷入模擬

 

說句人話就是,這玩意吧就是VMM幹了全部髒活累活。要解決的問題遠不止特權指令那麼簡單,比如記憶體地址。前文說到兩程式操作"同一地址"的記憶體,由於用的是虛擬記憶體最終會轉換到兩塊不同的實體記憶體,那麼Guest OS 的程式的虛擬記憶體 如何轉換到Host OS的實體記憶體,解決方案比如有影子頁表

0x2.3.1.2 硬體輔助全虛擬化

應用程式

Non-Root Mode

Guest OS

VMM

Root Mode

硬體

這玩意說人話就是,CPU幹了之前軟體乾的事情,CPU自己可以分辨來自GuestOs的特權指令直接就搞定了,BIOS裡要開的VT-X啥的就是,這就是為啥之前經常說BIOS開這玩意虛擬機器會塊很多,還有VT-D VT-C等,然後這裡沒Host OS是因為這時候VMM可以載入到Host OS核心裡,就不需要向下走Host OS了可以直接對接硬體,比如KVM,比如上門提到的影子頁表,Intel CPU支援了EPT之後就不需要使用影子頁表提高了不少效能。

0x2.3.2 半虛擬化

知道了全虛擬化,半虛擬化也就好理解了,就是這玩意需要修改Guest OS的部分程式碼,以此跟好的和和VMM協作。最簡單的例子就是vmtools,裝了之後就能解鎖好多功能。畢竟作業系統一開始設計並沒考慮到虛擬化這個事情。

0x2.3.3 裸機架構

這玩意就是說,上面兩種不管怎麼說虛擬機器都是一個軟體,要依託於作業系統對接硬體啊啥的。簡單來說就是上面的要先安裝作業系統,它呢就是可以直接部署在機器上,比如esxi,不過麼說是那麼說,esxi也是基於Linux開發的,沒自己考究我覺得他就是在Linux的base 版本里開發了一個軟體,然後打包了。

0x3 容器

0x3.1 由來

為啥會出現這個玩意?簡單舉個例子,虛擬機器有時候很蛋疼,比如我就想執行一個隔離的小服務,然後想隔離就得搞個虛擬機器,就先不說資源浪費大不大了,不嫌累嗎?主觀上就感覺很蛋疼。就和某些玩意列印個hello world要裝一堆依賴那樣。反正我是覺得很蛋疼。第二點。就是資源浪費。根據前面可以知道。那玩意吧執行一個指令要下發到vmm然後走Host OS 核心,這都是損耗,雖然吧現在有VT-C可以直通網路卡 VT-D可以直通IO,效能已經逼近宿主機了,但是吧。總歸損耗在,而且很臃腫,開三個虛擬機器就要執行四個作業系統,很多都是浪費實在沒必要。於是乎,就搞出了容器這麼個玩意。這玩意隔離的方式比較像程式

 

 

0x3.2 Union FS

由圖可知容器雖公用OS但是不公用Bins,(Libs程式也每個程式各一份)。所以可知得一個問題要解決如何讓每個容器各自獨立一份bins。說人話就是你啟動docker容器,不是要先pull映象,然後啟動。它裡面得那些檔案肯定每個容器都不一樣。這個要靠一個東西叫 Union FS,解釋我網上超了一段:

聯合檔案系統(Union File System):可以把多個目錄(也叫分支)內容聯合掛載到同一個目錄下,

而目錄的物理位置是分開的。UnionFS允許只讀和可讀寫目錄並存,就是說可同時刪除和增加內容。

這些分支或者是read-only或者是read-write的,所以當對這個虛擬後的聯合檔案系統進行寫操作時候,系統是真正寫到了一個新的檔案中。看起來這個虛擬後的聯合檔案系統是可以對任何檔案進行操作的,但是其實它並沒有改變原來的檔案,這是因為unionfs用到了重要的資管管理技術叫寫時複製。

簡單解釋一下。就是首先映象都依賴於linux作業系統,自帶了各種bins/libs,然後你安裝軟體,環境,做完之後那玩意就是映象。別人用就pull下來,然後由於比如nginx和php都是基於Ubuntu構建得,那麼他們兩個映象很多都是重複得,所以docker映象會分層。一個映象有好多層。底下相同得就可以只下載一份。這就是為啥docker pull 一個映象會下載好多個東西。但是最終他們得是一個東西。這就需要Union FS把這麼多個目錄合併成一個。

0x3.3 Namespaces

之前程式說的都是windows得情況。隔離簡單提了下,因為保護模式,docker設計得時候是利用了Linux得核心特性實現的隔離,而且公用一個OS核心所以,他的隔離方式和Windows的就不太一樣,當然了docker無法構建Windows環境,Windows下也無法直接執行docker,必須在windows下構建一個Linux環境才可以,Windows7是用的virtual box,windows10 則是自帶的Hyper-v,但是Hyper-v在2004版本之前無法和VMware共存,因為是兩種不太的虛擬化架構。不過2004 VMware16.0開始支援用Hyper-v來建立了。不過virtual box任然不支援。所以目前如果開了Hyper-v 幾乎所有Android模擬器全部不能執行。

那麼具體docker如何做到隔離,其中一個就是Namespaces,抄的網上解釋如下

名稱空間(namespaces)是 Linux 為我們提供的用於分離程式樹、網路介面、掛載點以及程式間通訊等資源的方法。在日常使用 Linux 或者 macOS 時,我們並沒有執行多個完全分離的伺服器的需要,但是如果我們在伺服器上啟動了多個服務,這些服務其實會相互影響的,每一個服務都能看到其他服務的程式,也可以訪問宿主機器上的任意檔案,這是很多時候我們都不願意看到的,我們更希望執行在同一臺機器上的不同服務能做到完全隔離,就像執行在多臺不同的機器上一樣

這玩意比較多

UTS名稱空間(系統呼叫CLONE_NEWUTS)

隔離主機名和網路資訊

IPC名稱空間(系統呼叫CLONE_NEWIPC)

隔離IPC(程式通訊的方式)的相關,入共享記憶體,訊號量,訊息佇列等

PID名稱空間(系統呼叫CLONE_NEWPID)

隔離PID

Mount名稱空間(系統呼叫CLONE_NEWNS)

隔離掛載點,功能上和chroot差不多

Network名稱空間

隔離網路資源

User名稱空間

隔離使用者

 

0x3.4 CGroup

完成了隔離還是有之前程式的老問題,如何分配資源。這就需要用到CGroup了。簡單來說他就是可以實現,限制資源使用,控制優先順序,審計統計,掛起恢復等功能。這玩意不太好解釋。有興趣自己百度吧

 

 

0x4 虛擬化,容器對比

隨便網上找了個,因為有多重水印,我就自己做了個表,就這樣吧,反正也就這點東西

特性

虛擬機器

容器

隔離級別

作業系統

程式

隔離策略

Hypervisor

CGroups

系統資源

5%-15%

0-5%

啟動時間

分鐘

映象儲存

GB-TB

KB-MB

叢集規模

上百

上萬

高可用策略

備份,容災,遷移

彈性,負載,動態

0x5 K8S

0x5.1 什麼是K8S

很明顯容器有他存在的意義,而且叢集規模還很大,一個東西一旦多了,怎麼管理他就是個問題。要不然肯定一團糟。這就是Kubernetes,掐頭去尾中間還剩8個字母,就叫K8S了。(我能說我要是寫程式碼這麼縮寫肯定要被打麼。。。)這玩意就是來管理一堆容器的(是容器,不是docker,docker只是其中一種容器技術,而且貌似k8s快不支援docker了。說docker設計之初就不是為了加入k8s設計的。廢話。。。。。)

0x5.2 K8S配置lnmp簡介

 

先上張圖,當然也是網上找的。

1.MASTER NODE

首先左邊的叫master,右邊的是node,

master,簡單來說是管理的,node就是幹活的。預設不會在master上排程pod,當然你可以手動刪除master解點預設汙點。

然後k8s不是一個軟體。是一堆軟體。講幾個比較重要的而且第一次配就得接觸的。

kubelet:管理容器的

kubectl:kubelet的客戶端,還有個高許可權版。也就初始化的時候用,這兩 類似於mysql 和 mysqld

apiservice:通訊用走flannel網路。要通訊只能靠他

kube-proxy:負載均衡網路流量。

然後吧node都需要通過apiservice訪問master的api然後完成各種排程。當然是走的一個內網,這個內網要自己設定

 

2.nginx,php負載均衡標準流程

1.準備好docker容器。

2.配置pod,啟動pod部署到node上

3.配置service,使得外部可以訪問到pod

然後,訪問就是,外部請求到service,然後交給kube-proxy,然後轉給對應pod(負載均衡也在這裡,如果有多個目標pod會自動負載均衡)

4.docker php容器安裝外掛必須到指定目錄,和 yum apt等包管理工具不一樣不能隨便一個目錄就安裝。

 

3.遇到的坑

1.一開始想錯了,以為只要在master配置好會自動同步到node,但是docker對映檔案需要在node對映(當然使用nfs同步到遠端位置就無所謂了,但是本機目錄需要在每個node配置)

2.nginx 配置檔案php路徑不能寫php service 內網ip。好像只能寫php.default.svc.cluster.local,不然就報404

3.同樣自己build的docker映象如果沒push到公網,node無法自動pull,需要手動去每個nodebuild一次。

4.配置過程

k8s節點上線具體過程。。。實在懶得網上抄下來了。基本照著做就行。。。比如:

https://blog.51cto.com/3241766/2405624

配置nginx,php坑上文說完了,步驟參考:

https://blog.csdn.net/bbwangj/article/details/82954187