Kubernetes控制器
Deployment -- 兩層控制器
通過(guò)ReplicaSet個(gè)數(shù)描述應(yīng)用版本(滾動(dòng)升級(jí)),再通過(guò)ReplicaSet屬性控制Pod數(shù)量(水平擴(kuò)展)

image
- Deployment 的控制器,實(shí)際上控制的是 ReplicaSet 的數(shù)目,以及每個(gè) ReplicaSet 的屬性。
- 一個(gè)應(yīng)用的版本,對(duì)應(yīng)的是一個(gè) ReplicaSet。這個(gè)版本應(yīng)用的 Pod 數(shù)量,則由 ReplicaSet 通過(guò)它自己的控制器(ReplicaSet Controller)來(lái)保證。
- 通過(guò)這樣的多個(gè) ReplicaSet 對(duì)象,Kubernetes 項(xiàng)目就實(shí)現(xiàn)了對(duì)多個(gè)“應(yīng)用版本”的描述。
有狀態(tài)應(yīng)用編排 -- Stateful
- 拓?fù)錉顟B(tài):應(yīng)用多實(shí)例有多種關(guān)系。主從、主備順序等。
- 存儲(chǔ)狀態(tài):應(yīng)用多實(shí)例分別綁定不同存儲(chǔ)數(shù)據(jù)。比如容器當(dāng)前讀取到的數(shù)據(jù)和半小時(shí)后讀取的數(shù)據(jù)是同一份數(shù)據(jù)。
- Stateful的實(shí)現(xiàn)方式就是記錄下這些狀態(tài),然后當(dāng)Pod被重建時(shí),恢復(fù)這些狀態(tài)。
Stateful 如何實(shí)現(xiàn)拓?fù)錉顟B(tài)?
外界如何訪問(wèn)Pod -- Service
Service就是外界連接Pod的網(wǎng)絡(luò)機(jī)制。比如一個(gè)Deployment控制了多個(gè)Pod,這是定義一個(gè)Service就能訪問(wèn)到這三個(gè)Pod。
那Service又是如何怎么被訪問(wèn)的呢
- 通過(guò)虛擬IP(virtual IP),當(dāng)訪問(wèn)一個(gè)預(yù)先定義好的VIP時(shí),K8s就會(huì)把這次的訪問(wèn)請(qǐng)求路由到Service上。
- 通過(guò)Service DNS,比如:
test-service.test-namespace.svc.cluster.test。在DNS解析時(shí)有兩種處理方式- 一種是通過(guò)
test-service.test-namespace.svc.cluster.test解析到VIP從而找到Pod - 另一種是訪問(wèn)時(shí),解析出來(lái)的就是直接暴露出來(lái)的Pod IP而不是VIP, 這種解析方式叫做
Headless Service。(Headless Service的定義其實(shí)就是將cluster IP字段置為None,從而讓這個(gè)Service沒有一個(gè)VIP 作為頭信息,從而暴露出Pod IP)
- 一種是通過(guò)
Stateful如何保持Pod拓?fù)錉顟B(tài)
- 當(dāng)定義Stateful時(shí)指定serviceName,比如如下,讓Stateful在控制循環(huán)的時(shí)候使用
test-sf來(lái)保證Pod的可解析身份
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: test-sf
spec:
serviceName: "test"
replicas: 2
selector:
matchLabels:
app: test-pod
template:
metadata:
labels:
app: test-pod
spec:
containers:
- name: test-pod
image: xxx
ports:
- containerPort: 80
name: testPod
- 當(dāng)啟動(dòng)
test這個(gè)svc和stateful后,Stateful就會(huì)創(chuàng)建兩個(gè)testPod,并為它們命名為 testPod-0 與 testPod-1 。然后Stateful就會(huì)把兩個(gè)Pod及其名稱存儲(chǔ)下來(lái),以后不管是testPod-0或1被刪除了,只要在Stateful生命周期內(nèi),這些順序關(guān)系就不會(huì)失效。
Stateful 如何實(shí)現(xiàn)存儲(chǔ)狀態(tài)?
Persistent Volume Claim
- 定義一個(gè) PVC,聲明想要的 Volume 的屬性:在這個(gè) PVC 對(duì)象里,不需要任何關(guān)于 Volume 細(xì)節(jié)的字段,只有描述性的屬性和定義。比如,storage: 1Gi,表示我想要的 Volume 大小至少是 1 GiB;accessModes: ReadWriteOnce,表示這個(gè) Volume 的掛載方式是可讀寫,并且只能被掛載在一個(gè)節(jié)點(diǎn)上而非被多個(gè)節(jié)點(diǎn)共享
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pv-claim-test
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
- 在應(yīng)用的 Pod 中,聲明使用這個(gè) PVC,只要我們創(chuàng)建這個(gè) PVC 對(duì)象,Kubernetes 就會(huì)自動(dòng)為它綁定一個(gè)符合條件的 Volume 即 pv
apiVersion: v1
kind: Pod
metadata:
name: pv-pod
spec:
containers:
- name: pv-container
image: nginx
ports:
- containerPort: 80
name: "http-server"
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: pv-storage
volumes:
- name: pv-storage
persistentVolumeClaim:
claimName: pv-claim-test
- Kubernetes 中 PVC 和 PV 的設(shè)計(jì),實(shí)際上類似于
接口和實(shí)現(xiàn)。開發(fā)者只要知道并會(huì)使用接口,即:PVC;而運(yùn)維人員則負(fù)責(zé)給接口綁定具體的實(shí)現(xiàn),即:PV。這種解耦,就避免了因?yàn)橄蜷_發(fā)者暴露過(guò)多的存儲(chǔ)系統(tǒng)細(xì)節(jié)而帶來(lái)的隱患。此外,這種職責(zé)的分離,往往也意味著出現(xiàn)事故時(shí)可以更容易定位問(wèn)題和明確責(zé)任
StatefulSet存儲(chǔ)狀態(tài)
- 回到StatefulSet對(duì)存儲(chǔ)狀態(tài)管理上來(lái)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: test-sf
spec:
serviceName: "test"
replicas: 2
selector:
matchLabels:
app: test-pod
template:
metadata:
labels:
app: test-pod
spec:
containers:
- name: test-pod
image: xxx
ports:
- containerPort: 80
name: xxx
volumeMounts:
- name: testVM
mountPath: /usr/share/xxx
volumeClaimTemplates:
- metadata:
name: testVM
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
- 這個(gè)
StatefulSet額外添加了一個(gè)volumeClaimTemplates字段。它跟 Deployment 里 Pod 模板(PodTemplate)的作用類似 => 凡是被這個(gè)StatefulSet管理的Pod,都會(huì)聲明一個(gè)對(duì)應(yīng)的 PVC;而這個(gè) PVC 的定義,就來(lái)自于volumeClaimTemplates這個(gè)模板字段。更重要的是,這個(gè) PVC 的名字,會(huì)被分配一個(gè)與這個(gè) Pod 完全一致的編號(hào)。這個(gè)自動(dòng)創(chuàng)建的 PVC,與 PV 綁定成功后,就會(huì)進(jìn)入 Bound 狀態(tài),這就意味著這個(gè) Pod 可以掛載并使用這個(gè) PV 了。 - 通過(guò)
kubectl get pvc -l app=nginx,可以看到,這些 PVC,都以<PVC 名字 >-<StatefulSet 名字 >-< 編號(hào) >的方式命名,并且處于 Bound 狀態(tài)。 - 這個(gè)
StatefulSet創(chuàng)建出來(lái)的所有 Pod,都會(huì)聲明使用編號(hào)的 PVC。比如,在名叫test-pod-0的 Pod 的 volumes 字段,它會(huì)聲明使用名叫testVM的 PVC,從而掛載到這個(gè) PVC 所綁定的 PV。
守護(hù)進(jìn)程 -- DaemonSet
- 舉個(gè)例子: 我們很多組件,比如網(wǎng)絡(luò)插件、存儲(chǔ)插件、監(jiān)控和日志組件都需要agent來(lái)幫助處理容器的網(wǎng)絡(luò),存儲(chǔ)目錄掛載、收集節(jié)點(diǎn)監(jiān)控?cái)?shù)據(jù)。而這個(gè)agent就是我們節(jié)點(diǎn)的守護(hù)進(jìn)程。
- 在K8s中,它也是一種編排對(duì)象 -- DaemonSet,它比其他所有對(duì)象的啟動(dòng)時(shí)機(jī)都要早。
- DaemonSetController通過(guò)給node打
污點(diǎn)的方式來(lái)保證 同樣能容忍這個(gè)污點(diǎn)的Pod 也就是 DaemonSet 的Pod 是第一個(gè)關(guān)聯(lián)到node上的。