前面提到了Deployment,但是Deployment有一个特点,就是它认为所有的Pod都相同,不存在顺序关系,无论在哪台宿主机运行,Deployment只需要维持数量跟预设保持一致即可。
但是这样并不适用于一些Pod有顺序依赖的场景,比如分布式应用的主从、主备关系,比如存储类应用在本地磁盘保存数据,不能简单的用Deployment管理,这样重建的话就会丢失实例与数据的对应关系。
StatefulSet是一个主要用于管理有状态应用的API 对象,这一点是之前的容器技术很难实现的。
常见的比如ElasticSearch集群、MongoDB集群,以及Redis集群、RabbitMQ集群、Kafka集群、ZooKeeper集群等。
与Deployment不同的是,StatefulSet为每个Pod提供了一个表示,比如建立三个MongoDB Pod,那么它们的名字就是MongoDB-1,MongoDB-2,MongoDB-3。
StatefulSet用于以下场景:
- 需要稳定的独一无二的网络标识符
- 需要持久化数据
- 需要有序的部署、拓展和滚动更新
使用Headless Service负责Pod通信,需要先创建该服务。
StatefulSet将应用状态抽象为了两种情况:
- 拓扑状态,多个实例之间不对等,必须按照某种顺序来启动,如果再次创建也必须按照规定的顺序。新的Pod的网络标识也会跟原来的一样
- 存储状态,多个实例之间绑定了不同的存储数据,对于一个Pod而言即使被重新创建,也依然读到跟之前一样的同一份数据。非常适合部署存储实例。
在将StatefulSet之前,需要了解Kubernetes中的一个重要概念:Headless Service
StatefulSet创建出的Pod使用Headless Service,采用Endpoint通信。
访问Service的方式有两种:通过Service的虚拟IP访问、通过Service的DNS访问。
第二种方式,只要访问 <service_name>.<namespace>.svc.cluster.local
,就可以访问到<namespace>
命名空间下名为<service_name>
的一个service
先创建一些持久化卷PV:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nginx-0
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
persistentVolumeReclaimPolicy: Recycle
storageClassName: "nginx-storage-class"
hostPath:
path: /data/nas/web/nginx0
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nginx-1
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
persistentVolumeReclaimPolicy: Recycle
storageClassName: "nginx-storage-class"
hostPath:
path: /data/nas/web/nginx1
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nginx-2
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
persistentVolumeReclaimPolicy: Recycle
storageClassName: "nginx-storage-class"
hostPath:
path: /data/nas/web/nginx2
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nginx-3
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
persistentVolumeReclaimPolicy: Recycle
storageClassName: "nginx-storage-class"
hostPath:
path: /data/nas/web/nginx3
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
# 创建Service
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
# clusterIp是None
clusterIP: None
selector:
app: nginx
---
# 创建StatefulSet,两个
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "nginx"
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
# PVC,绑定PV
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "nginx-storage-class"
resources:
requests:
storage: 1Gi
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-nginx-0 1Gi RWO Recycle Available nginx-storage-class 7h45m
pv-nginx-1 1Gi RWO Recycle Bound k8s-learning/www-web-1 nginx-storage-class 7h45m
pv-nginx-2 1Gi RWO Recycle Bound k8s-learning/www-web-0 nginx-storage-class 7h45m
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
www-web-0 Bound pv-nginx-2 1Gi RWO nginx-storage-class 42s
www-web-1 Bound pv-nginx-1 1Gi RWO nginx-storage-class 47s
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx ClusterIP None <none> 80/TCP 7h40m
$ kubectl get sts
NAME READY AGE
web 2/2 7h40m
|