有状态服务
生产上一般使用deployment来编排无状态服务的
deployment是编排无状态服务的
statefuSet编排有状态服务
有状态应用控制管理statefulSet (很少用过)
编排有状态服务
什么是有状态?
无状态一般都和集群相关的,一个节点都无所谓,如果只使用一个节点使用任何方式都行
如果是集群,比如nginx集群 tomcat集群 如果无状态 个个节点之间相互独立的,相互之间不知道对方,nginx tomcat这种他们相互之间不知道对方,因为访问的适合他们自己都能提供完整的服务,集群里面各个节点之前他们没有任何关联性的
无状态服务,如果其中一个状态停止了,我随机可以再启动一个状态就可以了,就是启动和停止前后两次他们之间也没有关联性,只要数据保持资源里有就可以
而有状态服务是啥意思:比如redis,集群之间各个状态之间他们各个节点资源都需要保存,比如cluster集群如果一个节点宕机其他节点要接替才行,然后我们cluster里面还有数据分布,每个集群节点还有个id号,这个集群每个节点都需要知道除了自己外还有其他节点信息都需要知道,如果不知道的话 后面数据都无法路由,所以有状态服务通常是集群之间节点之间都有关联性,同时集群还有个特性,如果有个集群宕机了,再去创建一个集群的时候他们之间和其他节点还需要有关联性,他们要保存之前的状态 比如mysql主从复制集群,做主从的时候除了要知道主的ip端口号,用户名密码,二进制文件索引点,都需要知道才能做主从复制集群,所以一个节点启动的时候要去关联其他节点,第二点还要记录我上一个节点之前的状态,如果一个节点停机了,在启动一个节点还要查看宕机的节点生前的状态,一般有状态服务都是数据库相关的,比如mysql reids 各种各样的数据库都是有状态的服务
平常使用应用服务 nginx php tomcat 各种各样的java服务 他们都是无状态的,像启一个直接启动就行,没有关联性,反向代理,之间像配置文件填写ip就行 不需要知道有谁,每个只提供自己的服务针对于这种情况k8s官方提供了一个statefuSet的pod控制器,它就是编排有状态服务的角色
什么是statefuSet
Kubernetes 系统使用专用的 StatefulSet控制器编排有状态应用。StatefulSet 表示一组具有唯一持久身份和稳定主机名的 Pod 对象(所有有状态的服务都有这样的特性),任何指定该类型 Pod 的状态信息和其他弹性数据都存放在与该StatefulSet 相关联的永久性磁盘存储空间中。StatefulSet 旨在部署有状态应用和集群化应用,这些应用会将数据保存到永久性存储空间,它适合部署 Kafka、MySQL、 Redis、ZooKeeper 以及其他需要唯一持久身份和稳定主机名的应用。
它的弹性增加和扩容不是随便的,比如nginx,随便扩容都可以,把节点从3变4 变3000都可以,这里面也可以扩容但是扩容以后还需要做相应的操作,整个statefuSet需要一个永久性的存储空间,还需要有一个无头的Service(Headless Service)
一般说来,一个典型的、完整可用的 StatefulSet 资源通常由两个组件构成∶ Headless Service 和StatefulSet 资源。Headless Service 用于为各 Pod 资源固定、唯一的标识符生成可解析的 DNS 资源记录,StatefulSet 用于编排 Pod对象,并借助 volumeClaimTemplate 以静态或动态的 PV 供给方式为各Pod 资源提供专有且固定的存储资源。
#和deployment的字段非常相似
apiVersion: apps/v1 # API群组及版本;
kind: StatefulSet # 资源类型的特有标识
metadata:
name <string> # 资源名称,在作用域中要唯一
namespace <string> # 名称空间;StatefulSet隶属名称空间级别
spec:
replicas <integer> # 期望的Pod副本数,默认为1
selector <object> # 标签选择器,须匹配Pod模板中的标签,必选字段
template <object> # Pod模板对象,必选字段
revisionHistoryLimit <integer> # 滚动更新历史记录数量,默认为10
updateStrategy <Object> # 滚动更新策略
type <string> # 滚动更新类型,可用值有OnDelete和Rollingupdate
rollingUpdate <Object> # 滚动更新参数,专用于RollingUpdate类型
partition <integer> # 分区指示索引值,默认为0
serviceName <string> # 相关的Headless Service的名称,必选字段 # 和deployment的区别是要有个service name
volumeClaimTemplates <[]Object> # 存储卷申请模板 #还需要有个卷 这个卷 还没有讲到卷 就先用本地卷
apiVersion <string> # PVC资源所属的API群组及版本,可省略
kind <string> # PVC资源类型标识,可省略
metadata <Object> # 卷申请模板元数据
spec <Object> # 期望的状态,可用字段同PVC
podManagementPolicy <string> # Pod管理策略,默认的“OrderedReady”表示顺序创 #默认启动顺序 这个启动顺序和之前将deployment和 rs不一样 他这里面是按照顺序启动的,比如说节点为三个 他会从0 1 2 启动 必须先启动第一个,当第一个状态为running 的时候 在启动第二个 依次进行
#建并逆序删除,另一可用值“Parallel”表示并行模式
写一个
[root@k8s-master1 statefuset]# vim statefuset-nginx-1.yml
apiVersion: v1
kind: Service #先定义Service
metadata:
name: nginx-2
spec:
ports:
- port: 80
name: web
clusterIP: None #这里字段特殊 没有类型 这个none的意思是 没有ip 产生的service本身没有ip
selector:
app: nginx
version: v2
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: nginx-2 #这个名字必须和上面那个service的名字一样 因为我们后面得通过在这个service来访问
replicas: 2 #副本
selector:
matchLabels:
app: nginx
version: v2 #要求和上面的标签一致
template:
metadata:
labels:
app: nginx
version: v2
spec:
containers:
- name: nginx
image: images.guoguo.com/apps/nginx:1.22.1
ports:
- containerPort: 80
name: web
#并没有定义卷组,因为nginx不需要存储,后面再说
[root@k8s-master1 statefuset]# kubectl apply -f statefuset-nginx-1.yml
service/nginx-2 created
statefulset.apps/web created
查看一下
[root@k8s-master1 statefuset]# kubectl get statefulsets.apps
NAME READY AGE
web 2/2 77s
[root@k8s-master1 statefuset]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 108s
web-1 1/1 Running 0 107s
#他是按照0和1的顺序来的 创建的
删除是从后往前删除,创建从前往后
statefulset删除有两种方式:
扩容
[root@k8s-master1 service]# kubectl scale statefulset web --replicas 5
statefulset.apps/web scaled
#扩容为5个
创建过程
[root@k8s-master1 statefuset]# kubectl get pods -l versinotallow=v2 -owide -w
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-0 1/1 Running 0 4m12s 192.17.65.217 k8s-node3.guoguo.com <none> <none>
web-1 1/1 Running 0 4m11s 192.26.131.152 k8s-node1.guoguo.com <none> <none>
web-2 0/1 Pending 0 0s <none> <none> <none> <none>
web-2 0/1 Pending 0 0s <none> k8s-node2.guoguo.com <none> <none>
web-2 0/1 ContainerCreating 0 0s <none> k8s-node2.guoguo.com <none>
web-2 0/1 ContainerCreating 0 0s <none> k8s-node2.guoguo.com <none>
web-2 1/1 Running 0 1s 192.28.252.232 k8s-node2.guoguo.com <none>
web-3 0/1 Pending 0 0s <none> <none> <none>
web-3 0/1 Pending 0 0s <none> k8s-node3.guoguo.com <none>
web-3 0/1 ContainerCreating 0 0s <none> k8s-node3.guoguo.com <none>
web-3 0/1 ContainerCreating 0 0s <none> k8s-node3.guoguo.com <none>
web-3 1/1 Running 0 1s 192.17.65.218 k8s-node3.guoguo.com <none>
web-4 0/1 Pending 0 0s <none> <none> <none>
web-4 0/1 Pending 0 0s <none> k8s-node1.guoguo.com <none>
web-4 0/1 ContainerCreating 0 0s <none> k8s-node1.guoguo.com <none>
web-4 0/1 ContainerCreating 0 0s <none> k8s-node1.guoguo.com <none>
web-4 1/1 Running 0 1s 192.26.131.153 k8s-node1.guoguo.com <none>
他是等web-3 创建完成 再去创建web4 然后
缩容
[root@k8s-master1 service]# kubectl scale statefulset web --replicas 3
statefulset.apps/web scaled
过程
[root@k8s-master1 statefuset]# kubectl get pods -l versinotallow=v2 -owide -w
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-0 1/1 Running 0 7m9s 192.17.65.217 k8s-node3.guoguo.com <none> <none>
web-1 1/1 Running 0 7m8s 192.26.131.152 k8s-node1.guoguo.com <none> <none>
web-2 1/1 Running 0 2m19s 192.28.252.232 k8s-node2.guoguo.com <none> <none>
web-3 1/1 Running 0 2m18s 192.17.65.218 k8s-node3.guoguo.com <none> <none>
web-4 1/1 Running 0 2m17s 192.26.131.153 k8s-node1.guoguo.com <none> <none>
web-4 1/1 Terminating 0 2m32s 192.26.131.153 k8s-node1.guoguo.com <none> <none>
web-4 1/1 Terminating 0 2m33s 192.26.131.153 k8s-node1.guoguo.com <none> <none>
web-4 0/1 Terminating 0 2m33s 192.26.131.153 k8s-node1.guoguo.com <none> <none>
web-4 0/1 Terminating 0 2m33s 192.26.131.153 k8s-node1.guoguo.com <none> <none>
web-4 0/1 Terminating 0 2m33s 192.26.131.153 k8s-node1.guoguo.com <none> <none>
web-3 1/1 Terminating 0 2m34s 192.17.65.218 k8s-node3.guoguo.com <none> <none>
web-3 1/1 Terminating 0 2m35s 192.17.65.218 k8s-node3.guoguo.com <none> <none>
web-3 0/1 Terminating 0 2m36s 192.17.65.218 k8s-node3.guoguo.com <none> <none>
web-3 0/1 Terminating 0 2m36s 192.17.65.218 k8s-node3.guoguo.com <none> <none>
web-3 0/1 Terminating 0 2m36s 192.17.65.218 k8s-node3.guoguo.com <none> <none>
他是从后往前删除 先删4 再删3 倒叙方式删除
还有更新策略
他的更新策略和前面讲的一样的
支持Rollingupdate 滚动更新
和前面deployment一样
删除有两种方式:
级联删除
如果是级联删除的话你删除statefulset就会把你的pod删除
非级联删除
在删除statefulset的时候会不会把你的pod删除,如果是非级联删除的话,他不会把你的pod删除,如果是级联删除的话你删除statefulset就会把你的pod删除
非级联删除方式:
加个--cascade=false参数
[root@k8s-master1 statefuset]# kubectl delete statefulsets.apps web --cascade=false
warning: --cascade=false is deprecated (boolean value) and can be replaced with --cascade=orphan.
statefulset.apps "web" deleted
再去查看pod和statefulset
#pod未被删除
[root@k8s-master1 statefuset]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 14m
web-1 1/1 Running 0 14m
web-2 1/1 Running 0 9m41s
#但是statefulset已经被删除了
[root@k8s-master1 statefuset]# kubectl get statefulsets.apps
No resources found in default namespace.
如果使用了非级联删除,想把pod删掉的话就一个一个删除pod就行了,因为statefulset pod控制器已经被删除了,不会再给你创建pod了
只有statefulset有级联删除概念
这玩意生产上用的比较少,因为不好用