大家都喜欢无状态的应用,因为存在随意停止、负载均衡,扩容、缩容等巨大优点,但是世界没有那么美好,都是无状态,那数据存放在哪里?
所以和Deployment差不多,K8S又搞了一个kind: StatefulSet来帮忙保存应用程序的数据,本质上在K8S上跑的是容器,容器本质是操作系统的进程,进程产生的数据就要保存下来,但是呢,因为K8S里面把容器又用POD包了一层,而POD是随时可能在集群的物理节点上漂移的。
如果我们让POD(也就是指POD里面的容器进程)的数据存放在它所在的物理主机,那么必然当漂移的时候,POD的数据是没法移动的,也就丢失了,这会导致应用程序崩溃的。
所以怎么搞,看看K8S怎么让POD漂来漂去的时候,POD产生的数据不会有丢失。
这真的是在线应用梦寐以求的功能,现在K8S直接赋能。
因为前面选择的是tomcat镜像,这个镜像有300多MB,所以创建需要一些时间,正在从dockerhub拉取。
等了一分钟不到,好了,我们启动了2个tomcat的POD
看看通过可视化仪表盘Dashboard鼠标点点点,就搞定一个StatefulSet的部署,看看它的yaml,如果是手写,那很容易出错,还要各种查资料,估计还写不出来。
kind: StatefulSet
apiVersion: apps/v1
metadata:
name: my-statefulset
namespace: default
labels:
app: my-statefulset
annotations:
author: andycui
company: jiatuxueyuan.com
kubesphere.io/alias-name: my-statefulset-alias
kubesphere.io/creator: admin
kubesphere.io/description: 做一下测试,测试StatefulSet功能
spec:
replicas: 2
selector:
matchLabels:
app: my-statefulset
template:
metadata:
creationTimestamp: null
labels:
app: my-statefulset
annotations:
logging.kubesphere.io/logsidecar-config: '{}'
spec:
containers:
- name: mytomcat-001
image: tomcat
ports:
- name: http-web-port
containerPort: 8080
protocol: TCP
resources:
limits:
cpu: '1'
memory: 2000Mi
requests:
cpu: 500m
memory: 1050Mi
volumeMounts:
- name: mypv
mountPath: /data
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
imagePullPolicy: IfNotPresent
restartPolicy: Always
terminationGracePeriodSeconds: 30
dnsPolicy: ClusterFirst
serviceAccountName: default
serviceAccount: default
securityContext: {}
affinity: {}
schedulerName: default-scheduler
volumeClaimTemplates:
- kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: mypv
namespace: default
creationTimestamp: null
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
storageClassName: local
volumeMode: Filesystem
status:
phase: Pending
serviceName: my-statefulset-hib7
podManagementPolicy: OrderedReady
updateStrategy:
type: RollingUpdate
rollingUpdate:
partition: 0
revisionHistoryLimit: 10
看这个StatefulSet的详情,因为之前创建的时候指定replicas: 2,所以这里有2个POD,注意这个POD里面只有一个容器,同时,POD的IP地址也可以看得到。
继续看看,能否从集群内访问这2个pod,可以看到确实可以访问,只不过因为这个tomcat镜像默认webapps目录下是空的,没有部署war,所以才会出现404,但是从输出来看,确实tomcat是已经启动了。
[root@linux4 ~]# curl http://10.233.115.113:8080
<!doctype html><html lang="en"><head><title>HTTP Status 404 – Not Found</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 404 – Not Found</h1><hr class="line" /><p><b>Type</b> Status Report</p><p><b>Description</b> The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.</p><hr class="line" /><h3>Apache Tomcat/10.0.10</h3></body></html>
[root@linux4 ~]# curl http://10.233.115.111:8080
<!doctype html><html lang="en"><head><title>HTTP Status 404 – Not Found</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 404 – Not Found</h1><hr class="line" /><p><b>Type</b> Status Report</p><p><b>Description</b> The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.</p><hr class="line" /><h3>Apache Tomcat/10.0.10</h3></body></html>[
这个就是通过K8S部署有状态的StatefulSet的应用,就算这个POD挂了,数据仍然不会丢失。
这里要注意:这个statefulSet中一个部署了3个POD,注意看,每个都关联了一个存储卷,如果对POD进行扩缩,这些存储卷不会消失,而且还会和POD一一对应。
比如把my-statefulset-2删掉,但是mypv-my-statefulset-2不会删除,此时如果重新再添加一个POD,又会自动和mypv-my-statefulset-2关联上,这样的话,这个POD的数据是不会丢失的,超级赞!
同样的,这个StatefulSet里面的3个POD,也可以通过Service对外提供服务,这个和Deployment是一模一样的操作。