您好,登錄后才能下訂單哦!
K8s有狀態(tài)應(yīng)用部署
目錄:分為兩類
1.Headless Service
2.StatefulSet
? 部署有狀態(tài)應(yīng)用
? 解決Pod獨立生命周期,保持Pod啟動順序和唯一性
說在前面的話,像我們的Mysql或者Redis了,Zookerper等等這些適不適合部署在K8s中,其實呢不是太適合,但部署在里面也可以,比如部署一個Mysql來講吧,部署到k8s中還是很容易的就一個Mysql實例,就像部署其他應(yīng)用一樣,通過service、IP去訪問它,但是要是作為集群的狀態(tài)去部署的話,那可能就比較麻煩了。
第一點:比如做一個Mysql的主從,Mysql主從它是有主從拓?fù)潢P(guān)系的,一個主一個從,而且各自的數(shù)據(jù)都不一樣,這就意味著,你要想搭建一個Mysql的主從,你要知道它的相互的ip地址,就是從肯定要知道主的ip地址,然后從連接主的ip地址,做數(shù)據(jù)的同步。
第二點:它的存儲,它兩個存儲的信息都不太一樣,那怎么去保證它兩個數(shù)據(jù)的存儲保證持久化呢,一個集群中可能會有多個節(jié)點,要是部署到k8s中,必須要保證部署的應(yīng)用,在任意的節(jié)點都能使用原來的狀態(tài),也就是說某一個節(jié)點掛了,上面的pod飄移到另一個節(jié)點,能不能用到之前的狀態(tài),所以要考慮這些問題。
而k8s設(shè)計的精髓在于并不是你部署一個單的實例,而是在于它的一個分布式一個部署,具有故障恢復(fù)能力的應(yīng)用,所以就談到了有狀態(tài)和無狀態(tài)應(yīng)用。
有狀態(tài)應(yīng)用:DB,好比一個Mysql主從,考慮兩點(自己的存儲,必須是遠(yuǎn)程的存儲,在任意節(jié)點掛載都恢復(fù)原來的狀態(tài))而且還有網(wǎng)絡(luò)ID的唯一,需要做主從的連接,我們的pod是短暫的,重建一個ip就換了,得保證這個ip一直去使用,不管是重建還是遷移pod,都能去使用。
無狀態(tài)應(yīng)用:典型的就是web系統(tǒng),本身就沒有什么狀態(tài)去維護,比如部署了三個副本,不需要考慮其他兩個副本是什么樣的,跟它沒有直接的關(guān)系,本地也沒有什么持久化的數(shù)據(jù),即使其中有一個副本掛了,幫它在其他節(jié)點起來,仍然可以繼續(xù)提供服務(wù),對原基礎(chǔ)服務(wù)是沒有任何影響的,所以這是一個前提,典型的就是web。
在k8s中呢在1.10版本之后有狀態(tài)部署才支持好一點,但是剛開始在落地K8s的時候,而不會去考慮有狀態(tài)部署的,主要做無狀態(tài)的部署,而數(shù)據(jù)庫適不適合部署在k8s中,在看k8s的一些特性,k8s有適合的一些特性,比如具有一些訪問比較大的應(yīng)用,版本迭代快的應(yīng)用,或者彈性伸縮的一些應(yīng)用,凡是這些是適合放在k8s,k8s最早就支持無狀態(tài),也是一直在推薦,有狀態(tài)的也是比較復(fù)雜,復(fù)雜點就在與有狀態(tài)的都是一些集群化的,比如zookerper,
Mysql主從,這些都是需要自身的一個狀態(tài)維護的,這些部署進去呢,可能去考慮它這個網(wǎng)絡(luò)拓?fù)潢P(guān)系,還有存儲狀態(tài)的持久化,而數(shù)據(jù)庫不具備這些特點,部署一個數(shù)據(jù)庫一般配置比較高一些,可以會抗很多的并發(fā)量,而且要擴容的話也是很方便,而且傳統(tǒng)的部署文章也很多,也比較成熟,在k8s中部署這些東西,那絕對是一種挑戰(zhàn),所以要根據(jù)不同的應(yīng)用特點去考慮上k8s,不要一味地上k8s,而且得不償失,達(dá)不到預(yù)期的效果,領(lǐng)導(dǎo)也會批你,所以在談有狀態(tài)部署的話,可以在兩者出發(fā),一個是Headless Service維護網(wǎng)絡(luò)的,一個是StatefulSet維護存儲狀態(tài)的。
statefulSet是一個控制器,與Deployment存在的原則一樣,都是部署應(yīng)用的,而Statefulset它主要是部署有狀態(tài)應(yīng)用的,而deployment是部署無狀態(tài)應(yīng)用的
Headless Service 其實和service差不多,這不過定義的這個叫無頭服務(wù),它們之間唯一的區(qū)別就是將Cluster ip 設(shè)置為了none,不會幫你配置ip
[root@k8s-master demo]# mkdir headless-service
[root@k8s-master demo]# cd headless-service/
[root@k8s-master headless-service]# vim headless-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
clusterIP: None
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 9376
[root@k8s-master headless-service]# kubectl create -f headless-svc.yaml
service/my-service created
[root@k8s-master headless-service]# kubectl get svc
kubernetes ClusterIP 10.1.0.1 <none> 443/TCP 23h
my-service ClusterIP None <none> 80/TCP 6s
service NodePort 10.1.207.32 <none> 80:30963/TCP 87m
zhao ClusterIP 10.1.75.232 <none> 80/TCP 9m1s
zhaocheng ClusterIP 10.1.27.206 <none> 80/TCP 10m
怎么去訪問?我們給它定義一個標(biāo)識
創(chuàng)建完之后會有這個標(biāo)識符,它會使用這個DNS來解析這個名稱,來相互的訪問,headless就不會通過ip去訪問了,必須通過名稱去訪問,
[root@k8s-master headless-service]# vim statefulset.yaml
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: nginx-statefulset
namespace: default
spec:
serviceName: my-service
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
[root@k8s-master headless-service]# kubectl create -f statefulset.yaml
[root@k8s-master headless-service]# kubectl get pod
my-pod 1/1 Running 0 3h60m
nfs-744d977b46-dh9xj 1/1 Running 0 22h
nfs-744d977b46-kcx6h 1/1 Running 0 22h
nfs-744d977b46-wqhc6 1/1 Running 0 22h
nfs-client-provisioner 1/1 Running 0 4h
nginx-797db8dc57-tdd5s 1/1 Running 0 100m
nginx-statefulset-0 1/1 Running 0 73s
nginx-statefulset-1 1/1 Running 0 46s
nginx-statefulset-2 1/1 Running 0 24s
這里的statfulset的 serviceName: my-service字段要關(guān)聯(lián)起來,這樣才能去基于名稱去訪問
可以通過busybox測試工具通過nslookup去測試解析。解析我們的my-service就能解析到
這里會分配一個名稱,這個my-service和這個編號是永久的,可以通過這個名稱訪問pod
要是mysql主從的話就可以通過訪問這個標(biāo)簽來連接我們從庫的狀態(tài),這個是維護的網(wǎng)絡(luò)狀態(tài)
然后再來看一下存儲狀態(tài)
官方文檔這個實例
https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/
這個其實我們也是部署一個nginx,使用的headless,ClusterIP為none,然后用headless來維護statefulset起得pod網(wǎng)絡(luò)id為1,以 volumeClaimTemplates:來維護pod獨立的一個存儲
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx # has to match .spec.template.metadata.labels
serviceName: "nginx"
replicas: 3 # by default is 1
template:
metadata:
labels:
app: nginx # has to match .spec.selector.matchLabels
spec:
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "managed-nfs-storage"
resources:
requests:
storage: 1Gi
這是我們的存儲要寫我們nfs的名稱
managed-nfs-storage
[root@k8s-master headless-service]# kubectl get sc
managed-nfs-storage fuseim.pri/ifs 22h
這里會給我們自動創(chuàng)建pv,并掛載到我們的NFS上
[root@k8s-master headless-service]# kubectl get pod
my-pod 1/1 Running 0 6h5m
nfs 1/1 Running 0 24h
nfs 1/1 Running 0 24h
nfs 1/1 Running 0 24h
nfs-client-provisioner-fbc 1/1 Running 0 6h33m
nginx-797db8dc57-tdd5s 1/1 Running 0 3h64m
nginx-a1-6d5fd7b8dd-w647x 1/1 Running 0 3m28s
nginx-statefulset-0 1/1 Running 0 135m
nginx-statefulset-1 1/1 Running 0 135m
nginx-statefulset-2 1/1 Running 0 134m
web-0 1/1 Running 0 3
web-1 1/1 Running 0 85s
web-2 1/1 Running 0 57s
[root@k8s-master headless-service]# kubectl get pv
pvc-06 1Gi RWO Delete Bound default/www-web-2 managed-nfs-storage 63s
pvc-4f 1Gi RWO Delete Bound default/www-web-0 managed-nfs-storage 6m3s
pvc-a2 5Gi RWX Delete Bound default/my-pvc managed-nfs-storage 6h5m
pvc-bc 1Gi RWO Delete Bound default/www-web-1 managed-nfs-storage
headless保證它的網(wǎng)絡(luò),statefulset存儲模版來保證每個pod存儲的唯一性,這樣才解決了有狀態(tài)應(yīng)用的兩大痛點
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。