kubernetes 概述及各組件詳細說明


一、kubernetes是什么

  一)kubernetes是什么

  1. kubernetes是權限的基於容器技術的分布式架構領先方案
  2. 我們的系統設計遵循了kubernetes的設計思想,不必關心和業務無關的底層代碼或功能模塊,不必費心負載均衡的選型和部署實施問題,不必再考慮引入或開發服務治理框架,不必再頭疼於服務監控和故障處理模塊的開發。(可以節省不少於百分之三十的成本,同時可以將精力更加集中於業務本身,提供了強大的自動化機制)
  3. kubernetes是一個開放平台:大多數語言都能毫無困難地映射為kubernetes的service,並通過標准的TCP通信協議進行交互,而且他對現有的編程語言、編程框架、中間件沒有任何侵入性。因為現有的系統也可以很容易改造升級並遷移至kubernetes平台上
  4. kubernetes是一個完備的分布式系統支撐平台。kubernetes具有完善的集群管理能力,包括多層次的安全保護和准入機制、多租戶應用支撐能力、透明的服務注冊和服務發現機制、內建智能負載均衡、強大的故障發現和自我修復能力、服務滾動升級和在線擴容能力,可擴展的資源自動調度機制,以及多粒度的資源配額管理能力。 同時kubernetes提供了完善的管理工具,這些工具包括開發、部署測試、運維監控在內的各個環節。

  二)為什么要用kubernetes

  1.  可以“輕裝上陣”地開發復雜系統了
  2. 使用kubernetes就是在全面擁抱微服務架構
  3. 系統可以隨時隨地整體“搬遷”到公有雲上
  4. kubernetes系統架構具備了超強的橫向擴展能力

  三)kubernetes特性

  kubernetes是一種用於在一組主機上運行和協同容器化應用程序的系統,旨在提供可預測性、可擴展性與高可用性的方法來完全管理容器化應用程序和服務的生命周期的平台。

  1. 自動裝箱:建立容器之上
  2. 自我修復:支持容器故障后自動重啟、節點故障后重新調度容器,以及其他可用節點、健康狀態檢查失敗后關閉容器並重新創建等自我修復機制。
  3. 水平擴展:支持通過簡單命令或UI手動水平擴展,以及基於CPU等資源負載率的自動水平擴展機制
  4. 服務發現和負載均衡:kubeDNS(或coreDNS)為系統內置了服務發現功能,它會為每個service配置DNS名稱,並允許集群內的客戶端直接使用此名稱發出訪問請求,而service則通過iptables或ipvs內建了負載機制
  5. 自動發布和回滾:監控更新過程中應用程序的監控狀態,以確保它不會在同一時刻殺掉所有實例,而此過程中,一旦有故障發生,就立即自動回滾操作
  6. 密鑰和配置管理:ConfigMap實現了配置數據與Docker鏡像解耦,需要時,僅對配置做出變更而無須重新構建docker鏡像。對於應用所依賴的一些敏感數據,如用戶名和密碼、令牌、密鑰等信息,kubernetes專門提供了secret對象為其解耦
  7. 存儲編排:本地存儲、公用雲存儲、網絡存儲(NFS、glusterFS、Ceph等)
  8. 批量處理執行:支持批處理作業及CI(持續集成),如需要,一樣可以實現容器故障后恢復

  四)k8s版本規划的意義

  1、k8s版本號的含義

  Kubernetes版本表示為xyz,其中x是主要版本,y是次要版本,z是補丁版本,遵循語義版本控制術語。有關更多信息,請參閱Kubernetes發布版本

  • k8s 發行版與 github 分支的關系
    簡單來講,kubernetes項目存在3類分支(branch),分別為masterrelease-X.Y,release-X.Y.Z。 master分支上的代碼是最新的,每隔2周會生成一個發布版本(release),由新到舊以此為master-->alpha-->beta-->Final release,這當中存在一些cherry picking的規則,也就是說從一個分支上挑選一些必要pull request應用到另一個分支上。 我們可以認為X.Y.0為穩定的版本,這個版本號意味着一個Final release。一個X.Y.0版本會在X.(Y-1).0版本的3到4個月后出現。 X.Y.Z為經過cherrypick后解決了必須的安全性漏洞、以及影響大量用戶的無法解決的問題的補丁版本。 總體而言,我們一般關心X.Y.0(穩定版本),和X.Y.Z(補丁版本)的特性。
  • 例子
    v1.14.0 : 1為主要版本 : 14為次要版本 : 0為補丁版本

  2、每個版本的支持時期

  Kubernetes項目維護最新三個次要版本的發布分支。結合上述一個X.Y.0版本會在X.(Y-1).0版本的3到4個月后出現的描述,也就是說1年前的版本就不再維護,每個次要版本的維護周期為9~12個月,就算有安全漏洞也不會有補丁版本。

 

  五)kubernetes基本概念和術語

  1、概述

  https://www.cnblogs.com/xhyan/p/6656062.html

  https://www.cnblogs.com/zhenyuyaodidiao/p/6500720.html

  2、pod深入了解

  https://www.cnblogs.com/xhyan/p/6708344.html

  https://www.jianshu.com/p/d867539a15cf

  3、ConfigMap

  https://www.cnblogs.com/cocowool/p/kubernetes_configmap_secret.html

  使用ConfigMap的限制條件

  • ConfigMap必須在Pod之前創建
  • ConfigMap也可以定義為屬於某個namespace。只有處於相同namespace中的pod可以引用它、、
  • ConfigMap中的配額管理還未實現
  • kubelet只支持被API server管理的pod使用ConfigMap。kubelet在本node上通過--mainifest-url或--config自動創建的靜態pod將無法引用ConfigMap

  注意:

  滾動升級

  • 刪除RC並不會影響通過該RC已創建好的pod。為了刪除所有pod,可以設置replicas的值為0,然后更新該RC。另外kubectl提供了stop和delete命令來一次性刪除RC和RC控制的全部pod。
  • deployment相對於RC的一個最大升級是我們可以隨時知道當前pod“部署”的進度。

二、kubernetes master 節點組件

  

  一)apiserver

    API服務器是kubernetes控制面的組件,該組件公開了kubernetes API。api服務器是kubernetes控制面的前端。

    ApiServer 對外提供增刪改查etcd中資源配置數據,worker節點kubelet同master節點的ApiServer進行交互

  master節點的scheduler和controller manager組件也需要同ApiServer進行交互以獲取和修改對應資源的狀態

  Kubernetes 集群中,API Server 扮演着通信樞紐的位置。API Server 不僅負責和 etcd 交互(其他組件不會直接操作 etcd,只有 API Server 這么做),並切對外提供統一的API調用入口, 所有的交互都是以 API Server 為核心的。API Server 提供了以下的功能:

  1. 整個集群管理的 API 接口:所有對集群進行的查詢和管理都要通過 API 來進行。集群內部的組件(如kubelet)也是通過Apiserver更新和同步數據到etcd中。
  2. 集群內部各個模塊之間通信的樞紐:所有模塊之前並不會之間互相調用,而是通過和 API Server 打交道來完成自己那部分的工作。
  3. 集群安全控制:API Server 提供的驗證和授權保證了整個集群的安全。
  4. 數據中心樞紐: API Server 負責和 Etcd 交互存放集群用到的運行數據。
  • 集群管理的API 入口

  • 資源配置控制入口

  • 提供完備的集群安全機制

  api server 是通過kube-apiserver 進程來提供服務的. 默認情況下在本機8080端口提供 rest 服務(--insecure-port), 也可以啟用HTTPS 安全端口 (--secure-port=6443)

  https://www.jianshu.com/p/2a70f7189a54

  ApiServer三層認證
    kubernetes認證

kubernetes認證:kubernetes提供了多種認證方式:比如客戶端證書、靜態token、靜態密碼文件、ServiceAccountToken等等。可以是使用一種或多種認證方式。只要通過任何一個都被認作認證通過。

 
         
  • 客戶端證書認證:客戶端證書認證叫做TLS雙向認證。也就是服務端客戶端互相驗證證書的正確性,在都正確的情況下協調通信加密方案。 api-server需要用-client-ca-file選項來開啟

  • 靜態Token:當有非常多的node節點時,手動為每個node節點配置TLS認證比較麻煩,這是就可以用到引導token的認證方式,前提需要在api-server開啟experimental-bootstrap-token-auth特性。客戶端的token信息與預先定義的token匹配認證通過后,自動為node頒發證書。當然引導token是一種機制,可以用到各種場景中

  • service account tokens認證:有些情況下,希望在pod內部訪問api-server,獲取集群的信息,甚至對集群進行改動。針對這種情況,kubernetes提供了一種特殊的認證方式:service account。

    • service account和pod、service、deployment一樣式kubernetes集群中一種資源,用戶也可以創建自己的service account

    • ServiceAccount 主要包含三個內容:namespace、Token和CA、

      • namespace指定了pod所在的namespace

      • CA用於驗證apiserver的證書

      • token用作身份驗證 它們都通過mount的方式保存在pod的文件系統中

    Role-Based Access,RBAC

在kubernetes1.6版本中新增角色訪問控制機制(Role-Based Access,RBAC)。讓集群管理員可以針對特定使用者或服務賬號的角色,進行更精確的資源訪問控制。在RBAC中,權限與角色相關聯,用戶通過稱為適當角色的成員而得到這些角色的權限。這就極大簡化了權限的管理。

 
         

在一個組織中,角色是為了完成各種工作而創建,用戶則依據它的責任和資格來指派響應角色,用戶可以很容易地從一個角色被指派到另一個角色

目前kubernetes中有一系列的鑒權機制,RBAC是更好的選擇
kubernetes准入控制准入控制(AdmissionControl)本質上為一段准入代碼,在對kubernetes api的請求過程中,順序為:先講過認證&授權,然后執行准入操作,最后對目標對象進行操作。這個准入代碼在api-server中,而且必須被編譯到二進制文件中才能被執行。
在對集群進行請求時,每個准入控制代碼都按照一定順序進行。若有一個准入控制拒絕了此次請求,那么整個請求結果將會立即返回,並提示用戶相應的error信息。
常用組件(控制代碼)如下

    * AlwaysAdmit:允許所有請求

    * AlwaysDeny:禁止所有請求,多用於測試環境

    * ServiceAccount:他講serviceAccount實現自動化,他會輔助serviceAccount做一個事情。比如若pod沒有serviceAccount屬性,則他會自動添加一個default,並確保pod的serviceAccount始終存在

    * LimtRanger:觀察所有的請求,確保沒有違反已經定義好的約束條件,這些條件定義在namespace中的LimitRange對象中。若在kubernetes中使用LimitRange對象,則必須使用這個插件

    * NamespaceExists:它會觀察所有的請求,若請求嘗試創建一個不存在的namespace,則這個請求被拒絕

 

  二)kube-scheduler及調度器性能調優

  在kubernetes中,調度指的是將新生成的pod調度到合適的Node節點上,然后Node上對應的kubelet才能運行pod。

  

  k8s預選策略和優選函數簡介:https://www.cnblogs.com/wn1m/p/11290733.html

  控制平面組件,負責監視新創建的、未指定運行節點(node)的pods。選擇節點讓pod在上面運行。

  默認調度器的調度規則是:根據Node最大資源空閑率來進行均衡調度。

  是一個策略豐富、拓撲感知、工作負載特定的功能,調度器顯著影響可用性、性能和容量。調度決策考慮的因素包括單個pod和pod的集合的資源請求、硬件/軟件/策略約束、親和性和反親和性規范、數據位置、工作負載剪得干擾和最后期限。

  1、調度概述

  調度器通過kubernetes的watch機制來發現新生成的且未調度到Node上的pod。調度器會將發現的每一個未調度的pod調度到合適的Node上運行,調度器會使用以下所述的調度原則來做出調度選擇。

  2、kube-scheduler

  kube-sceduler時kubernetes集群中默認調度器,並且是集群控制面的一部分,kube-scheduler在設計上允許你寫一個自己的調度組件並替換原有的kube-scheduler。

  對每一個新創建或未被調度的的pod,kube-scheduler都會選擇一個最優的Node去運行這個pod。然而,pod內的每一個容器對資源都有不同的需求,而且pod本身也有不同的資源需求。因此,pod被調度到Node之前,會根據這些特定的資源調度需求,對集群中的Node進行一次過濾。

  在一個集群中,滿足一個pod調度請求的所有node稱之為可調度節點。如果沒有任何一個Node滿足pod的調度請求,那個這個pod會一直處於未調度狀態直到調度器能夠找到合適的Node。

  調度器先在集群中找到pod的所有可調度節點,然后根據一系列函數對這些可調度節點打分,然后選出得分最高的Node來運行pod。之后,調度器將這個調度決定通知給kube-apiserver,這個過程叫做綁定。

  在做調度決定時需要考慮的因素包括:單獨和整體的資源需求,硬件/軟件/策略限制,親和以及反親和要求,數據局域性,負載間的干擾等。

  3、kube-scheduler調度流程

  kube-scheduler 給一個 pod 做調度選擇包含兩個步驟:

  • 預選策略(Predicate)——過濾:過濾階段會將所有滿足 Pod 調度需求的 Node 選出來。例如,PodFitsResources 過濾函數會檢查候選 Node 的可用資源能否滿足 Pod 的資源請求。在過濾之后,得出一個 Node 列表,里面包含了所有可調度節點;通常情況下,這個 Node 列表包含不止一個 Node。如果這個列表是空的,代表這個 Pod 不可調度。

    1. 根據運行Pod的資源限制來排除不符合要求的Node
    2. 根據運行Pod時,是否要求共享宿主機的網絡名稱空間來判斷,如: 某Pod啟動要共享宿主機的網絡名稱空間,啟動80端口,而某些Node的80已經被占用,那它就不符合,就也要不排除。
  • 優選策略(Priority)——打分:打分階段,調度器會為 Pod 從所有可調度節點中選取一個最合適的 Node。根據當前啟用的打分規則,調度器會給每一個可調度節點進行打分。最后,kube-scheduler 會將 Pod 調度到得分最高的 Node 上。如果存在多個得分最高的 Node,kube-scheduler 會從中隨機選取一個。

    • 默認啟用了7個紅色的優選函數
  LeastRequested: 【與它相反對一個優選函數:MostRequested,它是Node資源占用越高得分越高,有點像是,先將某Node的資源先全部占滿的意味,然后空出部分Node.】
     計算得分的算法公式=(cpu((capacity - sum(requested))*10 / capacity) + memory((capacity - sum(requested))*10 / capacity))/2
       此公式的含義:
      假如當前有16個核心,已經用了8個核心,那么總的使用率就是 (16-8)/16 = 0.5 ,而乘以10,是為了計算得分方便,將其轉化為0~10之間的數,
      而內存的計算含義一樣,假如內存32G,已經用了8G,則使用率為 (32-8)/32 = 0.75 ,乘以10
      將CPU + Memory/2 就可以得到一個平均值。該平均值越高,表示該節點的資源空閑率越高。
  BalanceResourceAllocation:
    它表示CPU內存資源占用率的相近程度,作為評估標准,越接近也優選選擇,比如: Node1的CPU和內存使用率一個48%一個50%,而Node2的CPU和內存使用率都是50%,則Node2勝出。
  #它通常要和LeastRequested 結合來評估Node的資源利用率的。
  #兩個組合主要是為了平衡各Node上資源的利用率。
NodePreferAvoidPods:
  根據Node節點上是否定義了注解信息"scheduler.alpha.kubernetes.io/preferAvoidPods",若沒有則該Node得分為10,而且權重為1萬,有此注解則說明該Node是適合運行Pod的。而對於那些有Replicas Controller的控制器則,該Node的得分為0,此時則表示Pod不能運行在該Node上,但這不能決定Pod一定不能運行在該Node上,因為最終是要看總體得分的。
  注解信息:
    # kubectl describe node node1.zcf.com
      Name: node1.zcf.com
      Roles: node
      ..........
      Annotations: node.alpha.kubernetes.io/ttl: 0      #這就是所謂的node上的注解信息。
      volumes.kubernetes.io/controller-managed-attach-detach: true

TaintToleration:
  基於Pod對調度Node上的污點容忍度來評估是否可調度到該Node上。
  簡單說:就是取出Pod對象中定義的spec.tolerations列表,查看其中能容忍的污點,然后,一個一個去對比Node上存在的污點,若匹配的越多,則該Node的得分越低,就越不會調度到該Node上。
SelectorSpreading:
  此優化函數是希望將相同標簽選擇器選取的Pod盡可能的散開到多個Node上。因此假如:ReplicaSet控制器,已經在B上創建了一個Pod,那么它要再創建一個Pod時,此優選函數在計算A,B,C三個Node的得分時,會根據那個Node上擁有此ReplicaSet控制器的標簽選擇器所匹配的Pod數量,來評分,數量越少,分數越高,反之越低。
  而使用標簽選擇器的資源對象有:Service,Replication Controller,ReplicaSet,StatefulSet。
InterPodAffinity:
  遍歷對象的親和性條目,並將能夠匹配到給定節點的條目的條目數相加結果值越大得分越高。
  簡單說:NodeA上運行了3個Pod,NodeB上運行了6個Pod,NodeC上運行了5個Pod,現在要調度一個Pod到其中一個Node上,而該Pod的比較親和某類Pod,此優選函數就會將這些Node上,所有匹配該Pod親和條目的數量相加,值越大,則越得分越高。其中條目的理解,我還不是很懂。
NodeAffinity:
  它是根據pod中定義的nodeSeletor來對Node做親和性檢查, 能成功匹配的數量越多,則得分越高。
NodeLabel:
  根據Node是否有某些標簽來做評估,然后計算得分的,此優選函數只關注標簽,不關注值,只有Node上有這個標簽就可以得分。
ImageLocality:
  它評分的標准是,判斷Node上是否有運行該Pod的鏡像,若有則得分,否則不得分。
  但它評估鏡像是根據鏡像總的體積大小來計算得分的,例如:NodeA上有1個鏡像1G,NodeB上有2鏡像,NodeC上有3個鏡像,而運行此Pod需要4個鏡像,其中一個鏡像1G,其它都是比較小,這時NodeA的得分會最高。

 

  • 選定(Select):當優選選出一個Node后,該Pod將會被綁定到該Node上運行

  調度方式

  1. 節點傾向性(或叫 節點親和性調度)
   這種調度通常會采用 nodeSelector 來完成調度。

  2. Pod傾向性 和 Pod非傾向性(這也稱為Pod親和性和非親和性)
   有時候我們需要讓某些Pod能運行在同一處時,就需要使用Pod親和性來定義,如:我們要定義一個NMT(Nginx+Tomcat+MySQL),若這三個Pod分別被調度三個不同地域的機房中,比如北京,上海,深圳等地,那肯定不是我們所希望的,這時我們就需要使用Pod親和性來定義這三個Pod能運行在相同的Node 或 相鄰的Node上。
  而在另外一些情況下,我們又希望某些Pod一定不能運行在相同Node上,這時就需要使用Pod的非親和性了。

  3. 污點 和 污點容忍調度
   Taints(污點):是定義在Node上的
   Tolerations(容忍): 是定義在Pod上的
    污點:指有時我們希望不將某些Pod調度到某些Node上,這時我們可對某些Node上打上污點,然后,當我們創建Pod時,我們可定義此Pod能容忍的污點范圍。
    假如:NodeA上有5個污點: "吃喝嫖賭抽",而此次要調度的Pod比較大度,能容忍5個污點,而NodeA的污點正好是Pod能容忍污點的范圍內,於是Pod就能"嫁入"該NodeA。
    假如,Pod運行到NodeA上后,后期我們又給該NodeA打上了新污點如:"坑蒙拐騙偷",此時Pod發現NodeA的惡性原來有這么多,怎么辦?通常有兩種選擇策略:
    1. Pod繼續運行在NodeA上"艱苦度日"
    2. Pod被驅逐,或者叫Pod逃離。 

  kube-scheduler給一個pod做調度選擇包含兩個步驟:

    1)過濾
    2)打分

  過濾階段會將所有滿足調度需求的node選擇出來。例如,PodFitsResources 過濾函數會檢查候選 Node 的可用資源能否滿足 Pod 的資源請求。在過濾之后,得出一個Node列表,里面包含了所有可調度節點;通常情況下,這個Node列表不止一個Node。如果這個列表是空的,說明這個pod不可調度。

  在打分階段,調度器會為pod在所有可調度節點中選擇最合適的Node。根據當前的打分規則,調度器會給每一個可調度節點進行打分。

  最后,kube-scheduler會將pod調度到得分最高的Node上。如果存在多個得分最高的Node,kube-scheduler會從中隨機選擇一個。

  默認策略
  kube-scheduler 有一系列的默認調度策略。

  過濾策略

  • PodFitsHostPorts:如果 Pod 中定義了 hostPort 屬性,那么需要先檢查這個指定端口是否 已經被 Node 上其他服務占用了。
  • PodFitsHost:若 pod 對象擁有 hostname 屬性,則檢查 Node 名稱字符串與此屬性是否匹配。
  • PodFitsResources:檢查 Node 上是否有足夠的資源(如,cpu 和內存)來滿足 pod 的資源請求。
  • PodMatchNodeSelector:檢查 Node 的 標簽 是否能匹配 Pod 屬性上 Node 的 標簽 值。
  • NoVolumeZoneConflict:檢測 pod 請求的 Volumes 在 Node 上是否可用,因為某些存儲卷存在區域調度約束。
  • NoDiskConflict:檢查 Pod 對象請求的存儲卷在 Node 上是否可用,若不存在沖突則通過檢查。
  • MaxCSIVolumeCount:檢查 Node 上已經掛載的 CSI 存儲卷數量是否超過了指定的最大值。
  • CheckNodeMemoryPressure:如果 Node 上報了內存資源壓力過大,而且沒有配置異常,那么 Pod 將不會被調度到這個 Node 上。
  • CheckNodePIDPressure:如果 Node 上報了 PID 資源壓力過大,而且沒有配置異常,那么 Pod 將不會被調度到這個 Node 上。
  • CheckNodeDiskPressure:如果 Node 上報了磁盤資源壓力過大(文件系統滿了或者將近滿了), 而且配置沒有異常,那么 Pod 將不會被調度到這個 Node 上。
  • CheckNodeCondition:Node 可以上報其自身的狀態,如磁盤、網絡不可用,表明 kubelet 未准備好運行 pod。 如果 Node 被設置成這種狀態,那么 pod 將不會被調度到這個 Node 上。
  • PodToleratesNodeTaints:檢查 pod 屬性上的 tolerations 能否容忍 Node 的 taints。
  • CheckVolumeBinding:檢查 Node 上已經綁定的和未綁定的 PVCs 能否滿足 Pod 對象的存儲卷需求。

  打分策略

  • SelectorSpreadPriority:盡量將歸屬於同一個 Service、StatefulSet 或 ReplicaSet 的 Pod 資源分散到不同的 Node 上。
  • InterPodAffinityPriority:遍歷 Pod 對象的親和性條目,並將那些能夠匹配到給定 Node 的條目的權重相加,結果值越大的 Node 得分越高。
  • LeastRequestedPriority:空閑資源比例越高的 Node 得分越高。換句話說,Node 上的 Pod 越多,並且資源被占用的越多,那么這個 Node 的得分就會越少。
  • MostRequestedPriority:空閑資源比例越低的 Node 得分越高。這個調度策略將會把你所有的工作負載(Pod)調度到盡量少的 Node 上。
  • RequestedToCapacityRatioPriority:為 Node 上每個資源占用比例設定得分值,給資源打分函數在打分時使用。
  • BalancedResourceAllocation:優選那些使得資源利用率更為均衡的節點。
  • NodePreferAvoidPodsPriority:這個策略將根據 Node 的注解信息中是否含有 scheduler.alpha.kubernetes.io/preferAvoidPods 來 計算其優先級。使用這個策略可以將兩個不同 Pod 運行在不同的 Node 上。
  • NodeAffinityPriority:基於 Pod 屬性中 PreferredDuringSchedulingIgnoredDuringExecution 來進行 Node 親和性調度。你可以通過這篇文章 Pods 到 Nodes 的分派 來了解到更詳細的內容。
  • TaintTolerationPriority:基於 Pod 中對每個 Node 上污點容忍程度進行優先級評估,這個策略能夠調整待選 Node 的排名。
  • ImageLocalityPriority:Node 上已經擁有 Pod 需要的 容器鏡像 的 Node 會有較高的優先級。
  • ServiceSpreadingPriority:這個調度策略的主要目的是確保將歸屬於同一個 Service 的 Pod 調度到不同的 Node 上。如果 Node 上 沒有歸屬於同一個 Service 的 Pod,這個策略更傾向於將 Pod 調度到這類 Node 上。最終的目的:即使在一個 Node 宕機之后 Service 也具有很強容災能力。
  • CalculateAntiAffinityPriorityMap:這個策略主要是用來實現pod反親和。
  • EqualPriorityMap:將所有的 Node 設置成相同的權重為 1。

  4、調度器性能調優

  在大規模 Kubernetes 集群下調度器性能優化的方式。

  設置打分階段 Node 數量占集群總規模的百分比

  在Kubernetes1.12版本之前,kube-scheduler會檢查集群中所有節點的可調度性,並且給可調度節點打分。Kubernetes1.12版本添加了一個新的功能,允許調度器在找到一定數量的可調度節點之后就停止繼續尋找可調度節點。

  該功能能提高調度器在大規模集群下的調度性能。這個數值是集群規模的百分比。這個百分比通過 percentageOfNodesToScore 參數來進行配置。其值的范圍在1到100之間,最大值就是100%。如果設置為0就代表沒有提供這個參數配置。

  Kubernetes1.14版本又加入了一個特性,在該參數沒有被用戶配置的情況下,調度器會根據集群的規模自動設置一個集群比例,然后通過這個比例篩選一定數量的可調度節點進入打分階段。該特性使用線性公式計算出集群比例,如在100-node 的集群下取 50%。在 5000-node 的集群下取 10%。這個自動設置的參數的最低值是5%。換句話說,調度器至少會對集群中 5% 的節點進行打分,除非用戶將該參數設置的低於5。

  注意: 當集群中的可調度節點少於 50 個時,調度器仍然會去檢查所有的 Node,因為可調度節點太少,不足以停止調度器最初的過濾選擇。

  如果想要關閉這個功能,你可以將 percentageOfNodesToScore 值設置成 100。

  調節 percentageOfNodesToScore 參數

  percentageOfNodesToScore 的值必須在 1 到 100 之間,而且其默認值是通過集群的規模計算得來的。另外,還有一個 50 個 Node 的數值是硬編碼在程序里面的。設置這個值的作用在於:當集群的規模是數百個 Node 並且percentageOfNodesToScore 參數設置的過低的時候,調度器篩選到的可調度節點數目基本不會受到該參數影響。當集群規模較小時,這個設置將導致調度器性能提升並不明顯。然而在一個超過 1000 個 Node 的集群中,將調優參數設置為一個較低的值可以很明顯的提升調度器性能。

  值得注意的是,該參數設置后可能會導致只有集群中少數節點被選為可調度節點,很多 node 都沒有進入到打分階段。這樣就會造成一種后果,一個本來可以在打分階段得分很高的 Node 甚至都不能進入打分階段。由於這個原因,這個參數不應該被設置成一個很低的值。通常的做法是不會將這個參數的值設置的低於 10。很低的參數值一般在調度器的吞吐量很高且對 node 的打分不重要的情況下才使用。換句話說,只有當你更傾向於在可調度節點中任意選擇一個 Node 來運行這個 Pod 時,才使用很低的參數設置。

如果你的集群規模只有數百個節點或者更少,我們並不推薦你將這個參數設置得比默認值更低。因為這種情況下不太可能有效的提高調度器性能。

  調度器做調度選擇的時候如何覆蓋所有的 Node

  在將 Pod 調度到 Node 上時,為了讓集群中所有 Node 都有公平的機會去運行這些 Pod,調度器將會以輪詢的方式覆蓋全部的 Node。你可以將 Node 列表想象成一個數組。調度器從數組的頭部開始篩選可調度點依次向后直到可調度節點的數量達到 percentageOfNodesToScore 參數的要求。

  在對下一個 Pod 進行調度的時候,前一個 Pod 調度篩選停止的 Node 列表的位置,將會來作為這次調度篩選 Node 開始的位置。

  如果集群中的 Node 在多個區域,那么調度器將從不同的區域中輪詢 Node,來確保不同區域的 Node 接受可調度性檢查。如下例,考慮兩個區域中的六個節點:

Zone 1: Node 1, Node 2, Node 3, Node 4
Zone 2: Node 5, Node 6

  調度器將會按照如下的順序去評估 Node 的可調度性:

Node 1, Node 5, Node 2, Node 6, Node 3, Node 4

  在評估完所有 Node 后,將會返回到 Node 1,從頭開始。

  三)controller-manager

  從邏輯上講,每個控制器都是一個單獨的進程, 但是為了降低復雜性,它們都被編譯到同一個可執行文件,並在一個進程中運行。

  以守護進程的形式運行着kubernetes幾個核心的控制循環(控制器)。包括deployment、replicaset、namespace、serviceaccount、node等等(以及下面的控制器),通過apiserver的list watch接口監控自己負責的資源的配置變化。

  1、controller manager組成

  Controller Manager 由 kube-controller-manager 和 cloud-controller-manager 組成, 是Kubernetes 的大腦, 它通過 apiserver 監控整個集群的狀態, 並確保集群處於預期的工作狀態。

    1)kube-controller-manager 組成
  • 節點控制器(Node Controller): 負責在節點出現故障時進行通知和響應
  • 任務控制器(Job controller): 監測代表一次性任務的 Job 對象,然后創建 Pods 來運行這些任務直至完成
  • 端點控制器(Endpoints Controller): 填充端點(Endpoints)對象(即加入 Service 與 Pod)
  • 服務帳戶和令牌控制器(Service Account & Token Controllers): 為新的命名空間創建默認帳戶和 API 訪問令牌

  必須啟動的控制器

EndpointController
ReplicationController
PodGCController
ResourceQuotaController
NamespaceController
ServiceAccountController
GarbageCollectorController
DaemonSetController
JobController
DeploymentController
ReplicaSetController
HPAController
DisruptionController
StatefulSetController
CronJobController
CSRSigningController
CSRApprovingController
TTLController

  默認啟動的可選控制器,可通過選項設置是否開啟

TokenController
NodeController
ServiceController
RouteController
PVBinderController
AttachDetachController

  默認禁止的可選控制器,可通過選項設置是否開啟

BootstrapSignerController
TokenCleanerController

 

    2)cloud-controller-manager 組成

  在 Kubernetes 啟用 Cloud Provider 的時候才需要, 用來配合雲服務提供商的控制, 也包括一系列的控制器

Node Controller
Route Controller
Service Controller

  從v1.6開始,cloud provider已經經歷了幾次重大重構,以便在不修改Kubernetes核心代碼的同時構建自定義的雲服務商支持

  2、常見Pod控制器及含義

    1)Replication Controller

  Replication Controller 保證了在所有時間內,都有特定數量的Pod副本正在運行,如果太多了,Replication Controller就殺死幾個,如果太少了,Replication Controller會新建幾個,和直接創建的pod不同的是,Replication Controller會替換掉那些刪除的或者被終止的pod,不管刪除的原因是什么(維護阿,更新啊,Replication Controller都不關心)。基於這個理由,我們建議即使是只創建一個pod,我們也要使用Replication Controller。Replication Controller 就像一個進程管理器,監管着不同node上的多個pod,而不是單單監控一個node上的pod,Replication Controller 會委派本地容器來啟動一些節點上服務(Kubelet ,Docker)。
  Replication Controller只會對那些RestartPolicy = Always的Pod的生效,(RestartPolicy的默認值就是Always),Replication Controller 不會去管理那些有不同啟動策略pod
  Replication Controller永遠不會自己關閉,但是,我們並不希望Replication Controller成為一個長久存在的服務。服務可能會有多個Pod組成,這些Pod又被多個Replication Controller控制着,我們希望Replication Controller 會在服務的生命周期中被刪除和新建(例如在這些pod中發布一個更新),對於服務和用戶來說,Replication Controller是通過一種無形的方式來維持着服務的狀態

    2)ReplicaSets

  ReplicaSet是下一代復本控制器。ReplicaSet和 Replication Controller之間的唯一區別是現在的選擇器支持。Replication Controller只支持基於等式的selector(env=dev或environment!=qa),但ReplicaSet還支持新的,基於集合的selector(version in (v1.0, v2.0)或env notin (dev, qa))。
  大多數kubectl支持Replication Controller的命令也支持ReplicaSets。rolling-update命令有一個例外 。如果想要滾動更新功能,請考慮使用Deployments。此外, rolling-update命令是必須的,而Deployments是聲明式的,因此我們建議通過rollout命令使用Deployments。
  雖然ReplicaSets可以獨立使用,但是今天它主要被 Deployments 作為協調pod創建,刪除和更新的機制。當使用Deployments時,不必擔心管理他們創建的ReplicaSets。Deployments擁有並管理其ReplicaSets。

    3)Deployment

  Deployment為Pod和Replica Set(下一代Replication Controller)提供聲明式更新。
  你只需要在Deployment中描述你想要的目標狀態是什么,Deployment controller就會幫你將Pod和Replica Set的實際狀態改變到你的目標狀態。你可以定義一個全新的Deployment,也可以創建一個新的替換舊的Deployment。

  一個典型的用例如下:

  1. 使用Deployment來創建ReplicaSet。ReplicaSet在后台創建pod。檢查啟動狀態,看它是成功還是失敗。
  2. 然后,通過更新Deployment的PodTemplateSpec字段來聲明Pod的新狀態。這會創建一個新的ReplicaSet,Deployment會按照控制的速率將pod從舊的ReplicaSet移動到新的ReplicaSet中。
  3. 如果當前狀態不穩定,回滾到之前的Deployment revision。每次回滾都會更新Deployment的revision。
  4. 擴容Deployment以滿足更高的負載。
  5. 暫停Deployment來應用PodTemplateSpec的多個修復,然后恢復上線。
  6. 根據Deployment 的狀態判斷上線是否hang住了。
  7. 清除舊的不必要的ReplicaSet。
    4)StatefulSet

  StatefulSet是為了解決有狀態服務的問題(對應Deployments和ReplicaSets是為無狀態服務而設計),其應用場景包括

  1. 穩定的持久化存儲,即Pod重新調度后還是能訪問到相同的持久化數據,基於PVC來實現
  2. 穩定的網絡標志,即Pod重新調度后其PodName和HostName不變,基於Headless Service(即沒有Cluster IP的Service)來實現
  3. 有序部署,有序擴展,即Pod是有順序的,在部署或者擴展的時候要依據定義的順序依次依次進行(即從0到N-1,在下一個Pod運行之前所有之前的Pod必須都是Running和Ready狀態),基於init containers來實現
  4. 有序收縮,有序刪除(即從N-1到0)

  StatefulSet由以下幾個部分組成:

  1. 用於定義網絡標志(DNS domain)的Headless Service
  2. 用於創建PersistentVolumes的volumeClaimTemplates
  3. 定義具體應用的StatefulSet

  StatefulSet中每個Pod的DNS格式為statefulSetName-{0..N-1}.serviceName.namespace.svc.cluster.local,其中

  1. serviceName為Headless Service的名字
  2. 0..N-1為Pod所在的序號,從0開始到N-1
  3. statefulSetName為StatefulSet的名字
  4. namespace為服務所在的namespace,Headless Servic和StatefulSet必須在相同的namespace
  5. .cluster.local為Cluster Domain
    5)DaemonSet

  DaemonSet保證在每個Node上都運行一個容器副本,常用來部署一些集群的日志、監控或者其他系統管理應用。典型的應用包括:

  1. 日志收集,比如fluentd,logstash等
  2. 系統監控,比如Prometheus Node Exporter,collectd,New Relic agent,Ganglia gmond等
  3. 系統程序,比如kube-proxy, kube-dns, glusterd, ceph等
     6) ResourceQuota Controller

  資源配額管理確保指定的資源對象在任何時候都不會超量占用系統物理資源。
  支持三個層次的資源配置管理:

1)容器級別:對CPU和Memory進行限制
2)Pod級別:對一個Pod內所有容器的可用資源進行限制
3)Namespace級別:包括

    Pod數量
    Replication Controller數量
    Service數量
    ResourceQuota數量
    Secret數量
    可持有的PV(Persistent Volume)數量
k8s配額管理是通過Admission Control(准入控制)來控制的;
Admission Control提供兩種配額約束方式:LimitRanger和ResourceQuota;
LimitRanger作用於Pod和Container;
ResourceQuota作用於Namespace上,限定一個Namespace里的各類資源的使用總額。
    7)Namespace Controller

  用戶通過API Server可以創建新的Namespace並保存在etcd中,Namespace Controller定時通過API Server讀取這些Namespace信息。

  如果Namespace被API標記為優雅刪除(即設置刪除期限,DeletionTimestamp),則將該Namespace狀態設置為“Terminating”,並保存到etcd中。同時Namespace Controller刪除該Namespace下的ServiceAccount、RC、Pod等資源對象。

    8)Endpoint Controller

  Service、Endpoint、Pod的關系

  Endpoints表示了一個Service對應的所有Pod副本的訪問地址,而Endpoints Controller負責生成和維護所有Endpoints對象的控制器。它負責監聽Service和對應的Pod副本的變化。

如果監測到Service被刪除,則刪除和該Service同名的Endpoints對象;
如果監測到新的Service被創建或修改,則根據該Service信息獲得相關的Pod列表,然后創建或更新Service對應的Endpoints對象。
如果監測到Pod的事件,則更新它對應的Service的Endpoints對象。

  

  kube-proxy進程獲取每個Service的Endpoints,實現Service的負載均衡功能。

    9)Service Controller

  Service Controller是屬於kubernetes集群與外部的雲平台之間的一個接口控制器。Service Controller監聽Service變化,如果是一個LoadBalancer類型的Service,則確保外部的雲平台上對該Service對應的LoadBalancer實例被相應地創建、刪除及更新路由轉發表

    10)Node Controller

  kubelet在啟動時會通過API Server注冊自身的節點信息,並定時向API Server匯報狀態信息,API Server接收到信息后將信息更新到etcd中。

  Node Controller通過API Server實時獲取Node的相關信息,實現管理和監控集群中的各個Node節點的相關控制功能。流程如下

  1. Controller Manager在啟動時如果設置了–cluster-cidr參數,那么為每個沒有設置Spec.PodCIDR的Node節點生成一個CIDR地址,並用該CIDR地址設置節點的Spec.PodCIDR屬性,防止不同的節點的CIDR地址發生沖突。
  2. 具體流程見以上流程圖。
  3. 逐個讀取節點信息,如果節點狀態變成非“就緒”狀態,則將節點加入待刪除隊列,否則將節點從該隊列刪除。

  四)etcd

  etcd在kubernetes集群是用來存放數據並通知變動的。
  Kubernetes中沒有用到數據庫,它把關鍵數據都存放在etcd中,這使kubernetes的整體結構變得非常簡單。

  在kubernetes中,數據是隨時發生變化的,比如說用戶提交了新任務、增加了新的Node、Node宕機了、容器死掉了等等,都會觸發狀態數據的變更。狀態數據變更之后呢,Master上的kube-scheduler和kube-controller-manager,就會重新安排工作,它們的工作安排結果也是數據。這些變化,都需要及時地通知給每一個組件。

  etcd有一個特別好用的特性,可以調用它的api監聽其中的數據,一旦數據發生變化了,就會收到通知。有了這個特性之后,kubernetes中的每個組件只需要監聽etcd中數據,就可以知道自己應該做什么。kube-scheduler和kube-controller-manager呢,也只需要把最新的工作安排寫入到etcd中就可以了,不用自己費心去逐個通知了

    • http server:(在etcd3里面變成grpc server),主要處理client的操作請求以及節點間的數據同步和心跳保持

    • raft狀態機:通過對raft一致性協議的實現來保證etcd集群的高可用

    • store:負責ecd中事務操作的邏輯,是api server的命令的具體體現

    • wal存儲:負責具體的數據持久存儲操作。它分為兩部分

      • entry 負責實際的日志數據存儲(在etcd里數據的存儲都是帶版本號的,對於同一個鍵值可能有多個版本的記錄存在,所以數據的存儲方式即通過食物日志進行存儲,而在內存里存有鍵和版本號的映射關系以方便查詢)

      • snapshot 則是對日志數據的狀態存儲,應防止過多的數據存在

三、kubernetes worker 節點組件

  一)kubelet

  一個在集群中每個節點(node)上運行的代理。它保證容器(containers)都運行在pod中。

  kubelet接收一組通過各機制提供給它的PodSpecs,確保這些PodSpecs中描述的容器處於運行狀態且健康。kubelet不會管理不是由kubernetes創建的容器。

  二)kube-proxy

  kube-proxy是集群中每個節點上運行的網絡代理,實現kubernetes服務概念的一部分。

  維護主機上kube服務涉及的網絡規則和連接轉發,負責service的實現,采用IPVs

  由於IPVS的優勢,所以盡可能的采用IPVS作為kube-proxy的工作模式

  kube-proxy有如下三種工作模式

  三)Container Runtime:容器引擎docker

  容器運行環境是負責運行容器的軟件。

  Kubernetes 支持多個容器運行環境: Docker、 containerdCRI-O 以及任何實現 Kubernetes CRI (容器運行環境接口)

四、CNI網絡組件

  一)CNi:

  1、什么是CNI?

       CNI是Container Network Interface的縮寫,是一個標准的通用的接口。為了讓用戶在容器創建或銷毀時都能夠更容易地配置容器網絡,現在容器平台:docker,kubernetes,mesos。

  2、CNI如何實現?

  CNI用於連接容器管理系統和網絡插件。提供一個容器所在的network namespace,將network interface插入該network namespace中(比如veth的一端),並且在宿主機做一些必要的配置(例如將veth的另一端加入bridge中),最后對namespace中的interface進行IP和路由的配置。

  CNI插件是可執行文件,會被kubelet調用。啟動kubelet --network-plugin=cni,--cni-conf-dir 指定networkconfig配置,默認路徑是:/etc/cni/net.d,並且,--cni-bin-dir 指定plugin可執行文件路徑,默認路徑是:/opt/cni/bin

  二)網絡解決方案:

     容器網絡解決方案:flannel、calico、weave、Canal、Terway、以及 Contiv。

  1、Flannel:

  在默認的Docker配置中,每個節點上的Docker服務會分別負責所在節點容器的IP分配。這樣導致的一個問題是,不同節點上容器可能獲得相同的內外IP地址。

      Flannel的功能簡單的來講就是讓集群中的不同節點主機創建的Docker容器都具有全集群唯一的虛擬IP地址。 

  Flannel的設計目的就是為集群中的所有節點重新規划IP地址的使用規則,從而使得不同節點上的容器能夠獲得同屬一個內網且不重復的IP地址,並讓屬於不同節點上的容器能夠直接通過內網IP通信。

  Flannel實質上是一種覆蓋網絡(overlay network),也就是將TCP數據包裝在另一種網絡包里面進行路由轉發和通信,目前已經支持udp、vxlan、host-gw、aws-vpc、gce和alloc路由等數據轉發方式,常用的的三種轉發模式。

 

hostgw 這種方式就是直接路由 (性能最高 要求集群節點在同一個網段)
vxlan 是flannel推薦的方式。需要通信的網絡設備能夠支持vxlan協議 (性能較好)
udp 該方式與vxlan很類似,它對ip層網絡進行包裝。通常用於調試環境或者不支持vxlan協議網絡環境中。(性能最差)
 

  優點:

                1.Flannel相對容易安裝和配置。

                2.支持多個Kubernetes發行版。

                3.使集群中的不同Node主機創建的Docker容器都具有全集群唯一的虛擬IP地址。

                4.Flannel可以使用Kubernetes集群的現有etcd集群來使用API存儲其狀態信息,因此不需要專用的數據存儲。

                5.默認路由使用的方法是使用VXLAN,因為VXLAN性能更良好並且需要的手動干預更少。

 

        缺點:

                1.不支持pod之間的網絡隔離。Flannel設計思想是將所有的pod都放在一個大的二層網絡中,所以pod之間沒有隔離策略。

                2.由於使用二層技術,vlan 隔離和 tunnel 隧道則消耗更多的資源並對物理環境有要求,隨着網絡規模的增大,整體會變得越加復雜在 較大的k8s集群規模下不適用。

  2、Calico:

  calico是基於BGP路由實現的容器集群網絡方案,Calico是一個純三層的協議,使用虛擬路由代替虛擬交換。與 Flannel 不同的是 Calico 不使用隧道或 NAT 來實現轉發,而是巧妙的把所有二三層流量轉換成三層流量,並通過 host 上路由配置完成跨 Host 轉發。

  基礎的calico使用體驗可能和flannel host-gw是基本一樣的。Calico在每個計算節點都利用Linux Kernel實現了一個高效的虛擬路由器vRouter來負責數據轉發。每個vRouter都通過BGP1協議把在本節點上運行的容器的路由信息向整個Calico網絡廣播,並自動設置到達其他節點的路由轉發規則。

  Calico保證所有容器之間的數據流量都是通過IP路由的方式完成互聯互通的。Calico節點組網時可以直接利用網絡結構,不需要額外的NAT、隧道或者Overlay Network,沒有額外的封包解包,能夠節約CPU運算,提高網絡效率。支持兩種網絡IPIP、BGP

  優點:

            1.二層網絡通訊需要依賴廣播消息機制,廣播消息的開銷與 host 的數量呈指數級增長,Calico 使用的三層路由方法,完全抑制了二層廣播,減少了資源開銷,不需要額外的NAT,隧道或者Overlay Network。

            2.不同之處在於flannel方案下路由都是通過代碼邏輯進行配置。calico會在每個節點建立bgp peer,bgp peer彼此之間會進行路由的共享和學習,所以自動生成並維護了路由。在k8s集群大規模的情況下集群間的網絡保持通暢。

            3.Calico 較少的依賴性使它能適配所有 VM、Container、混合環境場景。

            4.支持network-policy,自定義ingress(進棧)egress(出棧)規則。

            5.傳輸性能方便高於Flannel,自定義隔離pod間通信。

 
  缺點:

            1.通過路由規則可以看出,路由規模和 pod 分布有關,如果 pod離散分布在 host 集群中,會產生較多的路由項。

            2.1台 Host 上可能虛擬化十幾或幾十個容器實例,過多的 iptables 規則造成復雜性和不可調試性,同時也存在性能損耗。

            3.網關路由問題,當對端網絡不為二層可達時,需要通過三層路由機時,需要網關支持自定義路由配置,即 pod 的目的地址為本網段的網關地址,再由網關進行跨三層轉發。

            4.簡單使用和flannel無異,深層的使用需要有較高的學習成本。

  3、Weave Net:

  和flannel一樣它能夠創建一個虛擬網絡,用於連接部署在多台主機上的Docker容器,這樣容器就像被接入了同一個網絡交換機,那些使用網絡的應用程序不必去配置端口映射和鏈接等信息。外部設備能夠訪問Weave網絡上的應用程序容器所提供的服務,同時已有的內部系統也能夠暴露到應用程序容器上。Weave能夠穿透防火牆並運行在部分連接的網絡上。與Calico一樣,Weave也為Kubernetes集群提供網絡策略功能。Weave通過UDP封裝實現L2 Overlay,封裝支持兩種模式,一種是運行在user space的sleeve mode,另一種是運行在kernal space的 fastpath mode。
     

   優點:

               1.Weave通過創建虛擬網絡使Docker容器能夠跨主機通信並能夠自動相互發現。

               2.通過weave網絡,由多個容器構成的基於微服務架構的應用可以運行在任何地方主機,多主機,雲上或者數據中心。應用程序使用網絡就好像容器是插在同一個網絡交換機上一樣,不需要配置端口映射,連接等。

               3.Weave網絡自動在兩個節點之間選擇最快的路徑,提供接近本地網絡的吞吐量和延遲。同時支持主機間通信加密。

               4.Weave網絡能夠在節點間轉發流量,它甚至能夠在網狀網絡部分連接的情況下工作。這意味着你可以在混合了傳統系統和容器化的應用的環境中使用Weave網絡來保持通信。

  缺點:

               1.只能通過weave launch或者weave connect加入weave網絡。

  4、Canal:

          Canal 是一個項目的名稱,它試圖將Flannel提供的網絡層與Calico的網絡策略功能集成在一起。Canal名稱的由來是Flannel和Calico的結合,最終只實現了將兩種技術部署在一起的預期能力。出於這個原因,即使這個項目不復存在,業界還是會習慣性地將Flannel和Calico的組成稱為“Canal”。由於Canal是Flannel和Calico的組合,因此它的優點也在於這兩種技術的交叉。網絡層用的是Flannel提供的簡單overlay,可以在許多不同的部署環境中運行且無需額外的配置。在網絡策略方面,Calico強大的網絡規則評估,為基礎網絡提供了更多補充,從而提供了更多的安全性和控制。
 
  優點:集成Flannel和Calico和功能。
  缺點:部署相對比較復雜,維護和配置有較高的學習成本。

  5、Terway:

       Terway是阿里雲容器服務Kubernetes版自研的網絡插件,使用原生的彈性網卡分配給Pod實現Pod網絡。將阿里雲的彈性網卡和輔助IP分配給容器,支持Network Policy來定義容器間的訪問策略,支持對單個容器做帶寬的限流,兼容Calico的Network Policy。在Terway網絡插件中,每個Pod擁有自己網絡棧和IP地址。同一台ECS內的Pod之間通信,直接通過機器內部的轉發,跨ECS的Pod通信,報文通過VPC的彈性網卡直接轉發。由於不需要使用VxLAN等的隧道技術封裝報文,因此具有較高的通信性能。
      
        優點:相比Flannel支持了Network Policy訪問策略,支持對單個容器做帶寬對限流。
        缺點:依賴與阿里雲服務器平台。

  6、Contiv:

        Contiv是一個用於跨虛擬機、裸機、公有雲或私有雲的異構容器部署的開源容器網絡架構。Contiv具有2層、3層、overlay和ACI模式,能夠與思科基礎設施進行本地集成,並使用豐富的網絡和安全策略將應用意圖與基礎設施功能進行映射。能夠和非容器環境協作,不依賴物理網絡。支持物理網卡sriov和offload。支持Policy/ACI/Qos租戶,並支持L2(VLAN), L3(BGP), Overlay (VXLAN)。
  優點

              1.集成Flannel和Calico所有的功能。

              2.能夠與思科基礎設施完美的集成。

              3.支持物理網卡sriov和offload。支持Policy/ACI/Qos租戶。

              4.支持L2(VLAN), L3(BGP), Overlay (VXLAN)。 

  缺點

               1.集成配置比較復雜,學習資料少。

               2.學習成本較高,需要定制化開發

五、kubernetes核心組件:附加(add-on)組件

  一)DNS(kubeDNS / coreDNS)

  盡管其他插件都並非嚴格意義上的必需組件,但幾乎所有 Kubernetes 集群都應該 有集群 DNS, 因為很多示例都需要 DNS 服務。

  集群 DNS 是一個 DNS 服務器,和環境中的其他 DNS 服務器一起工作,它為 Kubernetes 服務提供 DNS 記錄。

  Kubernetes 啟動的容器自動將此 DNS 服務器包含在其 DNS 搜索列表中。

  二)dashboard

  Dashboard 是Kubernetes 集群的通用的、基於 Web 的用戶界面。 它使用戶可以管理集群中運行的應用程序以及集群本身並進行故障排除

  三)heapster

 

  四)ingress controller

  五)EFK

六、資源清單說明

  一)endpoint

  1、概述

  endpoint是k8s集群中的一個資源對象,存儲在etcd中,用來記錄一個service對應的所有pod的訪問地址。service配置selector,endpoint controller才會自動創建對應的endpoint對象;否則,不會生成endpoint對象。例如,k8s集群中創建一個名為hello的service,就會生成一個同名的endpoint對象,ENDPOINTS就是service關聯的pod的ip地址和端口。

  一個 Service 由一組 backend Pod 組成。這些 Pod 通過 endpoints 暴露出來。 Service Selector 將持續評估,結果被 POST 到一個名稱為 Service-hello 的 Endpoint 對象上。 當 Pod 終止后,它會自動從 Endpoint 中移除,新的能夠匹配上 Service Selector 的 Pod 將自動地被添加到 Endpoint 中。 檢查該 Endpoint,注意到 IP 地址與創建的 Pod 是相同的。現在,能夠從集群中任意節點上使用 curl 命令請求 hello Service <CLUSTER-IP>:<PORT> 。 注意 Service IP 完全是虛擬的,它從來沒有走過網絡,如果對它如何工作的原理感到好奇,可以閱讀更多關於 服務代理 的內容。

  Endpoints是實現實際服務的端點集合。

  Kubernetes在創建Service時,根據Service的標簽選擇器(Label Selector)來查找Pod,據此創建與Service同名的EndPoints對象。當Pod的地址發生變化時,EndPoints也隨之變化。Service接收到請求時,就能通過EndPoints找到請求轉發的目標地址。

  Service不僅可以代理Pod,還可以代理任意其他后端,比如運行在Kubernetes外部Mysql、Oracle等。這是通過定義兩個同名的service和endPoints來實現的。

  在實際的生產環境使用中,通過分布式存儲來實現的磁盤在mysql這種IO密集性應用中,性能問題會顯得非常突出。所以在實際應用中,一般不會把mysql這種應用直接放入kubernetes中管理,而是使用專用的服務器來獨立部署。而像web這種無狀態應用依然會運行在kubernetes當中,這個時候web服務器要連接kubernetes管理之外的數據庫,有兩種方式:一是直接連接數據庫所在物理服務器IP,另一種方式就是借助kubernetes的Endpoints直接將外部服務器映射為kubernetes內部的一個服務。

  簡單認為:動態存儲pod名字與pod ip對應關系的list,並提供將請求轉發到實際pod上的能力

  2、kubernetes發布tomcat服務,通過deployment,service布署

  service及deployment的yaml文件

[root@k8s-master ~]# pwd
/root
[root@k8s-master ~]# cat deployment-hello.yaml 
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: hello
spec:
  replicas: 4
  template:
    metadata:
      labels:
        run: hello
    spec:
      containers:
       - name: hello
         image: tomcat:8 #確保node節點上有該鏡像且可正常運行,注意是node節點機器上,不是master機器
         imagePullPolicy: IfNotPresent ##Always,IfNotPresent,Never
         ports:
         - name: http
           containerPort: 8080

 

[root@k8s-master ~]# cat service-hello.yaml 
apiVersion: v1
kind: Service
metadata:
  name: service-hello
  labels:
  name: service-hello
spec:
  type: NodePort      #這里代表是NodePort類型的,另外還有ingress,LoadBalancer
  ports:
  - port: 80          #這里的端口和clusterIP(kubectl describe service service-hello中的IP的port)對應,即在集群中所有機器上curl 10.98.166.242:80可訪問發布的應用服務。
    targetPort: 8080  #端口一定要和container暴露出來的端口對應,nodejs暴露出來的端口是8081,所以這里也應是8081
    protocol: TCP
    nodePort: 31111   # 所有的節點都會開放此端口30000--32767,此端口供外部調用。
  selector:
    run: hello         #這里選擇器一定要選擇容器的標簽,之前寫name:kube-node是錯的。
[root@k8s-master ~]# pwd
/root

  創建service

[root@k8s-master ~]# kubectl create -f service-hello.yaml 
service/service-hello created

[root@k8s-master ~]# kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4h24m
service-hello NodePort 10.98.166.242 <none> 80:31111/TCP 42s
[root@k8s-master ~]#

root@k8s-master ~]# kubectl get services -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4h25m <none>
service-hello NodePort 10.98.166.242 <none> 80:31111/TCP 104s run=hello

[root@k8s-master ~]# kubectl describe service service-hello
Name:                     service-hello
Namespace:                default
Labels:                   <none>
Annotations:              <none>
Selector:                 run=hello
Type:                     NodePort
IP:                       10.98.166.242
Port:                     <unset>  80/TCP
TargetPort:               8080/TCP
NodePort:                 <unset>  31111/TCP
Endpoints:                10.244.1.22:8080,10.244.1.23:8080,10.244.1.24:8080 + 1 more...
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>
[root@k8s-master ~]#

  endpoint

[root@k8s-master ~]# kubectl get endpoints
NAME            ENDPOINTS                                                        AGE
kubernetes      192.168.111.130:6443                                             20h
service-hello   10.244.1.22:8080,10.244.1.23:8080,10.244.1.24:8080 + 1 more...   15h
[root@k8s-master ~]# kubectl describe endpoint service-hello
error: the server doesn't have a resource type "endpoint"
[root@k8s-master ~]# kubectl describe endpoints service-hello
Name:         service-hello
Namespace:    default
Labels:       <none>
Annotations:  endpoints.kubernetes.io/last-change-trigger-time: 2019-04-03T02:18:57Z
Subsets:
  Addresses:          10.244.1.22,10.244.1.23,10.244.1.24,10.244.1.25
  NotReadyAddresses:  <none>
  Ports:
    Name     Port  Protocol
    ----     ----  --------
    <unset>  8080  TCP

Events:
  Type     Reason                  Age                From                 Message
  ----     ------                  ----               ----                 -------
  Warning  FailedToUpdateEndpoint  48m (x2 over 69m)  endpoint-controller  Failed to update endpoint default/service-hello: Operation cannot be fulfilled on endpoints "service-hello": the object has been modified; please apply your changes to the latest version and try again
[root@k8s-master ~]#

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM