史上最全k8s必學必會知識梳理 作者簡潔

正文

kube-apiserver

對外暴露了Kubernetes API。它是的 Kubernetes 核心控制層。它被設計爲水平擴展,即通過部署更多實例來橫向擴展。API Server 負責和 etcd 交互(其他組件不會直接操作 etcd,只有 API Server 這麼做),是整個 kubernetes 集羣的數據中心,所有的交互都是以 API Server 爲核心的。API Server 提供了以下的功能:

  • 整個集羣管理的 API 接口:所有對集羣進行的查詢和管理都要通過 API 來進行。

  • 集羣內部各個模塊之間通信的樞紐:所有模塊之間並不會互相調用,而是通過和 API Server 打交道來完成各自的工作。

  • 集羣安全控制:API Server 提供的驗證和授權保證了整個集羣的安全。

kube-controller-manager和kube-scheduler的高可用選主機制

https://blog.csdn.net/weixin_39961559/article/details/81877056

在k8s的組件中,其中有kube-scheduler和kube-controller-manager兩個組件是有leader選舉的,這個選舉機制是k8s對於這兩個組件的高可用保障。需要--leader-elect=true啓動參數。即正常情況下kube-scheduler或kube-manager-controller組件的多個副本只有一個是處於業務邏輯運行狀態,其它副本則不斷的嘗試去獲取鎖,去競爭leader,直到自己成爲leader。如果正在運行的leader因某種原因導致當前進程退出,或者鎖丟失,則由其它副本去競爭新的leader,獲取leader繼而執行業務邏輯。

在K8s中, 通過創建資源對象(當前的實現中實現了 ConfigMap 和 Endpoint 兩種類型的資源)來維護鎖的狀態。這兩種資源對象存在etcd裏,也可以說是用etcd來實現的。

分佈式鎖一般實現原理就是大家先去搶鎖,搶到的成爲 leader ,然後 leader 會定期更新鎖的狀態,聲明自己的活動狀態,不讓其他人把鎖搶走。K8s 的資源鎖也類似,搶到鎖的節點會將自己的標記。設爲鎖的持有者,其他人則需要通過對比鎖的更新時間和持有者來判斷自己是否能成爲新的 leader ,而 leader 則可以通過更新RenewTime來確保持續保有該鎖。

主要調用client-go包中的:

k8s.io/client-go/tools/leaderelection

總共有7個leader選舉參數:

  • lock-object-namespace和lock-object-name是鎖對象的命名空間和名稱。

  • leader-elect表示該組件運行時是否需要leader選舉(如果集羣中運行多副本,需要設置該選項爲true,否則每個副本都將參與實際工作)。

  • leader-elect-lease-duration爲資源鎖租約觀察時間,如果其它競爭者在該時間間隔過後發現leader沒更新獲取鎖時間,則其它副本可以認爲leader已經掛掉不參與工作了,將重新選舉leader。

  • leader-elect-renew-deadline leader在該時間內沒有更新則失去leader身份。

  • leader-elect-retry-period爲其它副本獲取鎖的時間間隔(競爭leader)和leader更新間隔。

  • leader-elect-resource-lock是k8s分佈式資源鎖的資源對象,目前只支持endpoints和configmaps。

etcd

Etcd使用的是raft一致性算法來實現的,是一款分佈式的一致性KV存儲,主要用於共享配置和服務發現。用於 Kubernetes 的後端存儲。所有集羣數據都存儲在此處,ETCD在k8s技術棧的地位,就彷彿數據庫(Mysql、Postgresql或oracle等)在Web應用中的地位,它存儲了k8s集羣中所有的元數據(以key-value的方式)。整個kubernetes系統需要用到etcd用來協同和存儲配置的有:

  • 網絡插件flannel、calico等網絡插件也需要用到etcd存儲網絡的配置信息

  • kubernetes本身,包括各種對象的狀態和元信息配置

注意:flannel操作etcd使用的是v2的API,而kubernetes操作etcd使用的v3的API,所以在下面我們執行etcdctl的時候需要設置ETCDCTL_API環境變量,該變量默認值爲2。

K8s中所有元數據的增刪改查都是由kube-apiserver來執行的。ETCD中key值通過觀察可以簡單得出下面幾個規律:

k8s主要把自己的數據註冊在/registry/前綴下面(在ETCD-v3版本後沒有了目錄的概念,只能一切皆前綴了)。通過觀察k8s中deployment、namespace、pod等在ETCD中的表示,可以知道這部分資源的key的格式爲/registry/{k8s對象}/{命名空間}/{具體實例名}。

kube-controller-manager

kube-controller-manager運行控制器,它們是處理集羣中常規任務的後臺線程。邏輯上,每個控制器是一個單獨的協程。用於監視 apiserver 暴露的集羣狀態,並且不斷地嘗試把當前狀態向集羣的目標狀態遷移。爲了避免頻繁查詢 apiserver,apiserver 提供了 watch 接口用於監視資源的增加刪除和更新,client-go 對此作了抽象,封裝一層 informer 來表示本地 apiserver 狀態的 cache 。

參考:

https://blog.csdn.net/huwh_/article/details/75675761

這些控制器包括:

節點控制器(node-controller): kubelet在啓動時會通過API Server註冊自身的節點信息,並定時向API Server彙報狀態信息,API Server接收到信息後將信息更新到etcd中。Node Controller通過API Server實時獲取Node的相關信息,實現管理和監控集羣中的各個Node節點的相關控制功能。

副本控制器(Replication Controller): 負責維護系統中每個副本控制器對象正確數量的 Pod。副本控制器的作用即保證集羣中一個RC所關聯的Pod副本數始終保持預設值。只有當Pod的重啓策略是Always的時候(RestartPolicy=Always),副本控制器纔會管理該Pod的操作(創建、銷燬、重啓等)。

**服務帳戶和令牌控制器(ServiceAccount Controller ): **爲新的命名空間創建默認帳戶和 API 訪問令牌。

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

  • 容器級別:對CPU和Memory進行限制;

  • Pod級別:對一個Pod內所有容器的可用資源進行限制;

  • Namespace級別:包括Pod數量、Replication Controller數量、Service數量、ResourceQuota數量、Secret數量、可持有的PV(Persistent Volume)數量

Namespace Controller:用戶通過API Server可以創建新的Namespace並保存在etcd中,NamespaceController定時通過API Server讀取這些Namespace信息。如果Namespace被API標記爲優雅刪除(即設置刪除期限,DeletionTimestamp),則將該Namespace狀態設置爲“Terminating”,並保存到etcd中。同時Namespace Controller刪除該Namespace下的ServiceAccount、RC、Pod等資源對象。

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

deployment controller:用來替代以前的ReplicationController來方便的管理應用。只需要在 Deployment 中描述您想要的目標狀態是什麼,Deployment controller 就會幫您將 Pod 和ReplicaSet 的實際狀態改變到您的目標狀態。您可以定義一個全新的 Deployment 來創建 ReplicaSet 或者刪除已有的 Deployment 並創建一個新的來替換。

  • 定義Deployment來創建Pod和ReplicaSet

  • 滾動升級和回滾應用

  • 擴容和縮容

  • 暫停和運行Deployment

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

  • 穩定的持久化存儲,即Pod重新調度後還是能訪問到相同的持久化數據,基於PVC來實現;

  • 穩定的網絡標誌,即Pod重新調度後其PodName和HostName不變,基於Headless Service(即沒有Cluster IP的Service)來實現。StatefulSet中每個Pod的DNS格式爲:

statefulSetPodName-{0..N-1}.serviceName.namespace.svc.cluster.local
  • 有序部署,有序擴展,即Pod是有順序的,在部署或者擴展的時候要依據定義的順序依次依次進行(即從0到N-1,在下一個Pod運行之前所有之前的Pod必須都是Running和Ready狀態),基於init containers來實現;

  • 有序收縮,有序刪除(即從N-1到0)

daemonset controller:DaemonSet確保全部(或者一些)Node 上運行一個 Pod 的副本。當有 Node 加入集羣時,也會爲他們新增一個 Pod 。當有 Node 從集羣移除時,這些 Pod 也會被回收。刪除 DaemonSet 將會刪除它創建的所有 Pod。

Horizontal Pod Autoscaling:僅適用於Deployment和ReplicaSet,在V1版本中僅支持根據Pod的CPU利用率擴所容,在v1alpha版本中,支持根據內存和用戶自定義的metric擴縮容。

persistentvolume-binder:定期同步磁盤卷掛載信息,負責pv和pvc的綁定。

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

  • 如果監測到Service被刪除,則刪除和該Service同名的Endpoints對象;

  • 如果監測到新的Service被創建或修改,則根據該Service信息獲得相關的Pod列表,然後創建或更新Service對應的Endpoints對象;

  • 如果監測到Pod的事件,則更新它對應的Service的Endpoints對象。

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

以上只是部分控制器,都是一個獨立的協程,被controller-manager這個進程所管理。

Statefulset和Deployment的區別

Deployment用於部署無狀態服務,StatefulSet用來部署有狀態服務。

如果部署的應用滿足以下一個或多個部署需求,則建議使用StatefulSet。

  • 穩定的、唯一的網絡標識;

  • 穩定的、持久的存儲;

  • 有序的、優雅的部署和伸縮;

  • 有序的、優雅的刪除和停止;

  • 有序的、自動的滾動更新;

  • 實現固定的Pod IP方案, 可以優先考慮基於StatefulSet

穩定的:主要是針對Pod發生re-schedule後仍然要保持之前的網絡標識和持久化存儲。這裏所說的網絡標識包括hostname、集羣內DNS中該Pod對應的A Record,並不能保證Pod re-schedule之後IP不變。要想保持Pod IP不變,我們可以藉助穩定的Pod hostname定製IPAM獲取固定的Pod IP。藉助StatefulSet的穩定的唯一的網絡標識特性,我們能比較輕鬆的實現Pod的固定IP需求,然後如果使用Deployment,那麼將會複雜的多,你需要考慮滾動更新的過程中的參數控制(maxSurge、maxUnavailable)、每個應用的IP池預留造成的IP浪費等等問題。

存儲:StatefulSet對應Pod的存儲最好通過StorageClass來動態創建:每個Pod都會根據StatefulSet中定義的VolumeClaimTemplate來創建一個對應的PVC,然後PVS通過StorageClass自動創建對應的PV,並掛載給Pod。所以這種方式,需要事先創建好對應的StorageClass。當然,你也可以通過預先由管理員手動創建好對應的PV,只要能保證自動創建的PVC能和這些PV匹配上。

爲了數據安全,當刪除StatefulSet中Pods或者對StatefulSet進行縮容時,Kubernetes並不會自動刪除StatefulSet對應的PV,而且這些PV默認也不能被其他PVC Bound。當你確認數據無用之後再手動去刪除PV的時候,數據是否刪除取決於PV的ReclaimPolicy配置。Reclaim Policy支持以下三種:

  • Retain,意味着需要你手動清理;

  • Recycle,等同於rm -rf /thevolume/*

  • Delete,默認值,依賴於後端的存儲系統自己實現。

部署和伸縮時與Deployment的區別

  • 當部署有N個副本的StatefulSet應用時,嚴格按照index從0到N-1的遞增順序創建,下一個Pod創建必須是前一個Pod Ready爲前提。

  • 當刪除有N個副本的StatefulSet應用時,嚴格按照index從N-1到0的遞減順序刪除,下一個Pod刪除必須是前一個Pod shutdown並完全刪除爲前提。

  • 當擴容StatefulSet應用時,每新增一個Pod必須是前一個Pod Ready爲前提。

  • 當縮容StatefulSet應用時,沒刪除一個Pod必須是前一個Pod shutdown併成功刪除爲前提。

kube-scheduler

kube-scheduler監視沒有分配節點的新創建的 Pod,選擇一個節點供他們運行。調度節點分配主要可以分爲預選(Predicates)與優選(Priorities)兩個環節:

預選

根據配置的PredicatesPolicies(默認爲DefaultProvider中定義的default predicates policies集合)過濾掉那些不滿足這些Policies 的 Node,預選的輸出作爲優選的輸入;

優選

根據配置的PrioritiesPolicies(默認爲DefaultProvider中定義的default priorities policies集合)給預選後的 Node 進行打分排名,得分最高的 Node 即作爲最適合的 Node ,該 Pod 就綁定(Bind)到這個 Node 。

注:如果經過優選將 Node 打分排名後,有多個 Node 並列得分最高,那麼kube-scheduler將隨機從中選擇一個 Node 作爲目標 Node 。

預選階段算法

NoDiskConflict:評估是否存在volume衝突。如果該 volume 已經 mount 過了,k8s可能會不允許重複mount(取決於volume類型);

NoVolumeZoneConflict:評估該節點上是否存在 Pod 請求的 volume;

PodFitsResources:檢查節點剩餘資源(CPU、內存)是否能滿足 Pod 的需求。剩餘資源=總容量-所有 Pod 請求的資源;

MatchNodeSelector:判斷是否滿足 Pod 設置的 NodeSelector;

CheckNodeMemoryPressure:檢查 Pod 是否可以調度到存在內存壓力的節點;

CheckNodeDiskPressure:檢查 Pod 是否可以調度到存在硬盤壓力的節點;

優選階段算法

依次計算該 Pod 運行在每一個 Node 上的得分。主要算法有:

LeastRequestedPriority:最低請求優先級,即 Node 使用率越低,得分越高;

BalancedResourceAllocation:資源平衡分配,即CPU/內存配比合適的 Node 得分更高;

SelectorSpreadPriority:儘量將同一 RC/Replica 的多個 Pod 分配到不同的 Node 上;

CalculateAntiAffinityPriority:儘量將同一 Service 下的多個相同 Label 的 Pod 分配到不同的 Node;

ImageLocalityPriority:Image本地優先,Node 上如果已經存在 Pod 需要的鏡像,並且鏡像越大,得分越高,從而減少 Pod 拉取鏡像的開銷(時間);

NodeAffinityPriority:根據親和性標籤進行選擇;

默認的預選、優選調度算法遠不止以上這些。可以通過kube-scheduler的啓動參數中加policy-config-file文件、configmaps(過時)、或者--config指定調度器用哪些預選、優選算法。


調度算法的擴展

如果kube-scheduler提供的調度算法不滿足調度要求,也可以自己開發擴展調度器,在kube-scheduler啓動參數的policy-config中指定擴展調度器的地址,包括(預選接口、優選接口、優先級搶佔,pod和node綁定的Bind接口)。

擴展調度器示例代碼:

https://github.com/liabio/k8s-scheduler-extender-example

由於默認調度器kube-scheduler需要調用擴展調度程序kube-scheduler-extender,故需要在kube-scheduler的啓動參數裏配置擴展調度器的地址。需要在master節點主機的/etc/kubernetes目錄下的scheduler.yaml中配置如下內容:(static pod方式部署的kube-scheduler不能用configmaps的方式掛載配置文件)


apiVersion: kubescheduler.config.k8s.io/v1alpha1
kind: KubeSchedulerConfiguration
algorithmSource:
  policy:
    file:
      path: /etc/kubernetes/scheduler-policy.json
clientConnection:
  kubeconfig: /etc/kubernetes/scheduler.conf
leaderElection:
  leaderElect: true

主要配置是否啓用選舉機制,以及與API Server交互時認證用的scheduler.conf文件地址,調度策略選擇用的scheduler-policy.json:


{
  "kind": "Policy",
  "apiVersion": "v1",
  "predicates": [
    {
      "name": "NoVolumeZoneConflict"
    },
    {
      "name": "MatchInterPodAffinity"
    },
    {
      "name": "NoDiskConflict"
    },
    {
      "name": "GeneralPredicates"
    },
    {
      "name": "PodToleratesNodeTaints"
    },
    {
      "name": "CheckVolumeBinding"
    }
  ],
  "priorities": [
    {
      "name": "SelectorSpreadPriority",
      "weight": 1
    },
    {
      "name": "InterPodAffinityPriority",
      "weight": 1
    },
    {
      "name": "LeastRequestedPriority",
      "weight": 1
    },
    {
      "name": "NodeAffinityPriority",
      "weight": 1
    },
    {
      "name": "BalancedResourceAllocation",
      "weight": 1
    },
    {
      "name": "NodePreferAvoidPodsPriority",
      "weight": 10000
    },
    {
      "name": "TaintTolerationPriority",
      "weight": 1
    }
  ],
  "extenders": [
    {
      "urlPrefix": "http://kube-scheduler-extender:80/scheduler",
      "filterVerb": "predicates/middleware_predicate",
      "prioritizeVerb": "",
      "preemptVerb": "",
      "bindVerb": "bind",
      "weight": 1,
      "enableHttps": false,
      "nodeCacheCapable": false
    }
  ],
  "hardPodAffinitySymmetricWeight": 10,
  "alwaysCheckAllPredicates": false
}

裏面指定了默認調度器用到的預選、優選算法,以及調用擴展調度器的service地址,預選和Bind接口URI。

在/etc/kubernetes/manifests目錄下的kube-scheduler.yaml中啓動參數中加--config=/etc/kubernetes/scheduler.yaml,該文件通過hostPath的方式掛載到容器內。

DNS

kube-dns這個插件是官方推薦安裝的。通過將 Service 註冊到 DNS 中,k8s 可以爲我們提供一種簡單的服務註冊發現與負載均衡方式。

kube-dns內部通過監聽services和endpoints的變更事件將域名和IP對應信息同步到本地緩存。比如服務 a 訪問服務 b,dns解析依賴a容器內 /etc/resolv.conf 文件的配置

cat/etc/resolv.conf

nameserver 10.233.0.3
search default.svc.cluster.local svc.cluster.localcluster.local

這個文件中,配置的 DNS Server,一般就是 K8S 中,kubedns 的 Service 的 ClusterIP,這個IP是虛擬IP,無法ping。

[root@node4 user1]#kubectl get svc -n kube-system
NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)         AGE
kube-dns              ClusterIP   10.233.0.3             53/UDP,53/TCP   270d
kubernetes-dashboard  ClusterIP   10.233.22.223          443/TCP         124d

所有域名的解析,其實都要經過 kubedns 的虛擬IP 10.233.0.3 ,負載到某一個kube-dns pod上去解析。如果不能解析,則會去kube-dns pod所在的主機上的dns服務(/etc/resolv.conf)做解析。Kubernetes 啓動的容器自動將 DNS 服務器包含在容器內的/etc/resolv.conf 中。

域名格式如下:

statefulset一般使用Headless Service,如statefulset名爲test,創建2個pod,則域名爲test-0.test.kube-system.svc.cluster.local和test-1.test.kube-system.svc.cluster.local

節點組件

節點組件在每個節點上運行,維護運行的 Pod 並提供Kubernetes 運行時環境。kubelet一般作爲二進制運行到每個k8s節點;kube-proxy作爲daemonset pod運行到每個k8s節點。

kubelet

在kubernetes集羣中,每個Node節點都會啓動kubelet進程,用來處理Master節點下發到本節點的任務,管理Pod和其中的容器。kubelet會在API Server上註冊節點信息,定期向Master彙報節點資源使用情況,並通過cAdvisor監控容器和節點資源。

  • pod被調度到kubelet所在節點時,調用CNI(Docker 運行或通過 rkt)運行 Pod 的容器;

  • 週期性的對容器生命週期進行探測。(健康檢查readness-隔離、liveness-重啓);

  • 檢查節點狀態,將節點的狀態報告給kube-apiserver;

  • 容器監控所在節點的資源使用情況,並定時向 kube-apiserver報告。知道整個集羣所有節點的資源情況,對於 pod 的調度和正常運行至關重要。kubelet 使用cAdvisor進行資源使用率的監控。

kube-proxy

https://blog.csdn.net/qq_21816375/article/details/86310844

service是一組pod的服務抽象,相當於一組pod的負載均衡器,負責將請求分發給對應的pod。service會提供一個clusterIP。kube-proxy的作用主要是負責service的實現,具體來說,就是實現了內部請求到service和外部的從node port向service的訪問,轉發到後端某個pod。

舉個例子,現在有podA,podB,podC和serviceAB。serviceAB是podA,podB的服務抽象(service)。那麼kube-proxy的作用就是可以將某一個發往(如podC發起的請求)向serviceAB的請求,進行轉發到service所代表的一個具體pod(podA或者podB)上。請求的分配方法一般分配是採用輪詢方法進行分配。

kube-proxy提供了三種負載均衡器(LB)模式: 一種是基於用戶態的模式userspace, 一種是iptables模式,一種是ipvs模式。

  • userspace:是以socket的方式實現代理的,userspace這種模式最大的問題是,service的請求會先從用戶空間進入內核iptables,然後再回到用戶空間,由kube-proxy完成後端Endpoints的選擇和代理工作,這樣流量從用戶空間進出內核帶來的性能損耗是不可接受的;

  • iptables mode:因爲使用iptable NAT來完成轉發,也存在不可忽視的性能損耗。另外,如果集羣中存在上萬的Service/Endpoint,那麼Node上的iptables rules將會非常龐大,性能還會再打折扣;

  • IPVS 模式:工作原理其實跟 iptables 模式類似,當我們創建了前面的Service 之後,kube-proxy首先會在宿主機上創建一個虛擬網卡(kube-ipvs0)併爲他分配service VIP作爲IP地址,kube-proxy會通過linux的IPVS模塊爲這個IP設置三個虛擬主機(後端的三個POD IP),使用輪詢作爲LB策略(ipvsadm命令查看),IPVS模塊會負責請求的轉發。

    以下截圖來自於極客時間張磊的課程描述:

    iptables模式和ipvs模式的對比

服務暴露方式

http://dockone.io/article/4884

NodePort

NodePort服務是引導外部流量到你的服務的最原始方式。可以通過訪問集羣內的每個NodeIP:NodePort的方式,訪問到對應Service後端的Endpoint。在所有節點(虛擬機)上開放一個特定端口,任何發送到該端口的流量都被轉發到對應服務。

NodePort 服務的 YAML 文件類似如下:

apiVersion: v1
kind: Service
metadata:  
  name: my-nodeport-service
selector:    
  app: my-app
spec:
  type: NodePort
  ports:  
  - name: http
    port: 80
    targetPort: 80
    nodePort: 30036
    protocol: TCP

NodePort 服務主要有兩點區別於普通的“ClusterIP”服務。第一,它的類型是“NodePort”。有一個額外的端口,稱爲 nodePort,它指定節點上開放的端口值。如果你不指定這個端口,系統將選擇一個隨機端口。

何時使用這種方式?

這種方法有許多缺點:

  • 每個端口只能是一種服務

  • 端口範圍只能是 30000-32767

  • 如果節點/VM 的 IP 地址發生變化,你需要能處理這種情況。

基於以上原因,我不建議在生產環境上用這種方式暴露服務。如果你運行的服務不要求一直可用,或者對成本比較敏感,你可以使用這種方法。這樣的應用的最佳例子是 demo 應用,或者某些臨時應用。

hostNetwork

這種方式在創建pod時的yaml中spec.hostNetwork: true指定走主機網絡,這種方式pod使用的端口必須是宿主機上沒有被佔用的端口。外部可以直接通過pod所在宿主機IP:Pod端口訪問。

LoadBalancer

這也是用來對集羣外暴露服務的,不同的是這需要雲服務商的支持,比如亞馬遜等。這個方式的最大缺點是每一個用 LoadBalancer 暴露的服務都會有它自己的 IP 地址,每個用到的 LoadBalancer 都需要付費,這是非常昂貴的。

Ingress

ingress配置一種路由轉發規則,ingress controller會根據ingress中的規則,生成路由轉發配置。如nginx-ingress-controller,控制循環會檢測ingress對象的添加,通過其規則和service、pod信息生成nginx的配置,通過nginx實現對外服務和負載均衡。

pod創建流程

1、客戶端提交創建請求,通過API Server的Restful API,或者用kubectl命令行工具。支持的數據類型包括JSON和YAML。

2、API Server處理用戶請求,存儲Pod數據到etcd。

3、kube-scheduler通過API Server查看未綁定的Pod。嘗試爲Pod分配主機。

4、kube-scheduler通過預選算法過濾掉不符合要求的主機。比如Pod指定了所需要的資源量,那麼可用資源比Pod需要的資源量少的主機會被過濾掉,端口被佔用的也被過濾掉;

5、kube-scheduler通過優選算法給主機打分,對預選篩選出的符合要求的主機進行打分,在主機打分階段,調度器會考慮一些整體優化策略,比如把一個deployment類型的pod分佈到不同的主機上,使得資源均衡;或者將兩個親和的服務分配到同一個主機上。

6、選擇主機:選擇打分最高的主機,進行binding(調用apiserver將pod和node綁定)操作,結果存儲到etcd中。

7、kubelet監聽Api Server,根據調度結果執行Pod創建操作:綁定成功後,scheduler會調用API Server的API在etcd中創建一個bound pod對象,描述在一個工作節點上綁定運行的所有pod信息。運行在每個工作節點上的kubelet也會定期與etcd同步bound pod信息,一旦發現應該在該工作節點上運行的bound pod對象沒有更新,則調用Docker API創建並啓動pod內的容器。

8、kubelet調用CNI(Docker 運行或通過 rkt)運行 Pod 的容器。並週期性的對容器生命週期進行探測。(健康檢查readness-隔離、liveness-重啓)


各組件基本都是通過API Server提供的list-watch API進行監聽資源對象變化,進行自己的控制循環,這些核心功能都被封裝到了client-go包中。我們可以根據自己的需求,通過CRD編寫controller、operator進行自己的控制循環邏輯、運維自動化部署,很輕鬆的擴展k8s能力。


作者簡潔

作者:小碗湯,一位熱愛、認真寫作的小夥,目前維護原創公衆號:『我的小碗湯』,專注於寫go語言、docker、kubernetes、java等開發、運維知識等提升硬實力的文章,期待你的關注。轉載說明:務必註明來源(註明:來源於公衆號:我的小碗湯,作者:小碗湯)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章