一、Replication Controller 和 ReplicaSet
1、Replication Controller
????????Replication Controller(復制控制器,RC)
RC 用來確保 Pod 副本數達到期望值,這樣可以確保一個或多個同類 Pod 總是可用的。
如果存在的 Pod 數量大于設定的值,Replication Controller 將終止額外的 Pod,如果太少,Replication Controller 將會啟動更多的 Pod 用于保證達到期望值,與手動創建 Pod 不同的是,用 Replication Controller 維護的 Pod 在失敗、刪除或終止時會自動替換。因此,即使應用程序只需要一個 Pod,也應該使用 Replication Controller 或其他方式管理。Replication Controller 類似于進程管理程序,但是 Replication Controller 不是監視單個節點上的各個進程,而是監視多個節點上的多個 Pod。1.1、編輯ReplicationController文件(RC)
vim replicationcontroller-nginx.yaml
apiVersion: v1 kind: ReplicationController metadata:name: nginx spec:replicas: 3selector:app: nginxtemplate:metadata:name: nginxlabels:app: nginxspec:containers:- name: nginximage: nginx:1.7.9ports:- containerPort: 80
1.2、創建RC并查看
##創建 ku create -f replicationcontroller-nginx.yaml##查看 ku get node -o wide ku get rc
1.3、刪除并查看Pod是否會固定到預期值
ku delete pod nginx-r4hdn
1.4、刪除RC
ku delete -f replicationcontroller-nginx.yaml
2、標簽與標簽選擇器
2.1、標簽
????????標簽是用來標識 K8S 對象的一組附加在其上的鍵值對,通過標簽我們可以方便地篩選或排除一組對象。
借鑒資料中的話來講,集群中的應用部署或是批處理的程序部署通常都是多維度的,為了實現對這些對象的管理,往往需要對某一特定維度的對象進行操作,而標簽可以通過用戶的意愿組織集群中的對象之間的結構,而不需要對集群進行修改。
在同一個對象之下標簽的 Key 值必須唯一的。名稱方面,標簽名不得多于 63 個字符且必須由字母或數字開頭或結尾,可以包含字母、數字、-、、. 等字符;標簽前綴是可選的,必須以 DNS 子域名的方式指定,例如:kubernetes.io,后用 / 將其與標簽名分隔。通常情況下,若不使用標簽前綴,那么該標簽的 Key 將被視為專屬于用戶的,在 K8S 的系統組件向對象添加標簽時,必須指定前綴。在標簽值方面,若標簽值不為空,則其長度不得多于 63 個字符且必須由字母或數字開頭或結尾,可以包含字母、數字、-、、. 等字符。2.2、標簽選擇器
????????標簽選擇器可以用來選擇一組對象(標簽并不能唯一標識一個對象),APIServer 支持兩種標簽選擇器:基于等式的標簽選擇器與基于集合的標簽選擇器:
基于等式的標簽選擇方式:在這種選擇方式下可以使用 =、==、!= 三種操作符來進行選擇,前兩個的含義是一樣的,都代表相等,第三種代表不等。選擇條件可以通過,疊加,例如 date=day1,name!=build 代表選擇 date 值為 day1 且 name 值不為 build 的對象。
基于集合的標簽選擇方式:這種選擇器可以同時選擇一組對象。支持的操作符有:in、notin、exists。具體的使用方法為:
選擇 date 包含有值為 day1、day2、day3 的標簽:date in (day1, day2, day3)
選擇 name 值不為 build、pipline 的標簽:name notin (build, pipline)
選擇所有包含 test 的標簽:test
選擇所有不包含 test 的標簽:!test
基于集合的標簽選擇器也支持使用 “,” 分隔以同時疊加選擇,相同意義上的選擇條件在這兩種選擇方式之間是等價的2.3、標簽與標簽選擇器
不等式標簽選擇器
集合標簽選擇器
????????matchlabels 是 {key,value} 對的映射。matchlabels 映射中的單個 {key,value} 等價于 matchexpressions 的元素,其鍵字段為 “key”,運算符為 “in”,值數組僅包含 “value”。
matchexpressions 是 pod 選擇器需求的列表。有效的運算符包括 in、notin、exists 和 doesnotexist。對于 in 和 notin,設置的值必須為非空。matchlabels 和 matchexpressions 中的所有要求都被放在一起,必須滿足所有這些要求才能匹配。3、ReplicaSet
????????ReplicaSet(復制集,RS)是支持基于集合的標簽選擇器的下一代 Replication Controller,它主要用于 Deployment 協調創建、刪除和更新 Pod,和 Replication Controller 唯一的區別是,ReplicaSet 支持標簽選擇器。在實際應用中,雖然 ReplicaSet 可以單獨使用,但是一般建議使用 Deployment 來自動管理 ReplicaSet,除非自定義的 Pod 不需要更新或有其他編排等。
3.1、編輯
vim replicaset-example.yaml
apiVersion: apps/v1 kind: ReplicaSet metadata:name: frontendlabels:app: guestbooktier: frontend spec:# modify replicas according to your casereplicas: 3selector:matchLabels:tier: frontendmatchExpressions:- {key: tier, operator: In, values: [frontend]}template:metadata:labels:app: guestbooktier: frontendspec:containers:- name: php-redisimage: nginx:1.7.9resources:requests:cpu: 100mmemory: 100Mienv:- name: GET_HOSTS_FROMvalue: dnsports:- containerPort: 80
內容描述 具體說明 matchExpressions 性質 是一個列表,可包含多個匹配表達式,示例中僅含一個 列表條目標識 - 表示列表中的一個條目 具體匹配表達式結構 {key: tier, operator: In, values: [frontend]} ,包含以下部分 key 標簽鍵(label key),此處為 tier operator 匹配操作符,此處為 In ,表示 “在… 之中” values 匹配值列表,此處僅有一個值 [frontend] requests 含義 代表容器啟動請求的資源限制,分配的資源必須要達到此要求 limits 含義 代表最多可以請求多少資源 ????????這個匹配表達式的含義是:“選擇那些在其標簽中包含鍵為 tier 并且該鍵對應的值為 frontend 的對象。” 例如如下寫法:
matchExpressions:
-? {key: tier, operator: In, values: ["frontend"]}
-? {key: environment, operator: In, values: ["production", "staging"]}
CPU 的計量單位叫毫核 (m)。一個節點的 CPU 核心數量乘以 1000,得到的就是節點總的 CPU 總數量。如,一個節點有兩個核,那么該節點的 CPU 總量為 2000m。該容器啟動時請求 100/2000 的核心(5%)。3.2、創建RS
ku create -f replicaset-example.yaml ku get pod
3.3、刪除RS
ku delete -f replicaset-example.yaml ku get pod
二、無狀態應用管理 Deployment
1、什么是無狀態
????????無狀態服務(stateless service)對單次請求的處理,不依賴其他請求,也就是說,處理一次請求所需的全部信息,要么都包含在這個請求里,要么可以從外部獲取到(比如說數據庫),服務器本身不存儲任何信息。這種服務叫做無狀態服務。
無狀態服務:就是沒有特殊狀態的服務,各個請求對于服務器來說統一無差別處理,請求自身攜帶了所有服務端所需要的所有參數(服務端自身不存儲跟請求相關的任何數據,不包括數據庫存儲信息)
?如果在啟動一個服務時,不依賴于該服務之前的運行狀態,或者不依賴于其他服務,這個服務就是無狀態服務;反之,就是有狀態服務。2、特點
無狀態服務特點
特點 內容 數據方面 無狀態服務不會在本地存儲持久化數據,多個實例可共享相同持久化數據 結果方面 多個服務實例對同一用戶請求響應結果完全一致 關系方面 多服務實例之間無依賴關系 影響方面 在 k8s 控制器中動態啟停無狀態服務的 pod 不影響其它 pod 示例方面 nginx 實例、tomcat 實例、web 應用 資源方面 相關 k8s 資源有 ReplicaSet、ReplicationController、Deployment 創建方式 Deployment 被設計用來管理無狀態服務的 pod 擴容方式 隨機擴容,由于是無狀態服務,所以這些控制器創建的 pod 序號都是隨機值。并且在縮容也是隨機,并不會明確縮容某一個 pod。因為所有實例得到的返回值都是一樣,所以縮容任何一個 pod 都可以
特性描述 具體內容 Pod 創建順序 無狀態服務內多個 Pod 創建無順序 Pod 名稱特點 無狀態服務內多個 Pod 名稱隨機 Pod 重啟調度后變化 Pod 被重新啟動調度,名稱與 IP 都會變化 存儲情況 無狀態服務內多個 Pod 背后共享存儲 3、無狀態服務的應用場景
????????Deployment 用來管理 RS,并為 Pod 和 RS 提供聲明性更新,以及許多其他的新的功能,生產環境中使用 Deployment 替代 RS。
????????Deployment 一般用于部署公司的無狀態服務,因為企業內部現在都是以微服務為主,微服務實現無狀態化也是最佳實踐。可以利用 Deployment 的高級功能做到無縫遷移、自動擴容縮容、自動災難恢復、一鍵回滾等功能。
????????無狀態服務不會在本地存儲持久化數據。多個服務實例對于同一個用戶請求的響應結果是完全一致的。這種多服務實例之間是沒有依賴關系,比如 web 應用,在 k8s 控制器中動態啟停無狀態服務的 pod 并不會對其它的 pod 產生影響。
????????Deployment 被設計用來管理無狀態服務的 pod, 每個 pod 完全一致
無狀態服務內的多個 Pod 創建的順序是沒有順序的。
無狀態服務內的多個 Pod 的名稱是隨機的.pod 被重新啟動調度后,它的名稱與 IP 都會發生變化。
無狀態服務內的多個 Pod 背后是共享存儲的。4、創建Deployment
4.1、編輯配置文件
vim nginx-deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata:name: nginx-deploymentlabels:name: nginx-deployment spec:replicas: 2selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: nginx:1.7.9ports:- name: nginxcontainerPort: 80
- replicas:pod 的副本數
- selector:定義 Deployment 如何找到要管理的 Pod,與 template 的 label 標簽對應。
- template:
- app:nginx 使用 label 標記 pod
- spec:定義 pod 的詳細信息
- name:nginx 表示 pod 運行一個名字為 nginx 的容器
- image:運行此 pod 使用的鏡像
- port:容器用于發送和接收流量的端口
4.2、創建
ku create -f nginx-deployment.yaml
4.3、查看狀態
ku get pod -o wide
4.4、查看整個創建過程的狀態
ku rollout status deployment/nginx-deployment
4.5、查看Deployment對應的RC
ku get rs -l app=nginx
4.6、查看此Deployment創建的Pod
ku get pod --show-labels
5、更新 Deployment
????????通過 Deployment 部署應用后,如果需要對 Deployment 文件的配置文件或者鏡像版本進行更新,更改后該 Deployment 會創建新的 ReplicaSet,之后會對管理的 Pod 進行滾動升級。
5.1、更新鏡像
ku set image deployment nginx-deployment nginx=nginx:1.9.1 record ku set image deployment nginx-deployment nginx=nginz:1.12.0 record
5.2、查看更新過程
ku rollout status deployment nginx-deployment
5.3、通過describe查看更詳細信息
ku describe deployment nginx-deployment
6、回滾
6.1、滾動更新測試
ku set image deployment nginx-deployment nginx=dotbalo/canary:v1 --record ku set image deployment nginx-deployment nginx=dotbalo/canary:v2 --record
6.2、查看更新歷史
ku rollout history deployment nginx-deployment
6.3、查看指定版本的相關信息
查看名為?
nginx-deployment
?的 Deployment 在?版本 3(revision=3)?時的部署歷史詳情。具體來說,它會展示該 Deployment 在第 3 個版本時的相關信息,包括:
- 該版本部署時的配置參數(如鏡像版本、資源限制等)
- 部署的時間
- 可能的注釋信息等
ku rollout history deployment nginx-deployment --revision=2 ku rollout history deployment nginx-deployment --revision=3
6.4、回滾至上個版本
ku rollout undo deployment nginx-deployment
6.5、回滾到指定版本
ku rollout undo deployment nginx-deployment --to-revision=3
7、擴縮容
7.1、擴容
ku scale deployment nginx-deployment --replicas=3
7.2、縮容
ku scale deployment nginx-deployment --replicas=2
7.3、刪除
ku delete -f nginx-deployment.yaml
三、有狀態應用管理 StatefulSet
1、有狀態服務的定義
????????StatefulSet(有狀態集,縮寫為 sts)常用于部署有狀態的且需要有序啟動的應用程序。比如在生產環境中,可以部署 Elasticsearch 集群、MongoDB 集群或者需要持久化的 RabbitMQ 集群、Redis 集群、Kafka 集群和 ZooKeeper 集群等。
一個 StatefulSet 管理著基于相同容器規范的 Pod。與 Deployment 不同的是,StatefulSet 為每個 Pod 維護了一個標識。這些 Pod 是根據相同規范創建的,但是不可互換,每個 Pod 都有一個持久的標識符,在重新調度時也會被保留。2、有狀態服務的特征
分類 具體內容 數據方面 有狀態服務需在本地存儲持久化數據,典型應用是分布式數據庫 結果方面 實例之間,請求結果可能存在不一致 關系方面 分布式節點實例之間有依賴的拓撲關系,比如主從關系 影響方面 若 K8S 停止分布式集群中任一實例 pod,可能導致數據丟失或者集群 crash(崩潰) 示例方面 mysql 數據庫、kafka、zookeeper、Redis 主從架構 資源方面 statefulSet 創建方式 statefulSet 管理 Stateful 管理有狀態的應用,Pod 有如下特征:
特性 說明 唯一性 每個 Pod 會被分配一個唯一序號 順序性 Pod 啟動、更新、銷毀按順序進行 穩定網絡標識 Pod 主機名、DNS 地址不隨重新調度變化 穩定持久化存儲 Pod 重新調度后仍掛載原有 PV,保障數據完整一致 3、有狀態服務的應用場景
????????有狀態的 pod 是用來運行有狀態應用的,所以其在數據卷上存儲的數據非常重要,在 Statefulset 縮容時刪除這個聲明將是災難性的,特別是對于 Statefulset 來說,縮容就像減少其 replicas 數值一樣簡單。基于這個原因,當需要釋放特定的持久卷時,需要手動刪除對應的持久卷聲明。
???有狀態服務需要在本地存儲持久化數據,典型的是分布式數據庫的應用,分布式節點實例之間有依賴的拓撲關系,比如,主從關系,如果 K8S 停止分布式集群中任一實例 pod,就可能會導致數據丟失或者集群的 crash(崩潰)。
有狀態服務,可以說是需要數據存儲功能的服務、或者指多線程類型的服務,隊列等。(mysql 數據庫、kafka、zookeeper 等)
有狀態服務常常用于實現事務(并不是唯一辦法,下文有另外的方案)。舉一個常見的例子,在商城里購買一件商品,需要經過放入購物車、確認訂單、付款等多個步驟。由于 HTTP 協議本身是無狀態的,所以為了實現有狀態服務,就需要通過一些額外的方案。比如最常見的 session,將用戶挑選的商品(購物車),保存到 session 中,當付款的時候,再從購物車里取出商品信息 。4、無狀態服務和有狀態服務的比較
(1) 無狀態服務
服務不依賴自身的狀態,實例的狀態數據可以維護在內存中。
任何一個請求都可以被任意一個實例處理。
不存儲狀態數據,實例可以水平拓展,通過負載均衡將請求分發到各個節點。
在一個封閉的系統中,只存在一個數據閉環。
通常存在于單體架構的集群中。(2) 有狀態服務
服務本身依賴或者存在局部的狀態數據,這些數據需要自身持久化或者可以通過其他節點恢復。
一個請求只能被某個節點(或者同等狀態下的節點)處理。
存儲狀態數據,實例的拓展需要整個系統參與狀態的遷移。
在一個封閉的系統中,存在多個數據閉環,需要考慮這些閉環的數據一致性問題。
通常存在于分布式架構中5、編寫statefulSet文件
apiVersion: v1 kind: Service metadata:name: redis-svcspec:selector:app: redis-stsports:- port: 6379protocol: TCPtargetPort: 6379apiVersion: apps/v1 kind: StatefulSet metadata:name: redis-stsspec:serviceName: redis-svcreplicas: 2selector:matchLabels:app: redis-ststemplate:metadata:labels:app: redis-stsspec:containers:- image: redis:5-alpinename: redisports:- containerPort: 6379
kind: Service 定義名為 redis - svc 的服務,用于網絡訪問代理等。
kind: StatefulSet 定義名為 redis - sts 的有狀態集合,replicas 指定要部署的 Pod 副本5.1、創建sts
ku create -f redis-statefulset.yaml ku get sts
5.2、查看集群狀態
ku get po -l app=redis-sts
-l:指定標簽(label)
????????注意 NAME 列,名稱是 sts 的 name - 序號,這里序號越小則說明創建的越早從 AGE 列也可以看出來,這就解決了有狀態應用中的啟動順序問題,比如可以讓 redis-sts-0 作為 redis 的主節點,redis-sts-1 作為從節點
5.3、擴容
ku scale sts redis-sts --replicas=3
6、非級聯刪除sts
刪除 StatefulSet 有兩種方式:級聯刪除和非級聯刪除。
使用非級聯方式刪除 StatefulSet 時,StatefulSet 的 Pod 不會被刪除。使用級聯方式刪除 StatefulSet 時,StatefulSet 和它的 Pod 都會被刪除
ku delete sts redis-sts --cascade=false ku get po -l app=redis-sts ku delete pod redis-sts-0
7、級聯刪除sts
ku create -f redis-statefulset.yaml ku delete sts redis-sts
四、守護進程集 DaemonSet
1、什么是 DaemonSet
????????有時候我們需要在每個 Kubernetes 節點或符合條件的節點上都部署某個應用,那么就可以使用 Kubernetes 的 DaemonSet 調度 Pod。DaemonSet 確保全部(或符合條件)的節點上運行一個 Pod 副本。當有新的節點加入集群時,也會為他們新增一個 Pod,當節點從集群中移除時,這些 Pod 會被回收,刪除 DaemonSet 將會刪除它創建的所有的 Pod。
2、定義一個DaemonSet
vim daemonset-nginx.yaml
apiVersion: apps/v1 kind: DaemonSet metadata:name: pod-controllernamespace: devlabels:controller: daemonset spec:selector:matchLabels:app: nginx-podtemplate:metadata:labels:app: nginx-podspec:containers:- name: nginximage: nginx:1.7.9ports:- name: nginx-portcontainerPort: 80protocol: TCP
3、創建ns
ku create namespace dev
4、創建DaemonSet
ku create -f daemonset-nginx.yaml
5、查看DS
ku get -n dev ds -o wide
6、查看Pod所在節點
ku get -n dev pod -o wide
7、刪除DS
ku delete ds pod-controller -n dev
五、CronJob
????????Cronjob(計劃任務,縮寫為 cj)用于以時間為基準的周期性地執行任務,這些自動化任務和運行在 Linux 系統上的 CronJob 一樣。
1、編輯CJ文件
vim cronjob-example.yaml
apiVersion: batch/v1 #1.21版本以上 改為batch/v1 kind: CronJob metadata:name: hello spec:schedule: "*/1 * * * *"jobTemplate:spec:template:spec:containers:- name: helloimage: busybox:v1args:- /bin/sh- -c- date; echo Hello from the Kubernetes clusterrestartPolicy: OnFailure
這個案例會在每分鐘執行一次計劃任務
并輸出當前時間和“Hello from the Kubernetes cluster”2、創建CJ
ku create -f cronjob-example.yaml
3、查看CJ、Pod及日志
ku get cj ku get job ku get pod ku logs -f hello-29218506-772nd
4、刪除CJ
ku delete -f cronjob-example.yaml