1 K8S概述
1.1 K8S的簡述
- Kubernetes(簡稱“K8s”或者“Kube”)是Google開源的、用於管理雲平臺中多個主機上的容器化應用的——容器集羣管理系統。
- 其設計目標是在主機集羣之間提供一個能夠自動化部署、可拓展、應用容器可運營的平臺。
- Kubernetes通常結合docker容器工具工作,並且整合多個運行着docker容器的主機集羣
- Kubernetes不僅僅支持Docker,還支持Rocket,這是另一種容器技術。
- Kubernetes與Google。
- K8s最初由 Google 的工程師開發和設計
- Google 是最早研發 Linux 容器技術的企業之一,曾公開分享介紹 Google 雲服務背後的技術- 如何將一切都運行於容器之中。
- Google 每週會啓用超過 20 億個容器全都由內部平臺 Borg 支撐。
- Borg 是 Kubernetes 的前身,多年來開發 Borg 的經驗教訓成了影響 Kubernetes 中許多技術的主要因素。
1.2 K8S的誕生背景:爲什麼需要Kubernetes?
-
K8s的目標是讓部署容器化的應用能夠簡單、且高效;它提供了應用部署、規劃、更新、維護的一種機制。
-
K8s是一種可自動實施Linux 容器操作的開源平臺。
- 它可以幫助用戶省去應用容器化過程的許多手動部署和擴展操作。
- 也就是說,您可以將運行 Linux 容器的多組主機聚集在一起,藉助 Kubernetes 編排功能,您可以構建跨多個容器的應用服務、跨集羣調度、擴展這些容器,並長期持續管理這些容器的健康狀況。
-
有了 Kubernetes,您便可切實採取一些措施來提高 IT 安全性。
-
而且這些集羣可跨公共雲、私有云或混合雲部署主機。
-
Kubernetes 還需要與聯網、存儲、安全性、遙測和其他服務整合,以提供全面的容器基礎架構。
-
綜上,對於要求快速擴展的雲原生應用而言,Kubernetes 是理想的託管平臺。
- K8s於 2015 年發佈,並迅速成爲事實上的容器編排標準。
1.2 K8S的特點
- 自動推出和回滾
K8s 會逐步推出應用程序或其配置的更改,同時監控應用程序運行狀況以確保它不會同時終止所有實例。
如果出現問題,K8s 會爲您回滾(rollback)更改。
利用不斷增長的部署解決方案生態系統。
- 服務發現和負載均衡
使用不熟悉的服務發現機制無需修改應用程序。
K8s 爲 Pod 提供了自己的 IP 地址和一組 Pod 的單個 DNS 名稱,並且可以在它們之間進行負載平衡。
- 存儲編排
自動掛載選擇的存儲系統,無論是本地存儲、公共雲提供商,還是網絡存儲系統。
- 機密和配置管理
部署和更新機密和應用程序配置,而無需重建映像,也無需在堆棧配置中公開機密。
- 自動打包
根據資源需求和其他限制自動放置容器,而且不犧牲可用性。混合使用關鍵工作負載和盡力而爲的工作負載,以提高利用率並節省更多資源。
- 批量執行
除了服務之外,K8s 還可以管理批處理和 CI(Continuously Integration) 工作負載,並根據需要替換出現故障的容器。
- IPv4/IPv6 雙網絡協議棧
將 IPv4 和 IPv6 地址分配給 Pod 和服務。
- 水平壓縮擴展
使用簡單的命令、UI 或根據 CPU 使用情況自動壓縮擴展應用程序。
- 自我恢復
重新啓動失敗的容器,在節點故障時替換和重新安排容器,終止不響應用戶定義健康檢查的容器,並且在它們準備好提供服務之前不向客戶端通告它們。
- 專爲可擴展性而設計
在不更改上游源代碼的情況下爲 K8s 集羣添加功能。
2 K8s的工作原理
2.1 運行架構
k8s 集羣的架構,從左到右,分爲兩部分:
- 第1部分: Master 節點(對應圖中的 Control Plane) / 整個集羣的大腦
- Master 節點,一般包括四個組件:apiserver、scheduler、controller-manager、etcd
- Apiserver
- 上知天文下知地理,上連其餘組件,下接ETCD,提供各類 api 處理、鑑權,和 Node 上的 kubelet 通信等
- 只有 apiserver 會連接 ETCD。
- Controller-manager:控制各類 controller,通過控制器模式,致力於將當前狀態轉變爲期望狀態。
- Scheduler:調度,打分,分配資源。
- Etcd:整個集羣的數據庫,也可不部署在 Master 節點,單獨搭建。
- 第2部分是 Node 節點 / 運行 Master 節點調度的應用
- Node 節點,一般也包括3個組件,docker,kube-proxy,kubelet
- Kube-proxy:主要負責網絡的打通,早期利用 iptables,現在使用 ipvs技術。
- Docker:具體跑應用的載體。
- Kubelet:agent,負責管理容器的生命週期。
2.2 k8s 組件調用流程
我們看下
kubectl create deployment redis-deployment --image=redis
下發之後,k8s 集羣做了什麼。
-
首先 controller-manager, scheduler, kubelet 都會和 apiserver 開始進行 List-Watch 模型
- List 是拿到當前的狀態,Watch 是拿到期望狀態
- k8s 集羣會致力於將當前狀態達到達期望狀態。
-
kubectl 下發命令到 apiserver,鑑權處理之後將創建信息存入 etcd,Deployment 的實現是使用 ReplicaSet 控制器,當 controller-manager 提前拿到當前的狀態(pod=0),接着接收到期望狀態,需要創建 ReplicaSet(pod=1),就會開始創建 Pod。
-
然後 scheduler 會進行調度,確認 Pod 被創建在哪一臺 Node 上。
-
之後 Node 上的 kubelet 真正拉起一個 docker。
這些步驟中,apiserver 的作用是不言而喻的,所以說上接其餘組件,下連 ETCD;但是 apiserver 是可以橫向擴容的,然後通過負載均衡,倒是 ETCD 在 k8s 架構中成了瓶頸。
最開始看這架構的時候,會想着爲啥 apiserver, scheduler, controller-manager 不合成一個組件?
其實在 Google Borg 中,borgmaster 就是這樣的,功能也是這些功能;
但是合在了一起,最後他們也發現集羣大了之後 borgmaster 會有些性能上的問題,包括 kubelet 的心跳就是很大一塊;
所以, k8s 從一開始開源,設計中有三個組件也是更好維護代碼吧。
2.3 核心概念
Container
- 一般地,1個container只應包含1個應用進程
因爲:這樣能更好的監控container的狀態
可理解爲k8s監控的最小粒度是container
Pod
-
在Kubernetes中,基本調度單元稱爲“pod”
- 通過該種抽象類別可以把更高級別的抽象內容增加到容器化組件
-
pod = 0..N 個 container
- 一個Pod可承載一個或者多個相關的容器
- 假定 Container 爲 Docker Container,則:
- 1個 Pod 中可以包含多個 Docker,這些 Docker 都會被調度到同一臺 Node 上
- 這些 Docker 共享 NetWork Namespace,且可聲明共享同一個 Volume 來共享磁盤空間
- 這樣的好處是什麼呢?
- 其實在真實的世界中,很多應用是有部署在同一臺機器的需求的
- 比如, Redis 日誌採集插件要採集日誌,肯定需要和 Redis 部署在同一臺機器(Pod)上才能讀到 Redis 的日誌
- 假定 Container 爲 Docker Container,則:
- 但一般地,1個pod中只會有1個container
- 1個pod下的container只會部署在1個物理節點
- 一個Pod可承載一個或者多個相關的容器
意味着:1個pod下不同container的交互可通過localhost進行
- 同一pod存在多個container的情況一般是:
- 1個爲主container
- 其他container負責做一些輔助任務
- 如:log agent負責上報主container生產的日誌
ReplicationController & ReplicaSet
- 背景
- 如果我們都人工的去解決遇到的pod重啓問題,似乎又回到了以前刀耕火種的時代了是吧?
- 如果有一種工具能夠來幫助我們管理Pod就好了,Pod不夠了自動幫我新增一個,Pod掛了自動幫我在合適的節點上重新啓動一個Pod。
- 這樣是不是遇到重啓問題我們都不需要手動去解決了。
- 幸運的是,Kubernetes就爲我們提供了這樣的資源對象:
- Replication Controller:用來部署、升級Pod
- Replica Set:下一代的Replication Controller
- Deployment:可以更加方便的管理Pod和ReplicaSet
ReplicationController
- Replication Controller簡稱RC,RC是Kubernetes系統中的核心概念之一
- 簡單來說,RC可以保證在任意時間運行Pod的副本數量,能夠保證Pod總是可用的。
- 如果實際Pod數量比指定的多,那就結束掉多餘的;如果實際數量比指定的少就新啓動一些Pod,當Pod失敗、被刪除或者掛掉後,RC都會去自動創建新的Pod來保證副本數量。
- 所以,即使只有一個Pod,我們也應該使用RC來管理我們的Pod。
- 可以說,通過ReplicationController,Kubernetes實現了集羣的高可用性。
ReplicaSet
-
Replication Set簡稱RS.
- 隨着Kubernetes的高速發展,官方已經推薦我們使用RS和Deployment來代替RC了
- 實際上RS和RC的功能基本一致,目前唯一的一個區別:
- RC只支持基於等式的selector(env=dev或environment!=qa)
- 但RS還支持基於集合的selector(version in (v1.0, v2.0))
- 這對複雜的運維管理就非常方便了。
-
kubectl命令行工具中關於RC的大部分命令同樣適用於我們的RS資源對象。
- 不過我們也很少會去單獨使用RS
- 它主要被Deployment這個更加高層的資源對象使用,除非用戶需要自定義升級功能或根本不需要升級Pod
-
在一般情況下,我們推薦使用 Deployment 而不直接使用 Replica Set。
小結
這裏總結下關於RC/RS的一些特性和作用:
- 大部分情況下,我們可以通過定義一個RC實現的Pod的創建和副本數量的控制
- RC中包含一個完整的Pod定義模塊(不包含apiversion和kind)
- RC是通過label selector機制來實現對Pod副本的控制的
- 通過改變RC裏面的Pod副本數量,可以實現Pod的擴縮容功能
- 通過改變RC裏面的Pod模板中鏡像版本,可以實現Pod的滾動升級功能(但是不支持一鍵回滾,需要用相同的方法去修改鏡像地址)
Deployment
定義與作用
- Deployment是k8s中用來管理髮布的控制器,在開發的過程中使用非常頻繁
- 聲明式API
- 最終一致性
- 水平觸發
- 資源對象
- Deployment 可定義多副本個 Pod,從而爲應用提供遷移能力
- 若單純使用 Pod,實際上當應用被調度到某臺機器之後,機器宕機應用也無法自動遷移,但是使用 Deployment,則:
- 會調用 ReplicaSet(一種控制器) 來保證當前集羣中的應用副本數和指定的一致。
- Deployment 定義一組pod的期望數量,controller會維持Pod的數量和期望的一致
- 其實deployment是通過管理 ReplicaSet 的狀態來間接管理pod
- 配置Pod的發佈方式,controller會按照給定的策略去更新pod資源,以此來保證更新過程中可用的pod數量和不可用的pod數量都在限定範圍內。(MaxUnavailable以及MaxSurge字段)
- 支持回滾操作,可記錄多個前置版本(數量可通過配置設置revisionHistoryLimit)
主要字段說明
Deployment 狀態遷移
Deployment 控制流程
- 同樣也是通過inform對事件進行list&watch,並調用相關的handle進行處理
- 其中關於Check Paused是對有關於一些Debugger模式下可以只同步replicas而不發佈版本。
- 而對應RS控制器則更加簡單了,只對pod數量進行控制管理就行。
- 相對而言,deployment更加複雜一些,同時能做的事情也更多。
Labels
- 所有k8s的資源都可以被打上標
比如pod、node
-
label爲kv形式,且一個資源上能打上多種標籤。
-
打完標籤後,可通過label selectors來篩選出打上特定label的資源。
-
【案例】
可將不同版本的pod通過label打上不同的標籤: version=v1/v2/…;
然後,利用label selectors就可將version=v1的pod全部取出。
- 【案例】label還可標示node資源
舉個例子:
如果某些node底層是gpu,
可將這些nodes搭上label:gpu=true,
然後,在部署需要在gpu上運行的服務時,便可通過label selectors來指定特定的pods需要部署在gpu=true的nodes上。
namespace
1個pod可能會有多個label,但只會有1個namespace。
namespace的概念可類比於【租戶】,通過namespace可指定到不同的租戶的命名空間。
但需注意的是,namespace僅僅是個邏輯上的分類,在你指定了某個namespace後,你只能看到對應namespace的pod,但並不作其他方面的區分。
比如,不同namespace的pod仍可以互相調用。
service
service可理解爲就是psm,提供了一類服務的入口。
本質上,replicaSets等負責管理pod,而service負責pod與內外部服務的交互。
在service定義時需要定義port和targetport,port代表service正在監聽的端口,收到請求後,service會將請求轉發到對應pod的targetport上。
3 實踐應用
3.1 ReplicationController & ReplicaSet & Deployment
3.1.1 ReplicationController
- 【案例】
Step0 開始演示
# 啓動k8s
minikube start
# 刪除上次的pod
kubectl delete -f pod_nginx.yml
Step1 查看rc_nginx.yml
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx
spec:
replicas: 3
selector:
app: nginx
template:
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
上面的YAML文件:
- kind:ReplicationController
- spec.replicas: 指定Pod副本數量,默認爲1
- spec.selector: RC通過該屬性來篩選要控制的Pod
- spec.template: 這裏就是我們之前的Pod的定義的模塊,但是不需要apiVersion和kind了
- spec.template.metadata.labels: 注意這裏的Pod的labels要和spec.selector相同,這樣RC就可以來控制當前這個Pod了。
# 創建1個ReplicationController的橫向擴展
kubectl create -f rc_nginx.yml
kubectl get pods
kubectl get rc
Step2 刪除一個看看效果如何
通過delete pods 的方式刪除一個容器,立刻就有一個新的容器起來
kubectl get rc
kubectl get pod
kubectl delete pods nginx-h2qbt
kubectl get pods
kubectl get rc
Step3 scale 水平擴展的數量
kubectl scale rc nginx --replicas=2
kubectl get rc
kubectl scale rc nginx --replicas=5
kubectl get pods -o wide
3.1.2 ReplicaSet
- 查看rc_nginx.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: nginx
labels:
tier: frontend
spec:
replicas: 3
selector:
matchLabels:
tier: frontend
template:
metadata:
name: nginx
labels:
tier: frontend
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
#刪除ReplicationController創建的pod
kubectl delete -f rc_nginx.yml
#創建一個ReplicationController的橫向擴展
kubectl create -f rs_nginx.yml
kubectl get pods -o wide
kubectl get pods
kubectl get rc
- 刪除一個看看效果如何
通過delete pods 的方式刪除一個容器,立刻就有一個新的容器起來
kubectl get rs
kubectl get pod
kubectl delete pods nginx-h2qbt
kubectl get pods
kubectl get rs
- scale 水平擴展的數量
kubectl scale rs nginx --replicas=2
kubectl get rs
kubectl scale rs nginx --replicas=5
kubectl get pods -o wide
通過這次瞭解了pod的擴展,ReplicaSet和ReplicationController的方式,基本上可以拋棄上次的直接pod的方式創建app了。下次說說Deployment。
Y 推薦資源
- Kubernetes
- CNCF (Cloud Native Computing Fundation) : CNCF projects are the foundation of cloud native computing
- 《深入剖析Kubernetes》張磊,CNCF TOC 成員,at 阿里巴巴
- 《Kubernetes 權威指南》第五版
- 《Large-scale cluster management at Google with Borg》