1. 程式人生 > >第一章 kubernetes入門

第一章 kubernetes入門

1.1 Kubernetes是什麼

  1. 首先,它是一個全新的基於容器技術的分散式架構領先方案;
  2. 其次,Kubernetes是一個開放的開發平臺;
  3. 最後,Kubernetes是一個完備的分散式系統支撐平臺。

1.2 為什麼要用Kubernetes

使用Kubernetes的理由很多,最根本的一個理由就是:IT從來都是一個由新技術驅動的行業。
使用Kubernetes所帶來的好處:

  1. 首先,最直接的感受就是我們可以“輕裝上陣”地開發複雜系統了;
  2. 其次,使用Kubernetes就是在全面擁抱微服務架構;
  3. 然後,我們的系統可以隨時隨地整體“搬遷”到公有云上;
  4. 最後,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資訊如下:

  1. Node地址:主機的IP地址,或者Node ID。
  2. Node執行狀態:包括Pending、Running、Terminated三種狀態。
  3. Node Condition(條件):描述Running狀態Node的執行條件,目前只有一種條件----Ready。Ready表示Node處於健康狀態,可以接收從Master發來的建立Pod的指令。
  4. Node系統容量:描述Node可用的系統資源,包括CPU、記憶體數量、最大可排程Pod數量等。
  5. 其他: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進行自注冊的啟動引數如下:

  1. --apiservers=: apiserver地址;
  2. --kubeconfig=: 登入apiserver所需憑據/證書的目錄;
  3. --cloud_provider=: 雲服務商地址,用於獲取自身的metadata;
  4. --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中的應用容器共享同一組資源,如下所述:

  1. PID名稱空間:Pod中的不同應用程式可以看到其他應用程式的程序ID;
  2. 網路名稱空間:Pod中的多個容器能夠訪問同一個IP和埠範圍;
  3. IPC名稱空間:Pod中的多個容器能夠使用SystemV IPC或者POSIX訊息佇列進行通訊;
  4. UTS名稱空間:Pod中的多個容器共享一個主機名;
  5. 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種狀態之一:

  1. Pending:Pod定義正確,提交到Master,但其所包含的容器映象還未完成建立。通常Master對Pod進行排程需要一些時間,之後Node對映象進行下載也需要一些時間;
  2. Running:Pod已被分配到某個Node上,且其包含的所有容器映象都已經建立完成,併成功執行起來;
  3. Succeeded:Pod中所有容器都成功結束,並且不會被重啟,這是Pod的一種最終狀態;
  4. 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使用等式類的表示式來進行選擇:

  1. name = redis-slave: 選擇所有包含Label中key="name"且value="redis-slave"的物件;
  2. env != production: 選擇所有包括Label中的key="env"且value不等於"production"的物件。

基於集合的Label Selector使用集合操作的表示式來進行選擇:

  1. name in (redis-master, redis-slave): 選擇所有包含Label中的key="name"且value="redis-master"或"redis-slave"的物件;
  2. 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型別,下面逐一進行說明。

  1. EmptyDir:一個EmptyDir Volume是在Pod分配到Node時建立的。從它的名稱就可以看出,它的初始內容為空。在同一個Pod中所有容器可以讀和寫EmptyDir中的相同檔案。當Pod從Node上移除時,EmptyDir中的資料也會永久刪除。
  2. hostPath:在Pod上掛載宿主機上的檔案或目錄。
  3. gcePersistentDisk:使用這種型別的Volume表示使用谷歌計算引擎(Google Compute Engine,GCE)上永久磁碟(Persistent Disk,PD)上的檔案。與EmptyDir不同,PD上的內容會永久儲存,當Pod被刪除時,PD只是被解除安裝(Unmount),但不會被刪除。需要注意的是,你需要先建立一個永久磁碟(PD)才能使用gcePersistentDisk。
  4. awsElasticBlockStore:與GCE類似,該型別的Volume使用Amazon提供的Amazon Web Service(AWS)的EBS Volume,並可以掛在到Pod中去。需要注意到是,需要首先建立一個EBS Volume才能使用awsElasticBlockStore。
  5. nfs:使用NFS(網路檔案系統)提供的共享目錄掛載到Pod中。在系統中需要一個執行中的NFS系統。
  6. iscsi:使用iSCSI儲存裝置上的目錄掛載到Pod中。
  7. glusterfs:使用開源GlusterFS網路檔案系統的目錄掛載到Pod中。
  8. rbd:使用Linux塊裝置共享儲存(Rados Block Device)掛載到Pod中。
  9. gitRepo:通過掛載一個空目錄,並從GIT庫clone一個git respository以供Pod使用。
  10. secret:一個secret volume用於為Pod提供加密的資訊,你可以將定義在Kubernetes中的secret直接掛載為檔案讓Pod訪問。secret volume是通過tmfs(記憶體檔案系統)實現的,所以這種型別的volume總是不會持久化的。
  11. 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來記錄的資訊包括:

  1. build資訊、release資訊、Docker映象資訊等,例如時間戳、release id號、PR號、映象hash值、docker registry地址等;
  2. 日誌庫、監控庫、分析庫等資源庫的地址資訊;
  3. 程式除錯工具資訊,例如工具名稱、版本號等;
  4. 團隊的聯絡資訊,例如電話號碼、負責人名稱、網址等。ß

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的叢集管理工具集。



作者:來二兩敵敵畏
連結:https://www.jianshu.com/p/63ffc2214788
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。

 

轉載自:https://www.jianshu.com/p/63ffc2214788