k8s 存储之pv和pvc

目录

概念

PersistentVolume (PV)

PersistentVolumeClaim (PVC)

静态 pv

动态PV

绑定PV

持久化卷声明的保护

持久化卷类型

PV访问模式

PV回收策略

PV状态

持久化演示说明 - NFS

Ⅰ、安装 NFS 服务器

Ⅱ、部署 PV

Ⅲ、创建服务并使用 PVC

Ⅳ、释放pv和删除pvc

Ⅴ、总结

关于StatefulSet的总结


在我们整个k8s集群中,外部可能有有一些存储的资源,比如说nfs,mfs,iscsi块存储,这些存储都是由我们的存储工程师去创建的,k8s工程师想要直接去使用他们的话,肯定是很不方便的,因为不同的存储方式不一样。在k8s中,给我们提供了一个新的对象资源,叫做PV,不同的PV会对应到不用的存储资源,这样我们在部署pod的时候直接调用集群内部的pv,即可完成对存储资源的使用,但是呢,直接调用PV的话,有个问题就是,这个pv是否满足我们的需求,因为我们可能需要的是存储能力比较大存储资源,所以这个时候需要一个一个去对比pv,这样很耗费资源,这个时候又引入了我们的pvc。我们在创建pod的时候会附带一个PVC的请求,PVC的请求相当于就是去寻找一个合适的pv,进行绑定,这样我们的pod就会使用到这个pv了。也就是说让我们的pvc去寻找pv,而不是我们的pod资源去寻找。

概念

PersistentVolume (PV)

是由管理员设置的存储,它是群集的一部分。就像节点是集群中的资源一样,PV 也是集群中的资源。 PV 是Volume 之类的卷插件,但具有独立于使用 PV 的 Pod 的生命周期(pod被删除了,我们的PV依然会被保留,类似于卷)。此 API 对象包含存储实现的细节,即 NFS、iSCSI 或特定于云供应商的存储系统。

PersistentVolumeClaim (PVC)

PVC 的全称是PersistentVolumeClaim(持久化卷声明),PVC 是用户存储的一种声明,PVC 和 Pod 比较类似,Pod 消耗的是节点,PVC 消耗的是 PV 资源,Pod 可以请求 CPU 和内存,而 PVC 可以请求特定的存储空间和访问模式,例如,可以以读/写一次或 只读多次模式挂载。对于真正使用存储的用户不需要关心底层的存储实现细节,只需要直接使用 PVC 即可。也就是我们集群中会有一个个的PV,可以被直接挂在到某个pod,也可以被PVC绑定,然后挂载到某个pod。

静态 pv

集群管理员创建一些 PV。它们带有可供群集用户使用的实际存储的细节。它们存在于 Kubernetes API 中,可用于消费。

动态PV

当管理员创建的静态 PV 都不匹配用户的 PersistentVolumeClaim 时,集群可能会尝试动态地为 PVC 创建卷。此配置基于 StorageClasses :PVC 必须请求 [存储类],并且管理员必须创建并配置该类才能进行动态创建。声明该类为 "" 可以有效地禁用其动态配置。

要启用基于存储级别的动态存储配置,集群管理员需要启用 API server 上的DefaultStorageClass [准入控制器]。例如,通过确保 DefaultStorageClass 位于 API server 组件的 --admission-control 标志,使用逗号分隔的有序值列表中,可以完成此操作。

绑定PV

master 中的控制环路监视新的 PVC,寻找匹配的 PV(如果可能),并将它们绑定在一起。如果为新的 PVC 动态调配 PV,则该环路将始终将该 PV 绑定到 PVC。否则,用户总会得到他们所请求的存储,但是容量可能超出要求的数量。一旦 PV 和 PVC 绑定后, PersistentVolumeClaim 绑定是排他性的,不管它们是如何绑定的,PVC 跟PV 绑定是一对一的映射。

持久化卷声明的保护

PVC 保护的目的是确保由 pod 正在使用的 PVC 不会从系统中移除,因为如果被移除的话可能会导致数据丢失。意思就是我们的PV被我们的PVC绑定的时候,某一天我们的pod被删除之后,这个PVC依然会存在我们的系统之中,并且这个PVC依然会跟我们的PV有一个绑定关系,主要是为了防止我们的pod出现丢失之后,PVC被删除了,数据就会丢失,这个肯定是合理的。

当启用PVC 保护 alpha 功能时,如果用户删除了一个 pod 正在使用的 PVC,则该 PVC 不会被立即删除。PVC 的删除将被推迟,直到 PVC 不再被任何 pod 使用。

持久化卷类型

PersistentVolume 类型以插件形式实现。Kubernetes 目前支持以下插件类型:

1. GCEPersistentDisk AWSElasticBlockStore AzureFile AzureDisk FC (Fibre Channel)

2. FlexVolume Flocker NFS iSCSI RBD (Ceph Block Device) CephFS

3. Cinder (OpenStack block storage) Glusterfs VsphereVolume Quobyte Volumes

4. HostPath VMware Photon Portworx Volumes ScaleIO Volumes StorageOS

持久卷演示,这里演示的是一个nfs的方案

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-test
spec:
  capacity:
    storage: 5Gi      #卷的大小
  volumeMode: Filesystem            #文件类型
  accessModes:             #访问策略
    - ReadWriteOnce        #只有一个人能进行读写,两个人同时不允许 
  persistentVolumeReclaimPolicy: Recycle     #回收策略
  storageClassName: slow     #存储类的名称,相当于的人为定义存储的一个tag
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:        #这里演示的是nfs机制
    path: /tmp      #挂载到哪个目录下,即指定nfs的挂载点
    server: 172.17.0.2      #哪一个服务器的某个目录下挂载

 分析:上面的就会把nfs服务封装成一个pv-test,并且它的存储类为slow,大小为5G。

扩展:存储类的说明

在我们的后端存储中,有很多种的存储方案,如下,1类,2类,3类存储,我们的PV也会有对应存储的类,当我们的PVC去请求绑定的时候,我们可以去指定它请求绑定的类,比如说,下面的是2类,那么它就会去绑定2类型的资源。。。

PV访问模式

PersistentVolume 可以以资源提供者支持的任何方式挂载到主机上。如下表所示,供应商具有不同的功能,每个PV 的访问模式都将被设置为该卷支持的特定模式。例如,NFS 可以支持多个读/写客户端,但特定的 NFS PV 可能以只读方式导出到服务器上。每个 PV 都有一套自己的用来描述特定功能的访问模式。。。

ReadWriteOnce——该卷可以被单个节点以读/写模式挂载

ReadOnlyMany——该卷可以被多个节点以只读模式挂载

ReadWriteMany——该卷可以被多个节点以读/写模式挂载

在命令行中,访问模式缩写为:

RWO - ReadWriteOnce

ROX - ReadOnlyMany

RWX - ReadWriteMany

注意:一个卷一次只能使用一种访问模式挂载,即使它支持很多种访问模式。例如:GCEPersistentDisk可以由单个节点作为ReadWriteOnce模式挂载,或由多个节点以ReadOnlyMany模式挂载,但不能同事挂载。

PV回收策略

1. Retain(保留)——手动回收

(也就意味着当有一天,我们的PV不再使用了,那这么PV也不允许被被别人使用,等待我们的管理员手动释放掉)

2. Recycle(回收)——基本擦除(相当于执行删除卷中所有文件的命令,即 rm -rf /thevolume/* )

3. Delete(删除)——关联的存储资产(例如 AWS EBS、GCE PD、Azure Disk 和 OpenStackCinder 卷)将被删除

当前,只有 NFS 和 HostPath 支持Recycle回收策略。AWS EBS、GCE PD、Azure Disk 和 Cinder 卷支持删除策略。。。

PV状态

卷可以处于以下的某种状态:

Available(可用)——一块空闲资源还没有被任何声明绑定

Bound(已绑定)——卷已经被声明绑定

Released(已释放)——声明被删除,但是资源还未被集群重新声明

Failed(失败)——该卷的自动回收失败

命令行会显示绑定到 PV 的 PVC 的名称。

持久化演示说明 - NFS

下面的是一个示例:nfs组成的一个PV,然后采用PVC的方式,去部署我们的 StatefulSet这个服务。完整的把我们的PV,PVC,StatefulSet结合起来。

环境准备,这里我准备了两台机器,一台master1当做k8s集群,一台master2当做nfs服务器,这台没有加入到k8s集群中。

[root@master1 pv-pvc]# kubectl get node
NAME      STATUS   ROLES    AGE     VERSION
master1   Ready    master   7d18h   v1.15.9
[root@master1 pv-pvc]# 

Ⅰ、安装 NFS 服务器

这个可以在我们的第三方主机安装,我们这个测试的主机IP是192.168.64.151,这个作为我们nfs服务器,下面操作没有说明,都在nfs服务器上做。

yum install -y nfs-common nfs-utils rpcbind      #所有的节点都需要安装
mkdir /nfsdata     #创建一个共享目录
chmod 777 /nfsdata
chown nfsnobody /nfsdata      #赋予nfsnobody这样一个身份
cat /etc/exports
    /nfsdata *(rw,no_root_squash,no_all_squash,sync)
systemctl start rpcbind
systemctl start nfs

我们创建好nfs服务器之后,然后去另外的一台主机上maser1测试一下这个nfs服务器可不可以用

[root@master1 pv-pvc]# mkdir /test
[root@master1 pv-pvc]# showmount -e 192.168.64.151
Export list for 192.168.64.151:
/nfsdata *
[root@master1 pv-pvc]#
[root@master1 pv-pvc]# mount -t nfs 192.168.64.151:/nfsdata /test/
[root@master1 pv-pvc]#
[root@master1 pv-pvc]# cd /test/
[root@master1 test]# ls 
[root@master1 test]# touch aaa
[root@master1 test]# ls
aaa
[root@master1 test]#
[root@master1 test]# cd ..
[root@master1 /]# umount /test 
[root@master1 /]# rm -rf /test/
[root@master1 /]#

nfs服务器那边的共享目录也可以同步数据,就算删除共享目录也不影响

[root@master2 nfsdata]# ls
aaa
[root@master2 nfsdata]#

Ⅱ、部署 PV

上面的nfs服务器搭建好之后,我们就可以使用这个nfs存储服务器了

在主节点创建 pv.yaml,当然下面的演示都是基于这个模板,创建了三个不用的pv

[root@master1 pv-pvc]# cat pv.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfspv0
spec:
  capacity:
    storage: 10Gi      #存储大小
  accessModes:
    - ReadWriteOnce    #当前存储模式
  persistentVolumeReclaimPolicy: Retain      #回收策略 
  storageClassName: nfs        #存储类的名称,也可以是V1,V2什么V3
  nfs:
    path: /nfsdata            #nfs服务器共享目录
    server: 192.168.64.151
[root@master1 pv-pvc]# kubectl apply -f pod2.yaml 
persistentvolume/nfspv1 created
[root@master1 pv-pvc]# 
[root@master1 pv-pvc]# kubectl get pv
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
nfspv0   10Gi       RWO            Retain           Available           nfs                     6s
[root@master1 pv-pvc]# 

Ⅲ、创建服务并使用 PVC

首先创建一个SVC,然后创建StatefulSet,让StatefulSet调用我们的PVC,如果想要建立StatefulSet这个服务的话,必须先建立一个无头服务,因为要提供稳定的网络标志,关于statefulset这个可以参考官方文档Kubernetes(k8s)中文文档 名词解释:StatefulSet_Kubernetes中文社区

为了演示效果,我们在nfs服务器上创建了三个共享目录

[root@master2 nfsdata]# cat /etc/exports
/nfsdata *(rw,no_root_squash,no_all_squash,sync)
/nfsdata1 *(rw,no_root_squash,no_all_squash,sync)
/nfsdata2 *(rw,no_root_squash,no_all_squash,sync)
[root@master2 nfsdata]# ls /nfsdata
nfsdata/  nfsdata1/ nfsdata2/
[root@master2 nfsdata]# chmod  777 /nfsdata*
[root@master2 nfsdata]# chown nfsnobody /nfsdata*
[root@master2 nfsdata]# systemctl restart rpcbind
[root@master2 nfsdata]# systemctl restart nfs
---------------------------------------------------------
测试nfs服务器是否可用
[root@master1 pv-pvc]# showmount -e 192.168.64.151
Export list for 192.168.64.151:
/nfsdata2 *
/nfsdata1 *
/nfsdata  *

然后在k8s服务器上对应这三个目录创建三个不同属性的pv,分别绑定nfs服务器的三个共享目录

[root@master1 pv-pvc]# cat pv.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfspv0
spec:
  capacity:
    storage: 10Gi      #存储大小
  accessModes:
    - ReadWriteOnce    #当前存储模式
  persistentVolumeReclaimPolicy: Retain      #回收策略 
  storageClassName: nfs        #存储类的名称,也可以是V1,V2什么V3
  nfs:
    path: /nfsdata            #nfs服务器共享目录
    server: 192.168.64.151
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfspv1
spec:
  capacity:
    storage: 15Gi      #存储大小
  accessModes:
    - ReadOnlyMany    #当前存储模式
  persistentVolumeReclaimPolicy: Retain      #回收策略 
  storageClassName: slow        #存储类的名称,也可以是V1,V2什么V3
  nfs:
    path: /nfsdata1            #nfs服务器共享目录
    server: 192.168.64.151
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfspv2
spec:
  capacity:
    storage: 5Gi      #存储大小
  accessModes:
    - ReadWriteMany    #当前存储模式
  persistentVolumeReclaimPolicy: Retain      #回收策略 
  storageClassName: nfs        #存储类的名称,也可以是V1,V2什么V3
  nfs:
    path: /nfsdata2           #nfs服务器共享目录
    server: 192.168.64.151
[root@master1 pv-pvc]# 

然后创建我们的pvc

[root@master1 pv-pvc]# cat pvc.yaml 
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx
  serviceName: "nginx"
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:alpine
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "nfs"
      resources:
        requests:
          storage: 1Gi
[root@master1 pv-pvc]#

注意:这里我们需要关注的是volumeClaimTemplates的字段,它会去匹配对应的PV。

查看运行之后的效果

[root@master1 pv-pvc]# kubectl get pod -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP             NODE      NOMINATED NODE   READINESS GATES
web-0   1/1     Running   0          74s   10.244.0.170   master1   <none>           <none>
web-1   0/1     Pending   0          71s   <none>         <none>    <none>           <none>
[root@master1 pv-pvc]# kubectl describe pod web-1
.........................
Warning  FailedScheduling  60s (x3 over 2m16s)  default-scheduler  pod has unbound immediate PersistentVolumeClaims

有一个pod处于pending状态,还有一个没创建,StatefulSet这个控制器管理的pod是按序创建的,第一个创建完成之后,才到第二个,第二个创建完成之后才到第三个,第二个现在没有创建成功,所以第三个就不会显示。

我们看看我们的pod的pvc需求

再看看pv,只有一个pv符合要求,我们之前说过,一个pv只能由一个pvc绑定

我们现在把不符合要求的pv改成我们pvc能够匹配到的样子,先删除不符合的pv

[root@master1 pv-pvc]# kubectl delete pv nfspv1 
persistentvolume "nfspv1" deleted
[root@master1 pv-pvc]# kubectl delete pv nfspv2
persistentvolume "nfspv2" deleted
[root@master1 pv-pvc]# 
[root@master1 pv-pvc]# kubectl get pv
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               STORAGECLASS   REASON   AGE
nfspv0   10Gi       RWO            Retain           Bound    default/www-web-0   nfs                     26m
[root@master1 pv-pvc]# 

然后把之前的pv.yaml文件修改一下

再重新创建一下

[root@master1 pv-pvc]# kubectl apply -f  pv.yaml 
persistentvolume/nfspv0 unchanged
persistentvolume/nfspv1 created
persistentvolume/nfspv2 created
[root@master1 pv-pvc]# 
[root@master1 pv-pvc]# kubectl get pv
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               STORAGECLASS   REASON   AGE
nfspv0   10Gi       RWO            Retain           Bound    default/www-web-0   nfs                     29m
nfspv1   15Gi       RWO            Retain           Bound    default/www-web-2   nfs                     41s
nfspv2   5Gi        RWO            Retain          Bound    default/www-web-1   nfs                     41s
[root@master1 pv-pvc]# 
[root@master1 pv-pvc]# kubectl get pod 
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          10m
web-1   1/1     Running   0          10m
web-2   1/1     Running   0          36s
[root@master1 pv-pvc]# 
[root@master1 pv-pvc]# kubectl get pvc
NAME        STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
www-web-0   Bound    nfspv0   10Gi       RWO            nfs            23m
www-web-1   Bound    nfspv2   5Gi        RWO            nfs            23m
www-web-2   Bound    nfspv1   15Gi       RWO            nfs            74s

 绑定成功之后,我们测试一下k8s集群的pod是否与nfs服务器共享目录

[root@master1 pv-pvc]# kubectl exec -it web-0 sh
# cd /usr/share/nginx/html
# ls
# # touch bbb
----------------------------------------------
[root@master2 nfsdata]# ls
bbb

同样我们可以通过ip访问

[root@master2 nfsdata]# echo 11111 > index.html
----------------------------------------------------
[root@master1 pv-pvc]# kubectl get pod  -o wide
NAME    READY   STATUS    RESTARTS   AGE     IP             NODE      NOMINATED NODE   READINESS GATES
web-0   1/1     Running   0          8m50s   10.244.0.178   master1   <none>           <none>
web-1   1/1     Running   0          7m58s   10.244.0.179   master1   <none>           <none>
web-2   1/1     Running   0          7m56s   10.244.0.180   master1   <none>           <none>
[root@master1 pv-pvc]# curl 10.244.0.178 
11111
[root@master1 pv-pvc]# 

这里我们还可以验证一下StatefulSet的一个特点,就是提供稳定的网络标识,这里的网络标识就是pod的name,我们删除一个pod,由于副本数目为3,删除之后马上创建一个pod,此时ip变了,但是pod的名字没有发生改变,且通过新的ip依旧可以访问。

Ⅳ、释放pv和删除pvc

某个pv在生命周期中可能处于以下四个阶段之一
Available:可用状态还未与某个pvc绑定
Bond:已与某个pvc进行绑定
Release:绑定的pvc已经删除,资源已经释放,但没有被集群回收
Failed:自动资源回收失败

当我们不想要这个集群里的数据了,删除如下:

如果我们有创建pod的时候的yaml文件的话,我们可以先delete 该yaml文件

删除完yaml文件,对应的pod会退出,如果有SVC的话,再接着删除SVC,这个只是删除pod的相关信息,我们的pvc还是有的,因为我们的pvc并不会随着pod的删除而删除。

这来我们主要测试如何释放已经绑定的pvc和pv,正确的说应该是删除pvc,释放pv的绑定以供其他服务使用。

[root@master1 pv-pvc]# kubectl get pvc
NAME        STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
www-web-0   Bound    nfspv0   10Gi       RWO            nfs            74m
www-web-1   Bound    nfspv2   5Gi        RWO            nfs            74m
www-web-2   Bound    nfspv1   15Gi       RWO            nfs            52m
[root@master1 pv-pvc]# kubectl get pvc
NAME        STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
www-web-0   Bound    nfspv0   10Gi       RWO            nfs            74m
www-web-1   Bound    nfspv2   5Gi        RWO            nfs            74m
www-web-2   Bound    nfspv1   15Gi       RWO            nfs            52m
[root@master1 pv-pvc]# 
[root@master1 pv-pvc]# kubectl delete pvc --all
persistentvolumeclaim "www-web-0" deleted
persistentvolumeclaim "www-web-1" deleted
persistentvolumeclaim "www-web-2" deleted
[root@master1 pv-pvc]# kubectl get pvc
No resources found.

查看一下pv,发现pv处于release状态

[root@master1 pv-pvc]# kubectl get pv
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM               STORAGECLASS   REASON   AGE
nfspv0   10Gi       RWO            Retain           Released   default/www-web-0   nfs                     82m
nfspv1   15Gi       RWO            Retain           Released   default/www-web-2   nfs                     54m
nfspv2   5Gi        RWO            Retain           Released   default/www-web-1   nfs                     54m
[root@master1 pv-pvc]#

然后我们需要手动去释放对应nfs服务器上进行绑定的目录资源

[root@master2 /]# rm -rf nfsdata*
[root@master2 /]#

这里我们需要手动删除一下对应pv的yaml文件中对应的claimRef的信息

kubectl edit pv nfspv0
kubectl edit pv nfspv1
kubectl edit pv nfspv2

 最后查看如下,至此我们所有的资源就被释放了

Ⅴ、总结

整个过程如下图

1. 准备好nfs服务器。

2. 准备好pv的yaml文件,并根据nfs服务器共享目录来创建多少个pv.

3. 准备好pod的yaml文件,确定好volumeClaimTemplates各个字段的需求。

关于pod通过volumeClaimTemplates字段来挂载pvc也可参考这个资料K8S有状态服务-StatefulSet使用最佳实践-阿里云开发者社区

当然我们还有其他的控制类型绑定pvc的字段,例如:persistentVolumeClaim,可以参考以下的文章PV、PVC、StorageClass讲解 - 昀溪 - 博客园

关于pv存储的存储原理,可以看https://www.qikqiak.com/k8strain/storage/csi/


关于StatefulSet的总结

  • 匹配 Pod name ( 网络标识 ) 的模式为:$(statefulset名称)-$(序号),比如上面的示例:web-0,web-1, web-2
  • StatefulSet 为每个 Pod 副本创建了一个 DNS 域名,这个域名的格式为: $(podname).(headless server name),也就意味着服务间是通过Pod域名来通信而非 Pod IP,因为当Pod所在Node发生故障时, Pod 会 被飘移到其它 Node 上,Pod IP 会发生变化,但是 Pod 域名不会有变化
  • StatefulSet 使用 Headless 服务来控制 Pod 的域名,这个域名的 FQDN 为:$(service name).$(namespace).svc.cluster.local,其中,“cluster.local” 指的是集群的域名 根据 volumeClaimTemplates,为每个 Pod 创建一个 pvc,pvc 的命名规则匹配模式: (volumeClaimTemplates.name)-(pod_name),比如上面的 volumeMounts.name=www, Pod name=web-[0-2],因此创建出来的 PVC 是 www-web-0、www-web-1、www-web-2
  • 删除 Pod 不会删除其 pvc,手动删除 pvc 将自动释放 pv

下面测试一下上面的总结:

1. 先查看pod与pod之间通过域名的通信方式,这里我们先进去一个pod,然后curl一下

2.关于域名

FQDN: 同时带有主机名和域名的名称

dig:命令主要用来从 DNS 域名服务器查询主机地址信息

[root@master1 pv-pvc]# dig -t A nginx.default.svc.cluster.local. @10.244.0.168

statefulset的启动顺序

  • 有序部署:部署StatefulSet时,如果有多个Pod副本,它们会被顺序地创建(从0到N-1)并且,在下一个 Pod运行之前所有之前的Pod必须都是Running和Ready状态。
  • 有序删除:当Pod被删除时,它们被终止的顺序是从N-1到0。
  • 有序扩展:当对Pod执行扩展操作时,与部署一样,它前面的Pod必须都处于Running和Ready状态。

StatefulSet使用场景

  • 稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于 PVC 来实现。
  • 稳定的网络标识符,即 Pod 重新调度后其 PodName 和 HostName 不变。
  • 有序部署,有序扩展,基于 init containers 来实现。
  • 有序收缩。
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一、安装准备: 1.环境 主机名 IP k8s-master 192.168.250.111 k8s-node01 192.168.250.112 k8s-node02 192.168.250.116 2.设置主机名 hostnamectl --static set-hostname k8s-master hostnamectl --static set-hostname k8s-node01 hostnamectl --static set-hostname k8s-node02 3.关闭防火墙和selinux systemctl disable firewalld systemctl stop firewalld sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config 执行完成后重启虚拟机。 4.在master机器上安装ansible 执行命令:sudo yum install ansible (离线处理补充) 5.配置 ansible ssh密钥登录,此操作需要在所有机器上执行 ssh-keygen -t rsa -b 2048 回车 回车 回车 ssh-copy-id $IP #$IP为所有虚拟机,按照提示输入yes 和root密码 (密钥补充) 二、安装kubernetes集群 进入ansible安装路径 : cd /etc/ansible 将路径下的roles文件夹和hosts文件删除。 解压压缩文件kubeasz.zip文件,将解压后的内容放入当前目录下(/etc/ansible) 根据搭建集群环境要求,进入/etc/ansible/example 目录下选取 hosts.allinone.example 单节点AllInOne hosts.m-masters.example 单主多节点 hosts.s-master.example 多主多节点 红色标记的是需要自行修改的地方 修改完成后将文件名改为hosts 放入/etc/ansible/目录下。 安装prepare ansible-playbook 01.prepare.yml 安装etcd ansible-playbook 02.etcd.yml 安装kubectl命令 ansible-playbook 03.kubectl.yml 安装docker ansible-playbook 04.docker.yml 如果执行时出现报错: 可忽略。 解决方法: 在master节点上执行:curl -s -S "https://registry.hub.docker.com/v2/repositories/$@/tags/" | jq '."results"[]["name"]' |sort 所有机器上执行: wget http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm rpm -ivh epel-release-latest-7.noarch.rpm yum install jq -y 在重新执行: ansible-playbook 04.docker.yml 安装calico ansible-playbook 05.calico.yml 部署master节点 ansible-playbook 06.kube-master.yml 加入node节点 ansible-playbook 07.kube-node.yml 如果执行成功,k8s集群就安装好了。 三、验证安装 如果提示kubectl: command not found,退出重新ssh登陆一下,环境变量生效即可 kubectl version #查看kubernetes版本 kubectl get componentstatus # 可以看到scheduler/controller-manager/etcd等组件 Healthy kubectl cluster-info # 可以看到kubernetes master(apiserver)组件 running kubectl get node # 可以看到单 node Ready状态 kubectl get pod --all-namespaces # 可以查看所有集群pod状态 kubectl get svc --all-namespaces # 可以查看所有集群服务状态 calicoctl node status # 可以在master或者node节点上查看calico网络状态 四、安装主要组件 安装kubedns kubectl create -f manifests/kubedns 安装heapster kubectl create -f manifests/heapster 安装dashboard kubectl create -f manifests/dashboard 访问dashboard 先执行命令查看dashboard的NodePort 端口 kubectl get svc -n kube-system 访问web页面 https://masterIP: 7443 选择令牌按钮 ,用命令查询登录令牌 之前安装过 heapster 执行命令:kubectl get secret -n kube-system 查询 heapster-token-twpw4 的详细内容 执行命令:kubectl describe secret heapster-token-twpw4 -n kube-system Token就是登录令牌,复制登录就好了 安装ingress kubectl create -f manifests/ingress/ 安装EFK(elasticsearch+ fluentd + kibana) 首先进入 manifests/EFK 文件夹下 (cd /etc/ansible/manifests/EFK) 查看并修改 ceph-sercet.yaml 文件。 此key值是 ceph存储用户的token值 ,将此key值转换为base64 将文件中红色选选中部分修改为转换后的值。 修改完成后 部署 pvpvc 执行命令:kubectl create -f es-pv-data.yaml kubectl create -f es-pvc-data.yaml 部署fluentd 执行命令:kubectl create -f fluentd-rbac.yml -f fluentd-configmap.yml -f fluentd-daemonset.yml 部署elasticsearch 先设置node节点中role ,指定master client data 部署位置 执行命令:kubectl get nodes kubectl label node 10.2.0.244 role=master (10.2.0.244 是我本机kubernetes 的master节点 ,所以我也将此master也部署在这里) 其余的两个节点分别是data 和 client 执行命令:kubectl create -f es-discovery-svc.yaml -f es-svc.yaml -f es-master.yaml -f es-client.yaml -f es-data.yaml 其中部署elasticsearch集群需要注意一些事项 : Master节点一般只有一个 并且提供9300 端口 客户端通讯使用 Client 节点一般提供9200端口 用于连接kibana 和 fluentd http访问使用 Data 节点是提供数据存储,持久化对data节点进行就可以。 其中 master , client , data 部署文件中 配置的 CLUSTER_NAME 指的是 elasticsearch集群名称 Java运行自行设置,最大值和最小值需要一致。 最小为-Xms256m 部署kibana 执行命令:kubectl create -f kibana-svc.yaml -f kibana.yaml 这里需要注意 kibana.yaml 文件中 参数的设置 这里的CLUSTER_NAME 也是elasticsearch部署文件中设置的集群名称。 #安装 flannel 执行命令: cd /etc/ansible/roles/flannel 先修改kube-flannel.yml文件 --iface 对应的是本机的网卡名称 command: [ "/opt/bin/flanneld", "--ip-masq", "--kube-subnet-mgr", "--iface=eth1" ] 修改完成后 执行: kubectl create -f kube-flannel-rbac.yml kubectl apply -f kube-flannel.yml
PV(PersistentVolume)和PVC(PersistentVolumeClaim)是Kubernetes中用于实现持久化存储的重要概念。 PV是集群中的一块存储,可以是NFS、iSCSI、本地存储等,由管理员进行配置或使用存储类进行动态配置。PV定义了存储的容量、访问模式、持久化存储的类型等属性。PV的生命周期是独立于Pod的,即使Pod被删除,PV仍然存在,可以被其他Pod继续使用。 PVC是一个持久化存储卷,用于访问各种类型的持久化存储,如本地存储、网络存储云存储等。PVC的使用使应用程序更加灵活和可移植,同时也提高了存储资源的利用率。PVCPV是一一对应的关系,即一个PVC只能绑定一个PV,而一个PV也只能被一个PVC绑定。 下面是一个演示k8s持久化存储PVPVC的案例: 1. 创建PV: ```yaml apiVersion: v1 kind: PersistentVolume metadata: name: my-pv spec: capacity: storage: 1Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: my-storage-class nfs: path: /data server: nfs-server-ip ``` 2. 创建PVC: ```yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: my-storage-class ``` 3. 创建Pod,并挂载PVC卷: ```yaml apiVersion: v1 kind: Pod metadata: name: my-pod spec: containers: - name: my-container image: nginx volumeMounts: - name: my-volume mountPath: /data volumes: - name: my-volume persistentVolumeClaim: claimName: my-pvc ``` 4. 删除PVC的正确步骤: ```shell kubectl delete pod my-pod kubectl delete pvc my-pvc kubectl delete pv my-pv ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值