3.2 副本控制器(ReplicationController)
ReplicationController(在kubectl命令中經常縮寫爲rc
或rcs
)是實際確保特定數量的Pod副本在任意時刻的運行。如果Pod副本超過指定數量ReplicationController就會終止超出數量的Pod,如果太少就添加Pod。和手動創建Pod不同,ReplicationController操作的Pod在失敗、刪除、終止後會自動進行替換,因此還是推薦使用ReplicationController的,即使只有1個Pod(這也是依靠一個ReplicationController創建可靠運行的Pod簡單場景)。
【運行一個ReplicationController】
下面是通過ReplicationController配置3個Nginx副本的栗子:
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx
spec:
replicas: 3
selector:
app: nginx
template:
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
可以通過kubectl apply -f xxx.yaml
的形式運行,然後可以查看ReplicationController的狀態(上述是nginx
):kubectl describe replicationcontrollers/nginx
,可以看到Pod的具運行狀態。如果要列出某個ReplicationController管理的所有的Pod,可以使用命令
pods=$(kubectl get pods --selector=app=nginx --output=jsonpath={.items..metadata.name})
echo $pods
選擇器和ReplicationController的一樣,其中--output=jsonpath
是指定了一個表達式,它只從返回列表中的每個Pod中獲取名稱。
【編寫ReplicationController規約Spec】
和其他K8S的配置一樣,一個ReplicationController需要apiVersion
和kind
以及metadata
字段,同樣副本集控制器也需要.spec
進行規範指定:
1.Pod模板(Pod Template)
.spec.template
是.spec
唯一必需的字段,幾乎和Pod的模式一樣,除了它是嵌套的、沒有apiVersion
和kind
。除此之外,ReplicationController必須指定合適的標籤label(注意不要和其他控制器重疊)和重啓策略(.spec.template.spec.restartPolicy
應該設爲Always
,如果不指定這也是默認值)。
2.ReplicationController上的標籤
副本控制器可以有自己的標籤(.metadata.labels
),通常是將其設置爲和.spec.template.metadata.labels
一樣的值,如果.metadata.labels
沒有指定,它默認會設置爲.spec.template.metadata.labels
一樣的值。當然它們的值也可以設置爲不同,.metadata.labels
並不會影響ReplicationController的行爲。
3.Pod選擇器
.spec.selector
字段是標籤選擇器,一個ReplicationController將會管理所有帶有和它標籤選擇器相匹配標籤的Pod,它不區分它創建或刪除的pods和另一個人或進程創建或刪除的pods。這就允許ReplicationController可以在不影響運行的Pod的前提下進行替換。如果指定.spec.template.metadata.labels
,那它必須只能指定爲.spec.selector
的值。如果.spec.selector
沒有指定,那默認就是.spec.template.metadata.labels
的值。正常情況下,不應該創建任何帶有和選擇器相匹配標籤的Pod,因爲ReplicationController會認爲它創建了其他的Pod。
4.多個副本
可以通過.spec.replicas
指定並行運行Pod的數量(默認爲1)。運行時的副本數量可能忽高忽低,因爲副本可能被增加、刪除、替換的Pod提前被創建
【ReplicationController的行爲】
1.刪除ReplicationController和它所有的Pod
kubectl將會將ReplicationController規模縮減爲0,然後在刪除ReplicationController本身前刪除每個Pod,如果kubectl命令被打斷,它將會重啓。在使用REST API操作時,需要明確按照上述的步驟執行(將副本縮減爲0–>等待pod刪除完成–>刪除ReplicationController)。
2.僅僅刪除ReplicationController
也可以在不影響任何Pod的情況下僅僅刪除ReplicationController,需要在kubectl delete
時指定--cascade=false
,刪除控制器後可以使用新的控制器替換,只要兩者的.spec.selector
相同即可,新的ReplicationController將會接管之前控制器的Pod,但不會嘗試去使用新的Pod模板創建已經存在的Pod,如果想升級老規範的Pod到新規範的Pod,需要使用rolling update。
【將Pod從ReplicationController中脫離】
只需要改變Pod的標籤即可。
【常見使用模式】
- 重新調度Rescheduling;
- 規模伸縮:更新
replicas
字段即可; - 滾動升級(Rolling updates):ReplicationController被設計爲通過挨個替換Pod的方式促進rolling update(可能名字也是由此而來)。推薦的方式是創建一個新的ReplicationController替換原來的控制器,並將它的副本數量設置爲1,然後每次增加一個新的控制器、刪除一箇舊的控制器,然後在縮減到只有0個副本時直接刪除舊的控制器,這可以預見性的更新pods副本集,而不考慮意外的失敗。滾動更新控制器理論上可以確保在任何時刻都有足夠數量的pod有效地提供服務。
- 多發佈模式(Multiple release tracks):爲了在滾動升級的進程中同時運行APP的多個版本,通常情況下,使用多個發佈版本跟蹤,長時間運行多個版本,甚至連續運行。比如一個Service的目標是
tier in (frontend), environment in (prod)
,現在滿足這個條件的有10個,但想要某個組件的金絲雀(canary)版本,那可以搞個控制器:先將ReplicationController的replicas
設置爲9,選擇器爲tier=frontend, environment=prod, track=stable
,再爲金絲雀版本搞一個ReplicationController將replicas
設置爲1,選擇器爲tier=frontend, environment=prod, track=canary
。 - 在Service中使用ReplicationController,一個Service中可以有多個ReplicationController,比如4中提到的場景。ReplicationController永遠不會自行終止,一般和Service共死。Service可以由多個ReplicationController控制的Pod組成