k8s基本概念及使用

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基本概念及使用

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章