1.概述
無狀態應用更關注群體,任何一個成員都可以被取代,有狀態應用關注的是個體。用deployment控制器管理的nginx、myapp等都屬於無狀態應用,像mysql、redis、zookeeper等都屬於有狀態應用,他們有的還有主從之分、先后順序之分.
statefulset控制器能實現有狀態應用的管理,但實現起來也是非常麻煩,需要把運維管理過程寫成腳本並注入到statefulset中才能使用,雖然互聯網上有人做好了stateful的腳本,但是還是建議大家不要輕易的把redis、mysql等這樣有狀態的應用遷移到k8s上.
在k8s中,statefulset管理的應用有以下特效:
a).每一個Pod穩定且有唯一的網絡標識符; b).穩定且持久的存儲設備; c).要求有序、平滑的部署和擴展; d).要求有序、平滑的終止和刪除; e).有序的滾動更新,應該先更新從節點,再更新主節點;
statefulset由三個組件組成:
a).headless service(無頭的服務,即沒名字); b).statefulset控制器; c).volumeClaimTemplate(存儲卷申請模板,因為每個pod要有專用存儲卷,而不能共用存儲卷)
2.創建StatefulSet控制器
kubectl explain sts cat stateful-demo.yaml apiVersion: v1 kind: Service metadata: name: myapp-svc labels: app: myapp-svc spec: ports: - port: 80 name: web clusterIP: None selector: app: myapp-pod --- apiVersion: apps/v1 kind: StatefulSet metadata: name: myapp spec: serviceName: myapp-svc replicas: 2 selector: matchLabels: app: myapp-pod template: metadata: labels: app: myapp-pod spec: containers: - name: myapp image: ikubernetes/myapp:v1 ports: - containerPort: 80 name: web volumeMounts: - name: myappdata mountPath: /usr/share/nginx/html volumeClaimTemplates: - metadata: name: myappdata spec: accessModes: ["ReadWriteOnce"] #storageClassName: "gluster-dynamic" resources: requests: storage: 5Gi
volumeClaimTemplates:存儲卷申請模板,為每個pod定義volume;為pod所在的名稱空間自動創建pvc.
kubectl apply -f stateful-demo.yaml kubectl get pods NAME READY STATUS RESTARTS AGE myapp-0 1/1 Running 0 4m myapp-1 1/1 Running 0 4m # pod和service會被刪除,但是pvc不會被刪,所以還能恢復. kubectl delete -f stateful-demo.yaml # 解析pod時的格式:pod名.svc名.namespace名.svc.cluster.local kubectl exec -it myapp-0 -- /bin/sh / # nslookup myapp-0.myapp-svc.default.svc.cluster.local nslookup: can't resolve '(null)': Name does not resolve Name: myapp-0.myapp-svc.default.svc.cluster.local Address 1: 10.244.1.110 myapp-0.myapp-svc.default.svc.cluster.local # 將pod為5個 kubectl scale sts myapp --replicas=5 # 也可以用patch打補丁的方法來進行擴容和縮容 kubectl patch sts myapp -p '{"spec":{"replicas":2}}' # 更新策略 kubectl explain sts.spec.updateStrategy.rollingUpdate 假設有4個pod(pod0,pod1,pod2,pod3),如果設置partition為5,那么說明大於等於5的pod更新,四個Pod就都不更新; 如果partition為4,那么說明大於等於4的pod更新,即pod3更新,其他pod都不更新; 如果partiton為3,那么說明大於等於3的pod更新,那么就是pod2和pod3更新,其他pod都不更新. kubectl patch sts myapp -p '{"spec":{"updateStrategy":{"rollingUpdate":{"partition":4}}}}' kubectl describe sts myapp Update Strategy: RollingUpdate Partition: 4 # 把myapp升級為v2版本 kubectl set image sts/myapp myapp=ikubernetes/myapp:v2 kubectl get pods myapp-4 -o yaml containerStatuses: image: ikubernetes/myapp:v2
可以參考github上別人做好的有狀態應用:github k8s statefulSet redis|mysql
參考博客:http://blog.itpub.net/28916011/viewspace-2215046/