RC、Deployment、DaemonSet都是面向无状态的服务,它们所管理的Pod的IP、Hostname、启停顺序等都是随机的,被管理的Pod重建时,Pod的IP、Hostname都会有变化。
而StatefulSet是有状态的集合,管理所有有状态的服务,比如MySQL、MongoDB集群等。
StatefulSet本质上是Deployment的一种变体,在v1.9版本中已成为GA版本,它为了解决有状态服务的问题,它所管理的Pod拥有固定的Pod名称、启停顺序。
statefulSet下的Pod有DNS地址,通过解析Pod的DNS可以返回Pod的IP,
deployment下的Pod没有DNS
在StatefulSet中,Pod名字称为网络标识(hostname),还必须要用到共享存储。
在Deployment中,与之对应的服务是service,而在StatefulSet中与之对应的headless service,headless service,即无头服务。
headless service与service的区别是:它没有Cluster IP,解析它的名称时将返回该Headless Service对应的全部Pod的Endpoint列表。
所以具有以下特性的应用应该使用statefullSet:
- 稳定且唯一的网络标识符;
- 稳定且持久的存储;
- 有序、平滑地部署和扩展;
- 有序、平滑的终止和删除;
- 有序的滚动更新;
对于一个完整的StatefulSet应用由三个部分组成:
headless service、
StatefulSet controller、
volumeClaimTemplate
实例:使用StatefulSet搭建MongoDB集群
本节以MongoDB为例,使用StatefulSet完成MongoDB集群的创建,为每个MongoDB实例在共享存储中(这里采用GlusterFS)都申请一片存储空间,以实现一个无单点故障、高可用、可动态扩展的MongoDB集群。部署架构如图:
前提条件
在创建StatefulSet之前,需要确保在Kubernetes集群中管理员已经创建好共享存储,并能够与StorageClass对接,以实现动态存储供应的模式。
本节的示例将使用GlusterFS作为共享存储(GlusterFS的部署方法)
创建StatefulSet
为了完成mongodb集群的搭建,需要创建三个资源对象
- 一个StorageClass,用于statefulset自动为各个应用pod申请pvc
- 一个Headless server,用于维护mongodb集群的状态。
- 一个statefulset
创建一个StorageClass对象
vim storageclass-fast.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast
provisioner: kubernetes.io/glusterfs
parameters:
resturl: "http://192.168.1.9:18080"
clusterid: "964027e984f3cecc86fe39a16c3a889f"
restauthenabled: "true"
restuser: "admin"
secretNamespace: "default"
secretName: "heketi-secret"
gidMin: "40000"
gidMax: "50000"
volumetype: "replicate:2"
创建mongodb StatefulSet
vim statefulset-mongo.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mongo
spec:
serviceName: "mongo"
selector:
matchLabels:
role: mongo
replicas: 3
template:
metadata:
labels:
role: mongo
environment: test
spec:
terminationGracePeriodSeconds: 10
containers:
- name: mongo
image: mongo
command:
- mongod
- "--replSet"
- rs0
- "--smallfiles"
- "--noprealloc"
ports:
- containerPort: 27017
volumeMounts:
- name: mongo-persistent-storage
mountPath: /data/db
- name: mongo-sidecar
image: cvallance/mongo-k8s-sidecar
env:
- name: MONGO_SIDECAR_POD_LABELS
value: "role=mongo,environment=test"
- name: KUBERNETES_MONGO_SERVICE_NAME
value: "mongo"
volumeClaimTemplates:
- metadata:
name: mongo-persistent-storage
annotations:
volume.beta.kubernetes.io/storage-class: "fast"
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 2Gi
创建 Headless Service
vim mongo-headless-service.yaml
apiVersion: v1
kind: Service
metadata:
name: mongo
labels:
name: mongo
spec:
ports:
- port: 27017
targetPort: 27017
clusterIP: None
selector:
role: mongo