龙空技术网

K8s StatefulSets(状态集)

于果YG 59

前言:

现在各位老铁们对“nginx启动报98错误”都比较关心,朋友们都需要剖析一些“nginx启动报98错误”的相关内容。那么小编在网上搜集了一些有关“nginx启动报98错误””的相关资讯,希望我们能喜欢,朋友们一起来了解一下吧!

此篇,我们将使用不同的示例了解 Kubernetes StatefulSets。StatefulSets 是在 Kubernetes 中引入的;它由 pod 和 Persistent Volume 之间的绑定组成。

K8s StatefulSets 概述

我们了解了ReplicaSets,它从单个 pod 模板创建多个 pod 副本。除了它们的名称和 IP 地址之外,这些副本彼此没有区别。如果 pod 模板包含一个引用特定的卷PersistentVolumeClaim,则该卷的所有副本都ReplicaSet将使用完全相同的,因此受声明约束的PersistentVolumeClaim相同PersistentVolume

来自同一 ReplicaSet 的所有 Pod 始终使用相同的 PersistentVolumeClaim 和 PersistentVolume。

ReplicaSet我们可以创建一个StatefulSet 资源,而不是使用 a来运行这些类型的 pod ,它是专门为应用程序量身定制的,在这些应用程序中,应用程序的实例必须被视为完全相似的个体,每个个体都有一个稳定的名称和状态。

a 创建的每个 pod StatefulSet都分配了一个序号索引(从零开始),然后使用该索引派生 pod 的名称和主机名,并将稳定的存储附加到 pod。因此,pod 的名称是可预测的,因为每个 pod 的名称都派生自 StatefulSet 的名称和实例的序号索引。pod 没有随机名称,而是组织得很好,

StatefulSet 创建的 Pod 具有可预测的名称(和主机名),这与 ReplicaSet 创建的不同

当一个由 a 管理的 pod 实例StatefulSet消失时(因为运行 pod 的节点出现故障,它被从节点中逐出,或者有人手动删除了 pod 对象),确保它被一个StatefulSet新实例替换——类似于ReplicaSets如何它。但与 相反ReplicaSets,替换 pod 与已消失的 pod 具有相同的名称和主机名。

StatefulSet 用具有相同身份的新 pod 替换丢失的 pod,而 ReplicaSet 用全新的不相关 pod 替换它。

总而言之,Kubernetes StatefulSet 管理一组 Pod 的部署和扩展并为这些 Pod 的顺序和唯一性提供保证。

局限性给定 Pod 的存储必须由PersistentVolume Provisioner根据请求的存储类别进行配置,或者由管理员预先配置。删除和/或缩减 StatefulSet 不会删除与 StatefulSet 关联的卷。这样做是为了确保数据安全,这通常比自动清除所有相关的 StatefulSet 资源更有价值。StatefulSets 目前需要一个 Headless Service 来负责 Pod 的网络身份。您负责创建此服务。删除 StatefulSet 时,StatefulSet 不提供任何关于 Pod 终止的保证。为了实现 StatefulSet 中 pod 的有序和优雅终止,可以在删除之前将 StatefulSet 缩小到 0。将滚动更新与默认的 Pod 管理策略 (OrderedReady) 一起使用时,可能会进入需要手动干预才能修复的损坏状态。创建有状态集资源

将动态供应和存储类与 StatefulSet 一起使用是有意义的,因为如果没有它,集群管理员将无法预先供应实际存储。Kubernetes 还可以通过动态配置PersistentVolumes.

当前(在撰写本教程时)动态配置仅适用于以下提供商:

云供应商

默认存储类名称

默认供应商

亚马逊网络服务

GP2

aws-ebs

微软天青

标准

天蓝色磁盘

谷歌云平台

标准

gce-pd

开放堆栈

标准

煤渣

VMware vSphere

薄的

vsphere体积

配置 NFS 服务器

由于我使用虚拟机来演示本教程,因此我将使用 NFS 服务器作为后端持久卷。缺点是我必须手动创建StatefulSets 中副本数所需的所有 PV 。在上一篇学习Kubernetes Persistent Volumes的文章中,我已经在控制器节点上配置了我的 NFS 服务器。

以下是我为计划使用 StatefulSets 创建的 3 个副本导出的共享:

[root@controller ~]# exportfs -v/share1         (sync,wdelay,hide,no_subtree_check,sec=sys,rw,secure,no_root_squash,no_all_squash)/share2         (sync,wdelay,hide,no_subtree_check,sec=sys,rw,secure,no_root_squash,no_all_squash)/share3         (sync,wdelay,hide,no_subtree_check,sec=sys,rw,secure,no_root_squash,no_all_squash)
创建持久卷

接下来我需要为各自的共享创建 3 个持久卷。我想再次重申,如果您使用动态配置,那么您只需要创建一个存储类,而不必担心为 Pod 创建卷。在这里,由于我手动创建持久卷,除非我保留额外的持久卷可用,否则StaefulSets将无法扩展。

我为每个共享分配了 1 GB 的存储大小。我们已经涵盖了此 YAML 文件中的不同部分。以下是用于创建 PV 的示例 YAML 文件:

[root@controller ~]# cat nfs-pv-share1.ymlapiVersion: v1kind: PersistentVolumemetadata:  name: nfs-pv-share1spec:  capacity:    storage: 1Gi  volumeMode: Filesystem  accessModes:   - ReadWriteMany  persistentVolumeReclaimPolicy: Recycle  mountOptions:    - hard    - nfsvers=4.1  nfs:    path: /share1    server: controller

同样,我还有 2 个 YAML 文件来为/share2和创建持久卷/share3

让我们创建这些 PV:

[root@controller ~]# kubectl create -f nfs-pv-share1.yml -f nfs-pv-share2.yml -f nfs-pv-share3.ymlpersistentvolume/nfs-pv-share1 createdpersistentvolume/nfs-pv-share2 createdpersistentvolume/nfs-pv-share3 created
创建有状态集

我将使用 StatefulSets 配置一个基本的 nginx 服务器,只是为了让您大致了解 statefulsets 的工作原理。获取Stateful sets的KIND和apiVersion可以参考api-resources:

[root@controller ~]# kubectl api-resources | grep -iE 'KIND|stateful'NAME                              SHORTNAMES   APIGROUP                       NAMESPACED   KINDstatefulsets                      sts          apps                           true         StatefulSet

要获取 :apiVersion

[root@controller ~]# kubectl explain StatefulSet | head -n 2KIND:     StatefulSetVERSION:  apps/v1

现在我们有了 KIND 和apiVersion,我们可以创建我们的 YAMl 文件:

[root@controller ~]# cat nfs-stateful.ymlapiVersion: apps/v1kind: StatefulSetmetadata:  name: nginx-statefulsetspec:  selector:    matchLabels:      name: nginx-statefulset  serviceName: nginx-statefulset  replicas: 3  template:    metadata:      labels:        name: nginx-statefulset    spec:      terminationGracePeriodSeconds: 10      containers:      - name: nginx-statefulset        image: nginx        ports:        - containerPort: 80          name: "web"        volumeMounts:        - name: db-data          mountPath: /var/www  volumeClaimTemplates:  - metadata:      name: db-data    spec:      accessModes: [ "ReadWriteMany" ]      storageClassName: ""      resources:        requests:          storage: 1Gi

这里我们计划创建 3 个副本,这就是我们之前创建 3 个持久卷的原因。如果 PVC 中未指定 storageClassName,则将使用默认存储类进行配置。由于我们没有存储类,所以我在 PVC 中设置了一个空字符串 (""),不会使用任何存储类。StatefulSets 将使用来自 volumeClaimTemplates 的值创建 Persistent Volume Claim。accessModes匹配来自的值很重要,PersistentVolume否则 PVC 将不会绑定到 PV。我们在 PV 中使用ReadWriteManyas our ,这就是为什么这里提到相同的原因。accessMode

接下来让我们继续创建这个StatefulSet

[root@controller ~]# kubectl create -f nfs-stateful.ymlstatefulset.apps/nginx-statefulset created
列出可用的有状态集

要获取可用的 Kubernetes StatefulSet 列表,请使用:

[root@controller ~]# kubectl get statefulsetsNAME                READY   AGEnginx-statefulset   0/3     36s

由于我们刚刚创建了这个 StatefulSet,因此总共 3 个中有 0 个准备就绪的 Pod。接下来查看可用的 PVC,因为预计 StatefulSet 将为我们之前创建的所有卷创建 Persistent Volume Claim:

[root@controller ~]# kubectl get pvcNAME                          STATUS   VOLUME          CAPACITY   ACCESS MODES   STORAGECLASS    AGEdb-data-nginx-statefulset-0   Bound    nfs-pv-share1   1Gi        RWX                            4s

如您所见,我们创建了一个 PVC,状态为 asBOUND这意味着它已成功绑定到可以在 VOLUME 下检查的持久卷之一,即nfs-pv-share-1

您还可以检查可用 PV 的列表,这里 nfs-pv-share1 由default/db-data-nginx-statefulset-0

[root@controller ~]# kubectl get pvNAME            CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM                                 STORAGECLASS    REASON   AGEnfs-pv-share1   1Gi        RWX            Recycle          Bound       default/db-data-nginx-statefulset-0                            2m3snfs-pv-share2   1Gi        RWX            Recycle          Available                                                                  2m3snfs-pv-share3   1Gi        RWX            Recycle          Available                                                                  2m3s

注意:

与 ReplicaSets 或其他类型的资源不同,StatefulSet 将按顺序创建资源。这就是您在此阶段只能看到单个 PVC 的原因,一旦映射到此 PVC 的 Pod 启动并运行,就会创建下一个 PVC。

接下来我们检查 Pod 的状态:

[root@controller ~]# kubectl get podsNAME                            READY   STATUS              RESTARTS   AGEnginx-statefulset-0             1/1     Running             0          10snginx-statefulset-1             0/1     ContainerCreating   0          1s

这里创建了第一个 Pod,您可以检查命名约定,它不包含 Deployments 或 ReplicaSets 中的任何随机字符串。创建第二个 Pod 后,将启动第三个 Pod。

等待一段时间后,我们有 2 个 PVC 和 Pod 启动并运行,我们所有的 Persistent Volumes 都被声明了:

[root@controller ~]# kubectl get podsNAME                            READY   STATUS    RESTARTS   AGEnginx-statefulset-0             1/1     Running   0          98snginx-statefulset-1             1/1     Running   0          89snginx-statefulset-2             1/1     Running   0          80s[root@controller ~]# kubectl get pvNAME            CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                 STORAGECLASS    REASON   AGEnfs-pv-share1   1Gi        RWX            Recycle          Bound    default/db-data-nginx-statefulset-0                            46mnfs-pv-share2   1Gi        RWX            Recycle          Bound    default/db-data-nginx-statefulset-1                            46mnfs-pv-share3   1Gi        RWX            Recycle          Bound    default/db-data-nginx-statefulset-2                            46m[root@controller ~]# kubectl get pvcNAME                          STATUS   VOLUME          CAPACITY   ACCESS MODES   STORAGECLASS    AGEdb-data-nginx-statefulset-0   Bound    nfs-pv-share1   1Gi        RWX                            44mdb-data-nginx-statefulset-1   Bound    nfs-pv-share2   1Gi        RWX                            44mdb-data-nginx-statefulset-2   Bound    nfs-pv-share3   1Gi        RWX                            44m
删除容器

让我们尝试一下我们的 Pod,以确保我们在上面学到的东西确实有效。因此,根据 StatefulSet 的定义,即使 Pod 被删除,Pod 的主机名、IP 地址、名称等也不应更改。

因此,为了验证这一点,让我们首先检查我们的 Pod 的详细信息:

[root@controller ~]# kubectl get pods -o wideNAME                            READY   STATUS    RESTARTS   AGE     IP          NODE                   NOMINATED NODE   READINESS GATESnginx-statefulset-0             1/1     Running   0          45m     10.36.0.1   worker-1.example.com   <none>           <none>nginx-statefulset-1             1/1     Running   0          45m     10.44.0.1   worker-2.example.com   <none>           <none>nginx-statefulset-2             1/1     Running   0          45m     10.36.0.3   worker-1.example.com   <none>           <none>

接下来让我们在nginx-statefulset-2 Pod 上创建一个虚拟文件:

[root@controller ~]# kubectl exec -it nginx-statefulset-2 -c nginx-statefulset -- touch /var/www/pod3-file

相同的文件应该出现在我们共享的 NFS 共享上 nginx-statefulset-2

[root@controller ~]# ls -l /share3/total 0-rw-r--r-- 1 root root 0 Jan  9 16:44 pod3-file

接下来,让我们删除这个 Pod:

[root@controller ~]# kubectl delete pod nginx-statefulset-2pod "nginx-statefulset-2" deleted

正如预期的那样,会自动创建一个具有相同 IP 地址和节点名称的新 Pod:

[root@controller ~]# kubectl get pods -o wideNAME                            READY   STATUS              RESTARTS   AGE     IP          NODE                   NOMINATED NODE   READINESS GATESnginx-statefulset-0             1/1     Running             0          48m     10.36.0.1   worker-1.example.com   <none>           <none>nginx-statefulset-1             1/1     Running             0          48m     10.44.0.1   worker-2.example.com   <none>           <none>nginx-statefulset-2             0/1     ContainerCreating   0          2s      <none>      worker-1.example.com   <none>           <none>

IP 尚未分配,因此让我们再次检查状态:

[root@controller ~]# kubectl get pods -o wideNAME                            READY   STATUS    RESTARTS   AGE     IP          NODE                   NOMINATED NODE   READINESS GATESnginx-statefulset-0             1/1     Running   0          49m     10.36.0.1   worker-1.example.com   <none>           <none>nginx-statefulset-1             1/1     Running   0          48m     10.44.0.1   worker-2.example.com   <none>           <none>nginx-statefulset-2             1/1     Running   0          22s     10.36.0.3   worker-1.example.com   <none>           <none>

接下来,让我们验证文件是否仍然存在于 Pod 中:

[root@controller ~]# kubectl exec -it nginx-statefulset-2 -c nginx-statefulset -- ls -l /var/www/total 0-rw-r--r-- 1 root root 0 Jan  9 11:14 pod3-file

所以 Pod 似乎按预期工作。即使 Pod 被删除,节点名、主机名和 IP 也将保持不变,这与 Deployments 和 ReplicaSets 不同。

结论

此篇,我们了解了 Kubernetes StatefulSets 以及它如何与 ReplicaSets 和 Deployments 进行比较。我们了解到,与 Deployment 一样,StatefulSet 管理基于相同容器规范的 Pod。与 Deployment 不同,StatefulSet 为其每个 Pod 维护一个粘性标识。这些 pod 是根据相同的规范创建的,但不可互换:每个 pod 都有一个持久标识符,它在任何重新调度期间都会维护该标识符。

如果您想使用存储卷为您的工作负载提供持久性,您可以使用 StatefulSet 作为解决方案的一部分。尽管 StatefulSet 中的单个 Pod 容易发生故障,但持久化的 Pod 标识符可以更轻松地将现有卷与新 Pod 相匹配,以替换任何发生故障的 Pod

让王者们更上一层楼!

让王者们更上一层楼!

欢迎各位小伙伴关注、点赞、评论、转发,你的关注和转发是我最大的动力!

标签: #nginx启动报98错误