一? ? pod 控制器相關理論介紹
1,Pod控制器?是什么
Pod控制器,又稱之為工作負載(workload),是用于實現管理pod的中間層,確保pod資源符合預期的狀態,pod的資源出現故障時,會嘗試進行重啟,當根據重啟策略無效,則會重新新建pod的資源。
?
2,pod控制器?類型
2.1?ReplicaSet
代用戶創建指定數量的pod副本,確保pod副本數量符合預期狀態,并且支持滾動式自動擴容和縮容功能。
ReplicaSet主要三個組件組成:
(1)用戶期望的pod副本數量
(2)標簽選擇器,判斷哪個pod歸自己管理
(3)當現存的pod數量不足,會根據pod資源模板進行新建
幫助用戶管理無狀態的pod資源,精確反應用戶定義的目標數量,但是RelicaSet不是直接使用的控制器,而是使用Deployment。
2.2??Deployment
工作在ReplicaSet之上,用于管理無狀態應用,目前來說最好的控制器。支持滾動更新和回滾功能,還提供聲明式配置。
ReplicaSet 與Deployment 這兩個資源對象逐步替換之前RC的作用。
?
2.3?DaemonSet
用于確保集群中的每一個節點只運行特定的pod副本,通常用于實現系統級后臺任務。比如ELK服務
特性:服務是無狀態的
服務必須是守護進程
?
2.4?StatefulSet
管理有狀態應用
應用范圍:
數據庫 ? ? ??分布式存儲 ? ??kafka ?等
2.5?Job
只要完成就立即退出,不需要重啟或重建
?
2.6?Cronjob
周期性任務控制,不需要持續后臺運行
?
3,什么是有狀態應用 和無狀態應用
3.1無狀態應用(Stateless Application)
定義:無狀態應用是指不依賴于任何先前交互上下文或會話數據的應用程序。每個請求都被視為獨立的,可以被任何實例處理,而不需要關心之前發生過什么。這類應用不保存客戶端會話數據,也不依賴于應用上次運行時的狀態。
特點:
- 可伸縮性:易于橫向擴展,可以簡單地增加或減少實例數量而不會影響應用狀態或導致數據一致性問題。
- 負載均衡:請求可以被任意實例處理,非常適合使用負載均衡器分發請求。
- 容錯性:實例可以隨時啟動或停止,因為沒有狀態需要保留,因此容錯性較高。
- 示例:簡單的Web服務器、API網關、緩存服務器(如Redis,當配置為不持久化數據時)等。
3.2 有狀態應用(Stateful Application)
定義:有狀態應用則相反,它需要維護一些跨請求或會話的數據狀態。這些應用依賴于特定實例上的數據或需要存儲和跟蹤客戶端交互的歷史信息,如用戶會話、數據庫連接或文件系統中的特定文件。
特點:
- 持久化存儲:需要持久化存儲來維持狀態,如數據庫、文件系統或專用存儲卷。
- 有序擴展:擴展時需要考慮狀態的連續性,不能隨意添加或移除實例,因為數據一致性至關重要。
- 標識與持久性:每個實例通常需要唯一的標識,并且與存儲資源綁定,如Kubernetes中的StatefulSet資源就為此設計。
- 示例:數據庫(如MySQL)、消息隊列(如RabbitMQ)、用戶會話服務等。
總結:有狀態應用和無狀態應用的主要區別在于是否需要維護持久化的狀態信息。無狀態應用更易于部署和擴展,而有狀態應用則需要更復雜的管理機制來確保數據的一致性和持久化。在設計和部署現代云原生應用時,理解這兩者的差異對于選擇合適的服務管理和部署策略至關重要。
4,??Pod與控制器之間的關系
controllers:在集群上管理和運行容器的 pod 對象, pod 通過 label-selector 相關聯。
Pod 通過控制器實現應用的運維,如伸縮,升級等。
Pods與控制器(Controllers)的基本概念:
Pod: 是Kubernetes中的最小可部署單元,包含一個或多個緊密相關的容器(例如微服務的一個實例),這些容器共享存儲和網絡空間。Pod用來封裝應用的運行環境。
控制器(Controllers): 是更高層次的抽象,用于管理Pod的生命周期,確保Pod按照預期的數量、狀態運行。常見的控制器包括Deployment、StatefulSet、DaemonSet、Job和CronJob等。
通過label-selector相關聯:
- 控制器管理Pod的方式之一是使用
label-selector
。每個Pod都會被打上一組鍵值對標簽(labels),控制器則根據這些標簽來選擇并管理目標Pod。例如,一個Deployment可能會配置為管理所有帶有特定標簽(如app=my-web-server
)的Pods,這樣控制器就能準確地知道哪些Pod屬于它的管理范圍,即使Pod因故障重建或擴縮容而發生變化。Pod通過控制器實現應用的運維:
伸縮(Scaling): 控制器允許自動或手動調整托管Pod的數量,以應對負載變化。比如,Deployment可以設置副本數(replicas),自動增加或減少Pod的數量以響應流量需求。
升級(Rolling Updates/Rollbacks): 控制器支持平滑升級,能夠在不中斷服務的情況下逐步替換舊版本Pod為新版本Pod。如果新版本有問題,還可以輕松回滾到之前的穩定版本。
健康檢查與自愈: 控制器負責監控Pod的健康狀況,如果發現某個Pod不健康或失敗,它會自動創建新的Pod替換它,確保應用總是按預期運行。
綜上所述,Pod與控制器之間的關系是:控制器利用label-selector機制識別并管理Pod集合,通過實施策略(如自動伸縮、滾動更新)來實現應用的自動化運維,保證服務的高可用性和靈活性。這種方式極大地簡化了分布式系統的服務管理和運維工作。
二? ?pod?控制器?實例演示
1,?Deployment
部署無狀態應用
管理Pod和ReplicaSet
具有上線部署、副本設定、滾動升級、回滾等功能
提供聲明式更新,例如只更新一個新的image
應用場景:web服務
deployment?啟動nginx pod
vim nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-deploymentlabels:app: nginx
spec:replicas: 3selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: nginx:1.15.4ports:- containerPort: 80
原神!?啟動!
kubectl create -f nginx-deployment.yaml
查看控制器配置
kubectl edit deployment/nginx-deployment
apiVersion: apps/v1
kind: Deployment
metadata:annotations:deployment.kubernetes.io/revision: "1"creationTimestamp: "2021-04-19T08:13:50Z"generation: 1labels:app: nginx #Deployment資源的標簽name: nginx-deploymentnamespace: defaultresourceVersion: "167208"selfLink: /apis/extensions/v1beta1/namespaces/default/deployments/nginx-deploymentuid: d9d3fef9-20d2-4196-95fb-0e21e65af24a
spec:progressDeadlineSeconds: 600replicas: 3 #期望的pod數量,默認是1revisionHistoryLimit: 10selector:matchLabels:app: nginxstrategy:rollingUpdate:maxSurge: 25% #升級過程中會先啟動的新Pod的數量不超過期望的Pod數量的25%,也可以是一個絕對值maxUnavailable: 25% #升級過程中在新的Pod啟動好后銷毀的舊Pod的數量不超過期望的Pod數量的25%,也可以是一個絕對值type: RollingUpdate #滾動升級template:metadata:creationTimestamp: nulllabels:app: nginx #Pod副本關聯的標簽spec:containers:- image: nginx:1.15.4 #鏡像名稱imagePullPolicy: IfNotPresent #鏡像拉取策略name: nginxports:- containerPort: 80 #容器暴露的監聽端口protocol: TCPresources: {}terminationMessagePath: /dev/termination-logterminationMessagePolicy: FilednsPolicy: ClusterFirstrestartPolicy: Always #容器重啟策略schedulerName: default-schedulersecurityContext: {}terminationGracePeriodSeconds: 30
......
查看歷史版本
kubectl rollout history deployment/nginx-deployment
deployment.apps/nginx-deployment
REVISION CHANGE-CAUSE
1 <none>
2,?DaemonSet
2.1?DaemonSet?是什么
DaemonSet 確保全部(或者一些)Node 上運行一個 Pod 的副本。當有 Node 加入集群時,也會為他們新增一個 Pod 。當有 Node 從集群移除時,這些 Pod 也會被回收。刪除 DaemonSet 將會刪除它創建的所有 Pod。
?
2.2?DaemonSet?典型用法
●運行集群存儲 daemon,例如在每個 Node 上運行 glusterd、ceph。
●在每個 Node 上運行日志收集 daemon,例如fluentd、logstash。
●在每個 Node 上運行監控 daemon,例如 Prometheus Node Exporter、collectd、Datadog 代理、New Relic 代理,或 Ganglia gmond。
應用場景:Agent
?
2.3?官方案例
//官方案例(監控)
https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/
?
2.4?示例
vim ds.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:name: nginx-daemonSetlabels:app: nginx
spec:selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: nginx:1.15.4ports:- containerPort: 80
DaemonSet會在每個node節點都創建一個Pod
kubectl apply -f ds.yamlkubectl get pods
nginx-deployment-4kr6h 1/1 Running 0 35s
nginx-deployment-8jrg5 1/1 Running 0 35s
3,??Job
常用于運行那些僅需要執行一次的任務
?
?3.1??應用場景
數據庫遷移、批處理腳本、kube-bench掃描、離線數據處理,視頻解碼等業務
?
3.2?官網
https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/?? ?
?
3.3?實例
寫yaml
vim job.yaml
apiVersion: batch/v1
kind: Job
metadata:name: pi
spec:template:spec:containers:- name: piimage: perlcommand: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]restartPolicy: NeverbackoffLimit: 4
//參數解釋
.spec.template.spec.restartPolicy該屬性擁有三個候選值:OnFailure,Never和Always。默認值為Always。它主要用于描述Pod內容器的重啟策略。在Job中只能將此屬性設置為OnFailure或Never,否則Job將不間斷運行。.spec.backoffLimit用于設置job失敗后進行重試的次數,默認值為6。默認情況下,除非Pod失敗或容器異常退出,Job任務將不間斷的重試,此時Job遵循 .spec.backoffLimit上述說明。一旦.spec.backoffLimit達到,作業將被標記為失敗。
?在所有node節點下載perl鏡像,因為鏡像比較大,所以建議提前下載好
docker pull perl
執行
kubectl apply -f job.yaml kubectl get pods
pi-bqtf7 0/1 Completed 0 41s
結果輸出到控制臺
kubectl logs pi-bqtf7
3.14159265......
4,?CronJob?
4.1?是什么
周期性任務,像Linux的Crontab一樣。
周期性任務
?
4.2?應用場景
通知,備份
https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs/
4.3?實例
每分鐘打印hello
vim cronjob.yaml
apiVersion: batch/v1beta1
kind: CronJob
metadata:name: hello
spec:schedule: "*/1 * * * *"jobTemplate:spec:template:spec:containers:- name: helloimage: busyboximagePullPolicy: IfNotPresentargs:- /bin/sh- -c- date; echo Hello from the Kubernetes clusterrestartPolicy: OnFailure
//cronjob其它可用參數的配置
spec:
? concurrencyPolicy: Allow? ? ? ? ? ? ? ? ? ? ? ? ? ?#要保留的失敗的完成作業數(默認為1)
? schedule: '*/1 * * * *'? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#作業時間表。在此示例中,作業將每分鐘運行一次
? startingDeadlineSeconds: 15? ? ? ? ? ? ? ? ? ? ? ?#pod必須在規定時間后的15秒內開始執行,若超過該時間未執行,則任務將不運行,且標記失敗
? successfulJobsHistoryLimit: 3? ? ? ? ? ? ? ? ? ? ?#要保留的成功完成的作業數(默認為3)
? terminationGracePeriodSeconds: 30? ? ? ? ? ?#job存活時間 默認不設置為永久
? jobTemplate:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#作業模板。這類似于工作示例
?
執行? ? 查看計劃任務
kubectl create -f cronjob.yaml kubectl get cronjob
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
hello */1 * * * * False 0 <none> 25s
查看日志
kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-1621587180-mffj6 0/1 Completed 0 3m
hello-1621587240-g68w4 0/1 Completed 0 2m
hello-1621587300-vmkqg 0/1 Completed 0 60s
kubectl logs hello-1621587180-mffj6
Fri May 21 09:03:14 UTC 2021
Hello from the Kubernetes cluster
4.4?報錯
//如果報錯:Error from server (Forbidden): Forbidden (user=system:anonymous, verb=get, resource=nodes, subresource=proxy) ( pods/log hello-1621587780-c7v54)
//解決辦法:綁定一個cluster-admin的權限
kubectl create clusterrolebinding system:anonymous --clusterrole=cluster-admin --user=system:anonymous
三? ??SatefulSet? 單獨介紹
1,理論
1.1?SatefulSet?是什么
部署有狀態應用
穩定的持久化存儲,即Pod重新調度后還是能訪問到相同的持久化數據,基于PVC來實現
穩定的網絡標志,即Pod重新調度后其PodName和HostName不變,基于Headless Service(即沒有Cluster IP的Service)來實現
有序部署,有序擴展,即Pod是有順序的,在部署或者擴展的時候要依據定義的順序依次進行(即從0到N-1,在下一個Pod運行之前所有之前的Pod必須都是Running和Ready狀態),基于init containers來實現
有序收縮,有序刪除(即從N-1到0)
?
1.2?常見的應用場景
用在數據庫
和 分布式存儲
和 kafka
1.3?官網
https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/
1.4?yaml?文件實例
apiVersion: v1
kind: Service
metadata:name: nginxlabels:app: nginx
spec:ports:- port: 80name: webclusterIP: Noneselector:app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:name: web
spec:selector:matchLabels:app: nginx # has to match .spec.template.metadata.labelsserviceName: "nginx"replicas: 3 # by default is 1template:metadata:labels:app: nginx # has to match .spec.selector.matchLabelsspec:terminationGracePeriodSeconds: 10containers:- name: nginximage: k8s.gcr.io/nginx-slim:0.8ports:- containerPort: 80name: webvolumeMounts:- name: wwwmountPath: /usr/share/nginx/htmlvolumeClaimTemplates:- metadata:name: wwwspec:accessModes: [ "ReadWriteOnce" ]storageClassName: "my-storage-class"resources:requests:storage: 1Gi
?
2,?三個組件
從上面的應用場景可以發現,StatefulSet由以下幾個部分組成:
●Headless Service(無頭服務):用于為Pod資源標識符生成可解析的DNS記錄。
●volumeClaimTemplates(存儲卷申請模板):基于靜態或動態PV供給方式為Pod資源提供專有的固定存儲。
●StatefulSet:用于管控Pod資源。
2.1?為什么要有headless?
在deployment中,每一個pod是沒有名稱,是隨機字符串,是無序的。而statefulset中是要求有序的,每一個pod的名稱必須是固定的。當節點掛了,重建之后的標識符是不變的,每一個節點的節點名稱是不能改變的。pod名稱是作為pod識別的唯一標識符,必須保證其標識符的穩定并且唯一。
為了實現標識符的穩定,這時候就需要一個headless service 解析直達到pod,還需要給pod配置一個唯一的名稱。
?
2.2?為什么要有volumeClainTemplate?
大部分有狀態副本集都會用到持久存儲,比如分布式系統來說,由于數據是不一樣的,每個節點都需要自己專用的存儲節點。而在 deployment中pod模板中創建的存儲卷是一個共享的存儲卷,多個pod使用同一個存儲卷,而statefulset定義中的每一個pod都不能使用同一個存儲卷,由此基于pod模板創建pod是不適應的,這就需要引入volumeClainTemplate,當在使用statefulset創建pod時,會自動生成一個PVC,從而請求綁定一個PV,從而有自己專用的存儲卷。
?
3,?服務發現
3.1?定義
就是應用服務之間相互定位的過程。
3.2?應用場景
●動態性強:Pod會飄到別的node節點
●更新發布頻繁:互聯網思維小步快跑,先實現再優化,老板永遠是先上線再慢慢優化,先把idea變成產品掙到錢然后再慢慢一點一點優化
●支持自動伸縮:一來大促,肯定是要擴容多個副本
?
3.3?K8S里服務發現的方式
DNS,使K8S集群能夠自動關聯Service資源的“名稱”和“CLUSTER-IP”,從而達到服務被集群自動發現的目的。
?
3.4?實現K8S里DNS功能的插件:
●skyDNS:Kubernetes 1.3之前的版本
●kubeDNS:Kubernetes 1.3至Kubernetes 1.11
●CoreDNS:Kubernetes 1.11開始至今
?
4,?安裝CoreDNS
僅二進制部署環境需要安裝CoreDNS
CoreDNS用于提供解析服務與自動發現,使K8S集群能夠自動關聯Service資源的“名稱”和“CLUSTER-IP”,從而達到服務被集群自動發現的目的
使用kubeadm安裝或其它一鍵安裝k8s集群的,會默認安裝CoreDNS,只有當使用二進制安裝的時候,需要手動去安裝CoreDNS
4.1?方法一
下載鏈接:https://github.com/kubernetes/kubernetes/blob/master/cluster/addons/dns/coredns/coredns.yaml.base
vim transforms2sed.sed
s/__DNS__SERVER__/10.0.0.2/g
s/__DNS__DOMAIN__/cluster.local/g
s/__DNS__MEMORY__LIMIT__/170Mi/g
s/__MACHINE_GENERATED_WARNING__/Warning: This is a file generated from the base underscore template file: coredns.yaml.base/gsed -f transforms2sed.sed coredns.yaml.base > coredns.yaml
4.2??方法二
上傳 coredns.yaml 文件
kubectl create -f coredns.yamlkubectl get pods -n kube-system
4.3? 驗證DNS是否可以使用
[root@master01 pod]#kubectl run busybox --image=busybox:1.28 -- sleep 36000
pod/busybox created
#創建一個busybox的pod,該容器提供一些基本的命令,主要用于測試環境
[root@master01 pod]#kubectl get pod busybox
NAME READY STATUS RESTARTS AGE
busybox 1/1 Running 0 4s
[root@master01 pod]#kubectl exec -it busybox sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # nslookup kubernetes #測試svc能否正常解析,可以使用kubectl get svc查看有哪些svc
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.localName: kubernetes
Address 1: 10.96.0.1 kubernetes.default.svc.cluster.local
#解析正常,解析kubernetes的地址為10.96.0.1
[root@master01 pod]#kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13d
mydb ClusterIP 10.96.50.193 <none> 80/TCP 5d17h
myservice ClusterIP 10.96.33.11 <none> 80/TCP 5d17h
nginx ClusterIP 10.96.222.66 <none> 80/TCP 3d20h
5,???創建service(無頭模式)
StatefulSet 資源依賴于無頭模式的service
[root@master01 pod]#vim service.yaml
[root@master01 pod]#cat service.yaml
apiVersion: v1 #指定API版本
kind: Service #創建資源類型為Service
metadata:name: headless-svc #指定service名稱labels:app: headless-svc #設置service標簽
spec:ports:- port: 80 #service端口name: web #端口名稱targetport: 80 #指定流量轉發的目標端口,與pod暴露的端口一致clusterIP: None #將clusterIP地址的值設置為None,表示無IP地址,即無頭模式selector: #選擇管理的標簽app: state #此標簽需要與StatefulSet控制器管理的pod模板中定義的標簽一致type: ClusterIP #設置類型為ClusterIP,此為默認設置,可以省略
創建service
[root@master01 pod]#kubectl apply -f service.yaml
service/headless-svc created
[root@master01 pod]#kubectl get svc headless-svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
headless-svc ClusterIP None <none> 80/TCP 10s
6,?創建StatefulSet
[root@master01 pod]#vim statefulset.yaml
[root@master01 pod]#cat statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet #創建資源類型為StatefulSet
metadata:name: state #指定資源名稱
spec:serviceName: headless-svc #指定需要綁定的service名稱replicas: 3 #創建pod數量為三個selector: #標簽選擇器,指定StatefulSet要管理哪些podmatchLabels: #指定標簽名稱app: state #必須與service中selector定義的標簽一致。pod含有此標簽的,都會去管理template: #指定pod創建模板metadata:labels:app: state #設置pod標簽,與上面標簽選擇器相同,StatefulSet才會管理spec:containers: #定義pod中運行的容器- name: nginx-pod #應當設置有狀態的服務,在此以nginx為例,官方文檔有MySQL示例image: nginx:1.18.0 #定義鏡像ports:- containerPort: 80 #定義容器監聽端口name: web #端口名稱volumeMounts: #定義將存儲卷卷掛載到指定目錄- name: html #指定存儲卷名稱mountPath: /usr/share/nginx/html #掛載到此目錄,此目錄為nginx服務的站點目錄volumeClaimTemplates: #PVC的請求模板- metadata:name: html #定義PVC的名稱annotations:volume.beta.kubernetes.io/storage-class: nfs-client-storageclass
#用于指定存儲類的注解。該存儲類定義了用于動態卷供應的后端存儲類型spec:accessModes: ["ReadWriteOnce"] #指定訪問模式為RWOresources:requests:storage: 2Gi #指定存儲卷的使用大小
創建pod查看
[root@master01 pod]#kubectl apply -f statefulset.yaml
statefulset.apps/state created
[root@master01 pod]#kubectl get statefulsets.apps state
NAME READY AGE
state 2/3 14s
[root@master01 pod]#kubectl get statefulsets.apps state
NAME READY AGE
state 3/3 17s
[root@master01 pod]#kubectl get pod
NAME READY STATUS RESTARTS AGE
busybox 1/1 Running 0 40m
nfs-client-provisioner-794bf7886f-85bwb 1/1 Running 0 5h51m
state-0 1/1 Running 0 25s
state-1 1/1 Running 0 19s
state-2 1/1 Running 0 13s
#它會按照0到N-1的順序去指定pod名稱,一定建立,指定pod生命周期結束,否則IP地址改變,它的名稱也不會改變
創建完之后,查看一下PV與PVC
在NFS服務器上自定義web界面
[root@nfs k8s]#ls
default-html-state-0-pvc-0bffc66c-b29e-40cd-bef5-18c1abe250af #state-0的PV卷
default-html-state-1-pvc-1aaee76c-7c94-4a8d-abc3-0b4f804239bc #state-1的PV卷
default-html-state-2-pvc-f82bb183-c3d8-49b1-be39-c4ee96f7e076 #state-2的PV卷
[root@nfs k8s]#echo "this is state-0" > default-html-state-0-pvc-0bffc66c-b29e-40cd-bef5-18c1abe250af/index.html
[root@nfs k8s]#echo "this is state-1" > default-html-state-1-pvc-1aaee76c-7c94-4a8d-abc3-0b4f804239bc/index.html
[root@nfs k8s]#echo "this is state-2" > default-html-state-2-pvc-f82bb183-c3d8-49b1-be39-c4ee96f7e076/index.html
由于沒有ClusterIP地址,想要通過IP地址訪問,只能在k8s集群中直接訪問podIP
7,? ?使用service訪問
此時,創建的service是可以進行解析的?
[root@master01 pod]#kubectl exec -it busybox sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # nslookup headless-svc
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.localName: headless-svc
Address 1: 10.244.2.208 state-0.headless-svc.default.svc.cluster.local
Address 2: 10.244.1.189 state-1.headless-svc.default.svc.cluster.local
Address 3: 10.244.2.209 state-2.headless-svc.default.svc.cluster.local
#該service會通過endpoint關聯到后端的pod
由于pod的IP地址是k8s集群內部的IP地址,且并沒有clusterIP去綁定podIP,只有域名管理,宿主機的DNS解析,無法解析k8s集群內部的域名與地址,所以使用宿主機無法訪問pod。只能通過創建pod,在pod中進行訪問
可以看到,訪問的pod是隨機的,因為k8s內部的負載均衡方式,是通過資源的使用率進行分配的,它會將請求優先分配到資源使用率較少的pod上,可以使用壓測工具去測試,而后再進行訪問?
8,?刪除與創建
當pod刪除時,會按照N-1到0的順序,倒序刪除?
[root@master01 pod]#kubectl delete -f statefulset.yaml
statefulset.apps "state" deleted
[root@master01 pod]#kubectl get pod -w
NAME READY STATUS RESTARTS AGE
busybox 1/1 Running 0 65m
centos 1/1 Running 0 9m12s
nfs-client-provisioner-794bf7886f-85bwb 1/1 Running 0 6h16m
state-0 1/1 Running 0 25m
state-1 1/1 Running 0 25m
state-2 1/1 Running 0 25m
state-2 1/1 Terminating 0 25m
state-1 1/1 Terminating 0 25m
state-0 1/1 Terminating 0 25m
state-2 0/1 Terminating 0 25m
state-1 0/1 Terminating 0 25m
state-0 0/1 Terminating 0 25m
state-2 0/1 Terminating 0 25m
state-1 0/1 Terminating 0 25m
state-0 0/1 Terminating 0 25m
重新創建的時候,數據會持久化 ,而且創建的順序還是按照0到N-1的順序創建?
重新創建之后再次訪問,數據不會丟失?
再次解析service的話,它的解析地址會發生改變
?
這就是無頭模式的作用,不論后端的IP地址如何變化,只通過DNS來解析service,從而綁定后端的IP地址,得到數據
9,??小結
StatefulSet控制器的實現,是一個相對復雜的過程,需要大家在平時多練多學,在生成環境中才能避免出現問題,因為StatefulSet管理的都是一些有狀態的服務,一旦容器失敗,導致數據丟失,可能會造成不好的影響
deployment與statefulset的區別
4.1 應用場景
Deployment:主要用于部署無狀態服務,即服務實例之間可以相互替換且不需要保留特定的網絡標識或存儲數據。它適用于那些不需要關心Pod具體身份且可任意替換的彈性服務。
StatefulSet:適用于部署有狀態的服務,比如數據庫集群、消息隊列等。這些服務需要穩定的持久化存儲和唯一、有序的網絡標識。StatefulSet為Pod分配的網絡標識符和存儲都是穩定的,使得應用能夠維持跨重啟或再調度的持久狀態。
4.2 Pod管理
Deployment:通過ReplicaSet確保指定數量的Pod副本始終運行,提供水平擴展和滾動更新能力。Pod由Deployment創建時,雖然可以自定義名稱,但通常由系統生成,并在重建或擴展時可能會發生變化。
StatefulSet:Pods在創建、更新和刪除時按照順序進行,以滿足那些依賴于嚴格順序啟動或停止的應用場景需求。每個Pod都有一個固定的、唯一的網絡標識符,并且其持久卷聲明(PVC)會綁定到持久化的存儲,即使Pod被刪除后重新創建,存儲的數據也會保留。
4.3 存儲與網絡
Deployment:通常不直接管理Pod的存儲和網絡,而是依賴于其他Kubernetes資源(如PersistentVolume和Service)來實現這些功能。
StatefulSet:為Pod提供穩定的存儲和網絡標識,確保有狀態應用能夠正常運行。StatefulSet通常與Headless Service和volumeClaimTemplate一起使用,以提供可解析的DNS資源記錄和專有且固定的存儲。
4.4 升級與回滾
Deployment:支持多種升級策略,如滾動更新和回滾,確保服務在整個升級過程中具有高可用性。通過更新Deployment的PodTemplateSpec字段來聲明Pod的新狀態,并逐步替換舊的Pod。
StatefulSet:也支持有序而自動的滾動更新,但由于涉及到有狀態應用,更新過程可能更加復雜和嚴格。同時,StatefulSet也支持回滾到之前的版本。
4.5 擴展性
Deployment:可以根據系統負載進行水平擴展和縮容,通過調整ReplicaSet的副本數來實現。
StatefulSet:雖然也支持擴展和縮容操作,但由于涉及到有狀態應用和數據一致性等問題,擴展性可能相對較弱。
10,??Headless Service
和 Cluster IP Service 是 Kubernetes (K8s) 中兩種不同類型的Service資源,它們的主要區別在于服務發現機制和流量管理方式。
Cluster IP Service:
-
概述: 這是Kubernetes中最常見的Service類型,它為一組Pod提供一個固定的、虛擬的Cluster IP地址和一個或多個端口。這個Cluster IP地址充當服務的前端入口,客戶端通過這個地址訪問服務,而實際流量會被kube-proxy組件根據負載均衡策略轉發到后端的一個或多個Pod上。
-
特點:
-
分配一個虛擬的Cluster IP。
-
通過kube-proxy實現負載均衡。
-
隱藏了后端Pod的細節,客戶端只與Cluster IP交互。
-
適用于需要負載均衡和高可用性的場景。
-
Headless Service:
-
概述: Headless Service不分配Cluster IP,意味著沒有一個中心的IP地址來負載均衡流量。當創建Headless Service時,Kubernetes不會為它分配Cluster IP,也不會通過kube-proxy來進行請求的代理或負載均衡。
-
特點:
-
不分配Cluster IP。
-
kube-proxy不會處理這類Service,不提供負載均衡。
-
每個關聯的Pod都有獨立的DNS記錄,可以直接通過Pod的IP或其DNS名稱訪問。
-
適用于需要直接訪問Pod、狀態ful應用(如MongoDB副本集)、或者客戶端需要自己決定連接哪個Pod的場景。
-
-
實現方式:
-
在DNS層面,Headless Service會返回一個包含所有關聯Pod IP地址的DNS記錄(通常是A或AAAA記錄的列表),允許客戶端直接選擇并連接到特定的Pod。
-
由于沒有Cluster IP,客戶端或服務間的通信可以更直接,適用于需要維護會話黏性或有特定Pod選擇邏輯的應用場景。
-
綜上,Headless Service通過放棄Cluster IP和負載均衡功能,提供了更直接的Pod訪問途徑,增加了服務發現的靈活性,特別適合那些需要直接交互或有狀態應用的場景。