Kubernetes(k8s)存储三、Volumes配置管理(.emptyDir、hostPath,pv、sc+nfs动态分配pv、StatefulSet+mysql)

容器中的文件在磁盘上是临时存放的,这给容器中运行的特殊应用程序带来一些问题。首先,当容器崩溃时,kubelet 将重新启动容器,容器中的文件将会丢失,因为容器会以干净的状态重建。其次,当在一个 Pod 中同时运行多个容器时,常常需要在这些容器之间共享文件。
Kubernetes 抽象出 Volume 对象来解决这两个问题

Kubernetes卷具有明确的生命周期,与包裹它的 Pod 相同。 因此,比 Pod 中运行的任何容器的存活期,在容器重新启动时数据也会得到保留。 当然,当一个 Pod 不再存在时,卷也将不再存在。也许更重要的是,Kubernetes 可以支持许多类型的卷,Pod 也能同时使用任意数量的卷。

卷不能挂载到其他卷,也不能与其他卷有硬链接。 Pod 中的每个容器必须独立地指定每个卷的挂载位置。

Kubernetes 支持下列类型的卷:

awsElasticBlockStore 、azureDisk、azureFile、cephfs、cinder、configMap、csi
downwardAPI、emptyDir、fc (fibre channel)、flexVolume、flocker
gcePersistentDisk、gitRepo (deprecated)、glusterfs、hostPath、iscsi、local、
nfs、persistentVolumeClaim、projected、portworxVolume、quobyte、rbd
scaleIO、secret、storageos、vsphereVolume

https://kubernetes.io/zh/docs/concepts/storage/volumes/

1.emptyDir卷

当 Pod 指定到某个节点上时,首先创建的是一个 emptyDir 卷,并且只要 Pod 在该节点上运行,卷就一直存在。 就像它的名称表示的那样,卷最初是空的。 尽管 Pod 中的容器挂载 emptyDir 卷的路径可能相同也可能不同,但是这些容器都可以读写 emptyDir 卷中相同的文件。 当 Pod 因为某些原因被从节点上删除时,emptyDir 卷中的数据也会永久删除。

emptyDir 的使用场景:
缓存空间,例如基于磁盘的归并排序。
为耗时较长的计算任务提供检查点,以便任务能方便地从崩溃前状态恢复执行。
在 Web 服务器容器服务数据时,保存内容管理器容器获取的文件。

默认情况下, emptyDir 卷存储在支持该节点所使用的介质上;这里的介质可以是磁盘或 SSD 或网络存储,这取决于您的环境。 但是,您可以将 emptyDir.medium 字段设置为 “Memory”,以告诉 Kubernetes 为您安装 tmpfs(基于内存的文件系统)。 虽然 tmpfs 速度非常快,但是要注意它与磁盘不同。 tmpfs 在节点重启时会被清除,并且您所写入的所有文件都会计入容器的内存消耗,受容器内存限制约束。

emptyDir 示例
在一个卷中,可以挂载到不同容器中

同一个pod中的容器,数据共享

访问vm2 vm1数据

[root@server2 volumes]# cat emptydir.yml 
apiVersion: v1
kind: Pod
metadata:
  name: vol1
spec:
  containers:
  - image: busyboxplus
    name: vm1
    stdin: true
    tty: true
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  - name: vm2
    image: myapp:v1
    volumeMounts:
    - mountPath: /usr/share/nginx/html
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir:
      medium: Memory
      sizeLimit: 100Mi

在这里插入图片描述

kubectl attach vol1 -c vm1 -it

在这里插入图片描述
可以看到文件超过sizeLimit,则一段时间后(1-2分钟)会被kubelet evict掉。之所以不是“立即”被evict,是因为kubelet是定期进行检查的,这里会有一个时间差。

$ kubectl  exec vol1 -it sh
/ # dd if=/dev/zero of=/cache/bigfile bs=1M count=200
200+0 records in
200+0 records out
$ kubectl  get pod -o wide
NAME   READY   STATUS    RESTARTS   AGE   IP       NODE        
vol1      0/1        Evicted            0          98s   <none>   server2  

emptydir缺点:
不能及时禁止用户使用内存。虽然过1-2分钟kubelet会将Pod挤出,但是这个时间内,其实对node还是有风险的;
影响kubernetes调度,因为empty dir并不涉及node的resources,这样会造成Pod“偷偷”使用了node的内存,但是调度器并不知晓;
用户不能及时感知到内存不可用

2.hostPath 卷

能将主机节点文件系统上的文件或目录挂载到您的 Pod 中。 虽然这不是大多数 Pod 需要的,但是它为一些应用程序提供了强大的逃生舱。(把容器的数据放在宿主机上)

hostPath 的一些用法有:
运行一个需要访问 Docker 引擎内部机制的容器,挂载 /var/lib/docker 路径。
在容器中运行 cAdvisor 时,hostPath 方式挂载 /sys。 监控宿主机占用
允许 Pod 指定给定的 hostPath 在运行 Pod 之前是否应该存在,是否应该创建以及应该以什么方式存在。

除了必需的 path 属性之外,用户可以选择性地为 hostPath 卷指定 type。
在这里插入图片描述
当使用这种类型的卷时要小心,因为:
具有相同配置(例如从 podTemplate 创建)的多个 Pod 会由于节点上文件的不同而在不同节点上有不同的行为。(路径一样,文件内容可能不一样)
当 Kubernetes 按照计划添加资源感知的调度时,这类调度机制无法考虑由 hostPath 使用的资源。
基础主机上创建的文件或目录只能由 root 用户写入。您需要在 特权容器 中以 root 身份运行进程,或者修改主机上的文件权限以便容器能够写入 hostPath 卷。

hostPath 示例

[root@server2 volumes]# cat hostpath.yml 
apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: myapp:v1
    name: vm1
    volumeMounts:
    - mountPath: /usr/share/nginx/html
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      path: /webdata
      type: DirectoryOrCreate

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
删除pod之后,数据在节点server3上依然存在

[root@server2 volumes]# kubectl delete  -f hostpath.yml 
pod "test-pd" deleted
[root@server2 volumes]# 
[root@server3 ~]# cd /webdata/
[root@server3 webdata]# ls
index.html
[root@server3 webdata]# cat index.html 
www.westos.org

NFS 示例

pod调度到哪个节点上,从远端server1mount,再挂载到pod内,

server1,server3: nfs服务,关闭火墙
yum install nfs-utils

[root@server1 ~]# vim /etc/exports
[root@server1 ~]# cat /etc/exports
/nfsdata    *(rw,no_root_squash)
[root@server1 ~]# systemctl enable --now nfs
[root@server1 ~]# showmount -e
Export list for server1:
/nfsdata *
[root@server1 ~]# cd /nfsdata/
[root@server1 nfsdata]# ls
config  server2  vol1
[root@server1 nfsdata]# rm -fr *
[root@server1 nfsdata]# echo www.westos.org > index.html
[root@server1 nfsdata]# 
[root@server2 volumes]# cat nfs.yml 
apiVersion: v1
kind: Pod
metadata:
  name: nfs-pd
spec:
  containers:
  - image: myapp:v1
    name: vm1
    volumeMounts:
    - mountPath: /usr/share/nginx/html
      name: test-volume
  volumes:
  - name: test-volume
    nfs:
      server: 172.25.10.1
      path: /nfsdata    #与server1上的路径一致

在server3上使用mount,把远端资源挂载到容器内部

在这里插入图片描述

3.PersistentVolume(持久卷,简称PV)

是集群内,由管理员提供的网络存储的一部分。就像集群中的节点一样,PV也是集群中的一种资源。它也像Volume一样,是一种volume插件,但是它的生命周期却是和使用它的Pod相互独立的。PV这个API对象,捕获了诸如NFS、ISCSI、或其他云存储系统的实现细节。

PersistentVolumeClaim(持久卷声明,简称PVC)是用户的一种存储请求。它和Pod类似,Pod消耗Node资源,而PVC消耗PV资源。Pod能够请求特定的资源(如CPU和内存)。PVC能够请求指定的大小和访问的模式(可以被映射为一次读写或者多次只读)。

有两种PV提供的方式静态和动态。
静态PV:集群管理员创建多个PV,它们携带着真实存储的详细信息,这些存储对于集群用户是可用的。它们存在于Kubernetes API中,并可用于存储使用。

动态PV:当管理员创建的静态PV都不匹配用户的PVC时,集群可能会尝试专门地供给volume给PVC。这种供给基于StorageClass。

PVC与PV的绑定是一对一的映射。没找到匹配的PV,那么PVC会无限期得处于unbound未绑定状态。

使用
Pod使用PVC就像使用volume一样。集群检查PVC(用户定义策略),查找绑定的PV,并映射PV给Pod。对于支持多种访问模式的PV,用户可以指定想用的模式。一旦用户拥有了一个PVC,并且PVC被绑定,那么只要用户还需要,PV就一直属于这个用户。用户调度Pod,通过在Pod的volume块中包含PVC来访问PV。

释放
当用户使用PV完毕后,他们可以通过API来删除PVC对象。当PVC被删除后,对应的PV就被认为是已经是“released”了,但还不能再给另外一个PVC使用。前一个PVC的属于还存在于该PV中,必须根据策略来处理掉。

回收
PV的回收策略告诉集群,在PV被释放之后集群应该如何处理该PV。当前,PV可以被Retained(保留)、 Recycled(再利用)或者Deleted(删除)。保留允许手动地再次声明资源。对于支持删除操作的PV卷,删除操作会从Kubernetes中移除PV对象,还有对应的外部存储(如AWS EBS,GCE PD,Azure Disk,或者Cinder volume)。动态供给的卷总是会被删除。

NFS持久化存储实战

NFS PV 示例:

[root@server2 volumes]# cat pv1.yml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv1
spec:
  capacity:
    storage: 2Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce   ##允许一个访问
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /nfsdata
    server: 172.25.10.1
[root@server2 volumes]# kubectl  apply -f pv1.yml 
persistentvolume/pv1 created
[root@server2 volumes]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv1    2Gi        RWO            Recycle          Available           nfs                     5s

访问模式
ReadWriteOnce – 该volume只能被单个节点以读写的方式映射
ReadOnlyMany – 该volume可以被多个节点以只读方式映射
ReadWriteMany – 该volume可以被多个节点以读写的方式映射

[root@server2 volumes]# cat pv1.yml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv1
spec:
  capacity:
    storage: 2Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /nfsdata
    server: 172.25.10.1
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv2
spec:
  capacity:
    storage: 2Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /nfsdata
    server: 172.25.10.1
---

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv3
spec:
  capacity:
    storage: 2Gi
  volumeMode: Filesystem
  accessModes:
    - ReadOnlyMany
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /nfsdata
    server: 172.25.10.1

[root@server2 volumes]# kubectl  get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv1    2Gi        RWO            Recycle          Available           nfs                     3m42s
pv2    2Gi        RWX            Recycle          Available           nfs                     6s
pv3    2Gi        ROX            Recycle          Available           nfs                     6s


在命令行中,访问模式可以简写为:
RWO - ReadWriteOnce
ROX - ReadOnlyMany
RWX - ReadWriteMany
回收策略
Retain:保留,需要手动回收
Recycle:回收,自动删除卷中数据
Delete:删除,相关联的存储资产,如AWS EBS,GCE PD,Azure Disk,or OpenStack Cinder卷都会被删除

当前,只有NFS和HostPath支持回收利用,AWS EBS,GCE PD,Azure Disk,or OpenStack Cinder卷支持删除操作。
状态:
Available:空闲的资源,未绑定给PVC
Bound:绑定给了某个PVC
Released:PVC已经删除了,但是PV还没有被集群回收
Failed:PV在自动回收中失败了
命令行可以显示PV绑定的PVC名称。
创建PVC

[root@server2 volumes]# cat pvc.yml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc1
spec:
  storageClassName: nfs
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

在这里插入图片描述

Pod挂载PV:

在这里插入图片描述

当不满足条件时,无法成功

[root@server1 nfsdata]# mkdir pv2 pv3
[root@server1 nfsdata]# ll
total 0
drwxr-xr-x. 2 root root 6 3月   8 05:04 pv1
drwxr-xr-x. 2 root root 6 3月   8 05:04 pv2
drwxr-xr-x. 2 root root 6 3月   8 05:04 pv3

[root@server2 volumes]# kubectl apply -f pv1.yml

[root@server2 volumes]# cat pv1.yml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv1
spec:
  capacity:
    storage: 2Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /nfsdata/pv1
    server: 172.25.10.1
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv2
spec:
  capacity:
    storage: 2Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /nfsdata/pv2
    server: 172.25.10.1
---

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv3
spec:
  capacity:
    storage: 2Gi
  volumeMode: Filesystem
  accessModes:
    - ReadOnlyMany
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /nfsdata/pv3
    server: 172.25.10.1

[root@server2 volumes]# kubectl apply -f pvc.yml

[root@server2 volumes]# cat pvc.yml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc1
spec:
  storageClassName: nfs
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
---
apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: myapp:v1
    name: nginx
    volumeMounts:
    - mountPath: /usr/share/nginx/html
      name: nfs-pv
  volumes:
  - name: nfs-pv
    persistentVolumeClaim:
      claimName: pvc1


[root@server1 nfsdata]# cd pv1/
[root@server1 pv1]# echo www.westos.org > index.html

在这里插入图片描述
在这里插入图片描述
挂载不同的路径pv1,pv2里面的内容不同,生成的pod访问不同内容

静态:需要创建好所对应pv

4.StorageClass(动态)

提供了一种描述存储类(class)的方法,不同的class可能会映射到不同的服务质量等级和备份策略或其他策略等。

每个 StorageClass 都包含 provisioner、parameters 和 reclaimPolicy 字段, 这些字段会在StorageClass需要动态分配 PersistentVolume 时会使用到。

StorageClass的属性
Provisioner(存储分配器):用来决定使用哪个卷插件分配 PV,该字段必须指定。可以指定内部分配器,也可以指定外部分配器。外部分配器的代码地址为: kubernetes-incubator/external-storage,其中包括NFS和Ceph等。

Reclaim Policy(回收策略):通过reclaimPolicy字段指定创建的Persistent Volume的回收策略,回收策略包括:Delete 或者 Retain,没有指定默认为Delete。

更多属性查看:https://kubernetes.io/zh/docs/concepts/storage/storage-classes/

NFS Client Provisioner

是一个automatic provisioner,使用NFS作为存储,自动创建PV和对应的PVC,本身不提供NFS存储,需要外部先有一套NFS存储服务。
PV以${namespace}-${pvcName}-${pvName}的命名格式提供(在NFS服务器上)
PV回收的时候以 archieved-${namespace}-${pvcName}-${pvName}的命名格式(在NFS服务器上)
archieved 打包
nfs-client-provisioner源码地址:https://github.com/kubernetes-incubator/external-storage/tree/master/nfs-client

NFS动态分配PV示例:

配置授权:
在这里插入图片描述

[root@server2 nfs-client]# cat nfs-client-provisioner.yaml 
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: default
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: nfs-client-provisioner-runner
rules:
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-client-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: default
roleRef:
  kind: ClusterRole
  name: nfs-client-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: default
rules:
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: default
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: default
roleRef:
  kind: Role
  name: leader-locking-nfs-client-provisioner
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-client-provisioner
  labels:
    app: nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: default
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: nfs-client-provisioner
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner
      containers:
        - name: nfs-client-provisioner
          image:  nfs-subdir-external-provisioner:v4.0.0
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: westos.org/nfs
            - name: NFS_SERVER
              value: 172.25.10.1
            - name: NFS_PATH
              value: /nfsdata
      volumes:
        - name: nfs-client-root
          nfs:
            server: 172.25.10.1
            path: /nfsdata
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-nfs-storage
provisioner: westos.org/nfs
parameters:
  archiveOnDelete: "true"
[root@server2 nfs-client]# 
[root@server1 nfsdata]# docker tag heegor/nfs-subdir-external-provisioner:v4.0.0 reg.westos.org/library/nfs-subdir-external-provisioner:v4.0.0
拉取镜像,上传至私有仓库

创建PVC,pod:

[root@server2 nfs-client]# kubectl  apply -f nfs-client-provisioner.yaml 

[root@server2 nfs-client]# cat pvc.yaml 
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: test-claim  
spec:
  storageClassName: managed-nfs-storage #当没有名字时,pvc其不能自动找到存储类,需使用默认类
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 2Gi
---
kind: Pod
apiVersion: v1
metadata:
  name: test-pod
spec:
  containers:
  - name: test-pod
    image: myapp:v1
    volumeMounts:
      - name: nfs-pvc
        mountPath: "/usr/share/nginx/html"
  volumes:
    - name: nfs-pvc
      persistentVolumeClaim:
        claimName: test-claim

[root@server2 nfs-client]# kubectl apply -f pvc.yaml
persistentvolumeclaim/test-claim created
pod/test-pod created
在这里插入图片描述

[root@server2 nfs-client]# kubectl get pod
NAME                                   READY   STATUS    RESTARTS   AGE
nfs-client-provisioner-9564c76-f52kx   1/1     Running   0          4m59s
test-pod                               1/1     Running   0          7s
[root@server2 nfs-client]# kubectl get pod -o wide
NAME                                   READY   STATUS    RESTARTS   AGE    IP               NODE      NOMINATED NODE   READINESS GATES
nfs-client-provisioner-9564c76-f52kx   1/1     Running   0          5m9s   10.244.141.226   server3   <none>           <none>
test-pod                               1/1     Running   0          17s    10.244.141.227   server3   <none>           <none>

NFS服务端:
在这里插入图片描述
在这里插入图片描述

[root@server2 nfs-client]# kubectl get pod
NAME                                   READY   STATUS    RESTARTS   AGE
nfs-client-provisioner-9564c76-f52kx   1/1     Running   0          12m    #分配器
test-pod                               1/1     Running   0          7m40s

如何迁移到指定namespace

创建namespace

[root@server2 nfs-client]# kubectl create  namespace  nfs-client-provisioner
namespace/nfs-client-provisioner created

将 nfs-client-provisioner.yaml 文件修改

:%s/default/nfs-client-provisioner/g
删除之前应用,重新应用

在不同namespace下建立,分开管理

[root@server2 nfs-client]# kubectl get pod -n nfs-client-provisioner 
NAME                                   READY   STATUS    RESTARTS   AGE
nfs-client-provisioner-9564c76-tph74   1/1     Running   0          14s
[root@server2 nfs-client]# kubectl get ns
NAME                     STATUS   AGE
default                  Active   14d
ingress-nginx            Active   24h
kube-node-lease          Active   14d
kube-public              Active   14d
kube-system              Active   14d
metallb-system           Active   4d2h
nfs-client-provisioner   Active   7m23s
[root@server2 nfs-client]# kubectl get pvc
NAME         STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
test-claim   Bound    pvc-7b1c0d3f-6dad-4cee-bdad-e65900499fbf   2Gi        RWX            managed-nfs-storage   23s
[root@server2 nfs-client]# kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                STORAGECLASS          REASON   AGE
pvc-7b1c0d3f-6dad-4cee-bdad-e65900499fbf   2Gi        RWX            Delete           Bound    default/test-claim   managed-nfs-storage            25s

默认的 StorageClass

将被用于动态的为没有特定 storage class 需求的 PersistentVolumeClaims 配置存储:(只能有一个默认StorageClass)
如果没有默认StorageClass,PVC 也没有指定storageClassName 的值,那么意味着它只能够跟 storageClassName 也是“”的 PV 进行绑定。

$ kubectl patch storageclass -p ‘{“metadata”: {“annotations”:{“storageclass.kubernetes.io/is-default-class”:“true”}}}’

[root@server2 nfs-client]# cat demo.yaml 
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: test-claim-2
spec:
  #storageClassName: managed-nfs-storage
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 2Gi

#storageClassName: managed-nfs-storage 关闭之后,创建pvc时,其不能自动找到存储类
在这里插入图片描述
在这里插入图片描述
回收创建的pod,pv,pvc

StatefulSet控制器

StatefulSet如何通过Headless Service维持Pod的拓扑状态, StatefulSet控制器创建

拓扑状态
后端没endpoint,无法解析,创建控制器

创建的时候串行,一个运行成功开始启动下一个,回收的时候也是

[root@server2 statefulset]# cat svc.yaml 
apiVersion: v1
kind: Service
metadata:
 name: nginx-svc
 labels:
  app: nginx
spec:
 ports:
 - port: 80
   name: web
 clusterIP: None
 selector:
  app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
 name: web
spec:
 serviceName: "nginx-svc"
 replicas: 2
 selector:
  matchLabels:
   app: nginx
 template:
  metadata:
   labels:
    app: nginx
  spec:
   containers:
   - name: nginx
     image: myapp:v1
     ports:
     - containerPort: 80
       name: web

StatefulSet将应用状态抽象成了两种情况:
拓扑状态:应用实例必须按照某种顺序启动。新创建的Pod必须和原来Pod的网络标识一样
存储状态:应用的多个实例分别绑定了不同存储数据。

StatefulSet给所有的Pod进行了编号,编号规则是:$(statefulset名称)-$(序号),从0开始。

Pod被删除后重建,重建Pod的网络标识也不会改变,Pod的拓扑状态按照Pod的“名字+编号”的方式固定下来,并且为每个Pod提供了一个固定且唯一的访问入口,即Pod对应的DNS记录

$ dig -t A web-0.nginx-svc.default.svc.cluster.local @10.96.0.10

;; ANSWER SECTION:
web-0.nginx-svc.default.svc.cluster.local. 30 IN A 10.244.1.122
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

StatefulSet控制器回收

pod
replicas: 0 将文件里面的副本数改为0

StatefulSet对存储状态的管理

PV和PVC的设计,使得StatefulSet对存储状态的管理成为了可能:
存储状态

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

StatefulSet还会为每一个Pod分配并创建一个同样编号的PVC。这样,kubernetes就可以通过Persistent Volume机制为这个PVC绑定对应的PV,从而保证每一个Pod都拥有一个独立的Volume。

[root@server2 statefulset]# kubectl get pvc
NAME        STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
www-web-0   Bound    pvc-d8f291e6-c40e-42f6-979d-c1293b5a37aa   1Gi        RWO            managed-nfs-storage   12m
www-web-1   Bound    pvc-823856a8-e80c-42b8-8ab9-7c4571c79898   1Gi        RWO            managed-nfs-storage   12m

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
ip可能发生改变,直接访问svc’
在这里插入图片描述
将副本数变为0之后,再次应用,其会有序回收pod,但pvc.pv还存在,页面还在,当再次将副本数变为2时,其重新重建pod,但页面信息依然是web-0,web-1,

kubectl 弹缩

首先,想要弹缩的StatefulSet. 需先清楚是否能弹缩该应用.
$ kubectl get statefulsets
改变StatefulSet副本数量:
$ kubectl scale statefulsets --replicas=

如果StatefulSet开始由 kubectl apply 或 kubectl create --save-config 创建,更新StatefulSet manifests中的 .spec.replicas, 然后执行命令 kubectl apply:
$ kubectl apply -f

也可以通过命令 kubectl edit 编辑该字段:
$ kubectl edit statefulsets

使用 kubectl patch:
$ kubectl patch statefulsets -p ‘{“spec”:{“replicas”:}}’

使用statefullset部署mysql主从集群:

见官方文档应用,注意内存
https://kubernetes.io/zh/docs/tasks/run-application/run-replicated-stateful-application/

在这里插入图片描述
这个 ConfigMap 提供 my.cnf 覆盖设置,使你可以独立控制 MySQL 主服务器和从服务器的配置。 在这里,你希望主服务器能够将复制日志提供给副本服务器,并且希望副本服务器拒绝任何不是通过 复制进行的写操作。

这个无头服务给 StatefulSet 控制器为集合中每个 Pod 创建的 DNS 条目提供了一个宿主。 因为服务名为 mysql,所以可以通过在同一 Kubernetes 集群和名字中的任何其他 Pod 内解析 <Pod 名称>.mysql 来访问 Pod。

客户端服务称为 mysql-read,是一种常规服务,具有其自己的集群 IP。 该集群 IP 在报告就绪的所有MySQL Pod 之间分配连接。 可能的端点集合包括 MySQL 主节点和所有副本节点。

请注意,只有读查询才能使用负载平衡的客户端服务。 因为只有一个 MySQL 主服务器,所以客户端应直接连接到 MySQL 主服务器 Pod (通过其在无头服务中的 DNS 条目)以执行写入操作。
StatefulSet

cm创建之后调用

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值