W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
本教程介紹了如何使用 StatefulSet 來管理應(yīng)用。 演示了如何創(chuàng)建、刪除、擴容/縮容和更新 StatefulSet 的 Pod。
在開始本教程之前,你應(yīng)該熟悉以下 Kubernetes 的概念:
說明:
本教程假設(shè)你的集群被配置為動態(tài)制備 PersistentVolume 卷。 如果沒有這樣配置,在開始本教程之前,你需要手動準(zhǔn)備 2 個 1 GiB 的存儲卷。
StatefulSet 旨在與有狀態(tài)的應(yīng)用及分布式系統(tǒng)一起使用。然而在 Kubernetes 上管理有狀態(tài)應(yīng)用和分布式系統(tǒng)是一個寬泛而復(fù)雜的話題。 為了演示 StatefulSet 的基本特性,并且不使前后的主題混淆,你將會使用 StatefulSet 部署一個簡單的 web 應(yīng)用。
在閱讀本教程后,你將熟悉以下內(nèi)容:
作為開始,使用如下示例創(chuàng)建一個 StatefulSet。它和 StatefulSet 概念中的示例相似。 它創(chuàng)建了一個 Headless Service ?nginx
?用來發(fā)布 StatefulSet ?web
?中的 Pod 的 IP 地址。
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "nginx"
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: k8s.gcr.io/nginx-slim:0.8
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
下載上面的例子并保存為文件 ?web.yaml
?。
你需要使用兩個終端窗口。在第一個終端中,使用 ?kubectl get
? 來監(jiān)視 StatefulSet 的 Pod 的創(chuàng)建情況。
kubectl get pods -w -l app=nginx
在另一個終端中,使用 ?kubectl apply
? 來創(chuàng)建定義在 ?web.yaml
? 中的 Headless Service 和 StatefulSet。
kubectl apply -f web.yaml
service/nginx created
statefulset.apps/web created
上面的命令創(chuàng)建了兩個 Pod,每個都運行了一個 NginX Web 服務(wù)器。 獲取 ?nginx
?Service:
kubectl get service nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx ClusterIP None <none> 80/TCP 12s
然后獲取 ?web
?StatefulSet,以驗證兩者均已成功創(chuàng)建:
kubectl get statefulset web
NAME DESIRED CURRENT AGE
web 2 1 20s
對于一個擁有 n 個副本的 StatefulSet,Pod 被部署時是按照 {0..n-1} 的序號順序創(chuàng)建的。 在第一個終端中使用 ?kubectl get
? 檢查輸出。這個輸出最終將看起來像下面的樣子。
kubectl get pods -w -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 0/1 Pending 0 0s
web-0 0/1 Pending 0 0s
web-0 0/1 ContainerCreating 0 0s
web-0 1/1 Running 0 19s
web-1 0/1 Pending 0 0s
web-1 0/1 Pending 0 0s
web-1 0/1 ContainerCreating 0 0s
web-1 1/1 Running 0 18s
請注意,直到 ?web-0
? Pod 處于 Running 并 Ready 狀態(tài)后,?web-1
? Pod 才會被啟動。
StatefulSet 中的每個 Pod 擁有一個唯一的順序索引和穩(wěn)定的網(wǎng)絡(luò)身份標(biāo)識。
獲取 StatefulSet 的 Pod:
kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 1m
web-1 1/1 Running 0 1m
如同 StatefulSet 概念中所提到的, StatefulSet 中的每個 Pod 擁有一個具有黏性的、獨一無二的身份標(biāo)志。 這個標(biāo)志基于 StatefulSet 控制器分配給每個 Pod 的唯一順序索引。 Pod 的名稱的形式為 ?<statefulset 名稱>-<序號索引>
?。 ?web
?StatefulSet 擁有兩個副本,所以它創(chuàng)建了兩個 Pod:?web-0
? 和 ?web-1
?。
每個 Pod 都擁有一個基于其順序索引的穩(wěn)定的主機名。使用 ?kubectl exec
? 在每個 Pod 中執(zhí)行 ?hostname
?:
for i in 0 1; do kubectl exec "web-$i" -- sh -c 'hostname'; done
web-0
web-1
使用 ?kubectl run
? 運行一個提供 ?nslookup
?命令的容器,該命令來自于 ?dnsutils
?包。 通過對 Pod 的主機名執(zhí)行 ?nslookup
?,你可以檢查他們在集群內(nèi)部的 DNS 地址:
kubectl run -i --tty --image busybox:1.28 dns-test --restart=Never --rm
這將啟動一個新的 Shell。在新 Shell 中運行:
# Run this in the dns-test container shell
nslookup web-0.nginx
輸出類似于:
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-0.nginx
Address 1: 10.244.1.6
nslookup web-1.nginx
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-1.nginx
Address 1: 10.244.2.6
(現(xiàn)在可以退出容器 Shell:?exit
?)
headless service 的 CNAME 指向 SRV 記錄(記錄每個 Running 和 Ready 狀態(tài)的 Pod)。 SRV 記錄指向一個包含 Pod IP 地址的記錄表項。
在一個終端中監(jiān)視 StatefulSet 的 Pod:
kubectl get pod -w -l app=nginx
在另一個終端中使用 ?kubectl delete
? 刪除 StatefulSet 中所有的 Pod:
kubectl delete pod -l app=nginx
pod "web-0" deleted
pod "web-1" deleted
等待 StatefulSet 重啟它們,并且兩個 Pod 都變成 Running 和 Ready 狀態(tài):
kubectl get pod -w -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 0/1 ContainerCreating 0 0s
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 2s
web-1 0/1 Pending 0 0s
web-1 0/1 Pending 0 0s
web-1 0/1 ContainerCreating 0 0s
web-1 1/1 Running 0 34s
使用 ?kubectl exec
? 和 ?kubectl run
? 查看 Pod 的主機名和集群內(nèi)部的 DNS 表項。 首先,查看 Pod 的主機名:
for i in 0 1; do kubectl exec web-$i -- sh -c 'hostname'; done
web-0
web-1
然后,運行:
kubectl run -i --tty --image busybox:1.28 dns-test --restart=Never --rm /bin/sh
這將啟動一個新的 Shell。在新 Shell 中,運行:
# Run this in the dns-test container shell
nslookup web-0.nginx
輸出類似于:
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-0.nginx
Address 1: 10.244.1.7
nslookup web-1.nginx
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-1.nginx
Address 1: 10.244.2.8
(現(xiàn)在可以退出容器 Shell:?exit
?)
Pod 的序號、主機名、SRV 條目和記錄名稱沒有改變,但和 Pod 相關(guān)聯(lián)的 IP 地址可能發(fā)生了改變。 在本教程中使用的集群中它們就改變了。這就是為什么不要在其他應(yīng)用中使用 StatefulSet 中 Pod 的 IP 地址進(jìn)行連接,這點很重要。
如果你需要查找并連接一個 StatefulSet 的活動成員,你應(yīng)該查詢 Headless Service 的 CNAME。 和 CNAME 相關(guān)聯(lián)的 SRV 記錄只會包含 StatefulSet 中處于 Running 和 Ready 狀態(tài)的 Pod。
如果你的應(yīng)用已經(jīng)實現(xiàn)了用于測試是否已存活(liveness)并就緒(readiness)的連接邏輯, 你可以使用 Pod 的 SRV 記錄(?web-0.nginx.default.svc.cluster.local
?、 ?web-1.nginx.default.svc.cluster.local
?)。因為他們是穩(wěn)定的,并且當(dāng)你的 Pod 的狀態(tài)變?yōu)?nbsp;Running 和 Ready 時,你的應(yīng)用就能夠發(fā)現(xiàn)它們的地址。
獲取 ?web-0
? 和 ?web-1
? 的 PersistentVolumeClaims:
kubectl get pvc -l app=nginx
輸出類似于:
NAME STATUS VOLUME CAPACITY ACCESSMODES AGE
www-web-0 Bound pvc-15c268c7-b507-11e6-932f-42010a800002 1Gi RWO 48s
www-web-1 Bound pvc-15c79307-b507-11e6-932f-42010a800002 1Gi RWO 48s
StatefulSet 控制器創(chuàng)建了兩個 PersistentVolumeClaims, 綁定到兩個 PersistentVolumes。
由于本教程使用的集群配置為動態(tài)制備 PersistentVolume 卷,所有的 PersistentVolume 卷都是自動創(chuàng)建和綁定的。
NginX Web 服務(wù)器默認(rèn)會加載位于 ?/usr/share/nginx/html/index.html
? 的 index 文件。 StatefulSet ?spec
?中的 ?volumeMounts
?字段保證了 ?/usr/share/nginx/html
? 文件夾由一個 PersistentVolume 卷支持。
將 Pod 的主機名寫入它們的 ?index.html
? 文件并驗證 NginX Web 服務(wù)器使用該主機名提供服務(wù):
for i in 0 1; do kubectl exec "web-$i" -- sh -c 'echo "$(hostname)" > /usr/share/nginx/html/index.html'; done
for i in 0 1; do kubectl exec -i -t "web-$i" -- curl http://localhost/; done
web-0
web-1
說明:
請注意,如果你看見上面的 curl 命令返回了 403 Forbidden 的響應(yīng),你需要像這樣修復(fù)使用 ?volumeMounts
?(原因歸咎于使用 hostPath 卷時存在的缺陷) 掛載的目錄的權(quán)限 運行:
?for i in 0 1; do kubectl exec web-$i -- chmod 755 /usr/share/nginx/html; done
?
在你重新嘗試上面的 ?curl
?命令之前。
在一個終端監(jiān)視 StatefulSet 的 Pod:
kubectl get pod -w -l app=nginx
在另一個終端刪除 StatefulSet 所有的 Pod:
kubectl delete pod -l app=nginx
pod "web-0" deleted
pod "web-1" deleted
在第一個終端里檢查 ?kubectl get
? 命令的輸出,等待所有 Pod 變成 Running 和 Ready 狀態(tài)。
kubectl get pod -w -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 0/1 ContainerCreating 0 0s
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 2s
web-1 0/1 Pending 0 0s
web-1 0/1 Pending 0 0s
web-1 0/1 ContainerCreating 0 0s
web-1 1/1 Running 0 34s
驗證所有 Web 服務(wù)器在繼續(xù)使用它們的主機名提供服務(wù):
for i in 0 1; do kubectl exec -i -t "web-$i" -- curl http://localhost/; done
web-0
web-1
雖然 ?web-0
? 和 ?web-1
? 被重新調(diào)度了,但它們?nèi)匀焕^續(xù)監(jiān)聽各自的主機名,因為和它們的 PersistentVolumeClaim 相關(guān)聯(lián)的 PersistentVolume 卷被重新掛載到了各自的 ?volumeMount
?上。 不管 ?web-0
? 和 ?web-1
? 被調(diào)度到了哪個節(jié)點上,它們的 PersistentVolume 卷將會被掛載到合適的掛載點上。
擴容/縮容 StatefulSet 指增加或減少它的副本數(shù)。這通過更新 ?replicas
?字段完成。 你可以使用 ?kubectl scale
? 或者 ?kubectl patch
? 來擴容/縮容一個 StatefulSet。
在一個終端窗口監(jiān)視 StatefulSet 的 Pod:
kubectl get pods -w -l app=nginx
在另一個終端窗口使用 ?kubectl scale
? 擴展副本數(shù)為 5:
kubectl scale sts web --replicas=5
statefulset.apps/web scaled
在第一個 終端中檢查 ?kubectl get
? 命令的輸出,等待增加的 3 個 Pod 的狀態(tài)變?yōu)?nbsp;Running 和 Ready。
kubectl get pods -w -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 2h
web-1 1/1 Running 0 2h
NAME READY STATUS RESTARTS AGE
web-2 0/1 Pending 0 0s
web-2 0/1 Pending 0 0s
web-2 0/1 ContainerCreating 0 0s
web-2 1/1 Running 0 19s
web-3 0/1 Pending 0 0s
web-3 0/1 Pending 0 0s
web-3 0/1 ContainerCreating 0 0s
web-3 1/1 Running 0 18s
web-4 0/1 Pending 0 0s
web-4 0/1 Pending 0 0s
web-4 0/1 ContainerCreating 0 0s
web-4 1/1 Running 0 19s
StatefulSet 控制器擴展了副本的數(shù)量。StatefulSet 按序號索引順序創(chuàng)建各個 Pod,并且會等待前一個 Pod 變?yōu)?nbsp;Running 和 Ready 才會啟動下一個 Pod。
在一個終端監(jiān)視 StatefulSet 的 Pod:
kubectl get pods -w -l app=nginx
在另一個終端使用 ?kubectl patch
? 將 StatefulSet 縮容回三個副本:
kubectl patch sts web -p '{"spec":{"replicas":3}}'
statefulset.apps/web patched
等待 ?web-4
? 和 ?web-3
? 狀態(tài)變?yōu)?nbsp;Terminating。
kubectl get pods -w -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 3h
web-1 1/1 Running 0 3h
web-2 1/1 Running 0 55s
web-3 1/1 Running 0 36s
web-4 0/1 ContainerCreating 0 18s
NAME READY STATUS RESTARTS AGE
web-4 1/1 Running 0 19s
web-4 1/1 Terminating 0 24s
web-4 1/1 Terminating 0 24s
web-3 1/1 Terminating 0 42s
web-3 1/1 Terminating 0 42s
控制器會按照與 Pod 序號索引相反的順序每次刪除一個 Pod。在刪除下一個 Pod 前會等待上一個被完全關(guān)閉。
獲取 StatefulSet 的 PersistentVolumeClaims:
kubectl get pvc -l app=nginx
NAME STATUS VOLUME CAPACITY ACCESSMODES AGE
www-web-0 Bound pvc-15c268c7-b507-11e6-932f-42010a800002 1Gi RWO 13h
www-web-1 Bound pvc-15c79307-b507-11e6-932f-42010a800002 1Gi RWO 13h
www-web-2 Bound pvc-e1125b27-b508-11e6-932f-42010a800002 1Gi RWO 13h
www-web-3 Bound pvc-e1176df6-b508-11e6-932f-42010a800002 1Gi RWO 13h
www-web-4 Bound pvc-e11bb5f8-b508-11e6-932f-42010a800002 1Gi RWO 13h
五個 PersistentVolumeClaims 和五個 PersistentVolume 卷仍然存在。 查看 Pod 的穩(wěn)定存儲,我們發(fā)現(xiàn)當(dāng)刪除 StatefulSet 的 Pod 時,掛載到 StatefulSet 的 Pod 的 PersistentVolume 卷不會被刪除。 當(dāng)這種刪除行為是由 StatefulSet 縮容引起時也是一樣的。
從 Kubernetes 1.7 版本開始,StatefulSet 控制器支持自動更新。 更新策略由 StatefulSet API 對象的 ?spec.updateStrategy
? 字段決定。這個特性能夠用來更新一個 StatefulSet 中 Pod 的的容器鏡像、資源請求和限制、標(biāo)簽和注解。
?RollingUpdate
?更新策略是 StatefulSet 默認(rèn)策略。
?RollingUpdate
?更新策略會更新一個 StatefulSet 中的所有 Pod,采用與序號索引相反的順序并遵循 StatefulSet 的保證。
對 ?web
?StatefulSet 應(yīng)用 Patch 操作來應(yīng)用 ?RollingUpdate
?更新策略:
kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate"}}}'
statefulset.apps/web patched
在一個終端窗口中對 ?web
?StatefulSet 執(zhí)行 patch 操作來再次改變?nèi)萜麋R像:
kubectl patch statefulset web --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"gcr.io/google_containers/nginx-slim:0.8"}]'
statefulset.apps/web patched
在另一個終端監(jiān)控 StatefulSet 中的 Pod:
kubectl get pod -l app=nginx -w
輸出類似于:
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 7m
web-1 1/1 Running 0 7m
web-2 1/1 Running 0 8m
web-2 1/1 Terminating 0 8m
web-2 1/1 Terminating 0 8m
web-2 0/1 Terminating 0 8m
web-2 0/1 Terminating 0 8m
web-2 0/1 Terminating 0 8m
web-2 0/1 Terminating 0 8m
web-2 0/1 Pending 0 0s
web-2 0/1 Pending 0 0s
web-2 0/1 ContainerCreating 0 0s
web-2 1/1 Running 0 19s
web-1 1/1 Terminating 0 8m
web-1 0/1 Terminating 0 8m
web-1 0/1 Terminating 0 8m
web-1 0/1 Terminating 0 8m
web-1 0/1 Pending 0 0s
web-1 0/1 Pending 0 0s
web-1 0/1 ContainerCreating 0 0s
web-1 1/1 Running 0 6s
web-0 1/1 Terminating 0 7m
web-0 1/1 Terminating 0 7m
web-0 0/1 Terminating 0 7m
web-0 0/1 Terminating 0 7m
web-0 0/1 Terminating 0 7m
web-0 0/1 Terminating 0 7m
web-0 0/1 Pending 0 0s
web-0 0/1 Pending 0 0s
web-0 0/1 ContainerCreating 0 0s
web-0 1/1 Running 0 10s
StatefulSet 里的 Pod 采用和序號相反的順序更新。在更新下一個 Pod 前,StatefulSet 控制器終止每個 Pod 并等待它們變成 Running 和 Ready。 請注意,雖然在順序后繼者變成 Running 和 Ready 之前 StatefulSet 控制器不會更新下一個 Pod,但它仍然會重建任何在更新過程中發(fā)生故障的 Pod,使用的是它們當(dāng)前的版本。
已經(jīng)接收到更新請求的 Pod 將會被恢復(fù)為更新的版本,沒有收到請求的 Pod 則會被恢復(fù)為之前的版本。 像這樣,控制器嘗試?yán)^續(xù)使應(yīng)用保持健康并在出現(xiàn)間歇性故障時保持更新的一致性。
獲取 Pod 來查看它們的容器鏡像:
for p in 0 1 2; do kubectl get pod "web-$p" --template '{{range $i, $c := .spec.containers}}{{$c.image}}{{end}}'; echo; done
k8s.gcr.io/nginx-slim:0.8
k8s.gcr.io/nginx-slim:0.8
k8s.gcr.io/nginx-slim:0.8
StatefulSet 中的所有 Pod 現(xiàn)在都在運行之前的容器鏡像。
說明:
你還可以使用 ?kubectl rollout status sts/<名稱>
? 來查看 StatefulSet 的滾動更新狀態(tài)。
你可以使用 ?RollingUpdate
?更新策略的 ?partition
?參數(shù)來分段更新一個 StatefulSet。 分段的更新將會使 StatefulSet 中的其余所有 Pod 保持當(dāng)前版本的同時允許改變 StatefulSet 的 ?.spec.template
?。
對 ?web
?StatefulSet 執(zhí)行 Patch 操作以為 ?updateStrategy
?字段添加一個分區(qū):
kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate","rollingUpdate":{"partition":3}}}}'
statefulset.apps/web patched
再次 Patch StatefulSet 來改變?nèi)萜麋R像:
kubectl patch statefulset web --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"k8s.gcr.io/nginx-slim:0.7"}]'
statefulset.apps/web patched
刪除 StatefulSet 中的 Pod:
kubectl delete pod web-2
pod "web-2" deleted
等待 Pod 變成 Running 和 Ready。
kubectl get pod -l app=nginx -w
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 4m
web-1 1/1 Running 0 4m
web-2 0/1 ContainerCreating 0 11s
web-2 1/1 Running 0 18s
獲取 Pod 的容器鏡像:
kubectl get pod web-2 --template '{{range $i, $c := .spec.containers}}{{$c.image}}{{end}}'
k8s.gcr.io/nginx-slim:0.8
請注意,雖然更新策略是 ?RollingUpdate
?,StatefulSet 還是會使用原始的容器恢復(fù) Pod。 這是因為 Pod 的序號比 ?updateStrategy
?指定的 ?partition
?更小。
你可以通過減少上文指定的 ?partition
?來進(jìn)行金絲雀發(fā)布,以此來測試你的程序的改動。
通過 patch 命令修改 StatefulSet 來減少分區(qū):
kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate","rollingUpdate":{"partition":2}}}}'
statefulset.apps/web patched
等待 ?web-2
? 變成 Running 和 Ready。
kubectl get pod -l app=nginx -w
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 4m
web-1 1/1 Running 0 4m
web-2 0/1 ContainerCreating 0 11s
web-2 1/1 Running 0 18s
獲取 Pod 的容器:
kubectl get pod web-2 --template '{{range $i, $c := .spec.containers}}{{$c.image}}{{end}}'
k8s.gcr.io/nginx-slim:0.7
當(dāng)你改變 ?partition
?時,StatefulSet 會自動更新 ?web-2
? Pod,這是因為 Pod 的序號大于或等于 ?partition
?。
刪除 ?web-1
? Pod:
kubectl delete pod web-1
pod "web-1" deleted
等待 ?web-1
? 變成 Running 和 Ready。
kubectl get pod -l app=nginx -w
輸出類似于:
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 6m
web-1 0/1 Terminating 0 6m
web-2 1/1 Running 0 2m
web-1 0/1 Terminating 0 6m
web-1 0/1 Terminating 0 6m
web-1 0/1 Terminating 0 6m
web-1 0/1 Pending 0 0s
web-1 0/1 Pending 0 0s
web-1 0/1 ContainerCreating 0 0s
web-1 1/1 Running 0 18s
獲取 ?web-1
? Pod 的容器鏡像:
kubectl get pod web-1 --template '{{range $i, $c := .spec.containers}}{{$c.image}}{{end}}'
k8s.gcr.io/nginx-slim:0.8
?web-1
? 被按照原來的配置恢復(fù),因為 Pod 的序號小于分區(qū)。當(dāng)指定了分區(qū)時,如果更新了 StatefulSet 的 ?.spec.template
?,則所有序號大于或等于分區(qū)的 Pod 都將被更新。 如果一個序號小于分區(qū)的 Pod 被刪除或者終止,它將被按照原來的配置恢復(fù)。
你可以使用類似金絲雀發(fā)布的方法執(zhí)行一次分階段的發(fā)布 (例如一次線性的、等比的或者指數(shù)形式的發(fā)布)。 要執(zhí)行一次分階段的發(fā)布,你需要設(shè)置 ?partition
?為希望控制器暫停更新的序號。
分區(qū)當(dāng)前為 2。請將分區(qū)設(shè)置為 0:
kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate","rollingUpdate":{"partition":0}}}}'
statefulset.apps/web patched
等待 StatefulSet 中的所有 Pod 變成 Running 和 Ready。
kubectl get pod -l app=nginx -w
輸出類似于:
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 3m
web-1 0/1 ContainerCreating 0 11s
web-2 1/1 Running 0 2m
web-1 1/1 Running 0 18s
web-0 1/1 Terminating 0 3m
web-0 1/1 Terminating 0 3m
web-0 0/1 Terminating 0 3m
web-0 0/1 Terminating 0 3m
web-0 0/1 Terminating 0 3m
web-0 0/1 Terminating 0 3m
web-0 0/1 Pending 0 0s
web-0 0/1 Pending 0 0s
web-0 0/1 ContainerCreating 0 0s
web-0 1/1 Running 0 3s
獲取 StatefulSet 中 Pod 的容器鏡像詳細(xì)信息:
for p in 0 1 2; do kubectl get pod "web-$p" --template '{{range $i, $c := .spec.containers}}{{$c.image}}{{end}}'; echo; done
k8s.gcr.io/nginx-slim:0.7
k8s.gcr.io/nginx-slim:0.7
k8s.gcr.io/nginx-slim:0.7
將 ?partition
? 改變?yōu)?nbsp;0 以允許 StatefulSet 繼續(xù)更新過程。
?OnDelete
?更新策略實現(xiàn)了傳統(tǒng)(1.7 之前)行為,它也是默認(rèn)的更新策略。 當(dāng)你選擇這個更新策略并修改 StatefulSet 的 ?.spec.template
? 字段時,StatefulSet 控制器將不會自動更新 Pod。
StatefulSet 同時支持級聯(lián)和非級聯(lián)刪除。使用非級聯(lián)方式刪除 StatefulSet 時,StatefulSet 的 Pod 不會被刪除。使用級聯(lián)刪除時,StatefulSet 和它的 Pod 都會被刪除。
在一個終端窗口監(jiān)視 StatefulSet 中的 Pod。
kubectl get pods -w -l app=nginx
使用 ?kubectl delete
? 刪除 StatefulSet。請確保提供了 ?--cascade=orphan
? 參數(shù)給命令。這個參數(shù)告訴 Kubernetes 只刪除 StatefulSet 而不要刪除它的任何 Pod。
kubectl delete statefulset web --cascade=orphan
statefulset.apps "web" deleted
獲取 Pod 來檢查它們的狀態(tài):
kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 6m
web-1 1/1 Running 0 7m
web-2 1/1 Running 0 5m
雖然 ?web
?已經(jīng)被刪除了,但所有 Pod 仍然處于 Running 和 Ready 狀態(tài)。 刪除 ?web-0
?:
kubectl delete pod web-0
pod "web-0" deleted
獲取 StatefulSet 的 Pod:
kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
web-1 1/1 Running 0 10m
web-2 1/1 Running 0 7m
由于 ?web
?StatefulSet 已經(jīng)被刪除,?web-0
? 沒有被重新啟動。
在一個終端監(jiān)控 StatefulSet 的 Pod。
kubectl get pods -w -l app=nginx
在另一個終端里重新創(chuàng)建 StatefulSet。請注意,除非你刪除了 ?nginx
?Service(你不應(yīng)該這樣做),你將會看到一個錯誤,提示 Service 已經(jīng)存在。
kubectl apply -f web.yaml
statefulset.apps/web created
service/nginx unchanged
請忽略這個錯誤。它僅表示 kubernetes 進(jìn)行了一次創(chuàng)建 nginx headless Service 的嘗試,盡管那個 Service 已經(jīng)存在。
在第一個終端中運行并檢查 ?kubectl get
? 命令的輸出。
kubectl get pods -w -l app=nginx
NAME READY STATUS RESTARTS AGE
web-1 1/1 Running 0 16m
web-2 1/1 Running 0 2m
NAME READY STATUS RESTARTS AGE
web-0 0/1 Pending 0 0s
web-0 0/1 Pending 0 0s
web-0 0/1 ContainerCreating 0 0s
web-0 1/1 Running 0 18s
web-2 1/1 Terminating 0 3m
web-2 0/1 Terminating 0 3m
web-2 0/1 Terminating 0 3m
web-2 0/1 Terminating 0 3m
當(dāng)重新創(chuàng)建 ?web
?StatefulSet 時,?web-0
? 被第一個重新啟動。 由于 ?web-1
? 已經(jīng)處于 Running 和 Ready 狀態(tài),當(dāng) ?web-0
? 變成 Running 和 Ready 時, StatefulSet 會接收這個 Pod。由于你重新創(chuàng)建的 StatefulSet 的 ?replicas
?等于 2, 一旦 ?web-0
? 被重新創(chuàng)建并且 ?web-1
? 被認(rèn)為已經(jīng)處于 Running 和 Ready 狀態(tài)時,?web-2
? 將會被終止。
讓我們再看看被 Pod 的 Web 服務(wù)器加載的 ?index.html
? 的內(nèi)容:
for i in 0 1; do kubectl exec -i -t "web-$i" -- curl http://localhost/; done
web-0
web-1
盡管你同時刪除了 StatefulSet 和 ?web-0
? Pod,但它仍然使用最初寫入 ?index.html
? 文件的主機名進(jìn)行服務(wù)。 這是因為 StatefulSet 永遠(yuǎn)不會刪除和一個 Pod 相關(guān)聯(lián)的 PersistentVolume 卷。 當(dāng)你重建這個 StatefulSet 并且重新啟動了 ?web-0
? 時,它原本的 PersistentVolume 卷會被重新掛載。
在一個終端窗口監(jiān)視 StatefulSet 里的 Pod。
kubectl get pods -w -l app=nginx
在另一個窗口中再次刪除這個 StatefulSet。這次省略 ?--cascade=orphan
? 參數(shù)。
kubectl delete statefulset web
statefulset.apps "web" deleted
在第一個終端檢查 ?kubectl get
? 命令的輸出,并等待所有的 Pod 變成 Terminating 狀態(tài)。
kubectl get pods -w -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 11m
web-1 1/1 Running 0 27m
NAME READY STATUS RESTARTS AGE
web-0 1/1 Terminating 0 12m
web-1 1/1 Terminating 0 29m
web-0 0/1 Terminating 0 12m
web-0 0/1 Terminating 0 12m
web-0 0/1 Terminating 0 12m
web-1 0/1 Terminating 0 29m
web-1 0/1 Terminating 0 29m
web-1 0/1 Terminating 0 29m
Pod 按照和他們序號索引相反的順序每次終止一個。 在終止一個 Pod 前,StatefulSet 控制器會等待 Pod 后繼者被完全終止。
說明:
盡管級聯(lián)刪除會刪除 StatefulSet 及其 Pod,但級聯(lián)不會刪除與 StatefulSet 關(guān)聯(lián)的 Headless Service。你必須手動刪除 ?nginx
?Service。
kubectl delete service nginx
service "nginx" deleted
再一次重新創(chuàng)建 StatefulSet 和 headless Service:
kubectl apply -f web.yaml
service/nginx created
statefulset.apps/web created
當(dāng) StatefulSet 所有的 Pod 變成 Running 和 Ready 時,獲取它們的 ?index.html
? 文件的內(nèi)容:
for i in 0 1; do kubectl exec -i -t "web-$i" -- curl http://localhost/; done
web-0
web-1
即使你已經(jīng)刪除了 StatefulSet 和它的全部 Pod,這些 Pod 將會被重新創(chuàng)建并掛載它們的 PersistentVolume 卷,并且 ?web-0
? 和 ?web-1
? 將繼續(xù)使用它的主機名提供服務(wù)。
最后刪除 ?nginx
?service
kubectl delete service nginx
service "nginx" deleted
并且刪除 ?web
?StatefulSet:
kubectl delete statefulset web
statefulset "web" deleted
對于某些分布式系統(tǒng)來說,StatefulSet 的順序性保證是不必要和/或者不應(yīng)該的。 這些系統(tǒng)僅僅要求唯一性和身份標(biāo)志。為了解決這個問題,在 Kubernetes 1.7 中 我們針對 StatefulSet API 對象引入了 ?.spec.podManagementPolicy
?。 此選項僅影響擴縮操作的行為。更新不受影響。
?OrderedReady
?Pod 管理策略是 StatefulSet 的默認(rèn)選項。它告訴 StatefulSet 控制器遵循上文展示的順序性保證。
?Parallel
?Pod 管理策略告訴 StatefulSet 控制器并行的終止所有 Pod, 在啟動或終止另一個 Pod 前,不必等待這些 Pod 變成 Running 和 Ready 或者完全終止?fàn)顟B(tài)。
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "nginx"
podManagementPolicy: "Parallel"
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: k8s.gcr.io/nginx-slim:0.8
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
下載上面的例子并保存為 ?web-parallel.yaml
?。
這份清單和你在上文下載的完全一樣,只是 ?web
? StatefulSet 的 ?.spec.podManagementPolicy
?設(shè)置成了 ?Parallel
?。
在一個終端窗口監(jiān)視 StatefulSet 中的 Pod。
kubectl get pod -l app=nginx -w
在另一個終端窗口創(chuàng)建清單中的 StatefulSet 和 Service:
kubectl apply -f web-parallel.yaml
service/nginx created
statefulset.apps/web created
查看你在第一個終端中運行的 ?kubectl get
? 命令的輸出。
kubectl get pod -l app=nginx -w
NAME READY STATUS RESTARTS AGE
web-0 0/1 Pending 0 0s
web-0 0/1 Pending 0 0s
web-1 0/1 Pending 0 0s
web-1 0/1 Pending 0 0s
web-0 0/1 ContainerCreating 0 0s
web-1 0/1 ContainerCreating 0 0s
web-0 1/1 Running 0 10s
web-1 1/1 Running 0 10s
StatefulSet 控制器同時啟動了 ?web-0
? 和 ?web-1
?。
保持第二個終端打開,并在另一個終端窗口中擴容 StatefulSet:
kubectl scale statefulset/web --replicas=4
statefulset.apps/web scaled
在 ?kubectl get
? 命令運行的終端里檢查它的輸出。
web-3 0/1 Pending 0 0s
web-3 0/1 Pending 0 0s
web-3 0/1 Pending 0 7s
web-3 0/1 ContainerCreating 0 7s
web-2 1/1 Running 0 10s
web-3 1/1 Running 0 26s
StatefulSet 啟動了兩個新的 Pod,而且在啟動第二個之前并沒有等待第一個變成 Running 和 Ready 狀態(tài)。
你應(yīng)該打開兩個終端,準(zhǔn)備在清理過程中運行 ?kubectl
?命令。
kubectl delete sts web
# sts is an abbreviation for statefulset
你可以監(jiān)視 ?kubectl get
? 來查看那些 Pod 被刪除
kubectl get pod -l app=nginx -w
web-3 1/1 Terminating 0 9m
web-2 1/1 Terminating 0 9m
web-3 1/1 Terminating 0 9m
web-2 1/1 Terminating 0 9m
web-1 1/1 Terminating 0 44m
web-0 1/1 Terminating 0 44m
web-0 0/1 Terminating 0 44m
web-3 0/1 Terminating 0 9m
web-2 0/1 Terminating 0 9m
web-1 0/1 Terminating 0 44m
web-0 0/1 Terminating 0 44m
web-2 0/1 Terminating 0 9m
web-2 0/1 Terminating 0 9m
web-2 0/1 Terminating 0 9m
web-1 0/1 Terminating 0 44m
web-1 0/1 Terminating 0 44m
web-1 0/1 Terminating 0 44m
web-0 0/1 Terminating 0 44m
web-0 0/1 Terminating 0 44m
web-0 0/1 Terminating 0 44m
web-3 0/1 Terminating 0 9m
web-3 0/1 Terminating 0 9m
web-3 0/1 Terminating 0 9m
在刪除過程中,StatefulSet 將并發(fā)的刪除所有 Pod,在刪除一個 Pod 前不會等待它的順序后繼者終止。
關(guān)閉 ?kubectl get
? 命令運行的終端并刪除 ?nginx
?Service:
kubectl delete svc nginx
說明:
你需要刪除本教程中用到的 PersistentVolume 卷的持久化存儲介質(zhì)。
基于你的環(huán)境、存儲配置和制備方式,按照必須的步驟保證回收所有的存儲。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: