kubernetes的数据管理

kubernetes的数据管理

kubernetes管理储存资源-------volume

      我们经常说:容器和pod是短暂的,其含义是他们的生命周期可能很短,会被频繁的销毁和创建。容器销毁时,保存在容器内部文件中的数据都会被清除。

     为了持久化保存容器的数据,可以使用kubernetes volume。

    volume的生命期独立于容器,pod中的容器可能被销毁和重建,但volume会被保留。
本质上, Kubernetes Volume是一个目录,这一点与Docker Volume类似。当Volume被mount到Pod, Pod中的所有容器都可以访问这个Volume, Kubernetes Volume也支持多种backend类型,包括emptyDirhostPath, GCE Persistent Disk, AWS Elastic Block Store, NFS, Ceph等,完整列表可参考https://kubernetes.io/docs/concepts/storage/volumes/#types-of-volumes

Volume提供了对各种backend的抽象,容器在使用Volume读写数据的时候不需要关心数据到底是存放在本地节点的文件系统中呢还是云硬盘上。对它来说,所有类型的Volume都只是一个目录。

emptydir

emptydir

          emptydir是最基础的volume类型。一个emptydir volume是host上的一个空目录。

         emptydir volume对于容器来说都是持久的,对于pod则不是,当pod从节点删除时,volume的内容也会被删除。但如果只是容器被销毁而pod还在,则volume不受影响。也就是说: emptydir volume的生命周期与pod一致。

案例:

[root@master de]# cat producer-consumer.yml 

apiVersion: v1
kind: Pod
metadata:
   name: producer-consumer
spec:
  containers:
  - image: busybox
    name: producer
    volumeMounts:
    - mountPath: /producer_dir
      name: shared-volume
    args:
    - /bin/sh
    - -c
    - echo "hello world" > /producer_dir/hello; sleep 30000
 
  - image: busybox
    name:  consumer
    volumeMounts:
    - mountPath: /consumer_dir
      name: shared-volume
    args:
    - /bin/sh
    - -c
    - cat /consumer_dir/hello ; sleep 3000
 
  volumes:
  - name: shared-volume
    emptyDir: {}

这里我们模拟了一个producer-consumer场景。Pod有两个容器producer和consumer ,它们共享一个Volume, producer负责往Volume中写数据, consumer则是从Volume读取数据。

1:文件最底部volumes定义了一个emptyDir类型的Volume shared-volume

2 :producer容器将shared-volume mount到/producer_dir目录。

3 producer通过echo将数据写到文件hello里。

4: consumer容器将shared-volume mount到/consumer_dir目录。

5 consumer通过cat从文件hello读数据。

验证结果:

[root@master de]# kubectl logs producer-consumer producer
[root@master de]# kubectl get pod
NAME                READY   STATUS    RESTARTS   AGE
producer-consumer   2/2     Running   0          7m59s
[root@master de]# kubectl logs producer-consumer consumer
hello world

kubectl logs 显示容器consumer 成功读到了 producer 写入的数据,验证两个容器共享emptydir volume

     因为emptydir是docker host 文件系统里的目录,其效果相当于执行了 docker run -v /producer_dir和 docker  run -v /consumer_dir 。通过docker_inspect 查看容器的详细配置信息,我们发现两个容器都mount到一个目录:

[root@node1 ~]# docker ps
CONTAINER ID        IMAGE                  COMMAND                   CREATED             STATUS              PORTS               NAMES
5a766d5d38b1        busybox                "/bin/sh -c 'cat /co…"    27 minutes ago      Up 27 minutes                           k8s_consumer_producer-consumer_default_cec3012a-5ecf-450f-afa6-33e0a797bd5f_0
d6ed136d6ae8        busybox                "/bin/sh -c 'echo "h…"   27 minutes ago      Up 27 minutes                           k8s_producer_producer-consumer_default_cec3012a-5ecf-450f-afa6-33e0a797bd5f_0
[root@node1 ~]# docker inspect d6ed136
"Mounts": [
            {
                "Type": "bind",
                "Source": "/var/lib/kubelet/pods/cec3012a-5ecf-450f-afa6-33e0a797bd5f/volumes/kubernetes.io~empty-dir/shared-volume",
                "Destination": "/producer_dir",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            },
            {
-------------------------------------------------------------------------
"Mounts": [
            {
                "Type": "bind",
                "Source": "/var/lib/kubelet/pods/cec3012a-5ecf-450f-afa6-33e0a797bd5f/volumes/kubernetes.io~empty-dir/shared-volume",
                "Destination": "/consumer_dir",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            },
            {

 emptydir是host上创建的临时目录,其优点是能够方便地为pod中的容器提供共享存储,不需要额外的配置,但他不具备持久性,如果pod不存在了,emptydir也没有了。

hostPath volume

       hostpath volume的作用是将docker host文件系统中已经存在的目录mount给pod的容器。大部分应用都不会使用hostPath volume,因为这实际上增加了pod与节点的耦合,限制了pod的使用。不过那些需要访问kubernetes或docker内部数据。

  比如kube-apiserver和kube-controller-manager就是这样应用,通过:

 [root@master de]# kubectl edit pod --namespace=kube-system kube-apiserver-master

volumeMounts:
    - mountPath: /etc/ssl/certs
      name: ca-certs
      readOnly: true
    - mountPath: /etc/pki
      name: etc-pki
      readOnly: true
    - mountPath: /etc/kubernetes/pki
      name: k8s-certs
      readOnly: true
  dnsPolicy: ClusterFirst
  enableServiceLinks: true
  hostNetwork: true
  nodeName: master
  priority: 2000000000
  priorityClassName: system-cluster-critical
  restartPolicy: Always
  schedulerName: default-scheduler
  securityContext: {}
  terminationGracePeriodSeconds: 30
  tolerations:
  - effect: NoExecute
    operator: Exists
  volumes:
  - hostPath:
      path: /etc/ssl/certs
      type: DirectoryOrCreate
    name: ca-certs
  - hostPath:
      path: /etc/pki
      type: DirectoryOrCreate
    name: etc-pki
  - hostPath:
      path: /etc/kubernetes/pki
      type: DirectoryOrCreate
    name: k8s-certs

外部storageprovider


如cephglusterfs独立于kubernetes集群的就算集群瘫痪了数据也不会丢失
PV(persistentVolume)和PVC(persistentVolumeClaim):
Pv是外部存储系统的一块存储空间,具有持久性,生命周期独立于pod
Pvc是对pv的申请,用户创建pvc时,指明存储资源的大小和访问模式等信息,
kubernetes会查找符合条件的pv
Kubernetes支持多中persistentVolume:NFSCephEBS等


在创建pv和pvc之前,先搭建一个NFS。

Nfs192.168.172.137
所有节点都安装:

yum -y  install rpcbindnfs-utils


在nfs节点上:

[root@localhost~]#vim /etc/exports
/volume*(rw,sync,no_root_squash)


创键这个目录:

[root@localhost~]#mkdir/volume


启动服务:所有节点

systemctlstartrpcbind&&systemctlenablerpcbind


在nfs节点:

[root@localhost~]#systemctl start nfs-server.service && systemctl enable
nfs-server.service


关闭防火墙和selinux:

[root@localhost~]#setenforce0
[root@localhost~]#systemctl stop firewalld


除了nfs节点随便找一个节点测试一下可以访问nfs节点的目录:

[root@masteremptydir]#showmount-e 192.168.172.137
Exportlistfor192.168.172.137:
/volume*


创键pv:

[root@masteremptydir]#cd..
[root@master]#mkdirpv-pvs
[root@master]#cdpv-pvs/
[root@masterpv-pvs]#vimmypv.yml
apiVersion:v1
kind:PersistentVolume
metadata:
name:mypv
spec:
capacity:
storage:1Gi
accessModes:
-ReadWriteOnce
persistentVolumeReclaimPolicy:Recycle
storageClassName:nfs
nfs:
path:/volume/mypv
server:192.168.172.137


kind:PersistentVolume      类型是pv
capacity:
storage:1Gi            指定pv的容量
accessModes:
-ReadWriteOnce       指定访问的模式读写模式mount到单个节点
ReadWriteMany       读写模式mount到多个节点
ReadOnlyMany         只读的模式mount到多个节点
persistentVolumeReclaimPolicy:Recycle          指定pv的回收策略
Recycle                  删除pv中的数据Retain需要手动清除数据
Delete                     删除storageprovider上对应的存储资源
storageClassName:nfs               指定pv的classpvc可以指定class中的pv
path:/volume/mypv                      需要手动在nfs节点上创建不然会报错
运行文件:

[root@masterpv-pvs]#kubectl apply-fmypv.yml
persistent   volume/mypv   created


查看:

[root@masterpv-pvs]#kubectl  get  pv
NAMECAPACITYACCESSMODESRECLAIMPOLICYSTATUSCLAIM
STORAGECLASSREASONAGE
mypv1GiRWORecycleAvailable
nfs14s


创建pvc:

apiVersion:v1
kind:PersistentVolumeClaim
metadata:
name:mypvc
spec:
accessModes:
-ReadWriteOnce
resources:
requests:
storage:1Gi


storageClassName:nfs
指定资源类型,访问模式,容量大小,指定class
运行文件:
[root@masterpv-pvs]#kubectl  apply-fmypvc.yml
persistentvolumeclaim/mypvccreated
查看:
[root@masterpv-pvs]#kubectlgetpvc
NAMESTATUSVOLUMECAPACITYACCESSMODESSTORAGECLASS
AGE
mypvcBoundmypv1GiRWOnfs
14s
在查看一下pv:
[root@masterpv-pvs]#kubectlgetpv
NAMECAPACITYACCESSMODESRECLAIMPOLICYSTATUSCLAIM
STORAGECLASSREASONAGE
mypv1GiRWORecycleBound
default/mypvcnfs4m22s
可以看到pvc已经成功bound到pv上了之前没创建pvc时pv的状态为
Available
创建一个pod,使用这个存储:
[root@masterpv-pvs]#vimpod.yml
apiVersion:v1
kind:Pod
metadata:
name:mypod
spec:
containers:
-image:busybox
name:test
args:
-/bin/sh
--c
-sleep300000000000
volumeMounts:
-mountPath:/aaaa
name:myvolu
volumes:
-name:myvolu
persistentVolumeClaim:
claimName:mypvc
运行文件:
[root@masterpv-pvs]#kubectlapply-fpod.yml
pod/mypodcreated
查看:
[root@masterpv-pvs]#kubectlgetpod
NAMEREADYSTATUSRESTARTSAGE
mypod1/1Running038s
测试创建一个文件试一下:
[root@masterpv-pvs]#kubectlexecmypodtouch/aaaa/hello
在nfs节点的目录查看:
[root@localhost~]#cd/volume/mypv/
[root@localhostmypv]#ls
hello
可以看到已经保存到nfs节点的/volume/mypv/下了
回收pv(删除pvc):
先删除pod:
[root@masterpv-pvs]#kubectldeletepodmypod
pod"mypod"deleted
删除pvc:
[root@masterpv-pvs]#kubectldeletepvcmypvc
persistentvolumeclaim"mypvc"deleted
查看一下pv的状态:
[root@masterpv-pvs]#kubectlgetpv
NAMECAPACITYACCESSMODESRECLAIMPOLICYSTATUSCLAIM
STORAGECLASSREASONAGE
mypv1GiRWORecycleAvailable
nfs16m
可以看到状态又变为Available了
到nfs节点查看还有数据么:
[root@localhostmypv]#ls可以看到数据已经没了
数据被清除是因为pv的回收策略是recycle所以数据被删除了
要想不被删除需要改成retain
[root@masterpv-pvs]#vimmypv.yml
执行文件
查看一下更新后的pv:
[root@masterpv-pvs]#kubectlgetpv
NAMECAPACITYACCESSMODESRECLAIMPOLICYSTATUSCLAIM
STORAGECLASSREASONAGE
mypv1GiRWORetainAvailable
nfs20m
再次创建pvc和pod:
[root@masterpv-pvs]#kubectlapply-fmypvc.yml
[root@masterpv-pvs]#kubectlapply-fpod.yml
查看一下这两个的状态确保开启了
创建一个文件:
[root@masterpv-pvs]#kubectlexecmypodtouch/aaaa/hello
再次删除pod和pvc:
[root@masterpv-pvs]#kubectldeletepodmypod
pod"mypod"deleted
[root@masterpv-pvs]#kubectldeletepvcmypvc
persistentvolumeclaim"mypvc"deleted
查看一下pv的状态:
[root@masterpv-pvs]#kubectlgetpv
NAMECAPACITYACCESSMODESRECLAIMPOLICYSTATUSCLAIM
STORAGECLASSREASONAGE
mypv1GiRWORetainReleased
default/mypvcnfs25m
状态变为了Released会一直保持这个状态,不能被其他pvc申请,可以删除pv,
存储空间中的数据不会被删除
删除pv:
[root@masterpv-pvs]#kubectldeletepvmypv
persistentvolume"mypv"deleted
在nfs节点查看数据是否保存下来了:
[root@localhostmypv]#ls
hello
Pv的动态供给:
没有满足pvc的条件会自动创建pv,是通过storageclass实现的
MYSQL使用pv,pvc:
创建pv,pvc:
[root@master]#mkdirmysql
[root@master]#cdmysql/
[root@mastermysql]#vimmysql-pv.yml
apiVersion:v1
kind:PersistentVolume
metadata:
name:mysql-pv
spec:
accessModes:
-ReadWriteOnce
capacity:
storage:1Gi
persistentVolumeReclaimPolicy:Retain
storageClassName:nfs
nfs:
path:/volume/mysql-pv
server:192.168.172.137
path:/volume/mysql-pv需要提前在nfs节点创建出来
Pvc:
[root@mastermysql]#vimmysql-pvc.yml
apiVersion:v1
kind:PersistentVolumeClaim
metadata:
name:mysql-pvc
spec:
accessModes:
-ReadWriteOnce
resources:
requests:
storage:1Gi
storageClassName:nfs
运行文件并查看:
[root@mastermysql]#kubectlapply-fmysql-pv.yml
[root@mastermysql]#kubectlgetpv
NAMECAPACITYACCESSMODESRECLAIMPOLICYSTATUS
CLAIMSTORAGECLASSREASONAGE
mysql-pv1GiRWORetainAvailable
nfs45s
[root@mastermysql]#kubectlapply-fmysql-pvc.yml
[root@mastermysql]#kubectlgetpvc
NAMESTATUSVOLUMECAPACITYACCESSMODES
STORAGECLASSAGE
mysql-pvcBoundmysql-pv1GiRWOnfs
5s
创建MYSQL:
[root@mastermysql]#vimmysql.yml
apiVersion:apps/v1
kind:Deployment
metadata:
name:mysql
labels:
app:mysql
spec:
selector:
matchLabels:
app:mysql
template:
metadata:
labels:
app:mysql
spec:
containers:
-image:mysql:5.7
name:mysql
env:
-name:MYSQL_ROOT_PASSWORD
value:password
ports:
-containerPort:3306
name:mysql
volumeMounts:
-name:mysql-volume
mountPath:/var/lib/mysql
volumes:
-name:mysql-volume
persistentVolumeClaim:
claimName:mysql-pvc
---
apiVersion:v1
kind:Service
metadata:
labels:
app:mysql
name:mysql
spec:
ports:
-protocol:TCP
port:3306
targetPort:3306
selector:
app:mysql
执行文件
进入mysql:
[root@mastermysql]#kubectlrun-it--rm--image=mysql:5.7
--restart=Nevermysql-client--mysql-hmysql-ppassword
回车一下
进入数据库创建库,表,插入数据
mysql>createdatabaseaaa;
QueryOK,1rowaffected(0.00sec)
mysql>useaaa;
Databasechanged
mysql>createtabletest(idint,namevarchar(20));
QueryOK,0rowsaffected(0.03sec)
mysql>insertintotestvalues(1,"aa");
QueryOK,1rowaffected(0.03sec)
mysql>insertintotestvalues(2,"bb");
QueryOK,1rowaffected(0.00sec)
mysql>insertintotestvalues(3,"cc"),(4,"dd");
mysql>select*fromtest;
+------+------+
|id|name|
+------+------+
|1|aa|
|2|bb|
|3|cc|
|4|dd|
+------+------+
退出
查看pod:
[root@mastermysql]#kubectlgetpod-owide
NAMEREADYSTATUSRESTARTSAGEIP
NODENOMINATEDNODEREADINESSGATES
mysql-7774bd7c76-5sk2l1/1Running06m33s
10.244.1.90k8snode2<none><none>
可以看到pod在node2上关闭node2模拟故障
等待一段时间会发现mysql服务转移到node1上了
[root@mastermysql]#kubectlgetpod-owide
NAMEREADYSTATUSRESTARTSAGEIP
NODENOMINATEDNODEREADINESSGATES
mysql-7774bd7c76-5sk2l1/1Terminating014m
10.244.1.90k8snode2<none><none>
mysql-7774bd7c76-6w49h1/1Running073s
10.244.2.83k8snode1<none><none>
登陆mysql,验证数据:
[root@mastermysql]#kubectlrun-it--rm--image=mysql:5.7
--restart=Nevermysql-client--mysql-hmysql-ppassword
mysql>showdatabases;
+--------------------+
|Database|
+--------------------+
|information_schema|
|aaa|
|mysql|
|performance_schema|
|sys|
+--------------------+
5rowsinset(0.01sec)
mysql>useaaa;
mysql>showtables;
+---------------+
|Tables_in_aaa|
+---------------+
|test|
+---------------+
1rowinset(0.00sec)
mysql>select*fromtest;
+------+------+
|id|name|
+------+------+
|1|aa|
|2|bb|
|3|cc|
|4|dd|
+------+------+
4rowsinset(0.00sec)
可以看到数据没有丢失

原文地址:https://www.cnblogs.com/cy888888/p/13369067.html