之前我都是对无状态进行的一个操作,我们想扩容就扩容,想缩容就缩容,根本不用去考虑他的一个网络环境,本地储存环境啥的一个状态
当我们做有状态的服务的操作,肯定要申请一个持久化的一个空间,以及网络,确保我数据的一个稳定性和安全性
本章我还是使用nginx进行一个演示,nginx的网页是储存在/usr/share/nginx/html/ 中,这个目录在容器内是一个不可靠的东西,所以我要把他存储到容器外,通过一个voluem进行一个存储,并且可以通过服务名进行一个访问
创建
我这里准备了一个配置文件用于等会的使用
---
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 # statefulSet 对象的名字
spec:
serviceName: "nginx" # 使用哪个 service 来管理dns
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports: # 容器卷内部要暴露的端口
- containerPort: 80 # 具体暴露的端口号
name: web # 该端口配置的名字
kubectl create -f web.yaml
这样我就创建好一个了
去访问一下试试,我们需要再去搞一个容器再去访问主机
run -it --image busybox:1.28.4 dns-test /bin/sh
这个意思是搞一个 busybox,这个容器他里面包含着很多的工具,然后耐心等待他的下载
这样就成功进入了
进入测试一下
扩容缩容
kubectl get sts
可以看到这里有2个
scale sts web --replicas=5
可以看到他的一个详细信息
如果要是缩容也是一样的
kubectl scale sts web --replicas=2
可以看到他又缩减下来的一个信息
镜像更新
kubectl patch sts web --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"nginx:1.9.1"}]'
使用json格式进行一个修改
kubectl rollout history sts web
可以看到历史的一个更新记录
查看一下第二个
可以看到就是更新的镜像
他是倒叙的更新方式
他更新也有两种方式一种是RollingUpdate 另外一种是OnDelete
RollingUpdate是什么:StatefulSet 也可以采用滚动更新策略,同样是修改 pod template 属性后会触发更新,但是由于 pod 是有序的,在 StatefulSet 中更新时是基于 pod 的顺序倒序更新的
OnDelete:只 有在 pod 被删除时会进行更新操作
灰度发布(金丝雀发布)
我们在发布项目到线上的时候,没法确保他的一个安全性以及测试覆盖性达到一个非常补充的状态,我们使用灰度发布的目的就是确保产品上线后对产品的影响降到最低
当我们在更新的时候,大部分采用滚动更新,一下把所有的容器全更新完,确实可以让用户无法察觉到更新,但是如果遇到bug那么全部的容器都将收到牵连,当我们使用了金丝雀发布,他只会对其中的一个或者一半的容器进行更新
当有问题的时候直接回滚一小部分,这对我们的损失还是降到很小了
利用滚动更新中的 partition 属性,可以实现简易的灰度发布的效果
例如我们有 5 个 pod,如果当前 partition 设置为 3,那么此时滚动更新时,只会更新那些 序号 >= 3 的 pod
利用该机制,我们可以通过控制 partition 的值,来决定只更新其中一部分 pod,确认没有问题后再主键增大更新的 pod 数量,最终实现全部 pod 更新
kubectl scale sts web --replicas=5
先把个数给他调到5
现在无论我们查看那个pod他都是1.9.1镜像版本
kubectl edit sts web
再去修改web
把这个值改为3,意为这>=3的
再把他的镜像改为1.7.9
现在我去看一下web4
这个0,1,2还都是1.9.1
假如现在我们还要扩大更新
现在我将他改为1,就是0以外的全部更新了
现在0以外的pod都进行了更新
也可以看到sts的详细信息
现在我更新成0
可以看到全部进行了更新
当删除时候才更新(更新策略)
直接编辑sts
kubectl edit sts web
直接将更新策略改为OnDelete
再保存退出
然后再去编辑sts
kubectl edit sts web
然后再去修改他的镜像再保存退出
kubectl describe po web-0
现在我们去查看任意一个pod他都没有去更新,只有在这个pod被删除的时候才会被更新
我现在把web-0删除
kubectl delete po web-0
我已经把他删除了,再去describe一下
kubectl describe po web-0
发现他已经更新了,现在除了web-0其他都没更新,因为就web-0被删除了,他又自己启动了一个更新的
级联删除与非级联删除
可以看到现在有pod和sts还有svc ,在实际删除中只需要删除sts和svc
当我们删除的时候他默认是做个级联删除,也就是把pod也一起删掉
非级联就只把sts删除,他的pod会留下
删除service的话直接指定他名字删除即可
kubectl delete sts web
现在我直接把sts进行删除
可以看到他那些pod都被带着删除了
kubectl delete svc nginx
这样也把service也删除了,这时平时最常用的删除
现在我再把他创建出来,做个非级联的方式
kubectl delete sts web --cascade=false
可以看到已经没有sts了po还在
现在再想删除pod可以手动去删除了
kubectl delete po web-0 web-1
kubectl delete svc nginx
再去删除一下svc就删除成功的移除的整个sts