《k8s權威指南》讀書筆記

抽空讀完了《k8s權威指南》一書,對k8s的總算有了較爲系統的認知。node

好記憶不如多寫字,如下是讀書筆記linux

第一章 k8s入門

k8s是什麼: 一個開源的容器集羣管理平臺,可提供容器集羣的自動部署,擴縮容,維護等功能。分爲管理節點Master和工做節點Node
web

核心組件算法

  • etcd保存了整個集羣的狀態;
  • apiserver提供了資源操做的惟一入口,並提供認證、受權、訪問控制、API註冊和發現等機制;
  • controller manager負責維護集羣的狀態,好比故障檢測、自動擴展、滾動更新等;
  • scheduler負責資源的調度,按照預約的調度策略將Pod調度到相應的機器上;
  • kubelet負責維護容器的生命週期,同時也負責Volume(CVI)和網絡(CNI)的管理;
  • Container runtime負責鏡像管理以及Pod和容器的真正運行(CRI);
  • kube-proxy負責爲Service提供cluster內部的服務發現和負載均衡;

分層架構:docker

  • 核心層:k8s最核心的功能,對外提供API構建高層應用,對內可提供插件式的應用執行環境。
  • 應用層:部署和路由
  • 管理層:策略管理,自動化管理,以及系統度量。
  • 接口層:kubectl命令行工具。
  • 生態系統:外部:日誌、監控、配置管理、CI、CD等 內部:CRI、CNI、CVI、鏡像倉庫、Cloud Provider、集羣自身的配置和管理等。

第二章 實踐指南

2.1 基本配置

apiVersion : v1 用來標識版本
kind : Pod/Service 類型可選Pod Service等
metadata: name: nameSpace:

後端

2.4 Pod

  • pod中的容器要求啓動命令必須之前臺命令做爲啓動命令【避免k8s 監控到pod運行結束 銷燬,根據配置的RC副本數量從新啓動,從而進入死循環】
  • pod 能夠由一個或者多個容器組合而成。
  • pod中的多個容器只須要localhost就能夠相互訪問。

2.4.3 靜態pod

靜態pod 是由kubelet進行管理建立的只存在於特定Node上的Pod,kubelet沒法對其進行靜態檢查,且通常只存在於kubelet所在的節點上。
且沒法經過API server進行管理,也不會和ReplicationController Deployment產生關聯。api

建立方式: yml文件【配置文件】或者http請求安全

如何刪除: 沒法經過API server進行管理,因此Master沒法對靜態pod進行刪除【狀態更新爲pending】。刪除只能經過所在的node節點刪除配置文件網絡

2.4.4 容器共享volume

在同一個pod內的容器能夠共享pod級別的volume架構

2.4.5 pod配置管理

pod能夠經過k8s提供的集羣化配置管理方案 configMap來實現配置信息和程序分離。

建立方式: yaml文件

2.4.6 生命週期和重啓策略

生命週期 在系統內被定義爲各類狀態。能夠分爲 Pending Running Succeeded Failed Unknow

  • Pending : API Server 已經建立好Pod,可是Pod內還有一個或者多個容器的鏡像沒建立,包括正在下載的鏡像。
  • Running : Pod內全部的容器已經建立成功,至少有一個容器處於運行,正在啓動或者重啓狀態。
  • Succeeded : Pod內的全部容器均成功執行退出,且不會再從新啓動。
  • Failed : 全部容器都已退出,至少有一個容器爲退出失敗狀態。
  • Unknow: 沒法獲取到Pod的狀態。

重啓策略 應用於Pod內的全部容器,並由Pod所在node節點上的kubelet進行狀態判斷和重啓。當容器異常退出或者健康檢查狀態失敗的時候,kubelet會根據所設置的重啓策略從新啓動該container

  • always : 當容器失效時,有kubelet自動重啓改容器。
  • OnFailure : 容器運氣終止且狀態碼不爲0的時候。
  • Never :不管狀態如何都不重啓該容器。

重啓的間隔時間以設定的間隔時間的2n來計算,且在成功重啓的10分鐘後重置該時間。

不一樣的控制器對Pod的重啓策略的要求是不同的:

  • RC和DaemonSet: 這2類控制器要求所管理的Pod 必須設置爲Always,才能保障整個k8s週期內,提供服務的副本數量是知足要求的。
  • Job: 這類控制器可根據需求靈活設定OnFailure 或者Never
  • Kubelet: 由kubelet管理的通常是靜態Pod,kubelet不會對其進行健康檢查,Pod失效就回進行重啓。和設置的重啓策略沒有關聯。

2.4.7 健康檢查

pod的健康檢查可以使用2類探針: LivenessProbe 和ReadinessProbe

  • LivenessProbe :用來判斷容器是否存活【running狀態】若容器不處於running狀態,則會有kubelet對容器根據設定的重啓策略進行操做。若容器內不存在LivenessProbe探針,kubelet會認爲容器的狀態是succeed
  • ReadinessProbe :用來判斷容器是不是ready狀態【這個狀態下能夠正常接收請求 處理任務】若ReadinessProbe 探針檢查失敗,EndPoint controller 會從service的endPoint中刪除包含該容器所在Pod的endPoint不讓該容器對外提供服務。

LivenessProbe 探針的實現方法

  • ExecAction 在容器內執行命令若返回狀態碼爲0 表示容器正常。
  • TcpSocketAction 成功創建Tcp鏈接表示狀態正常。
  • HttpGetAction 對容器路徑內調用httpGet方法若返回的狀態碼在200-400之間表示容器狀態正常。

2.4.8 Pod的調度方式

1 RC Deployment

全自動調度,用戶配置好應用容器的副本數量後RC會自動調度+持續監控始終讓副本數量爲此在規定的個數當中。

調度算法 系統內置的調度算法/NodeSelector/NodeAffinity

  • 內置調度算法: 對外無感知,沒法預知會調度到那個節點上,系統內完成的。
  • NodeSelector 定向調度:在Pod上若是設置了NodeSelector屬性 Scheduler會將該節點調度到和NodeSelector屬性一致的帶有Label的特定Node上去。【NodeSelector和Node Label精確匹配】
  • NodeAffinity 親和性調度: 在NodeSelector的基礎上作了一些改進,能夠設置在Node不知足當前調度條件時候,是否移除以前調度的Pod,以及在符合要求的Node節點中那些Node會被優先調度。
2 DaementSet

和RC相似,不一樣之處在於DaementSet控制每一臺Node上只容許一個Pod副本實例,適用於須要單個Node運行一個實例的應用:

  • 分佈式文件存儲相關 在每臺Node上運行一個應用實例如GlusterFS Ceph
  • 日誌採集程序 logStach
  • 每臺Node上運行一個健康程序,來讀當前Node的健康狀態進行採集。
3 Job 批處理任務調度

批處理模型

  • Job Template Expansion : 一個待處理的工做項就對應一個Job,效率較低。
  • Queue with Per Pod Work Item : 使用隊列存儲工做項,一個Job做爲消費者消費隊列中的工做項,同時啓動和隊列中work Item數量對應的Pod實例。
  • Queue with Variable Pod Work Item : 同per Pod 模式,不一樣之處在於Job數量是可變的。

這裏在項目中的具體應用待更新,如今項目所用的k8s 調度模型【後續會單獨寫篇文章更新】

2.4.9 Pod的擴縮容

手動更新 kubectl scale命令更新RC的副本實例數量
自動更新 使用HAP控制器,基於在controller-manager設置好的週期,週期性的對Pod的cup佔用率進行監控,自動的調節RC或者Deployment中副本實例進行調整來達到設定的CPU佔用率。

2.5 service

service能夠爲一組具備相同功能的容器提供一個統一的入口地址,並將請求負載進行分發到後端各個容器應用上。

2.5.2 service的基本使用

直接使用RC建立多個副本和建立SVC提供服務的異同
直接建立RC

  • 先定義RC yaml文件,如上所示
  • 執行建立命令 kubectl create -f name.yaml
  • 查看提供服務的Pod地址 kubectl get pods -l app=webapp -o yaml | grep podIP

由於RC配置的副本實例數量爲2 因此可得2個可用的Pod EndPoint 分別爲172.17.172.3:80 172.17.172.4:80 不管任何一個Pod出現問題,kubelet 會根據重啓策略對Pod進行從新啓動,再次查詢PodIP會發現PodIP發生變化

使用SVC

由於Pod的不可靠,從新啓動被k8s調度到其餘Node上會致使實例的endpoint不同。且在分佈式部署的狀況下,多個容器對外提供服務,還須要在Pod前本身動手解決負載均衡的問題,這些問題均可經過SVC解決。

建立方式 : kubectl expose命令/配置文件

kubectl expose命令

  • 建立SVC kubectl expose rc webapp 此時端口號會根據以前RC設置的containerPort 來進行設置
  • 查看SVC kubectl get SVC

配置文件方式啓動
定義的關鍵在於 selector 和ports

負載分發策略 RoundRobin/SessionAffinity/自定義實現

  • RoundRobin : 輪詢策略
  • SessionAffinity : 基於客戶端IP的回話保持策略,相同IP的會話,會落在後端相同的IP上面。
  • 自定義實現: 不給SVC設置clusterIP 經過label selector拿到全部的實例地址,根據實際狀況來選用。

2.5.3 集羣外部訪問SVC或者Pod

思路是把SVC或者pod的虛擬端口映射到宿主機的端口,使得客戶端應用能夠經過宿主機端口訪問容器應用。

將容器應用的端口號映射到主機
1 容器級別 設置hostPort = prodNum yaml中的配置表爲hostPort: 8081,指的是綁定到的宿主機端口。HostPort和containerPort能夠不相等

2 Pod級別 設置hostNetWork = true 這時候設置的全部的containerPort 都會直接映射到宿主機相同的端口上。默認且必須是HostPort = containerPort,若顯示的指定HostPort和containerPort不相等則無效。

將SVC端口號映射到主機
關鍵配置爲 kind = service type = NodePort nodePort = xxxxx,同時在物理機上對防火牆作對應的設置便可。

2.5.4 搭建DNS

能夠直接完成服務名稱到ClusterIP的解析。由如下部分組成

  • 1 etcd DNS信息存儲
  • 2 kube2sky 將k8sMaster中的 service註冊到etcd
  • 3 skyDNS 提供DNS解析
  • 4 healthz 提供對skyDNS的健康檢查

第三章 原理分析

3.1 API Server

主要提供了各種資源對象【SVC Pod RC】等的增刪查改以及Watch等Http Rest接口,是各個模塊之間的數據交互和通信的樞紐。

Kubernetes API Server : 提供API接口來完成各類資源對象的建立和管理,自己也是一個SVC 名稱爲Kubernetes

Kubernetes Proxy API :負責把收到的請求轉到對應Node上的kubelet守護進程的端口上,kubelet負責相應,來查詢Node上的實時信息 包括node pod SVC等 多用於集羣外想實時獲取Node內的信息用於狀態查詢以及管理。 【kubelet也會定時和etcd 同步自身的狀態,和直接查詢etcd存在必定的差別,這裏強調實時】

集羣模塊之間的通訊: 都須要經過API Server 來完成模塊之間的通訊,最終會將資源對象狀態同步到etcd,各個集羣模塊根據經過API Server在etcd定時同步信息,來對所管理的資源進行相應處理。

3.2 Controller Manager

集羣內部的管理中心,負責集羣內部的Node Pod Endpoint Namespace 服務帳號(ServiceAccount)資源定額(ResourceQuota)等的管理。出現故障時候會嘗試自動修復,達到預期工做狀態。

3.2.1 Replication Controller

通常咱們把資源對象 Replication Controller 簡寫爲RC 是爲了區別於Controller Manager 中的Replication Controller【副本控制器】,副本控制器是經過管理資源對象RC來達到動態調控Pod的

副本控制器Replication Controller的做用:

  • 【從新調度】確保當前集羣中存在N個pod實例,N是在RC中定義的Pod實例數量
  • 【彈性擴容】經過調整RC中配置的副本實例個數在實現動態擴縮容。
  • 【滾動升級】經過調整RC中Pod模板的鏡像版原本實現滾動升級。

3.2.2 Node Controller

Node節點在啓動時候,會同kubelet 主動向API Server彙報節點信息,API Server將節點信息存儲在etcd中,Node Controller經過API Server獲取到Node的相關信息對Node節點進行管理和監控。
節點狀態包括:就緒 未就緒 未知三種狀態

3.2.3 ResourceQuota Controller

資源配額管理,確保指定資源對象在任一時刻不會超量佔用系統物理資源。支持如下維度的系統資源配額管理

  • 容器級別能夠CPU和Memory進行限制
  • Pod級別能夠對一個Pod內的全部容器進行限制。
  • Namespace級別,能夠對多租戶進行限制,包括Pod數量,Replication Controller數量,SVC數量 ResourceQuota 數量等。

3.2.4 Namespace Controller

用戶經過API server 設置的Namespace會保存在etcd中,Namespace Controller會定時的獲取namespace狀態,根據所得狀態對不一樣的namespace進行相應的刪除,釋放namespace下對應的物理資源。

3.2.5 SVC Controller& Endpoint Controller

Endpoints 表示一個svc對應的全部的pod的訪問地址,Endpoint Controller是負責維護和生成全部endpoint對象的控制器。
每一個Node對應的kube-proxy獲取到svc對應的Endpoints來實現svc的負載均衡。

3.3 Scheduler

Scheduler 主要是接受controller Manager建立的pod爲Pod選定目標Node,調度到合適的Node後,由Node中的kubelet負責接下來的管理運維。
過程當中涉及三個對象 待調度的Pod列表,空閒的Node列表,調度算法和策略。
也就是根據調度算法和策略爲待調度的每一個Pod從空閒的Node中選擇合適的。 隨後kubelet經過API Server監聽到Pod的調度事件,獲取對應的Pod清單,下載Image鏡像,並啓動容器。

3.3.1 默認的調度流程以下:1&2

1【預選調度】遍歷全部的Node節點,選出合適的Node
2優選策略肯定最優節點

3.4 Kubelet

每一個Node節點中都會啓動一個Kubelet,該進程用於處理Master節點下發到本節點的任務,管理Pod以及Pod中的容器,每一個Kubelet都會向API Server註冊自身信息,按期和Master節點彙報Node節點資源使用狀況。

容器健康檢查

使用2類探針LivenessProbe 和ReadinessProbe

資源監控

使用cAdvisor

總結:kubelet 做爲鏈接K8s Master節點機和Node機器的橋樑,管理運行在Node機器上的Pod和容器,同時從cAdvisor中獲取容器使用統計信息,而後經過API Server上報資源使用信息。

3.5 Kube-Proxy

SVC是對一組提供相同服務Pod的抽象,會根據訪問策略來訪問這一組Pod。在每個Node節點上都存在一個Kube-proxy,能夠在任意Node上發起對SVC的訪問請求。

SVC的ClusterIp和NodePort等概念是kube-proxy服務經過IPtables的NAT轉換實現重定向到本地端口,再均衡到後端的Pod

3.6 集羣安全機制

待補充

3.7 網絡原理

k8s+docker 網絡原理經常涉及到如下問題

  • 1 k8s的網絡模型是什麼?
  • 2 Docker的網絡基礎是什麼?
  • 3 Docker的網絡模型和侷限?
  • 4 k8s的網絡組件之間是如何通信的?
  • 5 外部如何訪問k8s集羣?
  • 6 有那些開源組件支持k8s網絡模型?

1 k8s的網絡模型

IP-per-Pod:每一個Pod都有本身獨立的IP,不管是否處於同一個Node節點,Pod直接均可以經過IP相互訪問。同時Pod內的容器共享一個網絡堆棧【=網絡命名空間 包括IP地址,網絡設備,配置等】按照這個網絡模型抽象出來的一個Pod對應一個IP也叫IP-per-Pod

Pod內部應用程序看到的本身的IP+port和pod外部的應用程序看到的IP+port是一致的,他們都是Pod實際分配的ip地址,從docker0上分配的。這樣能夠不用NAT來進行轉換,設計的原則是爲了兼容之前的應用 。

K8S對網絡的要求:

  • 全部容器在不經過NAT的方式下和其餘容器進行通信
  • 全部節點在不使用NAT的方式下和容器相互通信
  • 容器的地址和外部看到的地址是同一個地址

2 Docker的網絡基礎是什麼?

  • Docker使用網絡命名空間來達到不一樣容器之間的網絡隔離【不一樣的網絡命名空間內的 IP地址 網絡設備 配置等是相互隔離不可見的】
  • Docker 使用Veth設備對來達到2個不一樣的網絡命名空間的相互訪問。【Veth設備對能夠直接將2個不一樣的網絡命名空間鏈接起來,其中一端稱爲另外一端的peer 從a端發送數據時候會直接觸發b端的接受操做,從而達到不一樣容器之間相互訪問的目的】

因爲網絡命名空間以及Veth設備對是創建在同一個linux內核的基礎上。因此Docker的跨主機通信處理的不夠友好。

3 Docker的網絡模型和侷限?

  • host模式 使用--net= host指定
  • container模式 使用--net = container: Id_or_NAME指定
  • none模式 使用--net= none指定
  • bridge模式 使用--net = bridge指定

bridge模式 : 也是docker默認的網絡模型,在這個模型下Docker第一次啓動會建立一個新的網橋 大名鼎鼎的docker0,每一個容器獨享一個網絡命名空間,且每個容器具備一個Veth設備對,一端鏈接容器設備eth0一端鏈接網橋,docker0。以下圖:

4 k8s的網絡組件之間是如何通信的?

  • 容器到容器之間的通信
  • Pod到Pod之間的通信
  • Pod到Service之間的通信
  • 集羣外與內部組件之間的通信
容器到容器之間的通信

同一個Pod內的容器共享同一個網絡命名空間,能夠直接使用Localhost進行通信,不一樣Pod之間容器的通信能夠理解爲Pod到Pod OR Pod到SVC之間的通信

Pod到Pod之間的通信

能夠分爲同一個Node內Pod之間的通信&不一樣Node內Pod之間的通信

同Node內Pod

同一Node中Pod的默認路由都是docker0的地址,因爲它們關聯在同一個docker0網橋上,地址網段相同,能夠直接進行通信。

不一樣Node的Pod

docker0網段和宿主機的網卡是2個不一樣的IP段,Pod地址和docker0處於同一網段。因此爲了使不一樣Node之間的Pod能夠通信,須要將PodIP和所在Node的IP進行關聯且保證惟一性。

Pod到Service之間的通信

SVC是對一組Pod服務的抽象,至關於一組服務的負載均衡。且對外暴露統一的clusterIP,因此Pod到SVC之間的通信能夠理解爲Pod到Pod之間的通信

集羣外與內部組件之間的通信

集羣外和內部組件之間通信,將Pod OR SVC端口綁定到物理機端口便可。

相關文章
相關標籤/搜索