一、概述
kubernetes中Service是真實應用的抽象,將用來代理Pod,對外提供固定IP作為訪問入口,這樣通過訪問Service便能訪問到相應的Pod,而對訪問者來說只需知道Service的訪問地址,而不需要感知Pod的變化;
Service是通過Label來關聯Pod的,在Service的定義中,設置 .spec.selector為name=redis-master,將關聯上Pod;
#kubectl get service redis-master
NAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR AGE
redis-master 10.254.233.212 <none> 6379/TCP 13s
Redis Master Service 的查詢信息中的顯示屬性CLUSTER_IP為10.254.233.212, 屬性PORT(S)為6379/TCP, 其中10.254.233.212是Kubernetes分配給Redis Master Service的屬性IP,6379/TCP則是Service會轉發的端口(通過Service定義文件中的.spec.ports[0].port指定),Kubernetes會將所有訪問10.254.233.212:6379的TCP請求轉發到Redis Master Pod中,目標端口是6379/TCP(通過Service定義文件中的spec.ports[0].targetPort指定)。
因為創建了Redis Master Service來代理Redis Master Pod,所以Redis Slave Pod通過Redis Master Service的虛擬IP 10.254.233.212就可以訪問到Redis Master Pod,但是如果只是硬配置Service的虛擬IP到Redis Slave Pod中,這樣還不是真正的服務發現,Kubernetes提供了兩種發現Service的方法;
note: 如何在外部網絡中訪問Redis Master Service呢?
因為Service的虛擬IP是由k8s虛擬出來的內部網絡,而外部網絡是無法尋址的,這時候就需要增加一層網絡轉發,即外網到內網的轉發。實現方式有很多種,我們這里采用一種叫作NodePort的方式來實現,即k8s將會在每個Node上設置端口,稱為NodePort,通過NodePort端口可以訪問到Pod。
二、k8s服務發現
- 環境變量 --- 存在局限性
- DNS
當有新的Service創建時,就會自動生成一條DNS記錄,以Redis Master Service為例,有一條DNS記錄:
redis-master => 10.254.233.212
使用這種服務發現,k8s集群必須安裝Cluster DNS
三、Pod與容器
在Docker中,容器是最小處理單位,增刪改查的對象是容器,容器是一種虛擬化技術,容器之間是隔離的,隔離是基於Linux Namespace實現的,Linux內核中提供了6中Linux Namespace隔離的系統調用,如下圖:
在k8s中,Pod包含了一個或者多個相關的容器,Pod可以認為是容器的一種延伸擴展,一個Pod也是一個隔離體,而Pod包含一組容器優勢共享的(當前共享的Linux Namespace 包括:PID, Network, IPC和UTS)。除此之外,Pod中的容器可以訪問共同的數據卷來實現文件系統的共享,所以k8s中的數據卷是Pod級別的,而不是容器級別的;
Pod是容器的集合,容器是真正的執行體。相比原生的容器接口,Pod提供了更高層次的抽象,但是Pod的設計並不是為了運行同一個應用的多個實例,而是運行一個應用多個緊密聯系的程序。而每個程序運行在單獨的容器中,以Pod的形式組合成一個應用。相比於在單個容器中運行多個程序,這樣的設計有以下好處:
- 透明性: 將Pod內的容器向基礎設施可見,底層系統就能向容器提供如進程管理和資源監控等服務,這樣能給用戶帶來極大的便利;
- 解綁軟件的依賴: 這樣單個容器可以獨立地重建和重新部署,可以實現獨立容器的試試更新;
- 易用性:用戶不需要運行自己的進程管理器,也不需要負責信號量和退出碼的傳遞等。
- 高效性:因為底層設備負責更多的管理,容器因而能更加輕量化;
四、Pod的網絡
Pod中的所有容器網絡都是共享的,一個Pod中的所有容器中的網絡是一致的,他們能夠通過本地地址(localhost)訪問其他用戶容器的端口。
在k8s網絡模型中,每一個Pod都擁有一個扁平化共享網絡命名空間的IP,稱為PodIP,通過PodIP,Pod就能夠跨網絡與其他物理機和容器進行通信;
五、Pod的生命周期
Pod的生命周期可描述為:首先Pod被創建,Pod被調度到Node進行部署運行。Pod是十分忠誠的,一旦被分配到Node后,就不會離開這個Node,直到它被刪除,生命周期完結;
- Pending: Pod已經被創建,但是一個或者多個容器還未創建,這包括Pod調度階段,以及容器image下載過程;
- Running:Pod已經被調度到Node,所有容器已經創建,並且至少一個容器在運行或者重啟;
- Succeeded:Pod中石油容器正常退出;
- Failed: Pod中所有容器退出,至少有一個容器是一次退出的。
六、RC —— ReplicationController
RC和Pod的關聯就是通過Label實現的,Label機制是k8s中很重要的一個設計,通過Label進行對象的弱關聯,可以靈活地進行分類和選擇。
對於Pod,需要設置Label來進行標示,Label是一系列的Key/Value對, Pod(或者Pod模板)的定義中通過.metadata.labels設置:
labels:
key1: value1
key2: value2
對於Replication Controller來說就是通過Label Selector來匹配Pod的Label,從而實現關聯關系。在RC的定義中通過.spec.selector來設置Label Selector;
彈性伸縮:
#kubectl get replicationcontroller my-nginx
#kubectl get pod --selector app=nginx
#kubectl scale replicationcontroller my-nginx --replicas=3
#kubectl scale replicationcontroller my-nginx [--current-replicas=2] --replicas=1
#kubectl scale replicationcontroller my-nginx --replicas=0
自動伸縮:
在k8s中通過Horizontal Pod Autoscaler來實現Pod的自動伸縮, Horizontal Pod Autoscaler同Replication Controller是一一對應的;Horizontal Pod Autoscaler將定時從平台監控系統中獲取Replication Controller關聯Pod的整體資源使用情況。當策略匹配的時候,通過Replication Controller來調整Pod的副本數,實現自動伸縮。
滾動升級:
#kubectl rolling-update my-web-v1 -f my-web-v2-rc.yaml --update-period=10s
#kubectl rolling-update my-web-v1 -f my-web-v2-rc.yaml --update-period=10s --rollback #升級回滾
七、Deployment
k8s提供了一種更加簡單的更新Replication Controller 和 Pod 的機制,叫做Deployment
八、Job
RC創建的Pod都是長時運行服務,相應的,k8s提供了另一種機制, Job來管理一次性任務的Pod; ---------- 兩者在yaml的最大區別是關於Pod的重啟策略;