Kubernetes(二)架構及資源關系簡單總結


Kubernetes架構

先引用一下官方的架構圖:

對於本文來說,我覺得這張圖有點復雜了,但是我又懶得自己畫了,就用這張吧。Kubernetes是一個集群,和傳統的集群相似,它也是有一個主節點和若干個工作節點組成。在Kubernetes中,主節點稱之為Master節點,就是上圖中左邊的大框;工作節點稱之為Node(原來稱為Minion,一個意思)。下面我們分別介紹Master節點和Node節點。

Master

Master節點上面主要由四個模塊組成:APIServer、scheduler、controller manager、etcd。

  1. APIServer。APIServer的功能如其名,負責對外提供RESTful的Kubernetes API服務,它是系統管理指令的統一入口,任何對資源進行增刪改查的操作都要交給APIServer處理后再提交給etcd。如架構圖中所示,kubectl(Kubernetes提供的客戶端工具,該工具內部就是對Kubernetes API的調用)是直接和APIServer交互的。

  2. schedule。scheduler的職責很明確,就是負責調度pod(Kubernetes中最小的調度單元,后面馬上就會介紹)到合適的Node上。如果把scheduler看成一個黑匣子,那么它的輸入是pod和由多個Node組成的列表,輸出是Pod和一個Node的綁定(bind),即將這個pod部署到這個Node上。雖然scheduler的職責很簡單,但我們知道調度系統的智能程度對於整個集群是非常重要的。Kubernetes目前提供了調度算法,但是同樣也保留了接口,用戶可以根據自己的需求定義自己的調度算法。

  3. controller manager。如果說APIServer做的是“前台”的工作的話,那controller manager就是負責“后台”的。后面我們馬上會介紹到資源,每個資源一般都對應有一個控制器,而controller manager就是負責管理這些控制器的。還是舉個例子來說明吧:比如我們通過APIServer創建一個pod,當這個pod創建成功后,APIServer的任務就算完成了。而后面保證Pod的狀態始終和我們預期的一樣的重任就由controller manager去保證了。

  4. etcd。etcd是一個高可用的鍵值存儲系統,Kubernetes使用它來存儲各個資源的狀態,從而實現了Restful的API。

至此,Kubernetes Master就簡單介紹完了。當然,每個模塊內部的實現都很復雜,而且功能也比較復雜,我現在也只是比較淺的了解了一下。如果后續了解的比較清楚了,再做總結分享。

Node

真正干活的來了。每個Node節點主要由三個模塊組成:kubelet、kube-proxy、runtime。先從簡單的說吧。

  1. runtime。runtime指的是容器運行環境,目前Kubernetes支持docker和rkt兩種容器,一般都指的是docker,畢竟docker現在是最主流的容器。

  2. kube-proxy。該模塊實現了Kubernetes中的服務發現和反向代理功能。反向代理方面:kube-proxy支持TCP和UDP連接轉發,默認基於Round Robin算法將客戶端流量轉發到與service對應的一組后端pod。服務發現方面,kube-proxy使用etcd的watch機制,監控集群中service和endpoint對象數據的動態變化,並且維護一個service到endpoint的映射關系,從而保證了后端pod的IP變化不會對訪問者造成影響。另外kube-proxy還支持session affinity。(這里涉及到了service的概念,可以先跳過,等了解了service之后再來看。)

  3. kubelet。Kubelet是Master在每個Node節點上面的agent,是Node節點上面最重要的模塊,它負責維護和管理該Node上面的所有容器,但是如果容器不是通過Kubernetes創建的,它並不會管理。本質上,它負責使Pod得運行狀態與期望的狀態一致。

至此,Kubernetes的Master和Node就簡單介紹完了。下面我們來看Kubernetes中的各種資源/對象。

Kubernetes資源/對象

當然上面已經介紹的Node也算Kubernetes的資源,這里就不再贅述了。

Pod

Pod是Kubernetes里面抽象出來的一個概念,它具有如下特點:

  • Pod是能夠被創建、調度和管理的最小單元;

  • 每個Pod都有一個獨立的IP;

  • 一個Pod由一個或多個容器構成;

  • 一個Pod內的容器共享Pod的所有資源,這些資源主要包括:共享存儲(以Volumes的形式)、共享網絡、共享端口等。

  • 集群內的Pod之間不論是否在同一個Node上都可以任意訪問,這一般是通過一個二層網絡來實現的。

Kubernetes雖然也是一個容器編排系統,但不同於其他系統,它的最小操作單元不是單個容器,而是Pod。這個特性給Kubernetes帶來了很多優勢,比如最顯而易見的是同一個Pod內的容器可以非常方便的互相訪問(通過localhost就可以訪問)和共享數據。使用Pod時我們需要注意兩點:

  1. 雖然Pod內可以有多個容器,但一般我們只將有親密關系的容器放在一個Pod內,比如這些容器需要相互訪問、共享數據等。舉個最典型的例子,比如我們有一個系統,前端是tomcat作為web,后端是存儲數據的數據庫mysql,那么將這兩個容器部署在一個Pod內就非常合理了,因為他們通過localhost就可以訪問彼此。

  2. 雖然每個Pod都有獨立的IP,但是不推薦前台通過IP去訪問Pod,因為Pod一旦銷毀重建,IP就會變化。如果我們的Pod提供了對外的Web服務,那么我們可以通過Kubernetes提供的service去訪問,后面會介紹到。

下面是一個Pod的描述文件nginx-pod.yaml:

YAML
 1 apiVersion: v1
 2 kind: Pod
 3 metadata:
 4   name: nginx-pod
 5   labels:
 6     app: nginx
 7 spec:
 8   containers:
 9     - image: registry.hnaresearch.com/library/nginx:latest
10       name:  nginx
11       ports:
12       - containerPort: 80

 

apiVersion表示API的版本,kind表示我們要創建的資源的類型。metadata是Pod的一些元數據描述。spec描述了我們期望該Pod內運行的容器。通過kubectl create -f nginx-pod.yaml就可以創建一個Pod,這個Pod里面只有一個nginx容器。

Bash
➜  kubectl create -f nginx-pod.yaml
pod "nginx-pod" created
➜  kubectl get pod
NAME        READY     STATUS    RESTARTS   AGE
nginx-pod   1/1       Running   0          1h

 

這里我們只是為了示例,其實實際應用中我們很少會去直接創建一個Pod,因為這樣創建的Pod就像個沒人管的孩子,掛了的話也不會有人去重新建立一個新的來頂替它。Kubernetes提供了很多創建Pod的方式,下面我們接着介紹。

Replication Controller

Replication Controller簡稱RC,一般翻譯為副本控制器,這里的副本指的是Pod。如它的名字所言RC的作用就是保證任意時刻集群中都有期望個數的Pod副本在正常運行。我們通過一個簡單的RC描述文件(mysql-rc.yaml)來介紹它:

YAML
 1 apiVersion: v1
 2 kind: ReplicationController
 3 metadata:
 4   name: mysql
 5 spec:
 6   replicas: 1
 7   selector:
 8     app: mysql
 9   template:
10     metadata:
11       labels:
12         app: mysql
13     spec:
14       containers:
15       - name: mysql
16         image: registry.hnaresearch.com/library/mysql:5.6
17         ports:
18         - containerPort: 3306
19         env:
20         - name: MYSQL_ROOT_PASSWORD
21           value: "123456"

 

上面這個文件描述了一個RC,名字叫mysql,最上面的spec描述了我們期望有1個副本,這些副本都是按照下面的template去創建的。如果某一時刻副本數比replicas描述的少,就按照template去創建新的,如果多了,就干掉幾個。而下面的spec描述了這個Pod內運行的容器。

Bash
➜  kubectl create -f mysql-rc.yaml
replicationcontroller "mysql" created
➜  kubectl get rc
NAME      DESIRED   CURRENT   READY     AGE
mysql     1         1         1         7s
➜  kubectl get pod
NAME          READY     STATUS    RESTARTS   AGE
mysql-1l717   1/1       Running   0          27s
nginx-pod     1/1       Running   0          1h

 

然后我們進行一些刪除操作:

Bash
➜  kubectl delete pod nginx-pod
pod "nginx-pod" deleted
➜  kubectl get pod
NAME          READY     STATUS    RESTARTS   AGE
mysql-1l717   1/1       Running   0          5m
➜  kubectl delete pod mysql-1l717
pod "mysql-1l717" deleted
➜  kubectl get pod
NAME          READY     STATUS    RESTARTS   AGE
mysql-2vl9k   1/1       Running   0          4s

 

我們先刪掉之前通過Pod描述文件創建的nginx-pod,按照預期它被刪除了,並沒有重建。然后我們刪掉mysql-1l717,發現又出來一個新的mysql-2vl9k。這是因為mysql這個是通過RC創建的,除非刪除它的RC,否則任意時刻該RC都會保證有預期個Pod副本在運行。

那么,RC是怎么和Pod產生關聯的呢?上面的selector是什么含義?OK,我們來介紹下一個對象。

Labels和Selector

Label是附屬在Kubernetes對象上的鍵值對,它可以在創建的時候指定,也可以隨時增刪改。一個對象上面可以有任意多個Labels。它往往對於用戶是有意義的,對系統是沒有特殊含義的。我個人理解你可以簡單把他當做Git上面的tag。這里我們只介紹一下它和Selector配合使用時的場景。我們從上面Pod和RC的描述文件中可以看到,每個Pod都有一個Labels,而RC的Selector部分也有一個定義了一個labels。RC會認為凡是和它Selector部分定義的labels相同的Pod都是它預期的副本。比如凡是labels為app=mysql的Pod都是剛才定義的RC的副本。

所以就有一個注意點,我們不要單獨去創建Pod,更不要單獨去創建符合某個RC的Selector的Pod,那樣RC會認為是它自己創建的這個Pod而導致與預期Pod數不一致而干掉某些Pod。當然Labels還有很多用途,Selector除了等值外也有一些其他判讀規則,這里不細述。

Service

終於輪到Service出場了,之前我們已經多次提到它了。Service是Kubernetes里面抽象出來的一層,它定義了由多個Pods組成的邏輯組(logical set),可以對組內的Pod做一些事情:

  • 對外暴露流量

  • 做負載均衡(load balancing)

  • 服務發現(service-discovery)。

前面我們說了如果我們想將Pod內容器提供的服務暴露出去,就要使用Service。因為Service除了上面的特性外,還有一個集群內唯一的私有IP和對外的端口,用於接收流量。如果我們想將一個Service暴露到集群外,即集群外也可以訪問的話,有兩種方法:

LoadBalancer - 提供一個公網的IP
NodePort - 使用NAT將Service的端口暴露出去。

為什么不能通過Pod的IP,而要通過Service呢?因為在Kubernetes中,Pod是可能隨時死掉被重建的,所以說其IP是不可靠的。但是Service一旦創建,其IP就會一直固定直到這個Service消亡。其實我們能夠看到,Kubernetes中一個Service就相當於一個微服務。這里我們就不細述Service的創建方法以及如何使用LB以及NodePort了。

Replica Sets和Deployment

Replica Sets被稱為下一代的Replication Controller,它被設計出來的目的是替代RC並提供更多的功能。就目前看,ReplicaSet和RC的唯一區別是對於Labels和Selector的支持。RC只支持等值的方式,而ReplicaSet還支持集合的選擇方式(In,Not In)。另外,ReplicaSet很少像RC一樣單獨使用(當然,它可以單獨使用),一般都是配合Deployment一起使用。

Deployment也是Kubernetes新增加的一種資源,從它的名字就可以看出它主要是為部署而設計的,之前的文章中已經有具體的例子了。想像一下我們利用RC創建了一些Pod,但現在我們想要更新Pod內容器使用的鏡像或者想更改副本的個數等。這些我們無法通過修改已有的RC去做,只能刪除舊的,創建新的。但這樣Pod內的容器就會停止,也即業務就會中斷,這在生產環境中往往是不可接受的。但有了Deployment以后,這些問題就都可以解決了。通過Deployment我們可以動態的控制副本個數、ReplicaSet和Pod的狀態、滾動升級等。Deployment的強大真的需要很長的一篇文章來介紹,后續的博客再介紹吧。

HPA

HPA全稱Horizontal Pod Autoscaling,即Pod的水平自動擴展,我覺得這個簡直就是Kubernetes的黑科技。因為它可以根據當前系統的負載來自動水平擴容,如果系統負載超過預定值,就開始增加Pod的個數,如果低於某個值,就自動減少Pod的個數。因為被以前的系統擴容縮容深深的折磨過,所以我覺得這個功能是多么的強大。當然,目前Kubernetes的HPA只能根據CPU和內存去度量系統的負載,而且目前還依賴heapster去收集CPU的使用情況,所以功能還不是很強大,但是其完善也只是時間的問題了。讓我們期待吧。

Namespace

Kubernetes提供了Namespace來從邏輯上支持多租戶的功能,默認有兩個Namespace:

  • default。用戶默認的namespace。

  • kube-system。系統創建的對象都在這個namespace下。

當然我們可以自己創建新的namespace。

Daemon Set

有時我們可能有這樣的需求,需要在所有Pod上面(包括將來新創建的)都運行某個容器,比如用於監控、日志收集等。那我們就可以使用DaemonSet,它可以保證所有容器上面都運行一份我們指定的容器的實例。而且,通過Labels和Selector,我們可以實現只在某些Pod上面部署,非常的靈活。

但是現在也有一些局限,比如如果我們無法更改已經部署的Daemon Set。如果需要更改,只能刪除重建。當然,更改的功能也已經在開發中了。

其他

當然,Kubernetes還有很多其他的資源/對象,比如執行一次任務的Job,存儲相關的Volume等,這些我覺得都沒法簡單的說清楚其功能。后續再介紹。

寫到這里,感覺本文已經和開始的說的簡明、簡短有些漸行漸遠了...Oops

 

轉載自:http://time-track.cn/Kubernetes-resources-summaries.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM