1.1 Kubernetes是什麼
首先,它是一個全新的基於容器技術的分佈式架構領先方案;
其次,Kubernetes是一個開放的開發平臺;
最後,Kubernetes是一個完備的分佈式系統支撐平臺。
1.2 爲什麼要用Kubernetes
使用Kubernetes的理由很多,最根本的一個理由就是:IT從來都是一個由新技術驅動的行業。
使用Kubernetes所帶來的好處:
首先,最直接的感受就是我們可以“輕裝上陣”地開發複雜系統了;
其次,使用Kubernetes就是在全面擁抱微服務架構;
然後,我們的系統可以隨時隨地整體“搬遷”到公有云上;
最後,Kubernetes系統架構具備了超強的橫向擴容能力。
1.3 Kubernetes基本概念和術語
在Kubernetes中,Node、Pod、Replication Controller、Service等概念都可以看作一種資源對象,通過Kubernetes提供的Kubectl工具或者API調用進行操作,並保存在etcd中。
1.3.1 Node(節點)
Node(節點)是Kubernetes集羣中相對於Master而言的工作主機,在較早的版本中也被稱爲Minion。Node可以是一臺物理主機,也可以是一臺虛擬機(VM)。在每個Node上運行用於啓動和管理Pid的服務Kubelet,並能夠被Master管理。在Node上運行的服務進行包括Kubelet、kube-proxy和docker daemon。
Node信息如下:
Node地址:主機的IP地址,或者Node ID。
Node運行狀態:包括Pending、Running、Terminated三種狀態。
Node Condition(條件):描述Running狀態Node的運行條件,目前只有一種條件----Ready。Ready表示Node處於健康狀態,可以接收從Master發來的創建Pod的指令。
Node系統容量:描述Node可用的系統資源,包括CPU、內存數量、最大可調度Pod數量等。
其他:Node的其他信息,包括實例的內核版本號、Kubernetes版本號、Docker版本號、操作系統名稱等。
1. Node的管理
Node通常是物理機、虛擬機或者雲服務商提供的資源,並不是由Kubernetes創建的。我們說Kubernetes創建一個Node,僅僅表示Kubernetes在系統內部創建了一個Node對象,創建後即會對其進行一系列健康檢查,包括是否可以連通、服務是否正確啓動、是否可以創建Pod等。如果檢查未能通過,則該Node將會在集羣中被標記爲不可用(Not Ready)。
2. 使用Node Controller對Node進行管理
Node Controller是Kubernetes Master中的一個組件,用於管理Node對象。它的兩個主要功能包括:集羣範圍內的Node信息同步,以及單個Node的生命週期管理。
Node信息同步可以通過kube-controller-manager的啓動參數--node-sync-period設置同步的時間週期。
3. Node的自注冊
當Kubelet的--register-node參數被設置爲true(默認值即爲true)時,Kubelet會向apiserver註冊自己。這也是Kubernetes推薦的Node管理方式。
Kubelet進行自注冊的啓動參數如下:
--apiservers=: apiserver地址;
--kubeconfig=: 登錄apiserver所需憑據/證書的目錄;
--cloud_provider=: 雲服務商地址,用於獲取自身的metadata;
--register-node=: 設置爲true表示自動註冊到apiserver。
4. 手動管理Node
Kubernetes集羣管理員也可以手工創建和修改Node對象。當需要這樣操作時,先要將Kubelet啓動參數中的--register-node參數的值設置爲false。這樣,在Node上的Kubelet就不會把自己註冊到apiserver中去了。
另外,Kubernetes提供了一種運行時加入或者隔離某些Node的方法。具體操作請參考第四章。
1.3.2 Pod
Pod是Kubernetes的最基本操作單元,包含一個活多個緊密相關的容器,類似於豌豆莢的概念。一個Pod可以被一個容器化的環境看作應用層的“邏輯宿主機”(Logical Host)。一個Pod中的多個容器應用通常是緊耦合的。Pod在Node上被創建、啓動或者銷燬。
爲什麼Kubernetes使用Pod在容器之上再封裝一層呢?一個很重要的原因是,Docker容器之間的通信受到Docker網絡機制的限制。在Docker的世界中,一個容器需要link方式才能訪問另一個容器提供的服務(端口)。大量容器之間的link將是一個非常繁重的工作。通過Pod的概念將多個容器組合在一個虛擬的“主機”內,可以實現容器之間僅需要通過Localhost就能相互通信了。
一個Pod中的應用容器共享同一組資源,如下所述:
PID命名空間:Pod中的不同應用程序可以看到其他應用程序的進程ID;
網絡命名空間:Pod中的多個容器能夠訪問同一個IP和端口範圍;
IPC命名空間:Pod中的多個容器能夠使用SystemV IPC或者POSIX消息隊列進行通信;
UTS命名空間:Pod中的多個容器共享一個主機名;
Volumes(共享存儲卷):Pod中的各個容器可以訪問在Pod級別定義的Volumes。
1. 對Pod的定義
對Pod的定義通過Yaml或Json格式的配置文件來完成。下面的配置文件將定義一個名爲redis-slave的Pod,其中kind爲Pod。在spec中主要包含了Containers(容器)的定義,可以定義多個容器。
apiVersion: v1
kind: Pod
metadata:
name: redis-slave
labels:
name: redis-slave
spec:
containers:
- name: slave
image: kubeguide/guestbook-redis-slave
env:
- name: GET_HOSTS_FROM
value: env
ports:
- containerPort: 6379
Pod的生命週期是通過Replication Controller來管理的。Pod的生命週期過程包括:通過模板進行定義,然後分配到一個Node上運行,在Pod所含容器運行結束後Pod也結束。在整個過程中,Pod處於一下4種狀態之一:
Pending:Pod定義正確,提交到Master,但其所包含的容器鏡像還未完成創建。通常Master對Pod進行調度需要一些時間,之後Node對鏡像進行下載也需要一些時間;
Running:Pod已被分配到某個Node上,且其包含的所有容器鏡像都已經創建完成,併成功運行起來;
Succeeded:Pod中所有容器都成功結束,並且不會被重啓,這是Pod的一種最終狀態;
Failed:Pod中所有容器都結束了,但至少一個容器是以失敗狀態結束的,這也是Pod的一種最終狀態。
Kubernetes爲Pod設計了一套獨特的網絡配置,包括:爲每個Pod分配一個IP地址,使用Pod名作爲容器間通信的主機名等。關於Kubernetes網絡的設計原理將在第2章進行詳細說明。
另外,不建議在Kubernetes的一個Pod內運行相同應用的多個實例。
1.3.3 Label(標籤)
Label是Kubernetes系統中的一個核心概念。Label以key/value鍵值對的形式附加到各種對象上,如Pod、Service、RC、Node等。Label定義了這些對象的可識別屬性,用來對它們進行管理和選擇。Label可以在創建時附加到對象上,也可以在對象創建後通過API進行管理。
在爲對象定義好Label後,其他對象就可以使用Label Selector(選擇器)來定義其作用的對象了。
Label Selector的定義由多個逗號分隔的條件組成。
"labels": {
"key1": "value1",
"key2": "value2"
}
當前有兩種Label Selector:基於等式的(Equality-based)和基於集合的(Set-based),在使用時可以將多個Label進行組合來選擇。
基於等式的Label Selector使用等式類的表達式來進行選擇:
name = redis-slave: 選擇所有包含Label中key="name"且value="redis-slave"的對象;
env != production: 選擇所有包括Label中的key="env"且value不等於"production"的對象。
基於集合的Label Selector使用集合操作的表達式來進行選擇:
name in (redis-master, redis-slave): 選擇所有包含Label中的key="name"且value="redis-master"或"redis-slave"的對象;
name not in (php-frontend): 選擇所有包含Label中的key="name"且value不等於"php-frontend"的對象。
在某些對象需要對另一些對象進行選擇時,可以將多個Label Selector進行組合,使用逗號","進行分隔即可。基於等式的LabelSelector和基於集合的Label Selector可以任意組合。例如:
name=redis-slave,env!=production
name not in (php-frontend),env!=production
1.3.4 Replication Controller(RC)
Replication Controller是Kubernetes系統中的核心概念,用於定義Pod副本的數量。在Master內,Controller Manager進程通過RC的定義來完成Pod的創建、監控、啓停等操作。
根據Replication Controller的定義,Kubernetes能夠確保在任意時刻都能運行用於指定的Pod“副本”(Replica)數量。如果有過多的Pod副本在運行,系統就會停掉一些Pod;如果運行的Pod副本數量太少,系統就會再啓動一些Pod,總之,通過RC的定義,Kubernetes總是保證集羣中運行着用戶期望的副本數量。
同時,Kubernetes會對全部運行的Pod進行監控和管理,如果有需要(例如某個Pod停止運行),就會將Pod重啓命令提交給Node上的某個程序來完成(如Kubelet或Docker)。
可以說,通過對Replication Controller的使用,Kubernetes實現了應用集羣的高可用性,並大大減少了系統管理員在傳統IT環境中需要完成的許多手工運維工作(如主機監控腳本、應用監控腳本、故障恢復腳本等)。
對Replication Controller的定義使用Yaml或Json格式的配置文件來完成。以redis-slave爲例,在配置文件中通過spec.template定義Pod的屬性(這部分定義與Pod的定義是一致的),設置spec.replicas=2來定義Pod副本的數量。
apiVersion: v1
kind: ReplicationController
metadata:
name: redis-slave
labels: redis-slave
name: redis-slave
spec:
replicas: 2
selector:
name: redis-slave
template:
metadata:
labels:
name: redis-slave
spec:
container:
- name: slave
image: kubeguide/guestbook-redis-slave
env:
- name: GET_HOSTS_FROM
value: env
ports:
- containerPort: 6379
通常,Kubernetes集羣中不止一個Node,假設一個集羣有3個Node,根據RC的定義,系統將可能在其中的兩個Node上創建Pod。
1.3.5 Service(服務)
在Kubernetes的世界裏,雖然每個Pod都會被分配一個單獨的IP地址,這個IP地址會隨時Pod的銷燬而消失。這就引出一個問題:如果有一組Pod組成一個集羣來提供服務,那麼如何來訪問它們呢?
Kubernetes的Service(服務)就是用來解決這個問題的核心概念。
一個Service可以看作一組提供相同服務的Pod的對外訪問接口。Service作用於哪些Pod是通過Label Selector來定義的。
1. 對Service的定義
對Service的定義同樣使用Yaml或Json格式的配置文件來完成。以redis-slave服務的定義爲例:
apiVersion: v1
kind: Service
metadata:
name: redis-slave
labels:
name: redis-slave
spec:
ports:
- port: 6379
selector:
name: redis-slave
通過該定義,Kubernetes將會創建一個名爲“redis-slave”的服務,並在6379端口上監聽。spec.selector的定義表示該Service將包含所有具有"name=redis-slave"的Label的Pod。
在Pod正常啓動後,系統將會根據Service的定義創建出與Pod對應的Endpoint(端點)對象,以建立起Service與後端Pod的對應關係。隨着Pod的創建、銷燬,Endpoint對象也將被更新。Endpoint對象主要有Pod的IP地址和容器所需監聽的端口號組成。
2. Pod的IP地址和Service的Cluster IP地址
Pod的IP地址是Docker Daemon根據docker0網橋的IP地址段進行分配的,但Service的Cluster IP地址是Kubernetes系統中的虛擬IP地址,由系統動態分配。Service的Cluster IP地址相對於Pod的IP地址來說相對穩定,Service被創建時即被分配一個IP地址,在銷燬該Service之前,這個IP地址都不會再變化了。而Pod在Kubernetes集羣中生命週期較短,可能被ReplicationContrller銷燬、再次創建,新創建的Pod將會分配一個新的IP地址。
3. 外部訪問Service
由於Service對象在Cluster IP Range池中分配到的IP只能在內部訪問,所以其他Pod都可以無障礙地訪問到它。到如果這個Service作爲前端服務,準備爲集羣外的客戶端提供服務,我們就需要給這個服務提供公共IP了。
Kubernetes支持兩種對外提供服務的Service的type定義:NodePort和LoadBalancer。
1. NodePort
在定義Service時指定spec.type=NodePort,並指定spec.ports.nodePort的值,系統就會在Kubernetes集羣中的每個Node上打開一個主機上的真實端口號。這樣,能夠訪問Node的客戶端都就能通過這個端口號訪問到內部的Service了。
以php-frontend service的定義爲例,nodePort=80,這樣,在每一個啓動了該php-frontend Pod的Node節點上,都會打開80端口。
apiVersion: v1
kind: Service
metadata:
name: frontend
labels:
name: frontend
spec:
type: NodePort
ports:
- port: 80
nodePort: 30001
selector:
name: frontend
2. LoadBalancer
如果雲服務商支持外接負載均衡器,則可以通過spec.type=LoadBalaner定義Service,同時需要制定負載均衡器的IP地址。使用這種類型需要指定Service的nodePort和clusterIP。例如:
apiVersion: v1
kind: Service
metadata: {
"kind" "Service",
"apiVersion": "v1",
"metadata": {
"name": "my-service"
},
"spec": {
"type": "LoadBalaner",
"clusterIP": "10.0.171.239",
"selector": {
"app": "MyApp"
},
"ports": [
{
"protocol": "TCP",
"port": 80,
"targetPort": 9376,
"nodePort": 30061
}
],
},
"status": {
"loadBalancer": {
"ingress": [
{
"ip": "146.148.47.155"
}
]
}
}
}
在這個例子中,status.loadBalancer.ingress.ip設置的146.146.47.155爲雲服務商提供的負載均衡器的IP地址。
之後,對該Service的訪問請求將會通過LoadBalancer轉發到後端Pod上去,負載分發的實現方式則依賴於雲服務上提供的LoadBalancer的實現機制。
1.3.6 Volume(存儲卷)
Volume是Pod中能夠被多個容器訪問的共享目錄。Kubernetes的Volume概念與Docker的Volume比較類似,但不完全相同。Kubernetes中的Volume與Pod生命週期相同,但與容器的生命週期不相關。當容器終止或者重啓時,Volume中的數據也不會丟失。另外,Kubernetes支持多種類型的Volume,並且一個Pod可以同時使用任意多個Volume。
Kubernetes提供了非常豐富的Volume類型,下面逐一進行說明。
EmptyDir:一個EmptyDir Volume是在Pod分配到Node時創建的。從它的名稱就可以看出,它的初始內容爲空。在同一個Pod中所有容器可以讀和寫EmptyDir中的相同文件。當Pod從Node上移除時,EmptyDir中的數據也會永久刪除。
hostPath:在Pod上掛載宿主機上的文件或目錄。
gcePersistentDisk:使用這種類型的Volume表示使用谷歌計算引擎(Google Compute Engine,GCE)上永久磁盤(Persistent Disk,PD)上的文件。與EmptyDir不同,PD上的內容會永久保存,當Pod被刪除時,PD只是被卸載(Unmount),但不會被刪除。需要注意的是,你需要先創建一個永久磁盤(PD)才能使用gcePersistentDisk。
awsElasticBlockStore:與GCE類似,該類型的Volume使用Amazon提供的Amazon Web Service(AWS)的EBS Volume,並可以掛在到Pod中去。需要注意到是,需要首先創建一個EBS Volume才能使用awsElasticBlockStore。
nfs:使用NFS(網絡文件系統)提供的共享目錄掛載到Pod中。在系統中需要一個運行中的NFS系統。
iscsi:使用iSCSI存儲設備上的目錄掛載到Pod中。
glusterfs:使用開源GlusterFS網絡文件系統的目錄掛載到Pod中。
rbd:使用Linux塊設備共享存儲(Rados Block Device)掛載到Pod中。
gitRepo:通過掛載一個空目錄,並從GIT庫clone一個git respository以供Pod使用。
secret:一個secret volume用於爲Pod提供加密的信息,你可以將定義在Kubernetes中的secret直接掛載爲文件讓Pod訪問。secret volume是通過tmfs(內存文件系統)實現的,所以這種類型的volume總是不會持久化的。
persistentVolumeClaim:從PV(PersistentVolume)中申請所需的空間,PV通常是一種網絡存儲,例如GCEPersistentDisk、AWSElasticBlockStore、NFS、iSCSI等。
1.3.7 Namespace(命名空間)
Namespace(命名空間)是Kubernetes系統中的另一個非常重要的概念,通過將系統內部的對象“分配”到不同的Namespace中,形成邏輯上分組的不同項目、小組或用戶組,便於不同的分組在共享使用整個集羣的資源的同時還能被分別管理。
Kubernetes集羣在啓動後,會創建一個名爲“default”的Namespace,通過Kubectl可以查看到。
使用Namespace來組織Kubernetes的各種對象,可以實現對用戶的分組,即“多租戶”管理。對不同的租戶還可以進行單獨的資源配額設置和管理,使得整個集羣的資源配置非常靈活、方便。
1.3.8 Annotation(註解)
Annotation與Label類似,也使用key/value鍵值對的形式進行定義。Label具有嚴格的命名規則,它定義的是Kubernetes對象的元數據(Metadata),並且用於Label Selector。Annotation則是用戶任意定義的“附加”信息,以便於外部工具進行查找。
用Annotation來記錄的信息包括:
build信息、release信息、Docker鏡像信息等,例如時間戳、release id號、PR號、鏡像hash值、docker registry地址等;
日誌庫、監控庫、分析庫等資源庫的地址信息;
程序調試工具信息,例如工具名稱、版本號等;
團隊的聯繫信息,例如電話號碼、負責人名稱、網址等。ß
1.3.9 小結
上述這些組件是Kubernetes系統的核心組件,它們共同構成了Kubernetes系統的框架和計算模型。通過對它們進行靈活組合,用戶就可以快速、方便地對容器集羣進行配置、創建和管理。
除了以上核心組件,在Kubernetes系統中還有許多可供配置的資源對象,例如LimitRange、ResourceQuota。另外,一些系統內部使用的對象Binding、Event等請參考Kubernetes的API文檔。
1.4 Kubernetes總體架構
Kubernetes集羣由兩類節點組成:Master和Node。在Master上運行etcd、API Server、Controller Manager和Scheduler四個組件,其中後三個組件構成了Kubernetes的總控中心,負責對集羣中所有資源進行管理和調度。在每個Node上運行Kubelet、Proxy和Docker Daemon三個組件,負責對本節點上的Pod的生命週期進行管理,以及實現服務代理的功能。另外在所有節點上都可以運行Kubectl命令行工具,它提供了Kubernetes的集羣管理工具集。
本文轉自CSDN-k8s基本概念及使用