StatefulSet 简介

在Kubernetes中,Pod的管理对象RC、Deployment、DaemonSet和Job都是面向无状态的服务。但现实中有很多服务是有状态的,特别是一些复杂的中间件集群,例如MySQL集群、MongoDB集群、Akka集群、ZooKeeper集群等。

以上集群有几个共同点: 1.每个节点都有固定的身份ID,通过这个ID,集群中的成员可以互相发现并且通信 2.集群的规模是比较固定的,集群规模不能随意变动。 3.集群里的每个节点都是有状态的,通常会持久化数据到永久存储中 4.如果磁盘损坏,则集群里的某个节点无法正常运行,集群功能受损。

如果用RC/Deployment 控制Pod 副本数的方式来实现上述有状态的集群,则我们会发现第一点是无法满足的,因为Pod的名字是随机产生的,Pod的IP地址也是在运行期才确定且可能有变动的,我们事先无法为每个Pod确定唯一不变的ID。另外,为了能够在其他节点上恢复某个失败的节点,这种集群中的Pod 需要挂载某种共享存储,Kubernetes在1.4版本引入了PetSet这个新资源对象,在1.5更名为"StatefulSet"。StatefulSet 从本质来将,可以看作Deployment/RC 的一种特殊变种

StatefulSet 特点

StatefulSet特点:

1.StatefulSet 里的每个Pod都有稳定、唯一的网络表示,可以用来发现集群内的其他成员。(假设StatefulSet 的名字叫kafka,那么第一个Pod叫kafka-0,第二个Pod叫kafka-1以此类推) 2.StatefulSet 控制的Pod副本的启动顺序是受控制的,操作第n个Pod,前n-1个Pod已经是运行且准备好的状态 3.StatefulSet 里的Pod采用稳定的持久化存储卷,通过PV/PVC来实现,删除Pod时默认不会删除与StatefulSet相关的存储卷(为了保证数据的安全)

StatefulSet是为了解决有状态服务的问题(对应DeploymentReplica Set是为无状态服务而设计),其应用场景包括

  • 稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现
  • 稳定的网络标志,即Pod重新调度后其PodName和HostName不变,基于Headless Service(即没有Cluster IP的Service)来实现
  • 有序部署,有序扩展,即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次依次进行(即从0到N-1,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态),基于init containers来实现
  • 有序收缩,有序删除(即从N-1到0

从上面的应用场景可以发现,StatefulSet由以下几个部分组成:

  • 用于定义网络标志(DNS domain)的Headless Service
  • 用于创建PersistentVolumes的volumeClaimTemplates
  • 定义具体应用的StatefulSet

StatefulSet 原理

StatefulSet由Service和volumeClaimTemplates组成。Service中的多个Pod将会被分别编号,并挂载volumeClaimTemplates中声明的PV。

注意: 官方提示StatefulSets在1.9中是稳定的

案例:K8s企业实践使用storageclass实现动态存储

StatefulSet 除了要与PV卷捆绑使用以存储Pod的状态数据,还要与Headless Service配合使用,在每个StatfulSet的定义中要声明它属于哪个Headless Service.Headless Service 与普通Service的关键区别在于, Headless Service它没有Cluster IP,如果解析Headless Service的DNS域名,则返回的是该Service对应的全部Pod的Endpoint列表。

StatefulSet在Headless Service的基础上又为StatefulSet控制的每个Pod实力创建了一个DNS域名,这个域名的格式为: ${podname}.${headless service name}

比如一个3节点的Kafka的StatefulSet集群,对应的Headless Service的名字为kafka,StatefulSet的名字为kafka,则StatefulSet 里面的3个Pod的DNS分别为kafka-0.kafka、kafka-1.kafka、kafka-3.kafka,这些DNS名称可以直接在集群的配置文件中固定下来。

简单点说:没有部署HeadlessService的话,PetSet/StatefulSet下的pod,无法通过域名进行访问。

实例演示

官方演示地址首先使用以下示例创建StatefulSet以一个简单的nginx服务web.yaml为例

StatefulSet注意事项

  • 还在beta状态,需要kubernetes v1.5版本以上才支持
  • 所有Pod的Volume必须使用PersistentVolume或者是管理员事先创建好
  • 为了保证数据安全,删除StatefulSet时不会删除Volume
  • StatefulSet需要一个Headless Service来定义DNS domain,需要在StatefulSet之前创建好
  • 目前StatefulSet还没有feature complete,比如更新操作还需要手动patch。

案例开始

application/web/web.yaml
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:
serviceName: "nginx"
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: k8s.gcr.io/nginx-slim:0.8
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi $ kubectl create -f web.yaml
service "nginx" created
statefulset "web" created # 查看创建的headless service和statefulset
$ kubectl get service nginx
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx None <none> 80/TCP 1m
$ kubectl get statefulset web
NAME DESIRED CURRENT AGE
web 2 2 2m # 根据volumeClaimTemplates自动创建PVC(在GCE中会自动创建kubernetes.io/gce-pd类型的volume)
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESSMODES AGE
www-web-0 Bound pvc-d064a004-d8d4-11e6-b521-42010a800002 1Gi RWO 16s
www-web-1 Bound pvc-d06a3946-d8d4-11e6-b521-42010a800002 1Gi RWO 16s # 查看创建的Pod,他们都是有序的
$ kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 5m
web-1 1/1 Running 0 4m # 使用nslookup查看这些Pod的DNS
$ kubectl run -i --tty --image busybox dns-test --restart=Never --rm /bin/sh
/ # nslookup web-0.nginx
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local Name: web-0.nginx
Address 1: 10.244.2.10
/ # nslookup web-1.nginx
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local Name: web-1.nginx
Address 1: 10.244.3.12
/ # nslookup web-0.nginx.default.svc.cluster.local
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local Name: web-0.nginx.default.svc.cluster.local
Address 1: 10.244.2.10

Statefulset 扩容与缩容

# 扩容
$ kubectl scale statefulset web --replicas=5 # 缩容
$ kubectl patch statefulset web -p '{"spec":{"replicas":3}}' # 镜像更新(目前还不支持直接更新image,需要patch来间接实现)
$ kubectl patch statefulset web --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"gcr.io/google_containers/nginx-slim:0.7"}]' # 删除StatefulSet和Headless Service
$ kubectl delete statefulset web
$ kubectl delete service nginx # StatefulSet删除后PVC还会保留着,数据不再使用的话也需要删除
$ kubectl delete pvc www-web-0 www-web-1

最新文章

  1. jquery 替换img 属性
  2. (转)jQuery源码解读 -- jQuery v1.10.2
  3. HtmlAgilityPack中通过sibling才能得到对应的InnerText和form,option等tag的子节点
  4. Delphi指针的用法
  5. C++运算法优先级
  6. gzip压缩JavaScript
  7. SCI写作经典替换词,瞬间高大上!(转)
  8. stdcall、cdecl、fastcall、thiscall 、naked call的汇编详解
  9. 【Tools】ubuntu无法virtualenv创建python虚拟环境的解决
  10. Android开发学习之路--网络编程之初体验
  11. TIPS FOR IMPROVING PERFORMANCE OF KAFKA PRODUCER
  12. Qt编写自定义控件10-云台仪表盘
  13. 手动卸载CAD 删除残留文件 清理遗留的文件
  14. noip第18课资料
  15. Go语言函数
  16. 「PKUSC2018」神仙的游戏
  17. mvc 文件下载
  18. 使用exec函数将当前的信息输入到文件中
  19. 2. Python3 基础入门
  20. [HDU6198]number number number

热门文章

  1. java代码获取项目版本号实例
  2. 微信小程序~模板template引用
  3. java构建简单的HTTP服务器
  4. BZOJ 4197: [Noi2015]寿司晚宴 状压dp+质因数分解
  5. windbg在加载模块时下断点
  6. 认识Dump文件
  7. facl
  8. Nginx 和 PHP 和 mysql扩展的安装
  9. java学习笔记(5) 控制语句、键盘输入
  10. HTML试题解析