kubernetes 的基礎和架構
一: kubernetes 概述
1.1 K8S 是什么
K8S 的全程是kubernetes (k8個字母s)
作用:
用於自動部署,擴展和管理 "容器化(containerized) 應用程序" 的開源系統。
可以理解成功k8s 是負責自動化運維管理多個容器化程序(比如Docker)的集群,是一個生態及其豐富的容器編排框架工具
由來:
k8s 由google 的Borg系統(博格系統,google內部使用的大規模容器編排工具) 作為原型,后經過GO語言沿用Borg 的思路重寫並捐獻給CNCF基金會開源。
含義:
詞根源於希臘與的舵手,飛行員。
官網:
GitHub
https://github.com/kubernetes/kubernetes
中文社區:
https://www.kubernetes.org.cn/docs
1.2 為什么使用k8s
1.2.1 傳統后端部署的方法和缺陷
傳統的后端部署方法:
把程序包(包括可執行二進制文件,配置文件等)放到服務器上,接着運行啟動腳本把程序跑起來,同時啟動守護腳本,定期檢查程序運行狀態,必要的話重新拉起程序
缺陷:
當服務的請求量上來,已部署的服務器可能響應不過來。傳統的做法是當請求量,內存,cpu超過閾值做了告警,運維人員立即在部署幾台服務器,部署好服務之后,接入負載均衡來分擔已有的服務的壓力
但是,從監控告警到部署服務,中間需要人力介入!我們就可以使用k8s:自動化運維管理容器化程序,來自動完成服務的部署,更新,卸載,擴容,縮容
1.2.2 裸跑docker的缺陷
裸跑docker的缺陷:
- 單機使用,無法有效集群
- 隨着容器數量的上升,管理成本攀升
- 沒有有效的容災,自愈機制
- 沒有預設編排模板,無法實現快速,大規模容器調度
- 沒有同一的配置管理中心工具
- 沒有容器生命周期的管理工具
- 沒有圖形化運維管理工具
而k8s可以有效的解決這些缺陷
1.3 k8s的特性
k8s提供了容器編排,資源調度,彈性伸縮,部署管理,服務發現等一些列功能
k8s 的特性:
- 彈性伸縮
- 使用命令,UI或者基於cpu使用情況自動快速擴容和縮容應用程序實例,保證業務高峰並發時的高可用性
- 業務低峰時回收資源,以最小成本運行服務
- 自我修復
- 在節點故障時重新啟動失敗的容器,替換和重新部署,保證預期的副本數量
- 殺死健康檢查失敗的容器,並且在未准備好之前不會處理客戶端請求,確保線上服務不中斷
- 服務發現和負載均衡
- k8s為多個容器提供一個統一訪問入口(內部IP地址和一個DNS名稱),並且負載均衡關聯的所有容器,使得用戶無需考慮容器IP問題
- 自動發布(默認滾動發布模式)和回滾
- k8s采用滾動更新策略更新應用,一次更新一個pod,而不是刪除所有pod
- 如果更新過程中出現問題,將回滾更改,確保升級不影響業務
- 集中化配置管理和密鑰管理
- 管理機密數據和應用程序配置,而不需要把敏感數據暴露在鏡像里,提高敏感數據安全性
- 可以將一些常用的配置存儲在k8s中,方便應用程序使用
- 存儲編排,支持外掛存儲並對外掛存儲資源進行編排
- 掛載外部存系統,無論是來自本地存儲,公有雲(如AWS),還是網絡存儲(如NFS,GFS,Ceph)都作為集群資源的一部分使用,極大提高存儲使用靈活性。
- 任務批處理運行:
- 提供一次性任務,定時任務
- 滿足批量數據吹和分析的場景
二: kubernetes集群架構和核心組件
2.1 集群架構
k8s是屬於主從設備模型(Master-Slave架構),即有Master節點負責集群的調度,管理和運維,Slave節點時集群中的運算工作負載節點。
在K8S中,主節點一般稱為Master節點,而從節點則被稱為Worker Node節點,每個Node都會被Master分配一些工作負載。
Master組件可以在集群中的任何計算機上運行,但建議Master節點占據一個獨立的服務器。因為Master是整個集群的大腦,如果Master所在的節點宕機或不可用,那么所有的控制命令都將失效。除了Master節點,在k8s集群中的其他機器都被稱為Worker Node節點,當某個Node宕機時,其上的工作負載會被Master自動轉移到其他節點上。
2.2 Master組件部分
2.2.1 kube-apiserver
- 用於暴露kubernetes API ,任何資源請求或調用操作都是通過 kube-apiserver 提供的接口進行。
- 以HTTP,Restful API 提供接口服務,所有對象資源的增刪改查和監聽操作都交給API Server 處理后再提交給Etcd存儲
- 可以理解為API Server 是k8s的請求入口服務。API Server 負責接收 K8S所有請求(來自 UI界面或者 CLI 命令行工具),然后根據用戶的具體請求,去通知其他組件干活。可以說,API Server 是K8S集群架構的大腦
2.2.2 kube-controller-manager
- 運行管理控制器,是k8s集群中處理常規任務的后台線程,是k8s集群里所有資源對象的自動化控制中心
- 在k8s集群中,一個資源對應一個控制器,而controller manager 就是負責管理這些控制器的
- 由一些列控制器組成,通過API Server 監控整個集群的狀態,並確保集群處於預期的工作狀態,比如當某個Node意外宕機時,Controller Manager 會及時發現並執行自動化修復流程,確保集群始終處於預期工作狀態
- 這些控制器主要包括:
- Node Controller(節點控制器):負責在節點出現故障時發現和響應
- Replication Controller(副本控制器):負責保證集群中一個RC(資源對象Replicaion Contraller)所關聯的Pod副本數始終保持在預設值。可以理解成確保集群中有且僅有N個Pod實例,N是RC中定義的Pod副本數量
- Endpoints Controller(端點控制器):填充端點對象(即連接Services和Pods),負責監聽Service和對應Pod副本的變化。可以理解端點是一個服務暴露出來的訪問點,如果需要訪問一個服務,則必須知道它的endpoint
- Service Accont && Token Controllers(服務賬戶和令牌控制器):為新的命名空間創建默認賬戶和API訪問令牌。
- ResourceQuota Controller (資源配置控制器):確保指定的資源對象在任何時候都不會超量占用系統物理資源
- Namespace Controller(命名空間控制器):管理namespace的生命周期
- Service Controller(服務控制器):屬於K8S集群與外部的雲平台之間的一個接口控制器
2.2.3 Kube-scheduler
-
是負責資源調度的進程,根據調度算法為新創建的Pod選擇一個合適的Node節點。
-
可以理解成 K8S 所有 Node 節點的調度器。當用戶要部署服務時,Scheduler 會根據調度算法選擇最合適的 Node 節點來部署 Pod,先使用預算策略在使用優選策略
- 預算策略(predicate)
- 優選策略(priorities)
2.3 etcd存儲中心
- K8S 的存儲服務
- etcd是分布式鍵值存儲系統,存儲了K8S的關鍵配置和用戶配置。
- K8S中僅API Server 才具備讀寫權限,其他組件必須通過API Server的接口才能讀寫數據
2.4 worker node 組件
2.4.1 Kubelet 組件
監視node 節點上的資源和服務狀態,並匯報給master節點的apiserver;和容器引擎交互,實現容器的生命周期管理
-
Node 節點的監視器,以及與 Master 節點的通訊器。
- Kubelet 是 Master 節點安插在 Node 節點上的 "眼線",它會定時向 API Server 匯報自己Node 節點上運行的服務的狀態,並接受來自 Master 節點的指示采取調整措施。
-
從 Master 節點獲取自已節點上 Pod 的期望狀態(比如運行什么容器、運行的副本數量、網絡或者存儲如何配置等),直接跟容器引擎交互實現容器的生命周期管理,如果自已節點上Pod 的狀態與期望狀態不一致,則調用對應的容器平台接口 (即 docker 的接口)達到這個狀態。
-
管理鏡像和容器的清理工作,保證節點上鏡像不會占滿磁盤空間,退出的容器不會占用太多資源。
2.4.2 Kube-Proxy
- 在每個 Node 節點上實現 Pod 網絡代理,是 Kubernetes Service 資源的載體,負責維護網絡規則和四層負載均衡工作。負責寫入規則至iptables、ipvs實現服務映射訪問的。
- Kube-Proxy本身不是直接給 Pod 提供網絡,Pod 的網絡是由 Kubelet 提供的,Kube-Proxy 實際上維護的是虛擬的 Pod 集群網絡。
- Kube-apiserver 通過監控 Kube-Proxy 進行對 Kubernetes Service 的更新和端點的維護。
- 在 K8S 集群中微服務的負載均衡是由 Kube-proxy 實現的。****Kube-proxy 是 K8S 集群內部的負載均衡器。它是一個分布式代理服務器,在 K8S 的每個節點上都會運行一個 Kube-proxy 組件。
2.4.3 docker 或rocket
- 容器引擎,運行容器,負責本機的容器創建和管理工作。
2.5 kubernetes 的工作過程
- 用戶通過客戶端發送請求給集群的唯一入口 API Server
- API Server 先將用戶的請求信息寫入到 etcd存儲中。再去找Controller manager 創建對應的pod
- Controller Manager通過API Server 去讀取etcd 里的用戶請求信息,根據請求去預設的模板(如什么鏡像,多少實例,健康檢查等),將模板寫入到etcd中,在根據模板創建pod
- Controller Manager 通過 API Server 去找到Scheduler調度pod,為新創建的Pod選擇node節點
- Scheduler 通過API Server 再etcd 存儲中讀取node節點的資源信息,通過預算策略和優選策略,從node節點中挑選最優的,並把pod調度到這個節點運行。
- 預算策略:將所有node節點的剩余資源和pod所需的資源對比,找出符合pod資源需求的node節點
- 優選策略:預算策略篩選后的node節點被交給優選策略。通過cpu負載,內存剩余等因素,找出最合適的node節點。把pod調度到這個節點運行
- Scheduler 確定了調度的節點后,通過API Server 去找到對應node節點上的kublet,由kublet 創建pod
- kublet 不僅和容器引擎交互,實現容器的生命周期管理。還 監控node節點上的資源信息,pod狀態。將這些通過API Server 存儲到etcd中。
- kube-proxy創建網絡規則,制定轉發規則。創建service,把用戶的請求負載均衡轉發到關聯的pod上
三:k8s的資源
- k8s包含多種資源對象:Pod , Label , Service , Replication , Controller 等
- 所有的資源對象通過k8s提供的kubctl 工具進行增刪改查等操作,並將其保存在etcd中持久化存儲
- Kubernets其實是一個高度自動化的資源控制系統,通過跟蹤對比etcd存儲里保存的資源期望狀態與當前環境中的實際資源狀態的差異,來實現自動控制和自動糾錯等高級功能
3.1 Pod
-
Pod是 Kubernetes 創建或部署的最小/最簡單的基本單位,一個 Pod 代表集群上正在運行的一個進程。可以把 Pod 理解成豌豆莢,而同一個Pod內的每個容器是一顆顆豌豆。
-
一個 Pod 由一個或多個容器組成,Pod中容器共享網絡、存儲和計算資源,在同一台 Docker 主機上運行。一個 Pod 里可以運行多個容器,又叫邊車模式(SideCara)模式。而在生產環境中一般都是單個容器或者具有強關聯互補的多個容器組成一個Pod。
-
同一個 Pod 之間的容器可以通過localhost 互相訪問,並且可以掛載Pod內所有的數據卷
不同的 Pod 之間的容器不能用 localhost 訪問,也不能掛載其他 Pod 的數據卷。
3.2 Pod 控制器
-
Pod 控制器是 Pod 啟動的一種模版,用來保證在K8S里啟動的 Pod 始終按照用戶的預期運行(副本數、生命周期、健康狀態檢查等)
-
K8S內提供了眾多的Pod控制器,常用的有以下幾種:
- Deployment:無狀態應用部署。Deployment 的作用是管理和控制Pod和Replicaset, 管控它們運行在用戶期望的狀態中 2
- Replicaset: 確保預期的Pod副本數量。Replicaset的作用就是管理和控制Pod,管控他們好好干活。但是,Replicaset受控於Deployment .
- 可以理解成Deployment 就是總包工頭,主要負責監督底下的工人Pod干活,確保每時每刻有用戶要求數量的Pod在工作,如果一旦發現某個工人Pod不行了,就趕緊新拉一個Pod過來替換它。而ReplicaSet就是總包工頭手下的小包工頭。
- 從K8S使用者角度來看,用戶會直接操作Deployment部署服務,而當Deployment被部署的時候,K8S會自動生成要求的ReplicaSet和Pod。用戶只需要關心Deployment而不操心ReplicaSet 資源對象.
- Replication Controller是ReplicaSet的前身,官方推薦用Deployment取代Replication Controller來部署服務
- Daemonset: 確保所有節點運行同一類Pod,保證每個節點上都有一個此類Pod運行,通常用於實現系統級后台任務
- Statefulset:有狀態應用部署
- Job: 一次性任務。根據用戶的設置,Job管理的Pod把任務成功完成就自動退出了
- Cronjob: 周期性計划性任務
3.3 Label 標簽
- 標簽,是K8S特色的管理方式,便於分類管理資源對象
- Label可以附加到各種資源對象上,例如Node、Pod、Service、 RC等,用於關聯對象、查詢和篩選
- 一個Label是一個key-value 的鍵值對,其中key 與value 由用戶自己指定
- 一個資源對象可以定義任意數量的Label,同一個Label也可以被添加到任意數量的資源對象中,也可以在對象創建后動態添加或者刪除
- 可以通過給指定的資源對象捆綁一個或多個不同的Label,來實現多維度的資源分組管理功能
- 與Label類似的,還有Annotation (注釋)。區別在於有效的標簽值必須為63個字符或更少,並且必須為空或以字母數字字符([a-z0-9A-Z]) 開頭和結尾,中間可以包含橫杠(-)、下划線(_)、點(.)和字母或數字。注釋值則沒有字符長度限制
3.4 Label選擇器(label selector
- 給某個資源對象定義一個Label, 就相當於給它打了一個標簽;隨后可以通過標簽選擇器(Label selector) 查詢和篩選擁有某些Label的資源對象
- 標簽選擇器目前有兩種:基於等值關系(等於、不等於)和基於集合關系(屬於、不屬於、存在)
3.5 service
在K8S的集群里,雖然每個Pod會被分配一個單獨的IP地址,但由於Pod是有生命周期的(它們可以被創建,而且銷毀之后不會再啟動),隨時可能會因為業務的變更,導致這個IP地址也會隨着Pod的銷毀而消失
Service就是用來解決這個問題的核心概念:
- K8S中的Service並不是我們常說的“服務”的含義,而更像是網關層,可以看作一組提供相同服務的Pod的對外訪問接口、流量均衡器
- Service作用於哪些Pod是通過標簽選擇器來定義的:
- 在K8S集群中,Service可以看作一組提供相同服務的Pod的對外訪問接口。客戶端需要訪問的服務就是Service對象。
- 每個Service都有一個固定的虛擬ip (這個ip也被稱為Cluster IP) ,自動並且動態地綁定后端的Pod, 所有的網絡請求直接訪問Service的虛擬ip,Service會自動向后端做轉發。
- 通俗來說就是Service通過標簽選擇器選擇那些關聯了對應label的Pod,把Pod的IP加入到自己的endpoints當中,當service收到請求后根據endpoints里的ip進行轉發
- Service除了提供穩定的對外訪問方式之外,還能起到負載均衡(Load Balance) 的功能,自動把請求流量分布到后端所有的服務上,service可以做到對客戶透明地進行水平擴展(scale),實現service這一功能的關鍵,就是kube-proxy。
- kube -proxy運行在每個節點上,監聽API Server中服務對象的變化,
- 可通過以下三種流量調度模式: userspace (廢棄)、iptables (瀕臨廢棄)、ipvs (推薦,性能最好)來實現網絡的轉發
- Service是K8S服務的核心,屏蔽了服務細節,統一對外暴露服務接口, 真正做到了“微服務”。
- 比如我們的一個服務A,部署了3個副本,也就是3個Pod;對於用戶來說,只需要關注一個Service 的入口就可以,而不需要操心究競應該請求哪一個Pod。
- 優勢非常明顯:一方面外部用戶不需要感知因為Pod. 上服務的意外崩潰、 K8S重新拉起Pod而造成的IP變更,外部用戶也不需要感知因升級、變更服務帶來的Pod替換而造成的IP變化
service 不是通過ip地址找到后端pod,而是通過標簽選擇器關聯具有對應label 的pod,然后把相關pod的ip加入到自己的endpoints(端點)中,service再根據endpoints里的ip進行轉發
3.6 Ingress
- Service主要負責K8S集群內部的網絡拓撲,那么集群外部怎么訪問集群內部呢?這個時候就需要Ingress了
- Ingress是整個K8S集群的接入層,負責集群內外通訊
- Ingress是K8S集群里工作在OSI網絡參考模型下,第7層的應用,對外暴露的接口,典型的訪問方式是http/https
- Service只能進行第四層的流量調度,表現形式是ip+port。Ingress則可以調度不同業務域、不同URL訪問路徑的業務流量。
- 比如:客戶端請求http://www.mynet.com:port ---> Ingress ---> Service ---> Pod
- 具體訪問流程:客戶端使用http/https通過url路徑訪問K8S集群里的Ingress接入層對外暴露的接口,Ingress層收到請求后找到對應是Service,Service根據標簽選擇器篩選查詢label對應的Pod,根據Pod的IP進行轉發獲取相應服務
3.7 Name
- 由於K8S內部,使用“資源”來定義每一種邏輯概念(功能),所以每種“資源”,都應該有自己的“名稱”
- “資源”有api版本(apiversion) 、類別(kind)、元數據(metadata) 、定義清單(spec)、狀態(status) 等配置信息
- “名稱”通常定義在“資源”的“元數據”信息里。在同一個namespace 空間中必須是唯一的
3.8 Namespace
- 隨着項目增多、人員增加、集群規模的擴大,需要一種能夠邏輯上隔離K8S 內各種“資源"的方法,這就是Namespace
- Namespace是為了把一個K8S集群划分為若千個資源不可共享的虛擬集群組而誕生的
- 不同Namespace 內的“資源”名稱可以相同,相同Namespace 內的同種“資源”, “名稱”不能相同
- 合理的使用K8S的Namespace,可以使得集群管理員能夠更好的對交付到K8S里的服務進行分類管理和瀏覽
- K8S里默認存在的Namespace 有: default、 kube-system、 kube-public 等
- 查詢K8S里特定“資源”要帶上相應的Namespace