deployment控制器(pod副本控制器)
實現pod的水平擴展和收縮功能 遵循滾動更新的方式來升級現有的容器
deployment操作的不是pod對象 而是控制replicaSet對象通過它來間接控制Pod滾動更新
Deployment 同樣通過"控制器模式",來操作 ReplicaSet 的個數和屬性,進而實現“水平擴展 / 收縮”和“滾動更新”這兩個編排動作
將一個集群中正在運行的多個Pod版本,交替地逐一升級的過程,就是"滾動更新"創建成功一個新的Pod后 再刪除一個舊版本的Pod
如果創建新的pod沒有正常運行起來 那么deployment控制器就不會刪除舊的pod 中止滾動更新
Deployment實際上是一個兩層控制器.首先,它通過ReplicaSet的個數來描述應用的版本.然后,它再通過ReplicaSet 的屬性(比如replicas 的值)來保證Pod的副本數量
Deployment只允許容器的restartPolicy=Always
一個應用的所有Pod是完全一樣的.所以,它們互相之間沒有順序也無所謂運行在哪台宿主機上
需要的時候Deployment就可以通過Pod模板創建新的Pod,不需要的時候Deployment就可以“殺掉”任意一個Pod
Deployment無法適用的場景
分布式應用,它的多個實例之間,往往有依賴關系,比如:主從關系/主備關系
數據存儲類應用,它的多個實例,往往都會在本地磁盤上保存一份自己獨立的數據 而這些實例一旦被殺掉,即便重建出來,實例與數據之間的對應關系也已經丟失
Deployment和ReplicaSet的關系
1. 一個定義了replicas=3的Deployment與它的ReplicaSet以及Pod的關系,實際上是一種“層層控制”的關系
2.ReplicaSet負責通過“控制器模式”保證系統中Pod的個數永遠等於指定的個數(比如3個)
3.Deployment同樣通過“控制器模式”來操作ReplicaSet的個數和屬性,進而實現“水平擴展 / 收縮”和“滾動更新”這兩個編排動作
DaemonSet控制器
在Kubernetes集群里的每一個節點(Node)上運行一個指定的Pod實例
跟其他編排對象不一樣,DaemonSet開始運行的時機,很多時候比整個Kubernetes集群出現的時機都要早.
在集群中指定的節點(不是所有節點)創建Daemon Pod 通過spec.nodeAffinity字段來設置 nodeAffinity相當於是過濾不相關的節點
DaemonSet Controller會在創建Pod的時候,自動在Pod 的API對象里加上一個nodeAffinity定義.其中,需要綁定的節點名字正是當前正在遍歷的這個節點
DaemonSet還會給這個Pod自動加上另外一個與調度相關的字段,叫作 tolerations.這個字段意味着這個Pod會“容忍”(Toleration)某些Node的“污點”(Taint)
相比於 Deployment,DaemonSet只管理Pod對象,然后通過 nodeAffinity 和Toleration 這兩個調度器的小功能,保證了每個節點上有且只有一個 Pod
DaemonSet 使用 ControllerRevision,來保存和管理自己對應的“版本”.這種“面向API對象”的設計思路簡化了控制器本身邏輯正是K8s“聲明式 API”的優勢
StatefulSet也是直接控制Pod對象的,那么它也在使用ControllerRevision 進行版本管理
在Kubernetes項目里ControllerRevision 其實是一個通用的版本管理對象
statefuset(有狀態應用)控制器
把所有的有狀態應用分為兩種情況:
拓撲狀態
應用的多個實例之間不是完全對等的關系.這些應用實例必須按照某些順序啟動,比如應用的主節點A要先於從節點B啟動.而如果你把A和B兩個Pod 刪除掉,它們再次被創建出來時也必須嚴格按照這個順序才行.並且新創建出來的 Pod,必須和原來Pod 的網絡標識一樣.這樣原先的訪問者才能使用同樣的方法訪問到這個新Pod
Pod 的創建,也是嚴格按照編號順序進行的.比如,在 web-0 進入到 Running 狀態、並且細分狀態(Conditions)成為 Ready 之前web-1 會一直處於 Pending 狀態
Kubernetes 就成功地將 Pod 的拓撲狀態(比如:哪個節點先啟動,哪個節點后啟動),按照 Pod 的“名字 + 編號”的方式固定了下來.此外,Kubernetes 還為每一個 Pod 提供了一個固定並且唯一的訪問入口,即:這個 Pod 對應的 DNS 記錄。這些狀態,在 StatefulSet 的整個生命周期里都會保持不變
存儲狀態
應用的多個實例分別綁定了不同的存儲數據.對於這些應用實例來說,Pod A第一次讀取到的數據和隔了十分鍾之后再次讀取到的數據應該是同一份
哪怕在此期間 Pod A 被重新創建過。這種情況最典型的例子,就是一個數據庫應用的多個存儲實例
PVC/PV 的設計 也使得 StatefulSet 對存儲狀態的管理成為了可能
PVC都以"<PVC 名字 >-<StatefulSet 名字 >-< 編號 >"的方式命名並且處於 Bound 狀態
StatefulSet管理的 Pod,都會聲明一個對應的PVC;而這個PVC的定義,就來自於volumeClaimTemplates 這個模板字段。
更重要的是這個 PVC 的名字會被分配一個與這個 Pod 完全一致的編號
StatefulSet的滾動更新
StatefulSet Controller就會按照與Pod編號相反的順序從最后一個 Pod 開始,逐一更新這個 StatefulSet 管理的每個 Pod.而如果更新發生了錯誤,這次“滾動更新”就會停止.此外,StatefulSet的“滾動更新”還允許我們進行更精細的控制,比如金絲雀發布(Canary Deploy)或者灰度發布,這意味着應用的多個實例中被指定的一部分不會被更新到最新的版本
service介紹
用來將一組Pod暴露給外部訪問的一種機制
normal service
通過虛擬IP(vip)的方式把請求轉發到所代理的某一個Pod上
通過service的DNS方式解析到vip(my-svc.my-namespace.svc.cluster.local)
headless service
clusterIP=None的service Headless Service 不需要分配一個VIP,而是可以直接以DNS記錄的方式解析出被代理Pod的IP地址
創建了一個Headless Service之后,它所代理的所有Pod的IP 地址都會被綁定一個這樣格式的DNS記錄(podname.svcname.namespace.svc.cluster.local)
這個DNS記錄 正是Kubernetes項目為Pod 分配的唯一的“可解析身份”(Resolvable Identity).有了這個“可解析身份”
只要你知道了一個Pod的名字以及它對應的 Service 的名字,你就可以非常確定地通過這條DNS記錄訪問到Pod的IP地址
statefuset的實現原理
StatefulSet 這個控制器的主要作用之一,就是使用 Pod 模板創建 Pod 的時候,對它們進行編號,並且按照編號順序逐一完成創建工作
StatefulSet 的“控制循環”發現 Pod 的“實際狀態”與“期望狀態”不一致,需要新建或者刪除 Pod 進行“調諧”的時候,它會嚴格按照這些 Pod 編號的順序,逐一完成這些操作
與此同時,通過 Headless Service 的方式,StatefulSet 為每個 Pod 創建了一個固定並且穩定的 DNS 記錄,來作為它的訪問入口
在部署“有狀態應用”的時候,應用的每個實例擁有唯一並且穩定的“網絡標識”,是一個非常重要的假設
StatefulSet的控制器直接管理的是Pod
Kubernetes 通過 Headless Service,為這些有編號的 Pod,在 DNS 服務器中生成帶有同樣編號的DNS記錄
StatefulSet 還為每一個 Pod 分配並創建一個同樣編號的 PVC
StatefulSet 其實就是一種特殊的 Deployment,而其獨特之處在於,它的每個 Pod 都被編號了.而且,這個編號會體現在Pod的名字和hostname等標識信息上,這不僅代表了 Pod 的創建順序也是Pod的重要網絡標識(即:在整個集群里唯一的、可被的訪問身份).
有了這個編號后,StatefulSet 就使用 Kubernetes 里的兩個標准功能:Headless Service 和 PV/PVC,實現了對 Pod 的拓撲狀態和存儲狀態的維護
statefuset實現mysql集群
1.搭建好k8s集群
2.下載好鏡像
docker pull gcr.io/google-samples/xtrabackup:1.0
docker pull mysql:5.7
3.創建好pv
使用nfs服務實現遠程存儲

vi /etc/exports /data/volumes/pv1 192.168.164.0/24(insecure,rw,async,no_root_squash) /data/volumes/pv2 192.168.164.0/24(insecure,rw,async,no_root_squash) /data/volumes/pv3 192.168.164.0/24(insecure,rw,async,no_root_squash)
kubectl apply -f pvs.yaml

apiVersion: v1 kind: PersistentVolume metadata: name: pv001 labels: name: pv001 spec: nfs: path: /data/volumes/pv1 server: 192.168.164.141 accessModes: ["ReadWriteMany","ReadWriteOnce"] capacity: storage: 20Gi --- apiVersion: v1 kind: PersistentVolume metadata: name: pv002 labels: name: pv002 spec: nfs: path: /data/volumes/pv2 server: 192.168.164.141 accessModes: ["ReadWriteMany","ReadWriteOnce"] capacity: storage: 10Gi --- apiVersion: v1 kind: PersistentVolume metadata: name: pv003 labels: name: pv003 spec: nfs: path: /data/volumes/pv3 server: 192.168.164.141 accessModes: ["ReadWriteMany","ReadWriteOnce"] capacity: storage: 10Gi
4.創建configmap

apiVersion: v1 kind: ConfigMap metadata: name: mysql labels: app: mysql data: master.cnf: | [mysqld] log-bin slave.cnf: | [mysqld] super-read-only
5.創建service

apiVersion: v1 kind: Service metadata: name: mysql labels: app: mysql spec: ports: - name: mysql port: 3306 clusterIP: None selector: app: mysql --- apiVersion: v1 kind: Service metadata: name: mysql-read labels: app: mysql spec: ports: - name: mysql port: 3306 selector: app: mysql
7.檢測結果
總結: