![63d2c7119f0b39e874093daeb2ac4234.png](https://i-blog.csdnimg.cn/blog_migrate/3023f761aeb5ae5f31d408408a3a3fb5.jpeg)
知乎的文章格式太烂,查看公众号原文更美观些。
k8s实践记录(六)mp.weixin.qq.com18.如何使用statefulset部署有状态应用?
首先了解下无状态应用和有状态应用,对比下deployment和statefulset异同点,然后实践下statefulset应用。
无状态应用 vs 有状态应用
- 无状态应用简单地说就是不用关心它的上下文的应用,如web搜索服务,执行搜索得到结果就行了,如果搜索时意外中断或关闭搜索,则只需重新开始即可,并不会影响你的搜索结果。
- 有状态应用则是需要关心它的上下文的应用,如银行交易服务,如果有状态事务被中断,其上下文和历史记录会被存储下来,这样就可以或多或少地从上次中断的地方继续。
具体可以参考https://www.redhat.com/zh/topics/cloud-native-apps/stateful-vs-stateless
deployment vs statefulset
deployment
1.多个副本pod的启动没有顺序,pod的名字不是固定的,遇到失败的情况重新生成的pod的名字与原来的pod的名字不一致
2.由默认调度器维持实际数量与期望数量一致
3.可以根据给定更新策略保证更新过程中不可用pod数量在一定访问,默认25%,更新会将所有的pod最终都更新到同一个版本
4.支持一键回滚,如回滚至上一个版本kubectl rollout undo deploymentname
statefulset
1.多个副本的pod的启动是按顺序的,只有第一个pod-0
启动状态变为runnig
才会启动第二个pod-1
,以此类推;回滚、更新则是逆序的。并且名字都是固定的,遇到失败的情况重新生成的pod的名字与原来的pod的名字是一致的。
2.每个pod都会挂载一个独立的持久卷,不与其他pod共享,当遇到失败、删除重建等情况时就可以保留之前的pod的数据及pod名字
3.在更新时可以根据给定更新策略的partition字段值大小来实现灰度发布,如partition值为2,replicas值为3,则在更新时比2大的pod,也就是pod-2版本将会被更新,小于等于2的pod会保持原来的版本不变,也就是pod-0和pod-1版本不变。
statefulset实践
- statefulset-pv.yaml
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: test-0
labels:
type: local
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/test-0"
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: test-1
labels:
type: local
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/test-1"
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: test-2
labels:
type: local
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/test-2"
- test-statefulset.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: test-statefulset
name: test-statefulset-svc
spec:
type: NodePort
ports:
- name: test-statefulset-port
protocol: TCP
port: 80
targetPort: 80
nodePort: 30000
selector:
app: statefulset-test
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
creationTimestamp: null
labels:
app: statefulset-test
name: statefulset-test
spec:
serviceName: test-statefulset-svc # deployment没有这个字段
#podManagementPolicy: "Parallel" # 不写这个字段默认按顺序启动、删除statefulset的pod,如果改为parallel则表示不用按顺序启动、删除
replicas: 3
selector:
matchLabels:
app: statefulset-test # Selector是事件选择器,必须匹配 spec.template.metadata.labels 中定义的条件
updateStrategy: # deployment没有这个字段
type: RollingUpdate
rollingUpdate:
partition: 2
template:
metadata:
labels:
app: statefulset-test
spec:
containers:
- image: nginx
name: nginx
resources: {}
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates: # deployment没有这个字段
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
#storageClassName: alicloud-disk-ssd # 云厂商提供的动态卷可以自动创建pv,就无需手动创建pv了。
resources:
requests:
storage: 1Gi
- test-deployment.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: test-nfs
name: test-nfs-svc
spec:
type: NodePort
ports:
- name: test-nfs-port
protocol: TCP
port: 80
targetPort: 80
nodePort: 31000
selector:
app: mynginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: mynginx
name: mynginx
spec:
replicas: 3
selector:
matchLabels:
app: mynginx
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: mynginx
spec:
containers:
- image: nginx
name: nginx
resources: {}
status: {}
因为我用的虚拟机无动态卷供应,所以需要先手动创建pv(或者使用ceph
来提供动态卷,之后会实践下)
[root@master-1 yamlfiles]# kubectl apply -f statefulset-pv.yaml
persistentvolume/test-0 created
persistentvolume/test-1 created
per