正文
kube-apiserver
對(duì)外暴露了Kubernetes API。它是的 Kubernetes 核心控制層。它被設(shè)計(jì)為水平擴(kuò)展,即通過部署更多實(shí)例來橫向擴(kuò)展。API Server 負(fù)責(zé)和 etcd 交互(其他組件不會(huì)直接操作 etcd,只有 API Server 這么做),是整個(gè) kubernetes 集群的數(shù)據(jù)中心,所有的交互都是以 API Server 為核心的。API Server 提供了以下的功能:
整個(gè)集群管理的 API 接口:所有對(duì)集群進(jìn)行的查詢和管理都要通過 API 來進(jìn)行。
集群內(nèi)部各個(gè)模塊之間通信的樞紐:所有模塊之間并不會(huì)互相調(diào)用,而是通過和 API Server 打交道來完成各自的工作。
集群安全控制:API Server 提供的驗(yàn)證和授權(quán)保證了整個(gè)集群的安全。
kube-controller-manager和kube-scheduler的高可用選主機(jī)制
https://blog.csdn.net/weixin_39961559/article/details/81877056
在k8s的組件中,其中有kube-scheduler和kube-controller-manager兩個(gè)組件是有l(wèi)eader選舉的,這個(gè)選舉機(jī)制是k8s對(duì)于這兩個(gè)組件的高可用保障。需要--leader-elect=true啟動(dòng)參數(shù)。即正常情況下kube-scheduler或kube-manager-controller組件的多個(gè)副本只有一個(gè)是處于業(yè)務(wù)邏輯運(yùn)行狀態(tài),其它副本則不斷的嘗試去獲取鎖,去競(jìng)爭(zhēng)leader,直到自己成為leader。如果正在運(yùn)行的leader因某種原因?qū)е庐?dāng)前進(jìn)程退出,或者鎖丟失,則由其它副本去競(jìng)爭(zhēng)新的leader,獲取leader繼而執(zhí)行業(yè)務(wù)邏輯。
在K8s中, 通過創(chuàng)建資源對(duì)象(當(dāng)前的實(shí)現(xiàn)中實(shí)現(xiàn)了 ConfigMap 和 Endpoint 兩種類型的資源)來維護(hù)鎖的狀態(tài)。這兩種資源對(duì)象存在etcd里,也可以說是用etcd來實(shí)現(xiàn)的。
分布式鎖一般實(shí)現(xiàn)原理就是大家先去搶鎖,搶到的成為 leader ,然后 leader 會(huì)定期更新鎖的狀態(tài),聲明自己的活動(dòng)狀態(tài),不讓其他人把鎖搶走。K8s 的資源鎖也類似,搶到鎖的節(jié)點(diǎn)會(huì)將自己的標(biāo)記。設(shè)為鎖的持有者,其他人則需要通過對(duì)比鎖的更新時(shí)間和持有者來判斷自己是否能成為新的 leader ,而 leader 則可以通過更新RenewTime來確保持續(xù)保有該鎖。
主要調(diào)用client-go包中的:
k8s.io/client-go/tools/leaderelection
總共有7個(gè)leader選舉參數(shù):
lock-object-namespace和lock-object-name是鎖對(duì)象的命名空間和名稱。
leader-elect表示該組件運(yùn)行時(shí)是否需要leader選舉(如果集群中運(yùn)行多副本,需要設(shè)置該選項(xiàng)為true,否則每個(gè)副本都將參與實(shí)際工作)。
leader-elect-lease-duration為資源鎖租約觀察時(shí)間,如果其它競(jìng)爭(zhēng)者在該時(shí)間間隔過后發(fā)現(xiàn)leader沒更新獲取鎖時(shí)間,則其它副本可以認(rèn)為leader已經(jīng)掛掉不參與工作了,將重新選舉leader。
leader-elect-renew-deadline leader在該時(shí)間內(nèi)沒有更新則失去leader身份。
leader-elect-retry-period為其它副本獲取鎖的時(shí)間間隔(競(jìng)爭(zhēng)leader)和leader更新間隔。
leader-elect-resource-lock是k8s分布式資源鎖的資源對(duì)象,目前只支持endpoints和configmaps。
etcd
Etcd使用的是raft一致性算法來實(shí)現(xiàn)的,是一款分布式的一致性KV存儲(chǔ),主要用于共享配置和服務(wù)發(fā)現(xiàn)。用于 Kubernetes 的后端存儲(chǔ)。所有集群數(shù)據(jù)都存儲(chǔ)在此處,ETCD在k8s技術(shù)棧的地位,就仿佛數(shù)據(jù)庫(Mysql、Postgresql或oracle等)在Web應(yīng)用中的地位,它存儲(chǔ)了k8s集群中所有的元數(shù)據(jù)(以key-value的方式)。整個(gè)kubernetes系統(tǒng)需要用到etcd用來協(xié)同和存儲(chǔ)配置的有:
網(wǎng)絡(luò)插件flannel、calico等網(wǎng)絡(luò)插件也需要用到etcd存儲(chǔ)網(wǎng)絡(luò)的配置信息
kubernetes本身,包括各種對(duì)象的狀態(tài)和元信息配置
注意:flannel操作etcd使用的是v2的API,而kubernetes操作etcd使用的v3的API,所以在下面我們執(zhí)行etcdctl的時(shí)候需要設(shè)置ETCDCTL_API環(huán)境變量,該變量默認(rèn)值為2。
K8s中所有元數(shù)據(jù)的增刪改查都是由kube-apiserver來執(zhí)行的。ETCD中key值通過觀察可以簡(jiǎn)單得出下面幾個(gè)規(guī)律:
k8s主要把自己的數(shù)據(jù)注冊(cè)在/registry/前綴下面(在ETCD-v3版本后沒有了目錄的概念,只能一切皆前綴了)。通過觀察k8s中deployment、namespace、pod等在ETCD中的表示,可以知道這部分資源的key的格式為/registry/{k8s對(duì)象}/{命名空間}/{具體實(shí)例名}。
kube-controller-manager
kube-controller-manager運(yùn)行控制器,它們是處理集群中常規(guī)任務(wù)的后臺(tái)線程。邏輯上,每個(gè)控制器是一個(gè)單獨(dú)的協(xié)程。用于監(jiān)視 apiserver 暴露的集群狀態(tài),并且不斷地嘗試把當(dāng)前狀態(tài)向集群的目標(biāo)狀態(tài)遷移。為了避免頻繁查詢 apiserver,apiserver 提供了 watch 接口用于監(jiān)視資源的增加刪除和更新,client-go 對(duì)此作了抽象,封裝一層 informer 來表示本地 apiserver 狀態(tài)的 cache 。
參考:
https://blog.csdn.net/huwh_/article/details/75675761
這些控制器包括:
節(jié)點(diǎn)控制器(node-controller): kubelet在啟動(dòng)時(shí)會(huì)通過API Server注冊(cè)自身的節(jié)點(diǎn)信息,并定時(shí)向API Server匯報(bào)狀態(tài)信息,API Server接收到信息后將信息更新到etcd中。Node Controller通過API Server實(shí)時(shí)獲取Node的相關(guān)信息,實(shí)現(xiàn)管理和監(jiān)控集群中的各個(gè)Node節(jié)點(diǎn)的相關(guān)控制功能。
副本控制器(Replication Controller): 負(fù)責(zé)維護(hù)系統(tǒng)中每個(gè)副本控制器對(duì)象正確數(shù)量的 Pod。副本控制器的作用即保證集群中一個(gè)RC所關(guān)聯(lián)的Pod副本數(shù)始終保持預(yù)設(shè)值。只有當(dāng)Pod的重啟策略是Always的時(shí)候(RestartPolicy=Always),副本控制器才會(huì)管理該P(yáng)od的操作(創(chuàng)建、銷毀、重啟等)。
**服務(wù)帳戶和令牌控制器(ServiceAccount Controller ): **為新的命名空間創(chuàng)建默認(rèn)帳戶和 API 訪問令牌。
資源配額管理控制器ResourceQuota Controller:資源配額管理確保指定的資源對(duì)象在任何時(shí)候都不會(huì)超量占用系統(tǒng)物理資源。支持三個(gè)層次的資源配置管理:
容器級(jí)別:對(duì)CPU和Memory進(jìn)行限制;
Pod級(jí)別:對(duì)一個(gè)Pod內(nèi)所有容器的可用資源進(jìn)行限制;
Namespace級(jí)別:包括Pod數(shù)量、Replication Controller數(shù)量、Service數(shù)量、ResourceQuota數(shù)量、Secret數(shù)量、可持有的PV(Persistent Volume)數(shù)量
Namespace Controller:用戶通過API Server可以創(chuàng)建新的Namespace并保存在etcd中,NamespaceController定時(shí)通過API Server讀取這些Namespace信息。如果Namespace被API標(biāo)記為優(yōu)雅刪除(即設(shè)置刪除期限,DeletionTimestamp),則將該Namespace狀態(tài)設(shè)置為“Terminating”,并保存到etcd中。同時(shí)Namespace Controller刪除該Namespace下的ServiceAccount、RC、Pod等資源對(duì)象。
Service Controller:屬于kubernetes集群與外部的云平臺(tái)之間的一個(gè)接口控制器。Service Controller監(jiān)聽Service變化,如果是一個(gè)LoadBalancer類型的Service,則確保外部的云平臺(tái)上對(duì)該Service對(duì)應(yīng)的LoadBalancer實(shí)例被相應(yīng)地創(chuàng)建、刪除及更新路由轉(zhuǎn)發(fā)表。
deployment controller:用來替代以前的ReplicationController來方便的管理應(yīng)用。只需要在 Deployment 中描述您想要的目標(biāo)狀態(tài)是什么,Deployment controller 就會(huì)幫您將 Pod 和ReplicaSet 的實(shí)際狀態(tài)改變到您的目標(biāo)狀態(tài)。您可以定義一個(gè)全新的 Deployment 來創(chuàng)建 ReplicaSet 或者刪除已有的 Deployment 并創(chuàng)建一個(gè)新的來替換。
定義Deployment來創(chuàng)建Pod和ReplicaSet
滾動(dòng)升級(jí)和回滾應(yīng)用
擴(kuò)容和縮容
暫停和運(yùn)行Deployment
statefulset controller:StatefulSet是為了解決有狀態(tài)服務(wù)的問題(對(duì)應(yīng)Deployments和ReplicaSets是為無狀態(tài)服務(wù)而設(shè)計(jì)),其應(yīng)用場(chǎng)景包括:
穩(wěn)定的持久化存儲(chǔ),即Pod重新調(diào)度后還是能訪問到相同的持久化數(shù)據(jù),基于PVC來實(shí)現(xiàn);
穩(wěn)定的網(wǎng)絡(luò)標(biāo)志,即Pod重新調(diào)度后其PodName和HostName不變,基于Headless Service(即沒有Cluster IP的Service)來實(shí)現(xiàn)。StatefulSet中每個(gè)Pod的DNS格式為:
statefulSetPodName-{0..N-1}.serviceName.namespace.svc.cluster.local
有序部署,有序擴(kuò)展,即Pod是有順序的,在部署或者擴(kuò)展的時(shí)候要依據(jù)定義的順序依次依次進(jìn)行(即從0到N-1,在下一個(gè)Pod運(yùn)行之前所有之前的Pod必須都是Running和Ready狀態(tài)),基于init containers來實(shí)現(xiàn);
有序收縮,有序刪除(即從N-1到0)
daemonset controller:DaemonSet確保全部(或者一些)Node 上運(yùn)行一個(gè) Pod 的副本。當(dāng)有 Node 加入集群時(shí),也會(huì)為他們新增一個(gè) Pod 。當(dāng)有 Node 從集群移除時(shí),這些 Pod 也會(huì)被回收。刪除 DaemonSet 將會(huì)刪除它創(chuàng)建的所有 Pod。
Horizontal Pod Autoscaling:僅適用于Deployment和ReplicaSet,在V1版本中僅支持根據(jù)Pod的CPU利用率擴(kuò)所容,在v1alpha版本中,支持根據(jù)內(nèi)存和用戶自定義的metric擴(kuò)縮容。
persistentvolume-binder:定期同步磁盤卷掛載信息,負(fù)責(zé)pv和pvc的綁定。
Endpoints controller:表示了一個(gè)Service對(duì)應(yīng)的所有Pod副本的訪問地址,而EndpointsController負(fù)責(zé)生成和維護(hù)所有Endpoints對(duì)象的控制器。它負(fù)責(zé)監(jiān)聽Service和對(duì)應(yīng)的Pod副本的變化。
如果監(jiān)測(cè)到Service被刪除,則刪除和該Service同名的Endpoints對(duì)象;
如果監(jiān)測(cè)到新的Service被創(chuàng)建或修改,則根據(jù)該Service信息獲得相關(guān)的Pod列表,然后創(chuàng)建或更新Service對(duì)應(yīng)的Endpoints對(duì)象;
如果監(jiān)測(cè)到Pod的事件,則更新它對(duì)應(yīng)的Service的Endpoints對(duì)象。
kube-proxy進(jìn)程獲取每個(gè)Service的Endpoints,實(shí)現(xiàn)Service的負(fù)載均衡功能。
以上只是部分控制器,都是一個(gè)獨(dú)立的協(xié)程,被controller-manager這個(gè)進(jìn)程所管理。
Statefulset和Deployment的區(qū)別
Deployment用于部署無狀態(tài)服務(wù),StatefulSet用來部署有狀態(tài)服務(wù)。
如果部署的應(yīng)用滿足以下一個(gè)或多個(gè)部署需求,則建議使用StatefulSet。
穩(wěn)定的、唯一的網(wǎng)絡(luò)標(biāo)識(shí);
穩(wěn)定的、持久的存儲(chǔ);
有序的、優(yōu)雅的部署和伸縮;
有序的、優(yōu)雅的刪除和停止;
有序的、自動(dòng)的滾動(dòng)更新;
實(shí)現(xiàn)固定的Pod IP方案, 可以優(yōu)先考慮基于StatefulSet
穩(wěn)定的:主要是針對(duì)Pod發(fā)生re-schedule后仍然要保持之前的網(wǎng)絡(luò)標(biāo)識(shí)和持久化存儲(chǔ)。這里所說的網(wǎng)絡(luò)標(biāo)識(shí)包括hostname、集群內(nèi)DNS中該P(yáng)od對(duì)應(yīng)的A Record,并不能保證Pod re-schedule之后IP不變。要想保持Pod IP不變,我們可以借助穩(wěn)定的Pod hostname定制IPAM獲取固定的Pod IP。借助StatefulSet的穩(wěn)定的唯一的網(wǎng)絡(luò)標(biāo)識(shí)特性,我們能比較輕松的實(shí)現(xiàn)Pod的固定IP需求,然后如果使用Deployment,那么將會(huì)復(fù)雜的多,你需要考慮滾動(dòng)更新的過程中的參數(shù)控制(maxSurge、maxUnavailable)、每個(gè)應(yīng)用的IP池預(yù)留造成的IP浪費(fèi)等等問題。
存儲(chǔ):StatefulSet對(duì)應(yīng)Pod的存儲(chǔ)最好通過StorageClass來動(dòng)態(tài)創(chuàng)建:每個(gè)Pod都會(huì)根據(jù)StatefulSet中定義的VolumeClaimTemplate來創(chuàng)建一個(gè)對(duì)應(yīng)的PVC,然后PVS通過StorageClass自動(dòng)創(chuàng)建對(duì)應(yīng)的PV,并掛載給Pod。所以這種方式,需要事先創(chuàng)建好對(duì)應(yīng)的StorageClass。當(dāng)然,你也可以通過預(yù)先由管理員手動(dòng)創(chuàng)建好對(duì)應(yīng)的PV,只要能保證自動(dòng)創(chuàng)建的PVC能和這些PV匹配上。
為了數(shù)據(jù)安全,當(dāng)刪除StatefulSet中Pods或者對(duì)StatefulSet進(jìn)行縮容時(shí),Kubernetes并不會(huì)自動(dòng)刪除StatefulSet對(duì)應(yīng)的PV,而且這些PV默認(rèn)也不能被其他PVC Bound。當(dāng)你確認(rèn)數(shù)據(jù)無用之后再手動(dòng)去刪除PV的時(shí)候,數(shù)據(jù)是否刪除取決于PV的ReclaimPolicy配置。Reclaim Policy支持以下三種:
Retain,意味著需要你手動(dòng)清理;
Recycle,等同于rm -rf /thevolume/*
Delete,默認(rèn)值,依賴于后端的存儲(chǔ)系統(tǒng)自己實(shí)現(xiàn)。
部署和伸縮時(shí)與Deployment的區(qū)別
當(dāng)部署有N個(gè)副本的StatefulSet應(yīng)用時(shí),嚴(yán)格按照index從0到N-1的遞增順序創(chuàng)建,下一個(gè)Pod創(chuàng)建必須是前一個(gè)Pod Ready為前提。
當(dāng)刪除有N個(gè)副本的StatefulSet應(yīng)用時(shí),嚴(yán)格按照index從N-1到0的遞減順序刪除,下一個(gè)Pod刪除必須是前一個(gè)Pod shutdown并完全刪除為前提。
當(dāng)擴(kuò)容StatefulSet應(yīng)用時(shí),每新增一個(gè)Pod必須是前一個(gè)Pod Ready為前提。
當(dāng)縮容StatefulSet應(yīng)用時(shí),沒刪除一個(gè)Pod必須是前一個(gè)Pod shutdown并成功刪除為前提。
kube-scheduler
kube-scheduler監(jiān)視沒有分配節(jié)點(diǎn)的新創(chuàng)建的 Pod,選擇一個(gè)節(jié)點(diǎn)供他們運(yùn)行。調(diào)度節(jié)點(diǎn)分配主要可以分為預(yù)選(Predicates)與優(yōu)選(Priorities)兩個(gè)環(huán)節(jié):
預(yù)選
根據(jù)配置的PredicatesPolicies(默認(rèn)為DefaultProvider中定義的default predicates policies集合)過濾掉那些不滿足這些Policies 的 Node,預(yù)選的輸出作為優(yōu)選的輸入;
優(yōu)選
根據(jù)配置的PrioritiesPolicies(默認(rèn)為DefaultProvider中定義的default priorities policies集合)給預(yù)選后的 Node 進(jìn)行打分排名,得分最高的 Node 即作為最適合的 Node ,該 Pod 就綁定(Bind)到這個(gè) Node 。
注:如果經(jīng)過優(yōu)選將 Node 打分排名后,有多個(gè) Node 并列得分最高,那么kube-scheduler將隨機(jī)從中選擇一個(gè) Node 作為目標(biāo) Node 。
預(yù)選階段算法
NoDiskConflict:評(píng)估是否存在volume沖突。如果該 volume 已經(jīng) mount 過了,k8s可能會(huì)不允許重復(fù)mount(取決于volume類型);
NoVolumeZoneConflict:評(píng)估該節(jié)點(diǎn)上是否存在 Pod 請(qǐng)求的 volume;
PodFitsResources:檢查節(jié)點(diǎn)剩余資源(CPU、內(nèi)存)是否能滿足 Pod 的需求。剩余資源=總?cè)萘?所有 Pod 請(qǐng)求的資源;
MatchNodeSelector:判斷是否滿足 Pod 設(shè)置的 NodeSelector;
CheckNodeMemoryPressure:檢查 Pod 是否可以調(diào)度到存在內(nèi)存壓力的節(jié)點(diǎn);
CheckNodeDiskPressure:檢查 Pod 是否可以調(diào)度到存在硬盤壓力的節(jié)點(diǎn);
優(yōu)選階段算法
依次計(jì)算該 Pod 運(yùn)行在每一個(gè) Node 上的得分。主要算法有:
LeastRequestedPriority:最低請(qǐng)求優(yōu)先級(jí),即 Node 使用率越低,得分越高;
BalancedResourceAllocation:資源平衡分配,即CPU/內(nèi)存配比合適的 Node 得分更高;
SelectorSpreadPriority:盡量將同一 RC/Replica 的多個(gè) Pod 分配到不同的 Node 上;
CalculateAntiAffinityPriority:盡量將同一 Service 下的多個(gè)相同 Label 的 Pod 分配到不同的 Node;
ImageLocalityPriority:Image本地優(yōu)先,Node 上如果已經(jīng)存在 Pod 需要的鏡像,并且鏡像越大,得分越高,從而減少 Pod 拉取鏡像的開銷(時(shí)間);
NodeAffinityPriority:根據(jù)親和性標(biāo)簽進(jìn)行選擇;
默認(rèn)的預(yù)選、優(yōu)選調(diào)度算法遠(yuǎn)不止以上這些??梢酝ㄟ^kube-scheduler的啟動(dòng)參數(shù)中加policy-config-file文件、configmaps(過時(shí))、或者--config指定調(diào)度器用哪些預(yù)選、優(yōu)選算法。
調(diào)度算法的擴(kuò)展
如果kube-scheduler提供的調(diào)度算法不滿足調(diào)度要求,也可以自己開發(fā)擴(kuò)展調(diào)度器,在kube-scheduler啟動(dòng)參數(shù)的policy-config中指定擴(kuò)展調(diào)度器的地址,包括(預(yù)選接口、優(yōu)選接口、優(yōu)先級(jí)搶占,pod和node綁定的Bind接口)。
擴(kuò)展調(diào)度器示例代碼:
https://github.com/liabio/k8s-scheduler-extender-example
由于默認(rèn)調(diào)度器kube-scheduler需要調(diào)用擴(kuò)展調(diào)度程序kube-scheduler-extender,故需要在kube-scheduler的啟動(dòng)參數(shù)里配置擴(kuò)展調(diào)度器的地址。需要在master節(jié)點(diǎn)主機(jī)的/etc/kubernetes目錄下的scheduler.yaml中配置如下內(nèi)容:(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
主要配置是否啟用選舉機(jī)制,以及與API Server交互時(shí)認(rèn)證用的scheduler.conf文件地址,調(diào)度策略選擇用的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
}
里面指定了默認(rèn)調(diào)度器用到的預(yù)選、優(yōu)選算法,以及調(diào)用擴(kuò)展調(diào)度器的service地址,預(yù)選和Bind接口URI。
在/etc/kubernetes/manifests目錄下的kube-scheduler.yaml中啟動(dòng)參數(shù)中加--config=/etc/kubernetes/scheduler.yaml,該文件通過hostPath的方式掛載到容器內(nèi)。
DNS
kube-dns這個(gè)插件是官方推薦安裝的。通過將 Service 注冊(cè)到 DNS 中,k8s 可以為我們提供一種簡(jiǎn)單的服務(wù)注冊(cè)發(fā)現(xiàn)與負(fù)載均衡方式。
kube-dns內(nèi)部通過監(jiān)聽services和endpoints的變更事件將域名和IP對(duì)應(yīng)信息同步到本地緩存。比如服務(wù) a 訪問服務(wù) b,dns解析依賴a容器內(nèi) /etc/resolv.conf 文件的配置
cat/etc/resolv.conf
nameserver 10.233.0.3
search default.svc.cluster.local svc.cluster.localcluster.local
這個(gè)文件中,配置的 DNS Server,一般就是 K8S 中,kubedns 的 Service 的 ClusterIP,這個(gè)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
所有域名的解析,其實(shí)都要經(jīng)過 kubedns 的虛擬IP 10.233.0.3 ,負(fù)載到某一個(gè)kube-dns pod上去解析。如果不能解析,則會(huì)去kube-dns pod所在的主機(jī)上的dns服務(wù)(/etc/resolv.conf)做解析。Kubernetes 啟動(dòng)的容器自動(dòng)將 DNS 服務(wù)器包含在容器內(nèi)的/etc/resolv.conf 中。
域名格式如下:
statefulset一般使用Headless Service,如statefulset名為test,創(chuàng)建2個(gè)pod,則域名為test-0.test.kube-system.svc.cluster.local和test-1.test.kube-system.svc.cluster.local
節(jié)點(diǎn)組件
節(jié)點(diǎn)組件在每個(gè)節(jié)點(diǎn)上運(yùn)行,維護(hù)運(yùn)行的 Pod 并提供Kubernetes 運(yùn)行時(shí)環(huán)境。kubelet一般作為二進(jìn)制運(yùn)行到每個(gè)k8s節(jié)點(diǎn);kube-proxy作為daemonset pod運(yùn)行到每個(gè)k8s節(jié)點(diǎn)。
kubelet
在kubernetes集群中,每個(gè)Node節(jié)點(diǎn)都會(huì)啟動(dòng)kubelet進(jìn)程,用來處理Master節(jié)點(diǎn)下發(fā)到本節(jié)點(diǎn)的任務(wù),管理Pod和其中的容器。kubelet會(huì)在API Server上注冊(cè)節(jié)點(diǎn)信息,定期向Master匯報(bào)節(jié)點(diǎn)資源使用情況,并通過cAdvisor監(jiān)控容器和節(jié)點(diǎn)資源。
pod被調(diào)度到kubelet所在節(jié)點(diǎn)時(shí),調(diào)用CNI(Docker 運(yùn)行或通過 rkt)運(yùn)行 Pod 的容器;
周期性的對(duì)容器生命周期進(jìn)行探測(cè)。(健康檢查readness-隔離、liveness-重啟);
檢查節(jié)點(diǎn)狀態(tài),將節(jié)點(diǎn)的狀態(tài)報(bào)告給kube-apiserver;
容器監(jiān)控所在節(jié)點(diǎn)的資源使用情況,并定時(shí)向 kube-apiserver報(bào)告。知道整個(gè)集群所有節(jié)點(diǎn)的資源情況,對(duì)于 pod 的調(diào)度和正常運(yùn)行至關(guān)重要。kubelet 使用cAdvisor進(jìn)行資源使用率的監(jiān)控。
kube-proxy
https://blog.csdn.net/qq_21816375/article/details/86310844
service是一組pod的服務(wù)抽象,相當(dāng)于一組pod的負(fù)載均衡器,負(fù)責(zé)將請(qǐng)求分發(fā)給對(duì)應(yīng)的pod。service會(huì)提供一個(gè)clusterIP。kube-proxy的作用主要是負(fù)責(zé)service的實(shí)現(xiàn),具體來說,就是實(shí)現(xiàn)了內(nèi)部請(qǐng)求到service和外部的從node port向service的訪問,轉(zhuǎn)發(fā)到后端某個(gè)pod。
舉個(gè)例子,現(xiàn)在有podA,podB,podC和serviceAB。serviceAB是podA,podB的服務(wù)抽象(service)。那么kube-proxy的作用就是可以將某一個(gè)發(fā)往(如podC發(fā)起的請(qǐng)求)向serviceAB的請(qǐng)求,進(jìn)行轉(zhuǎn)發(fā)到service所代表的一個(gè)具體pod(podA或者podB)上。請(qǐng)求的分配方法一般分配是采用輪詢方法進(jìn)行分配。
kube-proxy提供了三種負(fù)載均衡器(LB)模式: 一種是基于用戶態(tài)的模式userspace, 一種是iptables模式,一種是ipvs模式。
userspace:是以socket的方式實(shí)現(xiàn)代理的,userspace這種模式最大的問題是,service的請(qǐng)求會(huì)先從用戶空間進(jìn)入內(nèi)核iptables,然后再回到用戶空間,由kube-proxy完成后端Endpoints的選擇和代理工作,這樣流量從用戶空間進(jìn)出內(nèi)核帶來的性能損耗是不可接受的;
iptables mode:因?yàn)槭褂胕ptable NAT來完成轉(zhuǎn)發(fā),也存在不可忽視的性能損耗。另外,如果集群中存在上萬的Service/Endpoint,那么Node上的iptables rules將會(huì)非常龐大,性能還會(huì)再打折扣;
-
IPVS 模式:工作原理其實(shí)跟 iptables 模式類似,當(dāng)我們創(chuàng)建了前面的Service 之后,kube-proxy首先會(huì)在宿主機(jī)上創(chuàng)建一個(gè)虛擬網(wǎng)卡(kube-ipvs0)并為他分配service VIP作為IP地址,kube-proxy會(huì)通過linux的IPVS模塊為這個(gè)IP設(shè)置三個(gè)虛擬主機(jī)(后端的三個(gè)POD IP),使用輪詢作為L(zhǎng)B策略(ipvsadm命令查看),IPVS模塊會(huì)負(fù)責(zé)請(qǐng)求的轉(zhuǎn)發(fā)。
以下截圖來自于極客時(shí)間張磊的課程描述:
iptables模式和ipvs模式的對(duì)比
服務(wù)暴露方式
http://dockone.io/article/4884
NodePort
NodePort服務(wù)是引導(dǎo)外部流量到你的服務(wù)的最原始方式??梢酝ㄟ^訪問集群內(nèi)的每個(gè)NodeIP:NodePort的方式,訪問到對(duì)應(yīng)Service后端的Endpoint。在所有節(jié)點(diǎn)(虛擬機(jī))上開放一個(gè)特定端口,任何發(fā)送到該端口的流量都被轉(zhuǎn)發(fā)到對(duì)應(yīng)服務(wù)。
NodePort 服務(wù)的 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 服務(wù)主要有兩點(diǎn)區(qū)別于普通的“ClusterIP”服務(wù)。第一,它的類型是“NodePort”。有一個(gè)額外的端口,稱為 nodePort,它指定節(jié)點(diǎn)上開放的端口值。如果你不指定這個(gè)端口,系統(tǒng)將選擇一個(gè)隨機(jī)端口。
何時(shí)使用這種方式?
這種方法有許多缺點(diǎn):
每個(gè)端口只能是一種服務(wù)
端口范圍只能是 30000-32767
如果節(jié)點(diǎn)/VM 的 IP 地址發(fā)生變化,你需要能處理這種情況。
基于以上原因,我不建議在生產(chǎn)環(huán)境上用這種方式暴露服務(wù)。如果你運(yùn)行的服務(wù)不要求一直可用,或者對(duì)成本比較敏感,你可以使用這種方法。這樣的應(yīng)用的最佳例子是 demo 應(yīng)用,或者某些臨時(shí)應(yīng)用。
hostNetwork
這種方式在創(chuàng)建pod時(shí)的yaml中spec.hostNetwork: true指定走主機(jī)網(wǎng)絡(luò),這種方式pod使用的端口必須是宿主機(jī)上沒有被占用的端口。外部可以直接通過pod所在宿主機(jī)IP:Pod端口訪問。
LoadBalancer
這也是用來對(duì)集群外暴露服務(wù)的,不同的是這需要云服務(wù)商的支持,比如亞馬遜等。這個(gè)方式的最大缺點(diǎn)是每一個(gè)用 LoadBalancer 暴露的服務(wù)都會(huì)有它自己的 IP 地址,每個(gè)用到的 LoadBalancer 都需要付費(fèi),這是非常昂貴的。
Ingress
ingress配置一種路由轉(zhuǎn)發(fā)規(guī)則,ingress controller會(huì)根據(jù)ingress中的規(guī)則,生成路由轉(zhuǎn)發(fā)配置。如nginx-ingress-controller,控制循環(huán)會(huì)檢測(cè)ingress對(duì)象的添加,通過其規(guī)則和service、pod信息生成nginx的配置,通過nginx實(shí)現(xiàn)對(duì)外服務(wù)和負(fù)載均衡。
pod創(chuàng)建流程
1、客戶端提交創(chuàng)建請(qǐng)求,通過API Server的Restful API,或者用kubectl命令行工具。支持的數(shù)據(jù)類型包括JSON和YAML。
2、API Server處理用戶請(qǐng)求,存儲(chǔ)Pod數(shù)據(jù)到etcd。
3、kube-scheduler通過API Server查看未綁定的Pod。嘗試為Pod分配主機(jī)。
4、kube-scheduler通過預(yù)選算法過濾掉不符合要求的主機(jī)。比如Pod指定了所需要的資源量,那么可用資源比Pod需要的資源量少的主機(jī)會(huì)被過濾掉,端口被占用的也被過濾掉;
5、kube-scheduler通過優(yōu)選算法給主機(jī)打分,對(duì)預(yù)選篩選出的符合要求的主機(jī)進(jìn)行打分,在主機(jī)打分階段,調(diào)度器會(huì)考慮一些整體優(yōu)化策略,比如把一個(gè)deployment類型的pod分布到不同的主機(jī)上,使得資源均衡;或者將兩個(gè)親和的服務(wù)分配到同一個(gè)主機(jī)上。
6、選擇主機(jī):選擇打分最高的主機(jī),進(jìn)行binding(調(diào)用apiserver將pod和node綁定)操作,結(jié)果存儲(chǔ)到etcd中。
7、kubelet監(jiān)聽Api Server,根據(jù)調(diào)度結(jié)果執(zhí)行Pod創(chuàng)建操作:綁定成功后,scheduler會(huì)調(diào)用API Server的API在etcd中創(chuàng)建一個(gè)bound pod對(duì)象,描述在一個(gè)工作節(jié)點(diǎn)上綁定運(yùn)行的所有pod信息。運(yùn)行在每個(gè)工作節(jié)點(diǎn)上的kubelet也會(huì)定期與etcd同步bound pod信息,一旦發(fā)現(xiàn)應(yīng)該在該工作節(jié)點(diǎn)上運(yùn)行的bound pod對(duì)象沒有更新,則調(diào)用Docker API創(chuàng)建并啟動(dòng)pod內(nèi)的容器。
8、kubelet調(diào)用CNI(Docker 運(yùn)行或通過 rkt)運(yùn)行 Pod 的容器。并周期性的對(duì)容器生命周期進(jìn)行探測(cè)。(健康檢查readness-隔離、liveness-重啟)
各組件基本都是通過API Server提供的list-watch API進(jìn)行監(jiān)聽資源對(duì)象變化,進(jìn)行自己的控制循環(huán),這些核心功能都被封裝到了client-go包中。我們可以根據(jù)自己的需求,通過CRD編寫controller、operator進(jìn)行自己的控制循環(huán)邏輯、運(yùn)維自動(dòng)化部署,很輕松的擴(kuò)展k8s能力。
作者簡(jiǎn)潔
作者:小碗湯,一位熱愛、認(rèn)真寫作的小伙,目前維護(hù)原創(chuàng)公眾號(hào):『我的小碗湯』,專注于寫go語言、docker、kubernetes、java等開發(fā)、運(yùn)維知識(shí)等提升硬實(shí)力的文章,期待你的關(guān)注。轉(zhuǎn)載說明:務(wù)必注明來源(注明:來源于公眾號(hào):我的小碗湯,作者:小碗湯)