Kubernetes之StatefulSet
什么是StatefulSet
StatefulSet 是Kubernetes中的一种控制器,他解决的什么问题呢?我们知道Deployment是对应用做了一个简化设置,Deployment认为一个应用的所有的pod都是一样的,他们之间没有顺序,也无所谓在那台宿主机上。需要扩容的时候就可以通过pod模板加入一个,需要缩容的时候就可以任意杀掉一个。但是实际的场景中,并不是所有的应用都能做到没有顺序等这种状态,尤其是分布式应用,他们各个实例之间往往会有对应的关系,例如:主从、主备。还有数据存储类应用,它的多个实例,往往会在本地磁盘存一份数据,而这些实例一旦被杀掉,即使从建起来,实例与数据之间关系也会丢失,而这些实例有不对等的关系,实例与外部存储有依赖的关系的应用,被称作“有状态应用”。StatefulSet与Deployment相比,相同于他们管理相同容器规范的Pod,不同的时候,StatefulSet为pod创建一个持久的标识符,他可以在任何编排的时候得到相同的标识符。
StatefulSet的应用特点:
- 稳定且有唯一的网络标识符 当节点挂掉,既pod重新调度后其PodName和HostName不变,基于Headless Service来实现
- 稳定且持久的存储 当节点挂掉,既pod重新调度能访问到相同的持久化存储,基于PVC实现
- 有序、平滑的扩展、部署 即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次进行(即从0到N-1,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态),基于init containers来实现。
- 有序、平滑的收缩、删除 既Pod是有顺序的,在收缩或者删除的时候要依据定义的顺序依次进行(既从N-1到0,既倒序)。
我们可以把这些抽象成两种应用状态:
- 拓扑状态。是应用多个实例之间的不完全对等的关系,这些应用实例是必须按照定义的顺序启动的。例如主应用A先于从应用B启动,如果把A和B删掉,应用还要按照先启动主应用A再启动从应用B,且创建的应用必须和原来的应用的网络标识一样(既PodName和HostName)。这样他们就可以按照原来的顺序创建了。
之间不是完全对等的关系
极客时间版权所有: https://time.geekbang.org/column/article/41017
存储状态。应用实例分别绑定了不同的数据存储,Pod A第一次读到的数据要和10分钟后读到的数据,是同一份。哪怕这期间Pod A被重建。这种典型的例子就是数据库应用的多个存储实例。
所以 StatefulSet的核心功能就是,通过某种方式记录应用状态,在Pod被重建的时候,通过这种方式还可以恢复原来的状态。
从上面的应用场景可以发现,StatefulSet由以下几个部分组成:
- Headless Service 用于定义网络标识(DNS)
- volumeClaimTemplates 用于创建PV
- StatefulSet 用于定义具体应用
讲解Headless Service
我们知道kubernetes中的service是定义pod暴露外部访问的一种机制,例如:3个pod,我们可以定义一个service通过标签选择器选到这三个pod,然后让问这个service就可以访问这个pod。可以出门左转,看一下 Service的讲解。 我们这里具体讲一下Headless service。
Headless service是Service通过DNS访问的其中一种方式,只要我们访问"mypod.stsname.namespace.svc.cluster.local",我们就会访问到stsname下的mypod。而Service DNS的方式下有两种处理方法:
- Normal Service 这里访问"mypod.stsname.namespace.svc.cluster.local"的时候会得到mypod的service的IP,既VIP。
- Headless Service 这里访问"mypod.stsname.namespace.svc.cluster.local"的时候会得到mypod的IP,这里我们可以看到区别是,Headless Service 不需要分配一个VIP,而是通过DNS访问的方式可以解析出带代理的Pod的IP
Headleaa Service的定义方式:
apiVersion: v1
kind: Service
metadata:
name: myapp-headless
namespace: default
spec:
selector:
app: myapp
release: dev
clusterIP: "None"
ports:
- port:
targetPort:
Headless Service也是一个标准的Service的YAML文件,只不过clusterIP定义为None,既,这个service没有VIP作为"头"。以DNS会记录的方式记录所有暴露它代理的Pod。而它代理的Pod依然会采用标签选择器的机制选择。既:所有携带了 app=myapp 标签的pod。都会被service代理起来。
DNS格式:
pod-name.svc-name.namespace.svc.cluster.local
StatefulSet详解
kubectl explain sts.spec 主要字段解释:
- replicas 副本数
- selector 那个pod是由自己管理的
- serviceName 必须关联到一个无头服务商
- template 定义pod模板(其中定义关联那个存储卷)
- volumeClaimTemplates 生成PVC
部署一个statefulset服务
这里我们用的storageClass,PV和PVC会动态创建。这个跑成功必须创建一个rook服务的动态存储,创建方法参考 rook官网。
apiVersion: v1
kind: Service
metadata:
name: myapp-sts
labels:
app: myapp-sts
spec:
ports:
- port:
name: web
clusterIP: "None"
selector:
app: myapp-pod
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: myapp
spec:
serviceName: myapp-sts-svc
replicas:
selector:
matchLabels:
app: myapp-pod
template:
metadata:
labels:
app: myapp-pod
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
ports:
- containerPort:
name: web
volumeMounts:
- name: myappdata
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: myappdata
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "rook-ceph-block"
resources:
requests:
storage: 5Gi
查看一下服务
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
myapp-sts ClusterIP None <none> /TCP 5m
查看pv/pvc
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
myappdata-myapp- Bound pvc-550493cf-dc1f-11e8-b8c9- 5Gi RWO rook-ceph-block 43m
myappdata-myapp- Bound pvc-5a4276b4-dc1f-11e8-b8c9- 5Gi RWO rook-ceph-block 43m
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-550493cf-dc1f-11e8-b8c9- 5Gi RWO Delete Bound default/myappdata-myapp- rook-ceph-block 43m
pvc-5a4276b4-dc1f-11e8-b8c9- 5Gi RWO Delete Bound default/myappdata-myapp- rook-ceph-block 43m
查看pod
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
myapp- / Running 17h
myapp- / Running 17h
验证解析
$ kubectl exec -it myapp- -- /bin/sh
/ # nslookup myapp-.myapp-sts-svc.default.svc.cluster.local
nslookup: can't resolve '(null)': Name does not resolve Name: myapp-.myapp-sts-svc.default.svc.cluster.local
Address : 10.244.3.37 myapp-.myapp-sts-svc.default.svc.cluster.local
扩容(扩展应该是按顺序扩展)
$ kubectl scale sts myapp --replicas= $ kubectl get pod -w
NAME READY STATUS RESTARTS AGE
myapp- / Running 18h
myapp- / Running 18h
myapp- / Pending 0s
myapp- / Pending 0s
myapp- / Pending 0s
myapp- / ContainerCreating 0s
myapp- / Running 15s
myapp- / Pending 0s
myapp- / Pending 1s
myapp- / Pending 1s
myapp- / ContainerCreating 1s
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
myappdata-myapp-0 Bound pvc-550493cf-dc1f-11e8-b8c9-005056930126 5Gi RWO rook-ceph-block 18h
myappdata-myapp-1 Bound pvc-5a4276b4-dc1f-11e8-b8c9-005056930126 5Gi RWO rook-ceph-block 18h
myappdata-myapp-2 Bound pvc-25e46dbd-dcba-11e8-b8c9-005056930126 5Gi RWO rook-ceph-block 2m
myappdata-myapp-3 Bound pvc-2f420e8c-dcba-11e8-b8c9-005056930126 5Gi RWO rook-ceph-block 1m
myappdata-myapp-4 Bound pvc-4607d3c8-dcba-11e8-b8c9-005056930126 5Gi RWO rook-ceph-block 1m
缩容 (按倒序缩容)
$ kubectl scale sts myapp --replicas= $ kubectl get pod -w
NAME READY STATUS RESTARTS AGE
myapp- / Running 18h
myapp- / Running 18h
myapp- / Running 3m
myapp- / Running 3m
myapp- / Running 2m
myapp- / Terminating 2m
myapp- / Terminating 2m
myapp- / Terminating 2m
myapp- / Terminating 2m
myapp- / Terminating 3m
myapp- / Terminating 3m
myapp- / Terminating 3m
myapp- / Terminating 3m
升级
查看升级策略
kubectl explain sts.spec.updateStrategy
- rollingUpdate 滚动更新
kubectl explain sts.spec.updateStrategy.rollingUpdate
- partition 分区更新,默认partition的值是0,当partition等N,N+的都会更新。
默认partition是从0开始更新

当partition等于4的时候,4以后的都要更新。

$ kubectl set image sts/myapp myapp=ikubernetes/myapp:v2
$ kubectl describe pod myapp-
Name: myapp-
Namespace: default
Priority:
PriorityClassName: <none>
Node: k8s-node01/172.16.138.41
Start Time: Thu, Nov :: -
Labels: app=myapp-pod
controller-revision-hash=myapp-5775ff7474
statefulset.kubernetes.io/pod-name=myapp-
Annotations: <none>
Status: Running
IP: 10.244.1.13
Controlled By: StatefulSet/myapp
Containers:
myapp:
Container ID: docker://75d5e6b3958f053908eb3e5fa1c2846ce91d90c9ff696f27e6220a66d2e8cc7c
Image: ikubernetes/myapp:v2
Image ID: docker-pullable://ikubernetes/myapp@sha256:85a2b81a62f09a414ea33b74fb8aa686ed9b168294b26b4c819df0be0712d358
Port: /TCP
Host Port: /TCP
.....
Normal Service
极客时间版权所有
Kubernetes之StatefulSet的更多相关文章
- Kubernetes中StatefulSet介绍
StatefulSet 是Kubernetes1.9版本中稳定的特性,本文使用的环境为 Kubernetes 1.11.如何搭建环境可以参考kubeadm安装kubernetes V1.11.1 集群 ...
- kubernetes之StatefulSet详解
系列目录 概述 RC.Deployment.DaemonSet都是面向无状态的服务,它们所管理的Pod的IP.名字,启停顺序等都是随机的,而StatefulSet是什么?顾名思义,有状态的集合,管理所 ...
- kubernetes之StatefulSet部署zk和kafka
前提 至少需要三个node节点,否则修改亲和性配置 如果外部访问,需要自己暴露 需要有个storageClass,这样做的原因是避免手动创建pv了 部署zk和kafka 参考: https://www ...
- 图解kubernetes控制器StatefulSet核心实现原理
StatefulSet是k8s中有状态应用管理的标准实现,今天就一起来了解下其背后设计的场景与原理,从而了解其适用范围与场景 1. 基础概念 首先介绍有状态应用里面的需要考虑的一些基础的事情,然后在下 ...
- 12 . Kubernetes之Statefulset 和 Operator
Statefulset简介 k8s权威指南这样介绍的 "在Kubernetes系统中,Pod的管理对象RC.Deployment.DaemonSet和Job都面向无状态的服务.但现实中有很多 ...
- kubernetes使用statefulset部署mongoDB 单机版 自定义配置文件、密码等
注: 官方镜像地址: https://hub.docker.com/_/mongo?tab=description docker版的mongo移除了默认的/etc/mongo.conf, 修改了db数 ...
- 9、kubernetes之statefulset控制器
一.StatefulSet 有状态副本集 必要的三个组件:headless service.StatefulSet.volumeClaimTemplate 准备pv apiVersion: v1 ki ...
- kubernetes的Statefulset介绍
StatefulSet是一种给Pod提供唯一标志的控制器,他可以保证部署和扩展的顺序. Pod一致性 包含次序(启动和停止次序).网络一致性.此一致性和Pod相关.与被调度到哪个Node节点无关. 稳 ...
- StatefulSet: Kubernetes 中对有状态应用的运行和伸缩
在最新发布的 Kubernetes 1.5 我们将过去的 PetSet 功能升级到了 Beta 版本,并重新命名为StatefulSet.除了依照社区民意改了名字之外,这一 API 对象并没有太大变化 ...
随机推荐
- sql server 错误日志errorlog
一 .概述 SQL Server 将某些系统事件和用户定义事件记录到 SQL Server 错误日志和 Microsoft Windows 应用程序日志中. 这两种日志都会自动给所有记录事件加上时间戳 ...
- nginx实现新老网站跳转(原URL不变)
新老网站实现跳转 原URL保持不变 通过手动添加cookie 匹配cookie的方法进行跳转第一步 进行添加if判断条件 if ( $query_string ~* "sr=pro" ...
- Saltstack_使用指南01_部署
1. 主机规划 服务器名称 操作系统版本 内网IP 外网IP(模拟) Hostname 部署模块 salt100 CentOS7.5 172.16.1.100 10.0.0.100 salt100 s ...
- LeetCode算法题-Student Attendance Record I(Java实现)
这是悦乐书的第258次更新,第271篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第125题(顺位题号是551).您将获得一个表示学生出勤记录的字符串. 该记录仅包含以下 ...
- CentOS7.2重置root密码的处理方法
第一个里程碑 --在启动GRUB菜单中选择编辑选项,按键 "e" 进入编辑; 第二个里程碑 -- 大约在第16行找到 "ro" 将 "ro" ...
- java格式化
http://tool.oschina.net/apidocs/apidoc?api=jdk-zh https://www.jianshu.com/p/c8f16cab35e1# 参考官方的 api说 ...
- JavaScript的函数闭包详细解释
闭包是指有权访问另一个函数作用域中的变量的函数 一.创建闭包的常见的方式: 就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量. //通过闭包可以返回局部变量 function b ...
- c++11の数据竞争和互斥对象
一.数据竞争的产生 在下面例子中: void function_1() { ; i < ; i++) { std::cout << "from function 1:&qu ...
- CentOS7.5修改字符集
乱码产生的原因: 计算机中储存的信息都是用二进制数表示的:而我们在屏幕上看到的英文.汉字等字符是二进制数转换之后的结果.通俗的说,按照何种规则将字符存储在计算机中,如'a'用什么表示,称为" ...
- maven eclipse web 项目 问题 cannot change version of project facet dynamic web module to 3.0
cannot change version of project facet dynamic web module to 3.0 修改 web.xml 头部 xsi:schemaLocation=&q ...