0

Kubernetes(k8s)存储管理之数据卷volumes(一):volumes的引入和emptyDir数据卷 - 人生...

 1 year ago
source link: https://www.cnblogs.com/renshengdezheli/p/16970686.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

一.系统环境

服务器版本 docker软件版本 Kubernetes(k8s)集群版本 CPU架构
CentOS Linux release 7.4.1708 (Core) Docker version 20.10.12 v1.21.9 x86_64

Kubernetes集群架构:k8scloude1作为master节点,k8scloude2,k8scloude3作为worker节点

服务器 操作系统版本 CPU架构 进程 功能描述
k8scloude1/192.168.110.130 CentOS Linux release 7.4.1708 (Core) x86_64 docker,kube-apiserver,etcd,kube-scheduler,kube-controller-manager,kubelet,kube-proxy,coredns,calico k8s master节点
k8scloude2/192.168.110.129 CentOS Linux release 7.4.1708 (Core) x86_64 docker,kubelet,kube-proxy,calico k8s worker节点
k8scloude3/192.168.110.128 CentOS Linux release 7.4.1708 (Core) x86_64 docker,kubelet,kube-proxy,calico k8s worker节点

Kubernetes(k8s)数据卷volumes类型众多,本文介绍数据卷volumes之一emptyDir数据卷

使用数据卷volumes的前提是已经有一套可以正常运行的Kubernetes集群,关于Kubernetes(k8s)集群的安装部署,可以查看博客《Centos7 安装部署Kubernetes(k8s)集群》https://www.cnblogs.com/renshengdezheli/p/16686769.html

三.Docker数据卷volumes

Docker 也有卷(Volume) 的概念,但对它只有少量且松散的管理。 Docker 卷是磁盘上或者另外一个容器内的一个目录。 Docker 提供卷驱动程序,但是其功能非常有限。

[root@k8scloude1 ~]# docker volume create my-vol
[root@k8scloude1 ~]# docker volume ls
local               my-vol

查看卷属性

[root@k8scloude1 ~]# docker volume inspect my-vol
[
    {
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
        "Name": "my-vol",
        "Options": {},
        "Scope": "local"
    }
]
[root@k8scloude1 ~]# docker volume rm my-vol

运行一个带有卷的容器,可以使用--mount参数或者-v参数。

注意:如果您使用尚不存在的卷启动容器,Docker 会为您创建该卷。

[root@k8scloude1 ~]# docker run -d --name devtest --mount source=my-vol,target=/app nginx:latest
或者
[root@k8scloude1 ~]# docker run -d --name devtest -v my-vol:/app nginx:latest
  
 #查看Mounts部分,可以看到数据卷已经正确挂载
[root@k8scloude1 ~]# docker inspect devtest
......
"Mounts": [
    {
        "Type": "volume",
        "Name": "my-vol",
        "Source": "/var/lib/docker/volumes/my-vol/_data",
        "Destination": "/app",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
    }
],

四.Kubernetes 数据卷volumes

4.1 有状态容器和无状态容器

无状态容器应用stateless,意味着容器上应用所使用的历史数据或运行状态不需要进行持久化,重新拉起这个应用时,无需关注这些历史输入。简单来说,例如你要运行一个计算器(而且这个计算器不需要支持历史记录功能),当你重新拉起这个计算器时,之前的数据不需要重新被加载上来,计算器可以认为是一个无状态应用。其它类似的无状态容器应用还包括一些协议转换、请求转发等应用,大体都可以认为是无状态的。

有状态容器应用stateful,有状态容器应用的特征是应用中处理的历史请求或操作,对现在或未来的操作是有影响的,那历史数据就必须被记录下来,这种应用就被称之为有状态容器应用。最典型的有状态应用莫过于数据库了,当数据库重新拉起时,你当然“要求”之前写入数据库的记录必须能被正确无误地加载出来。其实同样地,很多的消息队列(例如RabbitMQ等),为了不使消息丢失,消息队列中间件也会将消息进行持久化。当然,随着容器应用的边界越发广阔,越来越多的有状态应用正在容器化,我们看到很多的AI、自动驾驶、HPC任务都在进行容器化。

4.2 Kubernetes 数据卷volumes解决的问题

容器Container 中的文件在磁盘上是临时存放的,这给 容器Container 中运行的较重要的应用程序带来一些问题。

  • 问题之一是当容器崩溃时文件丢失。 kubelet 会重新启动容器,但容器会以干净的状态重启。
  • 第二个问题会在同一 Pod 中运行多个容器并共享文件时出现。

Kubernetes 卷(Volume) 这一抽象概念能够解决这两个问题。

4.3 Kubernetes 数据卷volumes概述

Kubernetes 支持很多类型的卷。 Pod 可以同时使用任意数目的卷类型。 临时卷类型的生命周期与 Pod 相同,但持久卷可以比 Pod 的存活期长。 当 Pod 不再存在时,Kubernetes 也会销毁临时卷;不过 Kubernetes 不会销毁持久卷。 对于给定 Pod 中任何类型的卷,在容器重启期间数据都不会丢失。

卷的核心是一个目录,其中可能存有数据,Pod 中的容器可以访问该目录中的数据。 所采用的特定的卷类型将决定该目录如何形成的、使用何种介质保存数据以及目录中存放的内容。

使用卷时, 在 .spec.volumes 字段中设置为 Pod 提供的卷,并在 .spec.containers[*].volumeMounts 字段中声明卷在容器中的挂载位置。 容器中的进程看到的文件系统视图是由它们的容器镜像 的初始内容以及挂载在容器中的卷(如果定义了的话)所组成的。 其中根文件系统同容器镜像的内容相吻合。 任何在该文件系统下的写入操作,如果被允许的话,都会影响接下来容器中进程访问文件系统时所看到的内容。

卷挂载在镜像中的指定路径下。 Pod 配置中的每个容器必须独立指定各个卷的挂载位置。

卷不能挂载到其他卷之上(不过存在一种使用 subPath 的相关机制),也不能与其他卷有硬链接

五.临时卷emptyDir

5.1 临时卷emptyDir使用场景

有些应用程序需要额外的存储,但并不关心数据在重启后是否仍然可用。 例如,缓存服务经常受限于内存大小,而且可以将不常用的数据转移到比内存慢的存储中,对总体性能的影响并不大。临时卷 就是为此类用例设计的。因为卷会遵从 Pod 的生命周期,与 Pod 一起创建和删除, 所以停止和重新启动 Pod 时,不会受持久卷在何处可用的限制。

5.2 临时卷emptyDir简介

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

说明:容器崩溃并不会导致 Pod 被从节点上移除,因此容器崩溃期间 emptyDir 卷中的数据是安全的。

emptyDir 的一些用途:

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

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

你可以通过emptyDir.sizeLimit为默认介质指定大小限制,来限制 emptyDir 卷的存储容量。 此存储是从节点临时存储中分配的。 如果来自其他来源(如日志文件或镜像分层数据)的数据占满了存储,emptyDir 可能会在达到此限制之前发生存储容量不足的问题。

说明:
当启用 SizeMemoryBackedVolumes 特性门控时, 你可以为基于内存提供的卷指定大小。 如果未指定大小,则基于内存的卷的大小为 Linux 主机上内存的 50%。

5.3 创建普通的pod

查看k8s状态

[root@k8scloude1 ~]# kubectl get nodes
NAME         STATUS   ROLES                  AGE   VERSION
k8scloude1   Ready    control-plane,master   8d    v1.21.0
k8scloude2   Ready    <none>                 8d    v1.21.0
k8scloude3   Ready    <none>                 8d    v1.21.0

创建一个目录存放yaml文件

[root@k8scloude1 ~]# mkdir volume

创建一个namespace

[root@k8scloude1 ~]# kubectl create ns volume
namespace/volume created

切换namespace到volume

[root@k8scloude1 ~]# kubens volume
Context "kubernetes-admin@kubernetes" modified.
Active namespace is "volume".

生成创建pod的yaml文件

[root@k8scloude1 ~]# cd volume/

[root@k8scloude1 volume]# pwd
/root/volume

#生成创建pod的yaml文件
[root@k8scloude1 volume]# kubectl run pod --image=nginx --image-pull-policy=IfNotPresent --dry-run=client -o yaml >pod.yaml

[root@k8scloude1 volume]# vim pod.yaml 

[root@k8scloude1 volume]# cat pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: pod
  name: pod
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: pod
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

创建pod

[root@k8scloude1 volume]# kubectl apply -f pod.yaml 
pod/pod created

#可以看到pod运行在k8scloude2节点
[root@k8scloude1 volume]# kubectl get pod -o wide
NAME   READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
pod    1/1     Running   0          11s   10.244.112.180   k8scloude2   <none>           <none>

进入pod里面,创建container.txt文件

[root@k8scloude1 volume]# kubectl exec -it pod -- bash
root@pod:/# which nginx
/usr/sbin/nginx
root@pod:/# touch container.txt
root@pod:/# exit
exit

在pod里创建container.txt文件,对应的在k8scloude2节点上也有相应的文件

[root@k8scloude2 ~]# find / -name container.txt
/var/lib/docker/overlay2/909e91a50b6d90577e21c6c1ccb97d4571dddeecc296323934c28dfa3a26acf7/diff/container.txt
/var/lib/docker/overlay2/909e91a50b6d90577e21c6c1ccb97d4571dddeecc296323934c28dfa3a26acf7/merged/container.txt

删除pod

[root@k8scloude1 volume]# kubectl delete pod pod 
pod "pod" deleted

k8scloude2节点上对应的文件也没了

[root@k8scloude2 ~]# find / -name container.txt

5.4 创建有emptyDir卷的pod

当我们删除pod之后,我们往pod里写的数据都被删除了,这样的容器不存储任何数据,称为无状态的stateless,有时候我们需要pod能够存储数据,这样的容器称为有状态的statefull,docker 配置数据卷为:docker run xxx -v /xxx:/yyy

下面配置emptyDir数据卷,emptyDir类型的卷在物理机随机生成一个目录

[root@k8scloude1 volume]# vim pod-emptydir.yaml 

[root@k8scloude1 volume]# cat pod-emptydir.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: pod
  name: pod
spec:
  terminationGracePeriodSeconds: 0
  #指定卷
  volumes:
  #卷的名字
  - name: v1
    #卷的类型为emptyDir
    emptyDir: {}
  - name: v2
    emptyDir: {}
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: pod
    resources: {}
    #卷挂载,把v1卷挂载到/xx目录
    volumeMounts:
    - name: v1
      mountPath: /xx
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

创建pod

[root@k8scloude1 volume]# kubectl apply -f pod-emptydir.yaml 
pod/pod created

[root@k8scloude1 volume]# kubectl get pod -o wide
NAME   READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
pod    1/1     Running   0          5s    10.244.112.181   k8scloude2   <none>           <none>

进入pod,在挂载目录/xx/下写入数据

[root@k8scloude1 volume]# kubectl exec -it pod -- bash
root@pod:/# ls /xx/

root@pod:/# df -h
Filesystem      Size  Used Avail Use% Mounted on
overlay         150G  4.2G  146G   3% /
tmpfs            64M     0   64M   0% /dev
tmpfs          1018M     0 1018M   0% /sys/fs/cgroup
/dev/sda1       150G  4.2G  146G   3% /xx
shm              64M     0   64M   0% /dev/shm
tmpfs          1018M   12K 1018M   1% /run/secrets/kubernetes.io/serviceaccount
tmpfs          1018M     0 1018M   0% /proc/acpi
tmpfs          1018M     0 1018M   0% /proc/scsi
tmpfs          1018M     0 1018M   0% /sys/firmware

root@pod:/# echo "hello w" >/xx/h.txt
root@pod:/# cat /xx/h.txt 
hello w
root@pod:/# exit
exit

在k8scloude2节点上查看对应的docker容器,可以看到pod的容器名为82df167460ae

[root@k8scloude2 ~]# docker ps | grep pod
82df167460ae   605c77e624dd                                          "/docker-entrypoint.…"   About a minute ago   Up About a minute             k8s_pod_pod_volume_d8fda77c-1554-4110-9ca1-29b8f177cd1b_0
056dfa5153a8   registry.aliyuncs.com/google_containers/pause:3.4.1   "/pause"                 About a minute ago   Up About a minute             k8s_POD_pod_volume_d8fda77c-1554-4110-9ca1-29b8f177cd1b_0

查看容器属性的Mounts部分,可以看到emptyDir卷的目录和挂载目录

[root@k8scloude2 ~]# docker inspect 82df167460ae | grep -A10 Mounts
        "Mounts": [
            {
                "Type": "bind",
                "Source": "/var/lib/kubelet/pods/d8fda77c-1554-4110-9ca1-29b8f177cd1b/volumes/kubernetes.io~empty-dir/v1",
                "Destination": "/xx",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            },
            {
                "Type": "bind",

查看对应的物理机目录:/var/lib/kubelet/pods/d8fda77c-1554-4110-9ca1-29b8f177cd1b/volumes/kubernetes.io~empty-dir/v1

#也存在相应的文件
[root@k8scloude2 ~]# cat /var/lib/kubelet/pods/d8fda77c-1554-4110-9ca1-29b8f177cd1b/volumes/kubernetes.io~empty-dir/v1/h.txt 
hello w

删除pod

[root@k8scloude1 volume]# kubectl delete pod pod --force
warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
pod "pod" force deleted

当pod被删除之后,物理机上文件也没了

[root@k8scloude2 ~]# ls /var/lib/kubelet/pods/d8fda77c-1554-4110-9ca1-29b8f177cd1b/volumes/kubernetes.io~empty-dir/v1/
ls: 无法访问/var/lib/kubelet/pods/d8fda77c-1554-4110-9ca1-29b8f177cd1b/volumes/kubernetes.io~empty-dir/v1/: 没有那个文件或目录

emptyDir类型的数据卷默认是以内存为介质的,删除pod之后,物理机上对应的目录也没了

5.5 sidecar使用emptyDir卷共享数据

emptyDir一般用来共享数据,比如:一个pod里运行了两个容器,一个为nginx容器,nginx容器挂载一个目录a,日志生成了之后就放在目录a,另一个fluentd容器读取目录a进行日志分析,如下实例:

[root@k8scloude1 volume]# vim sharedir.yaml 

#v1卷分别挂载到n1和s1容器
[root@k8scloude1 volume]# cat sharedir.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: pod
  name: pod
spec:
  terminationGracePeriodSeconds: 0
  volumes:
  - name: v1
    emptyDir: {}
  - name: v2
    emptyDir: {}
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: n1
    resources: {}
    volumeMounts:
    - name: v1
      mountPath: /xx
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: s1
    resources: {}
    command: ["sh","-c","sleep 1000"]
    volumeMounts:
    - name: v1
      mountPath: /yy
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

创建pod

[root@k8scloude1 volume]# kubectl apply -f sharedir.yaml 
pod/pod created

[root@k8scloude1 volume]# kubectl get pods -o wide
NAME   READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
pod    2/2     Running   0          13s   10.244.112.182   k8scloude2   <none>           <none>

进入pod里的容器n1,创建文件

[root@k8scloude1 volume]# kubectl exec -it pod -c n1 -- bash
root@pod:/# echo "nginx log" >/xx/nginx.log
root@pod:/# exit
exit

进入pod里的容器s1,可以看到文件nginx.log

[root@k8scloude1 volume]# kubectl exec -it pod -c s1 -- bash
root@pod:/# cat /yy/nginx.log 
nginx log
root@pod:/# exit
exit

在k8scloude2节点上查看对应的容器

[root@k8scloude2 ~]# docker ps | grep pod
eb17cb0232c3   605c77e624dd                                          "sh -c 'sleep 1000'"     47 seconds ago   Up 46 seconds             k8s_s1_pod_volume_69ebce38-cfc6-4fdb-bd83-a3b8ddf034cf_0
0537eb92e1dc   605c77e624dd                                          "/docker-entrypoint.…"   47 seconds ago   Up 46 seconds             k8s_n1_pod_volume_69ebce38-cfc6-4fdb-bd83-a3b8ddf034cf_0
210302b1861f   registry.aliyuncs.com/google_containers/pause:3.4.1   "/pause"                 47 seconds ago   Up 47 seconds             k8s_POD_pod_volume_69ebce38-cfc6-4fdb-bd83-a3b8ddf034cf_0

查看两个容器的属性,可以看到/xx /yy 对应的物理机的目录是一样的

[root@k8scloude2 ~]# docker inspect eb17cb0232c3 | grep -A10 Mounts
        "Mounts": [
            {
                "Type": "bind",
                "Source": "/var/lib/kubelet/pods/69ebce38-cfc6-4fdb-bd83-a3b8ddf034cf/volumes/kubernetes.io~empty-dir/v1",
                "Destination": "/yy",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            },
            {
                "Type": "bind",

[root@k8scloude2 ~]# docker inspect 0537eb92e1dc | grep -A10 Mounts
        "Mounts": [
            {
                "Type": "bind",
                "Source": "/var/lib/kubelet/pods/69ebce38-cfc6-4fdb-bd83-a3b8ddf034cf/volumes/kubernetes.io~empty-dir/v1",
                "Destination": "/xx",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            },
            {
                "Type": "bind",
                
[root@k8scloude2 ~]# cat /var/lib/kubelet/pods/69ebce38-cfc6-4fdb-bd83-a3b8ddf034cf/volumes/kubernetes.io~empty-dir/v1/nginx.log 
nginx log                

删除pod

[root@k8scloude1 volume]# kubectl delete pod pod --force
warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
pod "pod" force deleted

删除pod之后,目录也消失了,emptyDir卷可以共享数据但是不可以永久存储,持久化存储请查看博客《hostPath数据卷》《NFS数据卷》《持久卷Persistent Volume》

[root@k8scloude2 ~]# cat /var/lib/kubelet/pods/69ebce38-cfc6-4fdb-bd83-a3b8ddf034cf/volumes/kubernetes.io~empty-dir/v1/nginx.log 
cat: /var/lib/kubelet/pods/69ebce38-cfc6-4fdb-bd83-a3b8ddf034cf/volumes/kubernetes.io~empty-dir/v1/nginx.log: 没有那个文件或目录

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK