能夠把容器想像成豆莢裏的豆子,把一個或多個關係緊密的豆子包在一塊兒就是豆莢(一個Pod)。在k8s中咱們不會直接操做容器,而是把容器包裝成Pod再進行管理.node
a. 使用Replication Controller 來部署、升級Pod b. Replica Set – 下一代Replication Controller c. Deployment – 更加方便的管理Pod和Replica Set
例子1: 提出疑惑python
先舉個例子,假設咱們有一個Pod在提供線上服務,如今有以下幾個場景,你們想一想如何應對: 1.節日活動,網站訪問量突增 2.遭到攻擊,網站訪問量突增 3.運行Pod的節點發生故障 第1種狀況,活動前預先多啓動幾個Pod,活動結束後再結束掉多餘的,雖然要啓動和結束的Pod有點多,但也能有條不紊按計劃進行 第2種狀況,正在睡覺忽然手機響了說網站反應特慢卡得要死,趕忙爬起來邊擴容邊查找攻擊模式、封IP等等…… 第3種狀況,正在休假忽然手機又響了說網站上不去,趕忙打開電腦查看緣由,啓動新的Pod
解決辦法:引入rcnginx
Pod須要手動管理,好累……可否在Pod發生問題時自動恢復呢,咱們先來看下Replication Controller(如下簡稱RC) 先說RC是什麼。RC保證在同一時間可以運行指定數量的Pod副本,保證Pod老是可用。若是實際Pod數量比指定的多就結束掉多餘的,若是實際數量比指定的少就啓動缺乏的。
當Pod失敗、被刪除或被終結時RC會自動建立新的Pod來保證副本數量。因此即便只有一個Pod也應該使用RC來進行管理。
這個文件定義了RC的屬性,咱們先關注以下字段: spec.replicas:副本數量3 spec.selector:RC經過spec.selector來篩選要控制的Pod spec.template:這裏寫Pod的定義(但不須要apiVersion和kind) spec.template.metadata.labels:Pod的label,能夠看到這個label與spec.selector相同 這個文件的意思是定義了一個RC對象,它的名字是hello-rc(metadata.name:hello-rc),保證有3個Pod運行(spec.replicas:3),
Pod的鏡像是index.tenxcloud.com/tailnode/hello:v1.0(spec.template.spec.containers.image: index.tenxcloud.com/tailnode/hello:v1.0)
關鍵在於spec.selector與spec.template.metadata.labels,這兩個字段必須相同,不然下一步建立RC會失敗。
(也能夠不寫spec.selector,這樣默認與spec.template.metadata.labels相同)
如今經過kubectl來建立RC:docker
解決辦法:引入rs,官方推薦使用RS代替RC數據庫
1.RC只支持基於等式的selector(env=dev或environment!=qa)但Replica Set還支持新的基於集合的selector(version in (v1.0, v2.0)或env notin (dev, qa)),
這對複雜的運維管理帶來很大方便 2.使用Deployment升級Pod只須要定義Pod的最終狀態,k8s會爲你執行必要的操做,雖然可以使用命令kubectl rolling-update完成升級,
但它是在客戶端與服務端屢次交互控制RC完成的,因此REST API中並無rolling-update的接口,這爲定製本身的管理系統帶來了一些麻煩。 3.Deployment擁有更加靈活強大的升級、回滾功能
Replica Set目前與RC的區別只是支持的selector不一樣,後續確定會加入更多功能。Deployment使用了Replica Set,是更高一層的概念。除非須要自定義升級功能或根本不須要升級Pod,因此推薦使用Deployment而不直接使用Replica Set。api
step.1 kubectl 向 k8s api server 發起一個create pod 請求(即咱們使用Kubectl敲一個create pod命令) 。 step.2 k8s api server接收到pod建立請求後,不會去直接建立pod;而是生成一個包含建立信息的yaml。 step.3 apiserver 將剛纔的yaml信息寫入etcd數據庫。到此爲止僅僅是在etcd中添加了一條記錄, 尚未任何的實質性進展。 step.4 scheduler 查看 k8s api ,相似於通知機制。 首先判斷:pod.spec.Node == null? 若爲null,表示這個Pod請求是新來的,須要建立;所以先進行調度計算,找到最「閒」的node。 而後將信息在etcd數據庫中更新分配結果:pod.spec.Node = nodeA (設置一個具體的節點) ps:一樣上述操做的各類信息也要寫到etcd數據庫中中。 step.5 kubelet 經過監測etcd數據庫(即不停地看etcd中的記錄),發現 k8s api server 中有了個新的Node; 若是這條記錄中的Node與本身的編號相同(即這個Pod由scheduler分配給本身了); 則調用node中的docker api,建立container。
4.ReplicaSet建立流程網絡
step.1 kubectl 發起 create replicaSet 請求 step.2 k8s api server 接受 replicaSet 建立請求,建立yaml。 step.3 k8s api server將yaml的信息寫入etcd數據庫。 step.4 Controller-Manager中的ReplicaSetController,在etcd數據庫中讀到了新的replicaSet 信息後, 向k8s api server發起請求,建立3個Pod(個數能夠本身指定)。 step.5 scheduler 在etcd中讀到相應信息 若 3pod.spec.Node == null 則執行調度計算,找到最「閒」的若干個Node(若是有一個Node真的太閒,可能3個Pod都會被起在這個Node上面) pod1.spec.Node = nodeA (更新記錄) pod2.spec.Node = nodeB pod3.spec.Node = nodeA (Node都是隨機分配的) 將這些信息寫回etcd數據庫中。 step.6 nodeA 的 kubelet 讀etcd時讀到apiserver的信息,調用docker api;建立屬於本身的pod1/pod3的container step.7 nodeB kubelet 讀到 k8s api server的信息,調用docker api,建立pod2的container。
掛起(Pending):Pod 已被 Kubernetes 系統接受,但有一個或者多個容器鏡像還沒有建立。等待時間包括調度 Pod 的時間和經過網絡下載鏡像的時間,這可能須要花點時間。 運行中(Running):該 Pod 已經綁定到了一個節點上,Pod 中全部的容器都已被建立。至少有一個容器正在運行,或者正處於啓動或重啓狀態。 成功(Succeeded):Pod 中的全部容器都被成功終止,而且不會再重啓。 失敗(Failed):Pod 中的全部容器都已終止了,而且至少有一個容器是由於失敗終止。也就是說,容器以非0狀態退出或者被系統終止。 未知(Unknown):由於某些緣由沒法取得 Pod 的狀態,一般是由於與 Pod 所在主機通訊失敗。
Always: 當容器失效時, 由kubelet自動重啓該容器 OnFailure: 當容器終止運行且退出碼不爲0時, 由kubelet自動重啓該容器 Never: 不論容器運行狀態如何, kubelet都不會重啓該容器
kubelet重啓失效容器的時間間隔以sync-frequency乘以2n來計算, 例如1丶2丶4丶8倍等, 最長延時5min, 而且在重啓後的10min後重置該時間
pod的重啓策略與控制方式息息相關app
RC和DeamonSet必須設置爲Always,須要保證該容器持續運行
Job: OnFailure或Never, 確保容器執行完成後再也不重啓
Always: 表示每次都嘗試從新拉取鏡像 IfNotPresent: 表示若是本地有鏡像, 則使用本地的鏡像, 本地不存在時拉取鏡像 Never: 表示僅使用本地鏡像
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment namespace: default labels: app: nginx spec: selector: matchLabels: app: nginx replicas: 1 template: metadata: labels: app: nginx spec: restartPolicy: Always containers: - name: nginx image: nginx:1.12 imagePullPolicy: IfNotPresent ports: - containerPort: 80