Kubernetes Pod的数据卷Volume

概述

因为容器自己是非持久化的,所以须要解决在容器中运行应用程序遇到的一些问题。首先,当容器崩溃时,kubelet将从新启动容器,可是写入容器的文件将会丢失,容器将会以镜像的初始状态从新开始;第二,在经过一个Pod中一块儿运行的容器,一般须要共享容器之间一些文件。Kubernetes经过存储卷解决上述的两个问题。php

在Docker有存储卷的概念卷,但Docker中存储卷只是磁盘的或另外一个容器中的目录,并无对其生命周期进行管理。Kubernetes的存储卷有本身的生命周期,它的生命周期与使用的它Pod生命周期一致。所以,相比于在Pod中运行的容器来讲,存储卷的存在时间会比的其中的任何容器都长,而且在容器从新启动时会保留数据。固然,当Pod中止存在时,存储卷也将再也不存在。在Kubernetes支持多种类型的卷,而Pod能够同时使用各类类型和任意数量的存储卷。html

在Pod中经过指定下面的字段来使用存储卷:mysql

  • spec.volumes:经过此字段提供指定的存储卷
  • spec.containers.volumeMounts:经过此字段将存储卷挂接到容器中

存储卷类型

emptryDir (本地数据卷)

emptyDir类型的Volume在Pod分配到Node上时被建立,Kubernetes会在Node上自动分配一个目录,所以无需指定宿主机Node上对应的目录文件。 这个目录的初始内容为空,当Pod从Node上移除时,emptyDir中的数据会被永久删除。web

emptyDir Volume主要用于某些应用程序无需永久保存的临时目录,多个容器的共享目录等。redis

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: gcr.io/google_containers/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir: {}

hostPath (本地数据卷)

hostPath类型的存储卷用于将宿主机的文件系统的文件或目录挂接到Pod中,除了须要指定path字段以外,在使用hostPath类型的存储卷时,也能够设置type,type支持的枚举值由下表。另外在使用hostPath时,sql

须要注意下面的事项:docker

  • 具备相同配置的Pod(例如:从同一个podTemplate建立的),可能会因为Node的文件不一样,而行为不一样。
  • 在宿主机上建立的文件或目录,只有root用户具写入的权限。您要么在容器中以root身份运行进程,要么在主机上修改的文件或目录的权限,以便具有写入内容到hostPath的存储卷中。
行为
空字符串(默认)是用于向后兼容,这意味着在挂接主机路径存储卷以前不执行任何检查。
DirectoryOrCreate 若是path指定目录不存在,则会在宿主机上建立一个新的目录,并设置目录权限为0755,此目录与kubelet拥有同样的组和拥有者。
Directory path指定的目标必需存在
FileOrCreate 若是path指定的文件不存在,则会在宿主机上建立一个空的文件,设置权限为0644,此文件与kubelet拥有同样的组和拥有者。
File path指定的文件必需存在
Socket path指定的UNIX socket必需存在
CharDevice path指定的字符设备必需存在
BlockDevice 在path给定路径上必须存在块设备。

下面是使用hostPath做为存储卷的YAML文件,此YAML文件定义了一个名称为test-pd的Pod资源。它经过hostPath类型的存储卷,将Pod宿主机上的/data挂接到容器中的/teset-pd目录数据库

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: k8s.gcr.io/test-webserver
    name: test-container
    # 指定在容器中挂接路径
    volumeMounts:
    - mountPath: /test-pd
      name: test-volume
  # 指定所提供的存储卷
  volumes:
  - name: test-volume
    hostPath:
      # 宿主机上的目录
      path: /data
      # this field is optional
      type: Directory

nfs (网络数据卷)

在Kubernetes中,能够经过nfs类型的存储卷将现有的NFS(网络文件系统)到的挂接到Pod中。在移除Pod时,NFS存储卷中的内容被不会被删除,只是将存储卷卸载而已。这意味着在NFS存储卷总能够预先填充数据,而且能够在Pod之间共享数据。NFS能够被同时挂接到多个Pod中,并能同时进行写入。须要注意的是:在使用nfs存储卷以前,必须已正确部署和运行NFS服务器,并已经设置了共享目录。api

下面是一个redis部署的YAML配置文件,redis在容器中的持久化数据保存在/data目录下;存储卷使用nfs,nfs的服务地址为:192.168.8.150,存储路径为:/k8s-nfs/redis/data。容器经过volumeMounts.name的值肯定所使用的存储卷安全

# for versions before 1.9.0 use apps/v1beta2
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
spec:
  selector:
    matchLabels:
      app: redis
  revisionHistoryLimit: 2
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      # 应用的镜像
      - image: redis
        name: redis
        imagePullPolicy: IfNotPresent
        # 应用的内部端口
        ports:
        - containerPort: 6379
          name: redis6379
        env:
        - name: ALLOW_EMPTY_PASSWORD
          value: "yes"
        - name: REDIS_PASSWORD
          value: "redis"   
        # 持久化挂接位置,在docker中 
        volumeMounts:
        - name: redis-persistent-storage
          mountPath: /data
      volumes:
      # 宿主机上的目录
      - name: redis-persistent-storage
        nfs:
          path: /k8s-nfs/redis/data
          server: 192.168.8.150

persistentVolumeClaim

persistentVolumeClaim类型存储卷将PersistentVolume挂接到Pod中做为存储卷。使用此类型的存储卷,用户并不知道存储卷的详细信息。

此处定义名为busybox-deployment的部署YAML配置文件,使用的镜像为busybox。基于busybox镜像的容器须要对/mnt目录下的数据进行持久化,在YAML文件指定使用名称为nfs的PersistenVolumeClaim对容器的数据进行持久化。

# This mounts the nfs volume claim into /mnt and continuously
# overwrites /mnt/index.html with the time and hostname of the pod. 
apiVersion: v1
kind: Deployment
metadata:  
  name: busybox-deployment
spec:  
  replicas: 2  
  selector:    
    name: busybox-deployment
  template:    
    metadata:      
      labels:        
        name: busybox-deployment    
    spec:      
      containers:      
      - image: busybox        
        command:          
        - sh          
        - -c          
        - 'while true; do date > /mnt/index.html; hostname >> /mnt/index.html; sleep $(($RANDOM % 5 + 5)); done'        
        imagePullPolicy: IfNotPresent        
        name: busybox        
        volumeMounts:          
        # name must match the volume name below          
        - name: nfs            
          mountPath: "/mnt"     
     volumes:      
     - name: nfs        
       persistentVolumeClaim:          
         claimName: nfs-pvc

subPath

有时,能够在一个pod中,将同一个卷共享,使其有多个用处。volumeMounts.subPath特性能够用来指定卷中的一个子目录,而不是直接使用卷的根目录。
这里有一个使用LAMP栈(Linux Apache Mysql PHP)的pod示例,该pod使用了一个共享的卷。HTML内容映射在它的html子目录,而数据库则保存在它的mysql目录

apiVersion: v1
kind: Pod
metadata:
  name: my-lamp-site
spec:
    containers:
    - name: mysql
      image: mysql
      volumeMounts:
      - mountPath: /var/lib/mysql
        name: site-data
        subPath: mysql
    - name: php
      image: php
      volumeMounts:
      - mountPath: /var/www/html
        name: site-data
        subPath: html
    volumes:
    - name: site-data
      persistentVolumeClaim:
        claimName: my-lamp-site-data

secret(信息数据卷)

Kubemetes提供了Secret来处理敏感数据,好比密码、Token和密钥,相比于直接将敏感数据配置在Pod的定义或者镜像中,Secret提供了更加安全的机制(Base64加密),防止数据泄露。Secret的建立是独立于Pod的,以数据卷的形式挂载到Pod中,Secret的数据将以文件的形式保存,容器经过读取文件能够获取须要的数据。

yaml示例以下:

apiVersion: v1
kind: Secret
metadata:
 name: mysecret
type: Opaque
data:
 username: emhlbnl1
 password: eWFvZGlkaWFv
--
apiVersion: v1
kind: Pod
metadata:
  labels:
    name: test-secret
    role: master
  name: test-secret
spec:
  containers:
    - name: test-secret
      image: registry:5000/back_demon:1.0
      volumeMounts:
       - name: secret
         mountPath: /home/laizy/secret
         readOnly: true
      command:
      - /run.sh
  volumes:
  - name: secret
    secret:
     secretName: mysecret

参考:

Kubernetes中的Volume介绍

Kubernetes-存储卷Volume

Kubernetes volumes简介

相关文章
相关标签/搜索