StatefulSet简介

有状态应用副本集

为什么要用statefulset控制器

有状态和无状态

无状态的, 更关注的是群体

有状态的, 更关注的是个体

有状态应用集的特点:

  1. 稳定且需要唯一的网络标识符;

    • 如: Redis集群,

      在Redis集群中,它是通过槽位来存储数据的,假如:第一个节点是01000,第二个节点是10012000,第三个节点2001~3000...等等,这就使得Redis集群中每个节点要通过ID来标识自己,如:

      第二个节点宕机了,重建后它必须还叫第二个节点,或者说第二个节点叫R2,它必须还叫R2,这样在获取1001~2000槽位的数据时,才能找到数据,否则Redis集群将无法找到这段数据。
  2. 稳定且持久的存储;
    • 可实现持久存储,新增或减少pod,存储不会随之发生变化。
  3. 要求有序, 平滑的部署和扩展;
    • 如 MySQL集群,要先启动主节点, 若从节点没有要求,则可一起启动,若从节点有启动顺序要求,可先启动第一个从节点,接着第二从节点等;这个过程就是有顺序,平滑安全的启动。
  4. 要求有序, 平滑的终止和删除;
    • 我们先终止从节点,若从节点是有启动顺序的,那么关闭时,也要按照逆序终止,即启动时是从S1~S4以此启动,则关闭时,则是先关闭S4,然后时S3,依次关闭,最后在关闭主节点。
  5. 有序的滚动更新;
    • MySQL在更新时,应该先更新从节点,全部的从节点都更新完了,最后在更新主节点,因为新版本一般可兼容老版本,但是一定要注意,若新版本不兼容老版本就很很麻烦

statefulset的组成:

  1. headless service 用于定义网络标识(DNS)
  2. StatefulSet 控制器,用于定义具体应用
  3. volumeClaimTemplate 存储卷申请模板,用于创建PV

简单测试 使用 StatefulSet

创建基础的PV

[root@master configmap]# cat ../volume/pv-demo.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv001
labels:
name: pv001
spec:
nfs:
path: /data/volumes/v1
server: 172.27.1.241
accessModes: ["ReadWriteMany", "ReadWriteOnce"]
capacity:
storage: 5Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv002
labels:
name: pv002
spec:
nfs:
path: /data/volumes/v2
server: 172.27.1.241
accessModes: ["ReadWriteOnce"]
capacity:
storage: 5Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv003
labels:
name: pv003
spec:
nfs:
path: /data/volumes/v3
server: 172.27.1.241
accessModes: ["ReadWriteMany", "ReadWriteOnce"]
capacity:
storage: 5Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv004
labels:
name: pv004
spec:
nfs:
path: /data/volumes/v4
server: 172.27.1.241
accessModes: ["ReadWriteMany", "ReadWriteOnce"]
capacity:
storage: 10Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv005
labels:
name: pv005
spec:
nfs:
path: /data/volumes/v5
server: 172.27.1.241
accessModes: ["ReadWriteMany", "ReadWriteOnce"]
capacity:
storage: 10Gi
[root@master volume]# kubectl apply -f pv-demo.yaml
persistentvolume/pv001 created
persistentvolume/pv002 created
persistentvolume/pv003 created
persistentvolume/pv004 created
persistentvolume/pv005 created
[root@master volume]# kubectl get pv -o wide
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
pv001 5Gi RWO,RWX Retain Available 5s Filesystem
pv002 5Gi RWO Retain Available 5s Filesystem
pv003 5Gi RWO,RWX Retain Available 5s Filesystem
pv004 10Gi RWO,RWX Retain Available 5s Filesystem
pv005 10Gi RWO,RWX Retain Available 5s Filesystem

StatefulSet 清单

[root@master manifests]# cat statefulset-demo.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-svc
namespace: default
labels:
app: myapp # service 名称
spec:
ports:
- port: 80
name: web
clusterIP: None # 配置headless service
selector:
app: myapp-pod # 匹配Pod 标签
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: myapp
spec:
serviceName: myapp # 名称
replicas: 3 # 三个副本
selector:
matchLabels:
app: myapp-pod # 匹配Pod
template:
metadata:
labels:
app: myapp-pod
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
ports:
- containerPort: 80
name: web
volumeMounts:
- name: myappdata
mountPath: /usr/shar/nginx/html
volumeClaimTemplates:
- metadata:
name: myappdata # pvc名称
spec:
accessModes: ["ReadWriteOnce"] # 权限
resources:
requests:
storage: 5Gi # pv 大小

创建

[root@master manifests]# kubectl apply -f statefulset-demo.yaml
service/myapp-svc unchanged
statefulset.apps/myapp created
[root@master manifests]# kubectl get sts
NAME READY AGE
myapp 3/3 5s
[root@master manifests]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-0 1/1 Running 0 92s
myapp-1 1/1 Running 0 91s
myapp-2 1/1 Running 0 32s

StatefulSet 会自动创建pvc, 然后去绑定对应符合要求的PV

[root@master manifests]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
myappdata-myapp-0 Bound pv002 5Gi RWO 2m42s
myappdata-myapp-1 Bound pv003 5Gi RWO,RWX 66s
myappdata-myapp-2 Bound pv001 5Gi RWO,RWX 7s
[root@master manifests]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001 5Gi RWO,RWX Retain Bound default/myappdata-myapp-2 20m
pv002 5Gi RWO Retain Bound default/myappdata-myapp-0 20m
pv003 5Gi RWO,RWX Retain Bound default/myappdata-myapp-1 20m
pv004 10Gi RWO,RWX Retain Available 20m
pv005 10Gi RWO,RWX Retain Available 20m

statefulset管理pod的启停顺序

  • 有序部署:部署StatefulSet时,如果有多个Pod副本,它们会被顺序地创建(从0到N-1)并且,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态。
  • 有序删除:当Pod被删除时,它们被终止的顺序是从N-1到0。
  • 有序扩展:当对Pod执行扩展操作时,与部署一样,它前面的Pod必须都处于Running和Ready状态

statefulset管理策略

  • OrderedReady:上述的启停顺序,默认设置。

    spec:
    podManagementPolicy: OrderedReady
  • Parallel:告诉StatefulSet控制器并行启动或终止所有Pod,并且在启动或终止另一个Pod之前不等待前一个Pod变为Running and Ready或完全终止。

    spec:
    podManagementPolicy: Parallel
扩容pod实验(顺序增加)
[root@master manifests]# kubectl scale sts myapp --replicas=5  #扩容到5个pod
[root@master manifests]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
myappdata-myapp-0 Bound pv002 5Gi RWO 14m
myappdata-myapp-1 Bound pv003 5Gi RWO,RWX 14m
myappdata-myapp-2 Bound pv001 5Gi RWO,RWX 14m
myappdata-myapp-3 Bound pv004 10Gi RWO,RWX 7s
myappdata-myapp-4 Bound pv005 10i RWO,RWX 7s
缩减pod实验(逆序减小,从最后的开始缩减)
[root@master manifests]# kubectl scale sts myapp --replicas=2  #缩减到2个pod
[root@master manifests]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
myappdata-myapp-0 Bound pv002 5Gi RWO 14m
myappdata-myapp-1 Bound pv003 5Gi RWO,RWX 14m

statefulSet的更新策略:

kubectl explain sts.spec.updateStrategy.rollingUpdate

partition: 这种更新策略的含义是, 若当前statefulSet的副本数为5个,则Pod名为pod-0~pod-4,那么此时定义partition=4, 就意味着我要更新大于等于4的Pod,而只有pod-4的ID 4 是大于等于4的,所以只有pod-4会被更新,其它不会,这就是金丝雀更新。若后期发现pod-4更新后,工作一切正常,那么就可以调整partition=0,这样只要大于等于0的pod ID都将被更新。

金丝雀更新

修改滚动更新策略,查看效果

kubectl patch sts myapp -p '{"spec":{"updateStrategy":{"rollingUpdate":{"partition":2}}}}'
#修改statefulset的image
kubectl set image sts/myapp myapp=ikubernetes/myapp:v2 #查看已经修改成功了
[root@master statfulset]# kubectl get sts myapp -o wide
NAME READY AGE CONTAINERS IMAGES
myapp 4/4 16h myapp ikubernetes/myapp:v2

因为策略写的是从第二个容器开始更新

通过命令kubectl get pod myapp-1 -o yaml可以看到2之前的image没有改变

通过命令kubectl get pod myapp-2 -o yaml可以看到2之后的image都已经改变了

#再重新把partition改为0, 则把之前的pod的image都修改生效了
kubectl patch sts myapp -p '{"spec":{"updateStrategy":{"rollingUpdate":{"partition":0}}}}'
[root@master statfulset]# kubectl get pods -l app=myapp-pod -o custom-columns=NAME:metadata.name,IMAGE:spec.containers[0].image
NAME IMAGE
myapp-0 ikubernetes/myapp:v2
myapp-1 ikubernetes/myapp:v2
myapp-2 ikubernetes/myapp:v2
myapp-3 ikubernetes/myapp:v2

暂存更新操作

分区更新操作

将spec.updateStrategy.rollingUpdate.partition设置为Pod副本数量时,即意味着所有Pod资源都不会处于可直接更新的分区内,直到partition小于Pod数时,才会开始更新

此时,即便删除某Pod,也会按旧版本进行重建,即暂存状态的更新对所有Pod资源均不产生影响

使用go-template自定义资源输出信息

kubectl get pod myapp-1 -o go-template --template='{{.status.podIP}}'
[root@master statfulset]# kubectl get pod myapp-1 -o go-template --template='{{range .spec.containers}}{{.image}}{{end}}'
ikubernetes/myapp:v2

因为这里查看containers的image信息是一个列表信息, 所以要用到range

关于更多的go-template的使用方法, 可以参考这位老哥写的博客: https://www.bbsmax.com/A/gAJGgjX3JZ/

访问测试:pod_name.service.ns_name.svc.cluster.local (myapp-2.myapp.default.svc.cluster.local)

十,StatefulSet简介及简单使用的更多相关文章

  1. C#可扩展编程之MEF学习笔记(一):MEF简介及简单的Demo

    在文章开始之前,首先简单介绍一下什么是MEF,MEF,全称Managed Extensibility Framework(托管可扩展框架).单从名字我们不难发现:MEF是专门致力于解决扩展性问题的框架 ...

  2. knockout.js的简介和简单使用

    1.knockout简介knockout是一个轻量级的UI类库,通过MVVM模式使JavaScript前端UI简单化knockout有四大重要概念:1)声明式绑定:使用简明移读的语法很容易地将模型(m ...

  3. linux设备驱动归纳总结(十二):简单的数码相框【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-116926.html linux设备驱动归纳总结(十二):简单的数码相框 xxxxxxxxxxxxxx ...

  4. MEF简介及简单的Demo

    MEF简介及简单的Demo 文章开始之前,首先简单介绍一下什么是MEF,MEF,全称Managed Extensibility Framework(托管可扩展框架).单从名字我们不难发现:MEF是专门 ...

  5. Redis简介与简单安装

    Redis简介与简单安装   一.NoSQL的风生水起 1.1 后Web2.0时代的发展要求 随着互联网Web2.0网站的兴起,传统的关系数据库在应付Web2.0网站,特别是超大规模和高并发的SNS类 ...

  6. C语言第十讲,枚举类型简单说明

    C语言第十讲,枚举类型简单说明 一丶C语言中的枚举类型(ENUM) 在我们实际工作中,或者编写代码中.我们有的时候会用固定的值.而且不是很多. 这个时候就可以使用枚举了.如果我们使用#define显然 ...

  7. gtest简介及简单使用

    本文摘自 gtest简介及简单使用 ,在此感谢作者的分享. 具体使用教程 _______________________________________________________________ ...

  8. WPF自学入门(十一)WPF MVVM模式Command命令 WPF自学入门(十)WPF MVVM简单介绍

    WPF自学入门(十一)WPF MVVM模式Command命令   在WPF自学入门(十)WPF MVVM简单介绍中的示例似乎运行起来没有什么问题,也可以进行更新.但是这并不是我们使用MVVM的正确方式 ...

  9. webUI框架miniUI,easyUI,extJS,Bootstrap简介及简单部署

    本文为大家讲解的是webUI框架miniUI,easyUI,extJS,Bootstrap简介及简单部属,感兴趣的同学参考下 ExtJS是一种主要用于创建前端用户界面,是一个基本与后台技术无关的前端a ...

随机推荐

  1. Swift的if let和guard let的使用 <一看就懂哟>

    // // ViewController.swift // 可选项的判断 // // Created by 思 彭 on 16/9/16. // Copyright © 2016年 思 彭. All ...

  2. Java泛型(3):泛型方法

    泛型还可以同样运用在方法.是否拥有泛型方法与其所在的类是否是泛型类没有关系. 无论何时,只要你能做到,都应该尽量使用泛型方法,如果泛型方法可以取代将整个类整个类泛型化,那么就应该只使用泛型方法. 下面 ...

  3. Ansible-galera

    在四台虚拟机上都安装好docker 一.控制节点 1. 域名解析 [root@d ansible]# vim /etc/hosts [root@d ansible]# scp /etc/hosts n ...

  4. 零零散散的shell笔记

    ls __paddlepalm_* > __palminfo__ 名字以__paddlepalm_开头的文件名打印到后面那个info里面 https://www.runoob.com/linux ...

  5. css 移动端1px更细

    1.最近写项目经常遇到4个入口菜单放在一行,然后加border:1px 在移动端显示却很粗,如下图: <div class="header"> <div clas ...

  6. ZOJ Problem Set - 1002

    参考: 1.http://www.cnblogs.com/phinecos/archive/2008/09/18/1293017.html 基本思想:回溯法 重点在void Solve(int k,i ...

  7. Python之Web前端Ajax

    Ajax: 对于WEB应用程序:用户浏览器发送请求,服务器接收并处理请求,然后返回结果,往往返回就是字符串(HTML),浏览器将字符串(HTML)渲染并显示浏览器上. 1.传统的Web应用 一个简单操 ...

  8. [转帖]Nginx 容器教程

    Nginx 容器教程 http://www.ruanyifeng.com/blog/2018/02/nginx-docker.html 里面有证书. 作者: 阮一峰 日期: 2018年2月27日 感谢 ...

  9. 查找担保圈-step6-对被包含过的组进行清理,只保留未被包含过的组

    USE [test] GO /****** Object: StoredProcedure [dbo].[p04_get_groupno_cleared] Script Date: 2019/7/8 ...

  10. Oracle的基本操作-序列的使用

    序列:默认从1开始,一次递增,主要用来给主键赋值使用 create sequence s_person; select s_person.nextval from dual; --dual是一张虚表, ...