Kubernetes高级对象StatefulSet

StatefulSet的由来

有状态应用 : 运行状态信息很重要,不能因为重启而丢失了状态。

“状态”不仅仅是数据持久化,在集群化、分布式的场景里,还有多实例的依赖关系、启动顺序和网络标识等问题需要解决,而这些问题恰恰是 Deployment 力所不及的。

使用 Deployment,多个实例之间是无关的,启动的顺序不固定,Pod 的名字、IP 地址、域名也都是完全随机的,这正是“无状态应用”的特点。

对于“有状态应用”,多个实例之间可能存在依赖关系,比如 master/slave、active/passive,需要依次启动才能保证应用正常运行,外界的客户端也可能要使用固定的网络标识来访问实例,而且这些信息还必须要保证在 Pod 重启后不变。

所以,Kubernetes 就在 Deployment 的基础之上定义了一个新的 API 对象,名字也很好理解,就叫 StatefulSet,专门用来管理有状态的应用。

YAML 描述 StatefulSet

Redis 的 StatefulSet示例

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-sts

spec:
  serviceName: redis-svc
  replicas: 2
  selector:
    matchLabels:
      app: redis-sts

  template:
    metadata:
      labels:
        app: redis-sts
    spec:
      containers:
      - image: redis:5-alpine
        name: redis
        ports:
        - containerPort: 6379

Kubernetes 里使用 StatefulSet

kubectl apply -f redis-sts.yml
kubectl get sts
kubectl get pod -o wide

在这里插入图片描述
StatefulSet 所管理的 Pod 不再是随机的名字了,而是有了顺序编号,从 0 开始分别被命名为 redis-sts-0、redis-sts-1,Kubernetes 也会按照这个顺序依次创建(0 号比 1 号的 AGE 要长一点),这就解决了“有状态应用”的第一个问题:启动顺序。

kubectl exec 登录 Pod 内部查看pod身份标志

kubectl exec -it redis-sts-0 -- sh

在这里插入图片描述
在 Pod 里查看环境变量 $HOSTNAME 或者是执行命令 hostname,都可以得到这个 Pod 的名字 redis-sts-0。有了这个唯一的名字,应用就可以自行决定依赖关系了,比如在这个 Redis 例子里,就可以让先启动的 0 号 Pod 是主实例,后启动的 1 号 Pod 是从实例。

Service 对象->网络标识
redis-svc.yml

apiVersion: v1
kind: Service
metadata:
  name: redis-svc

spec:
  selector:
    app: redis-sts

  ports:
  - port: 6379
    protocol: TCP
    targetPort: 6379

kubernetes中使用service

kubectl apply -f redis-svc.yml 
kubectl get pod -o wide
kubectl describe svc redis-svc

在这里插入图片描述
Service 自己会有一个域名,格式是“对象名. 名字空间”,每个 Pod 也会有一个域名,形式是“IP 地址. 名字空间”。但因为 IP 地址不稳定,所以 Pod 的域名并不实用,一般我们会使用稳定的 Service 域名。

把 Service 对象应用于 StatefulSet 的时候,情况就不一样了。Service 发现这些 Pod 不是一般的应用,而是有状态应用,需要有稳定的网络标识,所以就会为 Pod 再多创建出一个新的域名,格式是“Pod 名. 服务名. 名字空间.svc.cluster.local”。当然,这个域名也可以简写成“Pod 名. 服务名”。

kubectl exec 进入 Pod 内部,用 ping 命令来验证一下:

kubectl exec -it redis-sts-0 -- sh

ping redis-sts-0.redis-svc

ping redis-sts-1.redis-svc

在这里插入图片描述
在 StatefulSet 里的这两个 Pod 都有了各自的域名,也就是稳定的网络标识。那么接下来,外部的客户端只要知道了 StatefulSet 对象,就可以用固定的编号去访问某个具体的实例了,虽然 Pod 的 IP 地址可能会变,但这个有编号的域名由 Service 对象维护,是稳定不变的。

StatefulSet 与 Service 对象关系图
在这里插入图片描述

StatefulSet 数据持久化

为了强调持久化存储与 StatefulSet 的一对一绑定关系,Kubernetes 为 StatefulSet 专门定义了一个字段“volumeClaimTemplates”,直接把 PVC 定义嵌入 StatefulSet 的 YAML 文件里。这样能保证创建 StatefulSet 的同时,就会为每个 Pod 自动创建 PVC,让 StatefulSet 的可用性更高。

redis-pv-sts.yml

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-pv-sts

spec:
  serviceName: redis-pv-svc

  volumeClaimTemplates:
  - metadata:
      name: redis-100m-pvc
    spec:
      storageClassName: nfs-client
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 100Mi

  replicas: 2
  selector:
    matchLabels:
      app: redis-pv-sts

  template:
    metadata:
      labels:
        app: redis-pv-sts
    spec:
      containers:
      - image: redis:5-alpine
        name: redis
        ports:
        - containerPort: 6379

        volumeMounts:
        - name: redis-100m-pvc
          mountPath: /data

StatefulSet 对象的名字是 redis-pv-sts,表示它使用了 PV 存储。然后“volumeClaimTemplates”里定义了一个 PVC,名字是 redis-100m-pvc,申请了 100MB 的 NFS 存储。在 Pod 模板里用 volumeMounts 引用了这个 PVC,把网盘挂载到了 /data 目录,也就是 Redis 的数据目录。

StatefulSet 对象完整关系图
在这里插入图片描述
kubectl apply 创建对象

 kubectl apply -f redis-pv-sts.yml
 kubectl get pod -o wide
 kubectl get pvc

在这里插入图片描述
PVC 的命名,不是随机的,是有规律的,用的是 PVC 名字加上 StatefulSet 的名字组合而成,所以即使 Pod 被销毁,因为它的名字不变,还能够找到这个 PVC,再次绑定使用之前存储的数据。

验证服务状态

添加数据到pod

kubectl exec 运行 Redis 的客户端,在里面添加一些 KV 数据:

kubectl exec -it redis-pv-sts-0 -- redis-cli
set a 111
set b 222
keys *
get a

删除Pod

kubectl delete pod redis-pv-sts-0
kubectl get pod

在这里插入图片描述
由于 StatefulSet 和 Deployment 一样会监控 Pod 的实例,发现 Pod 数量少了就会很快创建出新的 Pod,并且名字、网络标识也都会和之前的 Pod 一模一样

验证pod数据

kubectl exec -it redis-pv-sts-0 -- redis-cli
keys *
get a
get b

在这里插入图片描述
因为把 NFS 网络存储挂载到了 Pod 的 /data 目录,Redis 就会定期把数据落盘保存,所以新创建的 Pod 再次挂载目录的时候会从备份文件里恢复数据,内存里的数据就恢复原状了。

  • 32
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值