Kubernetes基本概念以及術語
kubernetes 是什麼?
- kubernetes又稱k8s,他是一個基於容器技術的分散式架構方案。他是谷歌
Borg
的一個開源版本,基於容器技術用於大規模叢集管理。
它能做那些事?
- 資源管理自動化
- 跨多個數據中心的資源利用率的最大化
- 降低開發成本(負載均衡器、服務治理、服務監控、故障處理模組等都不用開發了)
- 降低運維難度和運維成本(基於配置檔案的UI運維)
- 開放的開發平臺,可使用任意語言通過TCP協議進行互動
- 分散式系統支撐平臺,具有完備的叢集管理能力,包括多層次的安全防火和准入機制、多租戶應用支撐能力、透明的服務註冊和服務發現機制、內建智慧負載均衡器、強大的故障發現和自我修復能力、服務滾動升級和線上擴容能力、可擴充套件的資源排程機制、多粒度的資源配額管理功能
為什麼要使用它?
- 降低複雜系統的開發難度
- 全面擁抱微服務架構
- 具備搬遷至公有云的能力
- 超強的橫向擴容能力
kubernetes的基本概念和術語
kubernetes叢集管理角色有兩種:Master和Node,包含“資源物件”如Node Pod Replication Controller Services
等
管理角色
Master 叢集控制節點,每個叢集中都需要有一個Master節點負責整個叢集的管理和控制(高可用部署建議部署3臺),Master節點上有以下程序:
- kube-apiserver:提供了http rest介面的關鍵服務程序,是叢集控制的入口程序
- kube-controller-manager:所有資源物件的自動化控制中心
- kube-scheduler:Pod排程的程序
- etcd:用於儲存資源物件的資料
Node 除了Master之外的機器為Node節點,主要是叢集工作中的負載節點,當一個node宕機時,其上的工作會被master轉移到其他節點上去,Node之上執行著以下程序:
- kubelet:負責Pod對應容器的建立、啟停等任務,同時與master節點密切協作,實現叢集管理的基本功能
- kube-proxy:實現kubernetes services 的通訊與負載均衡機制的重要元件
- Docker Engine
資源物件
kubernetes裡的資源物件都可以使用yaml
或者json
檔案進行描述定義
Pod
Pod:由一個根容器(Pause)和一組使用者容器組成。Pause容器的狀態代表了整個容器組的狀態,多個業務容器共享Pause容器的IP,共享Pause容器掛接的Volume。 K8s為每個Pod都分配了唯一的IP地址,稱為
Pod IP
,所以在叢集中一個Pod裡的容器與另外主機的Pod容器能夠直接通訊;Pod有兩種型別:普通的Pod以及靜態的Pod,後者不存在於Etcd裡,而是在具體Node上的一個具體檔案中舉例
$ cat > k8s-tomcat-pod.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
name: k8s-tomcat
labels:
name: demo
spec:
containers:
- name: k8s-tomcat
image: alleyz.com:5000/k8s-tomcat-demo:1211
ports:
- containerPort: 8080
resources:
requests:
memory: "128Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
EOF
$ kubectl apply -f k8s-tomcat-pod.yaml
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
k8s-tomcat 1/1 Running 0 20s
Label
Label:一個label就是一個
key=value
的鍵值對,key和value均可自己指定。Label可以附加到各種資源物件上,一個資源物件可以定義任意數量的Label。通途
通過給指定的資源物件捆綁一個或者多個不同的Label來實現多維度的資源分組管理功能,以便於靈活、方便地進行資源分配、排程、配置、部署等管理工作,例如:部署不同的版本到不同的環境中Label Selector:當給資源物件打上標籤以後,就可以通過label selector查詢和篩選這些資源物件。一般有兩種label selector表示式,如
基於等式:
- name=demo 匹配所有具有標籤name=demo的資源物件
- name!=demo 匹配所有不具有name=demo的物件
- 基於集合:
- name in (dev, test) 匹配所有具有name=dev或者name=test的資源物件
- name not in (dev, test) 匹配所有不具備name=dev或者name=test的資源物件
Label Selector的使用場景:
- kube-controller程序通過資源物件RC上定義的Label Selector來篩選要監控的Pod副本數量,從而實現Pod副本數量始終符合預期設定的全自動控制流程
- kube-proxy 程序通過service的label selector來選擇對應的pod,自動建立起每個service到pod的請求轉發路由表,從而實現service的智慧均衡負載機制
- 通過對某些Node定義特定的label,並且在pod定義檔案中使用NodeSelector進行定向排程
Replication Controller
簡稱RC,用於宣告某個Pod的副本數量在任意時刻的預期值,它主要包括下邊幾個部分:
- pod期待的副本數
- 用於篩選目標pod的label selector
- 當pod數量小於預期數量時,用於建立新pod的模板(template)
Replica Set: 新版本的RC,與Replication Controller的唯一區別是:ReplicaSet支援集合labelselector,而RC只支援等式的labelSelector,當然在後續的版本里,deployment已經取代了RC(後文詳述)
特性:
- 通過定義RC實現Pod的建立過程以及副本數量的自動控制
- RC裡包括完整的Pod定義模板
- RC通過Label Selector機制實現對Pod副本的自動控制
- 通過改變RC裡的Pod副本數量,可以實現Pod的擴容或者縮容功能
- 通過改變RC裡Pod模板中的映象版本可以實現Pod的滾動升級功能
舉例:
$ cat > k8s-tomcat-demo-rc.yaml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
name: k8s-tomcat-rc
spec:
replicas: 3
selector:
demo: k8s-tomcat
template:
metadata:
labels:
demo: k8s-tomcat
name: demo
spec:
containers:
- name: tomcat-demo
image: alleyz.com:5000/k8s-tomcat-demo:1211
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
EOF
$ kubectl apply -f k8s-tomcat-demo-rc.yaml
$ kubectl get rc
NAME DESIRED CURRENT READY AGE
k8s-tomcat-rc 3 3 3 12m
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
k8s-tomcat 1/1 Running 0 15m
k8s-tomcat-rc-klnvv 1/1 Running 0 12m
k8s-tomcat-rc-zb1r0 1/1 Running 0 12m
Deployment
Deployment可以認為是RC的升級版,最大的區別是我們可以隨時知道POD容器的部署進度,典型的使用場景有:
- 建立一個Deployment物件來生成RC並完成Pod副本的建立過程
- 檢查Deployment的狀態看部署動作是否完成
- 更新deployment以建立新的Pod(升級)
- 如果當前Deployment不穩定則回滾到早先版本
- 暫停Deployment以便於一次修改多個PodTemplateSpec的配置項,之後再進行釋出
- 擴充套件Deployment以應對高負載
- 檢視Deployment的狀態,以此作為釋出是否成功的指標
- 清理不在需要的舊版本RC
例子
$ cat > k8s-tomcat-demo-deploy.yaml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: k8s-tomcat-dep
spec:
replicas: 4
selector:
matchLabels:
demo: k8s-tomcat
template:
metadata:
labels:
demo: k8s-tomcat
name: demo
spec:
containers:
- name: tomcat-demo
image: alleyz.com:5000/k8s-tomcat-demo:1211
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
EOF
$ kubectl apply -f k8s-tomcat-demo-deploy.yaml
$ kubectl get deploy
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
k8s-tomcat-dep 4 4 4 4 21s
HPA(橫向自動擴容)
Horizontal Pod Autoscaler 即HPA也是一種資源物件,通過追蹤分析RC控制的pod的負載變化情況來確定是否需要針對性地調整目標pod的副本數(增加或者減少),當前主要有以下兩種方式作為Pod負載的度量指標:
- CpuUtilizationPercentage(CPU利用率),取所有副本自身CPU利用率的平均值(需要定義Pod Request值)
- 應用程式自定義的度量指標,比如TPS或者QPS
StatefulSet
用於實現有狀態的叢集管理,可以將它看做Deployment/RC的一個變種,它有以下特性
- StatefulSet裡的每個Pod都有穩定、唯一的網路標識,可以用來發現叢集的其他成員
- StatefulSet控制的Pod副本的啟停順序是受控的,如StatefulSet名叫zk,則第一個叫做zk-0,第二個叫做zk-2,依次類推
- Stateful裡的Pod採用穩定的持久化儲存卷,通過PV/PVC實現
詳細使用待了解過PV/PVC之後進行zookeeper叢集部署時進行說明
Service
service定義了一個服務的訪問入庫地址,前端應用(Pod)通過這個入口地址訪問其背後的一組由Pod副本組成的叢集例項,Service與其後端Pod副本叢集之間則是通過Label Selector來實現無縫對接的。RC的作用實際上是保證service服務能力和服務質量始終處於預期的標準。
一組Pod組成的服,客戶端如何訪問?每個Node上的kube-proxy程序負責把對service的請求轉發的後端某個Pod的例項上,並在內部實現了服務的負載均衡與會話保持機制。但需要注意的是:service不是共用一個IP,而是每個Service分配了一個全域性唯一的虛擬IP地址(ClusterIP),服務呼叫就變成一個TCP網路通訊。
kubernetes的服務發現機制,Service物件都有一個唯一的ClusterIP以及唯一的名字,在老版本中通過自動注入環境變數將service的name與ClusterIP繫結,新版本中採用外掛的方式引入了DNS系統,把service的name作為DNS域名,然後程式就可以通過service的name來建立通訊連線了
外部系統訪問service的關鍵在於3種IP,即:
Node IP node節點的IP地址
,叢集之外的節點訪問叢集內的服務時,必須要通過NodeIP進行訪問Pod IP pod的IP地址
,Docker Engine根據dicker0網橋的IP地址段進行分類的一個虛擬的二層網路的IP地址Cluster IP service的IP地址
,虛擬的IP,它的特點:- 僅作用域service物件,由k8s管理和分配IP地址
- 無法被
ping
- 只能結合service port組成一個具體的通訊埠,單獨的Cluster IP不具備通訊基礎
- 叢集之內 Node/pod/cluster之間的通訊與通常的IP路由與很大的不同
service的cluster IP無法供外部直接使用,但通過指定服務的port繫結在節點的port上,即可進行訪問;當pod位於多個node時,通過nodeip:port訪問到的是nodeip所在node上的pod,如需負載可以考慮使用硬體負載均衡器或者Nginx
例子:只在叢集內進行訪問的service
$ cat > k8s-tomcat-demo-svc.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
name: k8s-tomcat-svc
spec:
ports:
- port: 8080
selector:
demo: k8s-tomcat
EOF
$ kubectl apply -f k8s-tomcat-demo-svc.yaml
$ kubectl get svc
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
k8s-tomcat-svc 10.108.64.29 <none> 8080/TCP 14h
$ kubectl get endpoints
NAME ENDPOINTS AGE
k8s-tomcat-svc 10.36.0.3:8080,10.36.0.4:8080,10.36.0.5:8080 + 4 more... 14h
- 例子:叢集之外可以進行訪問的service
$ cat > k8s-tomcat-demo-svc.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
name: k8s-tomcat-svc
spec:
type: NodePort
ports:
- port: 8080
nodePort: 30001
selector:
demo: k8s-tomcat
EOF
$ kubectl apply -f k8s-tomcat-demo-svc.yaml
$ kubectl get svc
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
k8s-tomcat-svc 10.108.64.29 <nodes> 8080:30001/TCP 15h
Volume
volume是pod中能夠別多個容器訪問的共享目錄;k8s中volume定義在pod上,然後被pod中的多個容器掛載到具體的目錄下;volume與pod的生命週期相同
volume具有豐富的型別:
emptyDir:Pod分配到node時建立的,它的初始內容為空,並且無需指定宿主機上對應的目錄檔案,pod從node上移除時,則emptyDir中的資料永久刪除;emptyDir的用途有:
- 臨時空間
- 長時間任務的checkpoint點
- 一個容器需要從另一個容器獲取資料的目錄
hostPath,在pod上掛載宿主機的檔案或目錄,
主要用途:
- 容器應用生成的檔案(如日誌)需要永久儲存時
- 需要訪問宿主機的檔案時
注意事項:
- 不同的node上具有相同配置的pod可能因為宿主機上的目錄和檔案不同而導致對Volume上目錄和檔案的訪問結果不一致
- hostPath無法納入資源配額管理
NFS,使用NFS網路檔案系統共享儲存資料
其他型別:
ceph
、glusterfs
等
PV (Persistent Volume,持久卷)
PV是k8s叢集中某個網路儲存中對應的一塊儲存,它和Volume的區別:
- PV只能是網路儲存,不屬於任何Node,但可以在每個Node上訪問
- PV獨立於Pod定義
- PV目前支援的型別涵蓋了很多公有云平臺儲存(gce、aws)以及一些網路檔案系統(NFS)
Pod想申請PV時,需要先定義一個PVC(Persistent Volume Claim),然後在Pod的Volume中引用定義好的PVC
Namespace 名稱空間
Namespace通過將叢集中的資源物件分配(邏輯上的)到不同的Namespace中,形成邏輯上的分組不同的專案、使用者組等,便於實現多租戶資源管理。 預設的namespace是
default
宣告資源物件時,在metadata一項中可以指定,如
namespace: dev
Annotation
- 註解與
Label
類似,但具有嚴格的命名規則
參考資料:《kubernetes權威指南》