目录
k8s存储卷-volumes
为什么要用volumes?
容器中的磁盘的生命周期是短暂的, 这就带来了一些列的问题:
- 当一个容器损坏之后, kubelet会重启这个容器, 但是文件会丢失, 这个容器将是一个全新的状态
- 当很多容器运行在同一个pod中时, 很多时候需要数据文件的共享
- 在
k8s
中,由于pod
分布在各个不同的节点之上,并不能实现不同节点之间持久性数据的共享,并且,在节点故障时,可能会导致数据的永久性丢失。
volumes就是用来解决以上问题的
Volume 的生命周期独立于容器,Pod 中的容器可能被销毁和重建,但 Volume 会被保留。
volumes类型
emptyDir
一个emptyDir第一次被创建是在一个pod被指定到具体node的时候, 并且会一直存在在pod的生命周期中, 它初始化是一个空的目录,pod中的容器都可以读写这个目录,这个目录可以被挂在到各个容器相同或者不相同的的路径下。当一个pod因为任何原因被移除的时候,这些数据会被永久删除。注意:一个容器崩溃了不会导致数据的丢失,因为容器的崩溃并不移除pod. |
apiVersion: v1kind: Podmetadata: name: pod-demo #name必须小写 namespace: default labels: app: myapp tier: frontend annotations: create-by: tianpei.wangspec: containers: - name: myapp image: ikubernetes/myapp:v1 ports: - name: http containerPort: 80 volumeMounts: - name: html mountPath: /data/web/html/ - name: busybox image: busybox:latest imagePullPolicy: IfNotPresent volumeMounts: - name: html mountPath: /data/ command: ["/bin/sh", "-c", "sleep 7200"] volumes: - name: html emptyDir: {}
gitrepo
本质上还是一个emptyDir,创建的那一刻从git上clone下来文件,不会在更新,所以会借助sidecar容器来更新或者推送目录中的文件代码 |
hostPath
一个hostPath类型的磁盘就是挂在了主机的一个文件或者目录,这个功能可能不是那么常用,但是这个功能提供了一个很强大的突破口对于某些应用来说 例如,如下情况我们旧可能需要用到hostPath!!!!!! 一. 某些应用需要用到docker的内部文件,这个时候只需要挂在本机的/var/lib/docker作为hostPath!!!!!! 二. 在容器中运行cAdvisor,这个时候挂在/dev/cgroups!!!!!! |
apiVersion: v1kind: Podmetadata: name: pod-volume-hostpath namespace: defaultspec: containers: - name: myapp image: ikubernetes/myapp:v1 volumeMounts: - name: html mountPath: /usr/share/nginx/html volumes: - name: html hostPath: path: /data/pod/volume1 type: DirectoryOrCreate
nfs
安装部署nfs
yum install -y nfs-utils rpcbindsystemctl start rpcbindsystemctl start nfs[root@test share]# cat /etc/exports/data/share 10.0.0.0/24(rw,no_root_squash)
apiVersion: v1kind: Podmetadata: name: pod-volume-hostpath namespace: defaultspec: containers: - name: myapp image: ikubernetes/myapp:v1 volumeMounts: - name: html mountPath: /usr/share/nginx/html volumes: - name: html nfs: path: /data/share server: 10.0.0.53
k8s--PV, PVC
PV PVC带来了哪些好处
Volume 提供了非常好的数据持久化方案,不过在可管理性上还有不足。
如前面nfs-volume举例, 当我们创建一个挂载到nfs服务器上的pod时, 我们需要知道:
- nfs服务的ip
- nfs服务的共享目录
Pod 通常是由应用的开发人员维护,而 Volume 则通常是由存储系统的管理员维护。开发人员要获得上面的信息:
- 要么询问管理员。
- 要么自己就是管理员。
这样就带来一个管理上的问题:应用开发人员和系统管理员的职责耦合在一起了。如果系统规模较小或者对于开发环境这样的情况还可以接受。但当集群规模变大,特别是对于生成环境,考虑到效率和安全性,这就成了必须要解决的问题。
Kubernetes 给出的解决方案是 PersistentVolume 和 PersistentVolumeClaim。
PersistentVolume (PV)
是外部存储系统中的一块存储空间,由管理员创建和维护。与 Volume 一样,PV 具有持久性,生命周期独立于 Pod。
PersistentVolumeClaim (PVC)
是对 PV 的申请 (Claim)。PVC 通常由普通用户创建和维护。需要为 Pod 分配存储资源时,用户可以创建一个 PVC,指明存储资源的容量大小和访问模式(比如只读)等信息,Kubernetes 会查找并提供满足条件的 PV。有了 PersistentVolumeClaim,用户只需要告诉 Kubernetes 需要什么样的存储资源,而不必关心真正的空间从哪里分配,如何访问等底层细节信息。这些 Storage Provider 的底层信息交给管理员来处理,只有管理员才应该关心创建 PersistentVolume 的细节信息。
- 一个pv只能对应一个pvc,但是一个pvc可以对应多个pod
- pv属于集群级别的资源,整个集群都可以用;pvc属于namespace级别的资源,只属于所属namespace
- pvc资源存储在etcd中,只要etcd服务正常就不会丢失,和节点没有关系
基于nfs配置pv和pvc
nfs的配置参考前文
定义pv
apiVersion: v1kind: PersistentVolumemetadata: name: pv001 labels: name: pv001spec: nfs: path: /data/volumes/test1 server: 10.0.0.53 accessModes: ["ReadWriteMany","ReadWriteOnce"] capacity: storage: 2Gi---apiVersion: v1kind: PersistentVolumemetadata: name: pv002 labels: name: pv002spec: nfs: path: /data/volumes/test2 server: 10.0.0.53 accessModes: ["ReadWriteMany","ReadWriteOnce"] capacity: storage: 2Gi---apiVersion: v1kind: PersistentVolumemetadata: name: pv003 labels: name: pv003spec: nfs: path: /data/volumes/test3 server: 10.0.0.53 accessModes: ["ReadWriteMany","ReadWriteOnce"] capacity: storage: 7Gi
[root@master volumes]# kubectl get pvNAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGEpv001 2Gi RWO,RWX Retain Available 14mpv002 2Gi RWO,RWX Retain Available 14mpv003 7Gi RWO,RWX Retain Available 14m
accessModes:
- ReadWriteOnce (RWO) – the volume can be mounted as read-write by a single node
- ReadOnlyMany (ROX) – the volume can be mounted read-only by many nodes
- ReadWriteMany (RWX) – the volume can be mounted as read-write by many nodes
定义pvc
apiVersion: v1kind: PersistentVolumeClaimmetadata: name: mypvc namespace: defaultspec: accessModes: ["ReadWriteMany"] resources: requests: storage: 6Gi---apiVersion: v1kind: Podmetadata: name: myapp-pvc namespace: defaultspec: containers: - name: myapp image: ikubernetes/myapp:v1 volumeMounts: - name: html mountPath: /usr/share/nginx/html volumes: - name: html persistentVolumeClaim: claimName: mypvc
此时发现有符合要求的pv被绑定到了pod上
[root@master volumes]# kubectl get pvNAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGEpv001 2Gi RWO,RWX Retain Available 15mpv002 2Gi RWO,RWX Retain Available 15mpv003 7Gi RWO,RWX Retain Bound default/mypvc 15m
以mysql:5.6镜像为例
直接使用上例创建的pv
创建mysql的pvc和deployment
apiVersion: v1kind: PersistentVolumeClaimmetadata: name: mypvc namespace: defaultspec: accessModes: ["ReadWriteMany"] resources: requests: storage: 6Gi---apiVersion: apps/v1kind: Deploymentmetadata: name: mysql-deployment namespace: defaultspec: replicas: 1 selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: containers: - name: mysql image: mysql:5.6 imagePullPolicy: IfNotPresent args: - "--ignore-db-dir=lost+found" ports: - containerPort: 3306 env: - name: MYSQL_ROOT_PASSWORD value: "mysql" volumeMounts: - name: mysql mountPath: /var/lib/mysql volumes: - name: mysql persistentVolumeClaim: claimName: mypvc
然后在创建的pod中创建数据
kubectl exec -it pod mysql-deployment-5b9cf7df5c-mh94v -- /bin/sh#在pod中可以看到挂载好的nfs磁盘# df -hFilesystem Size Used Avail Use% Mounted onoverlay 20G 3.7G 16G 19% /tmpfs 64M 0 64M 0% /devtmpfs 912M 0 912M 0% /sys/fs/cgroup/dev/sda2 20G 3.7G 16G 19% /etc/hostsshm 64M 0 64M 0% /dev/shm10.0.0.53:/data/volumes/test3 20G 4.3G 16G 22% /var/lib/mysql#进入mysql# mysql -uroot -pmysql#创建新的数据库mysql> create database wtp;#进入新库mysql> use wtp;#创建新的表mysql> CREATE TABLE `tbl_dept`( -> `id` INT(11) NOT NULL AUTO_INCREMENT, -> `deptName` VARCHAR(30) DEFAULT NULL, -> `locAdd` VARCHAR(40) DEFAULT NULL, -> PRIMARY KEY (`id`) -> )ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;Query OK, 0 rows affected (0.12 sec)#删除mysql的deploymentkubectl delete deployments mysql-deployment#重新创建mysql的deploymentkubectl apply -f pvc.yaml#进入新的mysql podkubectl exec -it mysql-deployment-5b9cf7df5c-ztfwx -- /bin/sh#可以看到依旧挂载的之前的目录# df -hFilesystem Size Used Avail Use% Mounted onoverlay 20G 3.7G 16G 19% /tmpfs 64M 0 64M 0% /devtmpfs 912M 0 912M 0% /sys/fs/cgroup/dev/sda2 20G 3.7G 16G 19% /etc/hostsshm 64M 0 64M 0% /dev/shm10.0.0.53:/data/volumes/test3 20G 4.3G 16G 22% /var/lib/mysql#进入mysql查看之前的数据都还在mysql> show databases;+--------------------+| Database |+--------------------+| information_schema || mysql || performance_schema || wtp |+--------------------+4 rows in set (0.08 sec)mysql> use wtpReading table information for completion of table and column namesYou can turn off this feature to get a quicker startup with -ADatabase changedmysql> show tables -> ;+---------------+| Tables_in_wtp |+---------------+| tbl_dept |+---------------+1 row in set (0.00 sec)