Kubernetes工作负载资源之StatefulSet

共 6173字,需浏览 13分钟

 ·

2022-08-25 21:21

这里将介绍Kubernetes工作负载资源中的StatefulSet

abstract.png

创建StatefulSet

不同于RC、RS、Deployment可以用于部署无状态的应用。而对于有状态的应用而言,其要求Pod需要具有稳定的、唯一的网标识符,稳定的、持久的存储。这对于RS、Deployment而言是无法满足的。为此K8s中提供了一种专用于有状态应用的StatefulSet,其可以保证当一个有状态的Pod被删除后(比如人工手动删除),K8s则会创建一个与之完全一致的Pod出来,包括Pod名称、网络主机名、存储等

对于StatefulSet的Pod而言,即使其被重新调度到别的节点,其也必须挂载旧Pod此前所使用的存储。为此Pod所使用的必须是PV持久卷,且需要与Pod解耦。故需要将每个Pod绑定各自的PVC持久卷声明。为此在StatefulSet的定义中,我们需设置PVC模板即可。以便StatefulSet能够按照PVC模板创建出与Pod数量相同的PVC。而PV持久卷则既可以是管理员提前创建的,也可以是动态制备的

这里我们先手动创建两个PV

# 创建持久卷PV

apiVersion: v1
kind: PersistentVolume
metadata:
  # PV卷名称
  name: pv-a
spec:
  # 容量
  capacity: 
    # 存储大小: 30MB
    storage: 30Mi
  # 该卷支持的访问模式
  accessModes:
    - ReadWriteOnce # RWO, 该卷可以被一个节点以读写方式挂载
    - ReadOnlyMany  # ROX, 该卷可以被多个节点以只读方式挂载
  # 回收策略: 保留
  persistentVolumeReclaimPolicy: Retain
  # 该持久卷的实际存储类型: 此处使用HostPath类型卷
  hostPath:
    path: /tmp/PvA

---

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-b
spec:
  capacity: 
    storage: 30Mi
  accessModes:
    - ReadWriteOnce
    - ReadOnlyMany
  persistentVolumeReclaimPolicy: Retain
  hostPath:
    path: /tmp/PvB

---

效果如下所示

figure 1.jpeg

对于StatefulSet而言,其还需要提前创建一个Headless Service

# 创建 Headless Service

apiVersion: v1
kind: Service
metadata:
  name: my-kubia-headless-service
spec:
  type: ClusterIP
  # 对于ClusterIP类型服务而言, 当clusterIP为None时表示这是一个Headless Service
  clusterIP: None
  selector:
    app: my-kubia
  ports:
  - port: 12121 # 服务监听端口
    targetPort: 8080 # 服务将请求转发到Pod的目标端口

现在我们开始创建StatefulSet,配置文件如下所示

# 创建 StatefulSet

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: my-statefulset-kubia
spec:
  # 标签选择器
  selector:
    matchLabels:
      app: my-kubia
  # 设定Headless Service的服务名称
  serviceName: my-kubia-headless-service
  # Pod的副本数
  replicas: 2
  # Pod模板
  template:
    metadata:
      labels:
        # 标签信息
        app: my-kubia
    spec:
      containers:
      - name: my-app-kubia
        image: luksa/kubia-pet
        # 仅用于展示容器所使用的端口
        ports:
          - containerPort: 8080
            protocol: TCP
        volumeMounts:
        # 将名为my-volume-data的卷挂载到容器指定路径/var/data上
        - name: my-volume-data
          mountPath: /var/data
  # PVC模板
  volumeClaimTemplates:
  - metadata:
      # 卷的名称
      name: my-volume-data
    spec:
      # 禁止使用动态制备的卷, 即使用静态制备
      storageClassName: ""
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 10Mi

效果如下所示,两个Pod分别绑定各自的PVC。而这两个PVC进一步地分别使用了我们之前创建的两个PV。与此同时,对于StatefulSet创建的Pod而言,其名称命名规则是StatefulSet名称加索引编号

figure 2.jpeg

测试

该应用支持通过POST请求将数据存储到容器内的/var/data路径下,通过GET请求获取容器内的/var/data路径下的数据内容。这里我们先启动一个代理,然后利用API服务器访问指定的Pod。效果如下所示,符合预期

figure 3.jpeg

对于包含N个Pod副本的StatefulSet而言,其会按照索引顺序依次创建N个Pod。即先创建索引为0的Pod,再创建索引为1的Pod,再创建索引为2的Pod,以此类推。而当我们进行缩容的时候,则它们是按照索引逆序的顺序依次终止Pod的,即顺序为N-1、N-2、N-3、...、2、1、0。现在我们将该StatefulSet的Pod副本数缩容为1

# 将StatefulSet的Pod副本数调整为指定数量
kubectl scale statefulset  my-statefulset-kubia --replicas=1

# 将指定名称的StatefulSet的Pod副本数调整为指定数量
kubectl scale statefulset <StatefulSet的名称> --replicas=<Pod的副本数>

效果如下所示。而且即使缩容了,索引1的Pod所使用的PVC、PV也依然会被保留。这样当你再次扩容时,其依然会创建一个索引为1的Pod,且依然会绑定此前索引为1的Pod所使用的PVC。无论这个新Pod会被调度哪个集群节点当中

figure 4.jpeg

现在我们重新将该StatefulSet扩容到2。可以看到索引为1的Pod再次使用了之前的PVC。且访问该Pod可以查询到此前的数据,进一步验证了这个结果

figure 5.jpeg

查询SRV记录

现在我们创建一个Pod演示如何用于获取该StatefulSet中全部Pod的网络信息

# 创建一个包含dig、ping命令的Pod

apiVersion: v1
kind: Pod
metadata:
  # Pod 名称
  name: my-dnsutils
spec:
  # 容器信息
  containers:  
  - name: my-dnsutils
    # 镜像信息
    image: tutum/dnsutils
    # 设置容器启动时执行的命令、参数
    command:  # 该命令可以保持容器一直运行, 而不会结束退出
      - sleep
      - infinity

在创建StatefulSet时我们指定了一个Headless Service。其目的在于该Headless Service会创建出相应的SRV记录。通过SRV记录我们就可以知道来该服务对应Pod的域名、IP、端口等信息了。其中该StatefulSet的域名规则一般如下所示

# StatefulSet的域名规则
<Headless Service的服务名称>.<命名空间的名称>.svc.cluster.local 

# 通过dig srv命令查询SRV记录
dig srv my-kubia-headless-service.default.svc.cluster.local

效果如下所示。这样我们就可以实现获取StatefulSet中全部Pod的网络地址了

figure 6.jpeg

参考文献

  1. Kubernetes in Action中文版 Marko Luksa著
  2. 深入剖析Kubernetes 张磊著
浏览 50
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐