只有nfs和rbd的,本人翻译确实很渣
 
 
 
 
在容器中磁盘文件寿命是短暂的,当在容器中运行一些重要程序时,这会产生一些问题。 首先,当一个容器崩溃后,kubelet将重新启动该容器,但是文件将会丢失 - 容器将会以最初的状态启动。 第二,当在一个Pod中运行多个容器的时候,它需要在多个容器中共享文件。 k8s的Volume就是为了解决这些问题
 
 
Background
 
Docker也有  volumes的概念, 尽管它点失败和缺乏有效的管理。 在Docker里, 一个volume是一个简单的磁盘上的目录或者在其他容器中。 Lifetimes are not managed and until very recently there were only local-disk-backed volumes。 Docker现在开始提供新的存储驱动,但是这个功能是被限制的(例如,在Docker1.7中,每一个container只允许有一个volume,而且也没有什么办法向volume传递参数)
 
一个K8s的Volume,有一个明确的生命周期,和它所在的Pod一样。 因此,一个Volume和任何container无关,而是在Pod中存在,所以即使contaner重启了,数据也保存着。当然,当一个Pod不再存在,这个volume也不再存在。也许比这更重要的是,k8s支持多类型的volume,一个Pod可以同时使用任意数量的volume.
 
它的核心概念是,一个volume仅仅是一个目录,可能在其中有一些数据,这些数据对pod中的container是可访问的。这是目录是怎么来的,背后的媒介是什么,正在使用volume的特定类型所决定的内容是什么(  the contents of it are determined by the particular volume type used.)
 
为了使用volume,一个pod需要指定什么样的volume提供给pod(spec.volumes字段),把他们挂载到容器的哪里(在spec.containers.volumeMounts中设置)。
 
A process in a container sees a filesystem view composed from their Docker image and volumes。 Docker iamge位于文件系统的最低层, 在image中,任何volume都可以挂载到指定路径。Volume不能挂载到其他的volume(目录不可重复挂载volume),不能和其他的volume有hard link( Volumes can not mount onto other volumes or have hard links to other volumes)。每一个在pod中的container必须独立的指定每一个volume的挂载点。
 
Types of Volumes
 
k8s支持以下类型的volume:
 
 
  • emptyDir
  • hostPath
  • gcePersistentDisk
  • awsElasticBlockStore
  • nfs
  • iscsi
  • flocker
  • glusterfs
  • rbd
  • cephfs
  • gitRepo
  • secret
  • persistentVolumeClaim
  • downwardAPI
  • azureFileVolume
  • vsphereVolume
 
当一个pod指定到一个node的时候,一个emptyDir volumn就会被创建,只要pod在node上运行,该volume就会一直存在。就像他的名称一样,初始化的时候是个空的目录。在这个emptyDir中,该Pod中的所有容器可以读写到相同的文件
虽然,这个emptyDir会被挂载到每一个容器相同或者不同的目录。当一个Pod被从node移除后,对应的emptyDir中的数据会被永久删除。 注意:一个容器崩溃不会将pod从node上移除,所以一个container崩溃,在emptyDir中的数据是安全的。
 

Some uses for an emptyDir are:

  • scratch space, such as for a disk-based merge sort
  • checkpointing a long computation for recovery from crashes
  • holding files that a content-manager container fetches while a webserver container serves the data
默认情况下,emptyDir volume are stored 不论你后台机器的存储媒介是什么。媒介可能是磁盘或SSD,或者网络存储,这依赖于你的环境。你可以通过把emptyDir.medium设置成"memory"来告诉k8s, 挂载一个tmpfs(RAM-backed filesystem)。tmpfs非常快,但是它不像disk,当你的物理机重启后,tmpfs将会被清空,你所生成的任何文件,都会对你的container的内存限制造成影响。 
 
hostPath
 
一个hostPath Volume 挂载一个来自host node的文件系统的一个文件或者目录到你的pod,这里不需要pod做什么,  it offers a powerful escape hatch for some applications
 
下面是,一些使用hostPath的例子
  1. 运行一个容器,需要访问Docker的内部,则用hostPath挂载/var/lib/docker
  2. 在container中运行一个cAdvisor,使用hostPath挂载 /dev/cgroups
当使用hostPath的时候需要注意,因为:
  1. 因为在不同的node中,文件不同,所以使用相同配置的pod(比如,从podTemplate创建的)可能在不同的node上,有不同的行为。
  2. 当k8s添加 resource-aware scheduling,就不能认为资源是由hostPath使用( when Kubernetes adds resource-aware scheduling, as is planned, it will not be able to account for resources used by a hostPath
  3. 在underlying hosts创建的文件夹,只能被root写,你需要在一个特权容器中,使用root运行你的进程,或者更改host的文件权限,以便可以写入hostPath volume
 
Example pod
 
apiVersion: v1
kind: Pod
metadata:

  name: test-pdspec:
  containers:
  - image: gcr.io/google_containers/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /test-pd
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      # directory location on host

      path: /data
Example pod
 
apiVersion: v1
kind: Pod
metadata:

  name: test-hostpathspec:
  containers:
  - image: myimage
    name: test-container
    volumeMounts:
    - mountPath: /test-hostpath
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      path: /path/to/my/dir

 
NFS
 
一个nfs volume允许一个已存在的NFS(Network file system) 可以共享的挂载到你的pod, 不像emptyDir, 当一个Pod移除的时候,就会被擦出, nfs volume中的内容是保留的,volume仅仅是变为unmounted,这意味着一个NFS volume可以在其中预先放入一些数据。这些数据可以被"handed off" 在pod之间。 NFS可以被多个写入着同时挂载(  NFS can be mounted by multiple writers simultaneously)。
 
重要: 在你可以使用share exports前,你必须让你自己的NFS 服务器运行起来。
更多的细节请参考  NFS example
 
NFS example
 
这里的实例展示了如何创建一个前台的web服务,一个用GCE自动预分配持久存储,一个支持NFS的持久存储请求(an NFS-backed persistent claim)
 
一些k8s的概念
  1. Persistent Volumes定义一个持久的disk(disk的生命周期不和Pod相关联)
  2. Services  to enable Pods to locate one another.
 
 
就像上面图展示的一样,这个例子使用了两个PV
  1. 前台的web Pod使用一个基于NFS服务的PV
  2. NFS服务使用一个被GCE PD或者AWS EBS自动分配的  persistent volume
注意:这个例子里使用的NFS container不支持NFSv4
 
QuickStart
 
$ kubectl create -f examples/volumes/nfs/provisioner/nfs-server-gce-pv.yaml
$ kubectl create -f examples/volumes/nfs/nfs-server-rc.yaml
$ kubectl create -f examples/volumes/nfs/nfs-server-service.yaml
# get the cluster IP of the server using the following command
$ kubectl describe services nfs-server
# use the NFS server IP to update nfs-pv.yaml and execute the following
$ kubectl create -f examples/volumes/nfs/nfs-pv.yaml
$ kubectl create -f examples/volumes/nfs/nfs-pvc.yaml
# run a fake backend
$ kubectl create -f examples/volumes/nfs/nfs-busybox-rc.yaml
# get pod name from this command
$ kubectl get pod -l name=nfs-busybox
# use the pod name to check the test file
$ kubectl exec nfs-busybox-jdhf3 -- cat /mnt/index.html
 
Example of NFS based persistent volume
 
可以参考 NFS Service and Replication Controller中的在RC中如何使用NFS volume claim
 
It relies on the NFS persistent volume and NFS persistent volume claim in this example as well
 
Complete setup
这下面的例子展示了如何从一个pod rc导出一个NFS share,并把它导入两个rc中
 
NFS server part
定义NFS Service、rc和NFS service( Define the NFS Service and Replication Controller and NFS service):
NFS server导出一个自动预先分配的由GCE PD提供支持的持久存储
 
$ kubectl create -f examples/volumes/nfs/provisioner/nfs-server-gce-pv.yaml(创建一个PVC)
$ kubectl create -f examples/volumes/nfs/nfs-server-rc.yaml(创建以RC,在RC中指定了PVC的名称,来使用对应的PVC)
$ kubectl create -f examples/volumes/nfs/nfs-server-service.yaml(创建一个service)
这个目录包含虚拟的index.html。 等到Pod运行的时候,使用kubctl get pods -l role=nfs-server来查看
 
Create the NFS based persistent volume claim
 
刚开始的时候,NFS busybox controller使用一个简单的脚本来生成数据写入NFS server. 你需要找的找到server的cluster IP
$ kubectl describe services nfs-server
 
在nfs pv中替换无效的ip(未来,我们将会使用service names来把它们聚集到一起,但是现在,你不得不硬编码IP)
用你的NFS server创建persistent volume和pvc, pv和pvc提供了一种迂回的方法来允许多个pod关联到NFS server, 那就是使用一个虚拟的名称,而不是硬编码的server address. 
$ kubectl create -f examples/volumes/nfs/nfs-pv.yaml
$ kubectl create -f examples/volumes/nfs/nfs-pvc.yaml
 
Setup the fake backend
 NFS busybox controller在NFS server每10秒更新一次index.html。 
 
$ kubectl create -f examples/volumes/nfs/nfs-busybox-rc.yaml
 
这是一个busybox的pod, 所以我们可以很简单的查看到我们的挂载正在运行。 找到一个busybox pod,然后exec:
 
$ kubectl get pod -l name=nfs-busybox
NAME                READY     STATUS    RESTARTS   AGEnfs-busybox-jdhf3   1/1       Running   0          25mnfs-busybox-w3s4t   1/1       Running   0          25m
$ kubectl exec nfs-busybox-jdhf3 -- cat /mnt/index.html
Thu Oct 22 19:20:18 UTC 2015
nfs-busybox-w3s4t
 
如果一切正常的话,你可以看到和上面相似的输出。 如果不一样,请确认一下,你在NFS PV文件中是不是使用了无效的IP,确定一下上述的describe services命令已经在endpoint列出来( make sure the describe services command above had endpoints listed) (表明这个service和运行的Pod关联起来)。
 
Setup the web server
 
 web server controller是另一个简单的RC ,展示了使用了在上面的NFS导出的作为一个NFS volume,并运行了一个简单的web server。
 
定义Pod
 
$ kubectl create -f examples/volumes/nfs/nfs-web-rc.yaml
 
这将会创建两个pod, 每一个pod都对外提供上面提到的index.html,我们可以使用一个简单的server来放到pod的前面
kubectl create -f examples/volumes/nfs/nfs-web-service.yaml
 
我们可以使用busybos容器,然后检测nginx是否提供了适当的数据
 
$ kubectl get pod -l name=nfs-busybox
NAME                READY     STATUS    RESTARTS   AGEnfs-busybox-jdhf3   1/1       Running   0          1hnfs-busybox-w3s4t   1/1       Running   0          1h
$ kubectl get services nfs-web
NAME      LABELS    SELECTOR            IP(S)        PORT(S)
nfs-web   <none>    role=web-frontend   10.0.68.37   80/TCP
$ kubectl exec nfs-busybox-jdhf3 -- wget -qO- http://10.0.68.37
Thu Oct 22 19:28:55 UTC 2015
nfs-busybox-w3s4t
 
rbd
 
一个rdb存储允许一个 Rados Block Device volume挂载到你的pod,不像emptyDir当pod被移除后被擦除,rdb中的内容会被保留,volume的状态变为unmounted,这以为这RDB bolume可以预先存储一些数据,这些数据可以在pod之间"handed off"
 
重要的是: 当你在使用RBD之前,你必须让你自己的Ceph installation运行 
RBD的一个特点是,他只能同时被多个消费者同时挂载为只读的。这意味着你可以在一个volume中预先放入一些设置数据,然后让其并行的为多个你需要的pod提供数据。
 
更多的详细信息参考  RBD example
 
rdb example
 
How to use it
 
在你的k8s host上安装Ceph, 例如在Fedora 21上
# yun -y install ceph-common
 
如果你没有一个Ceph集群,你可以设置一个容器化的Ceph集群
从Ceph得到keyring,并把它复制到/etc/ceph/keyring
 
一旦你安装了新的Ceph和新的k8s,利用  rbd.json rbd-with-secret.json来创建一个pod
在这个JSON中,你需要提供一下信息:
    1. nitors: ceph的monitors
    2. pool: RADOS pool的名称,如果没有提供的话,将会使用默认的rdb pool
    3. image: rdb创建的image的名称
    4. user: RADOS用户名称,如果没有提供,将会使用默认的admin
    5. keyring: keyring文件的路径,如果没有提供,将会使用默认的/etc/ceph/keyring
    6. secretName: 验证密码的名称,如果提供了,secretName将会重写keyring。注意: 看下面如何创建一个secret
    7. fsType: 文件系统的类型(ext4, xfs等),对应的是设备上的格式
    8. readOnly: 这个文件系统是不是被用作只读的在容器中磁盘文件寿命是短暂的,当在容器中运行一些重要程序时,这会产生一些问题。 首先,当一个容器崩溃后,kubelet将重新启动该容器,但是文件将会丢失 - 容器将会以最初的状态启动。 第二,当在一个Pod中运行多个容器的时候,它需要在多个容器中共享文件。 k8s的Volume就是为了解决这些问题
       
       
      Background
       
      Docker也有  volumes的概念, 尽管它点失败和缺乏有效的管理。 在Docker里, 一个volume是一个简单的磁盘上的目录或者在其他容器中。 Lifetimes are not managed and until very recently there were only local-disk-backed volumes。 Docker现在开始提供新的存储驱动,但是这个功能是被限制的(例如,在Docker1.7中,每一个container只允许有一个volume,而且也没有什么办法向volume传递参数)
       
      一个K8s的Volume,有一个明确的生命周期,和它所在的Pod一样。 因此,一个Volume和任何container无关,而是在Pod中存在,所以即使contaner重启了,数据也保存着。当然,当一个Pod不再存在,这个volume也不再存在。也许比这更重要的是,k8s支持多类型的volume,一个Pod可以同时使用任意数量的volume.
       
      它的核心概念是,一个volume仅仅是一个目录,可能在其中有一些数据,这些数据对pod中的container是可访问的。这是目录是怎么来的,背后的媒介是什么,正在使用volume的特定类型所决定的内容是什么(  the contents of it are determined by the particular volume type used.)
       
      为了使用volume,一个pod需要指定什么样的volume提供给pod(spec.volumes字段),把他们挂载到容器的哪里(在spec.containers.volumeMounts中设置)。
       
      A process in a container sees a filesystem view composed from their Docker image and volumes。 Docker iamge位于文件系统的最低层, 在image中,任何volume都可以挂载到指定路径。Volume不能挂载到其他的volume(目录不可重复挂载volume),不能和其他的volume有hard link( Volumes can not mount onto other volumes or have hard links to other volumes)。每一个在pod中的container必须独立的指定每一个volume的挂载点。
       
      Types of Volumes
       
      k8s支持以下类型的volume:
       
       
      • emptyDir
      • hostPath
      • gcePersistentDisk
      • awsElasticBlockStore
      • nfs
      • iscsi
      • flocker
      • glusterfs
      • rbd
      • cephfs
      • gitRepo
      • secret
      • persistentVolumeClaim
      • downwardAPI
      • azureFileVolume
      • vsphereVolume
       
      当一个pod指定到一个node的时候,一个emptyDir volumn就会被创建,只要pod在node上运行,该volume就会一直存在。就像他的名称一样,初始化的时候是个空的目录。在这个emptyDir中,该Pod中的所有容器可以读写到相同的文件
      虽然,这个emptyDir会被挂载到每一个容器相同或者不同的目录。当一个Pod被从node移除后,对应的emptyDir中的数据会被永久删除。 注意:一个容器崩溃不会将pod从node上移除,所以一个container崩溃,在emptyDir中的数据是安全的。
       

      Some uses for an emptyDir are:

      • scratch space, such as for a disk-based merge sort
      • checkpointing a long computation for recovery from crashes
      • holding files that a content-manager container fetches while a webserver container serves the data
      默认情况下,emptyDir volume are stored 不论你后台机器的存储媒介是什么。媒介可能是磁盘或SSD,或者网络存储,这依赖于你的环境。你可以通过把emptyDir.medium设置成"memory"来告诉k8s, 挂载一个tmpfs(RAM-backed filesystem)。tmpfs非常快,但是它不像disk,当你的物理机重启后,tmpfs将会被清空,你所生成的任何文件,都会对你的container的内存限制造成影响。 
       
      hostPath
       
      一个hostPath Volume 挂载一个来自host node的文件系统的一个文件或者目录到你的pod,这里不需要pod做什么,  it offers a powerful escape hatch for some applications
       
      下面是,一些使用hostPath的例子
      1. 运行一个容器,需要访问Docker的内部,则用hostPath挂载/var/lib/docker
      2. 在container中运行一个cAdvisor,使用hostPath挂载 /dev/cgroups
      当使用hostPath的时候需要注意,因为:
      1. 因为在不同的node中,文件不同,所以使用相同配置的pod(比如,从podTemplate创建的)可能在不同的node上,有不同的行为。
      2. 当k8s添加 resource-aware scheduling,就不能认为资源是由hostPath使用( when Kubernetes adds resource-aware scheduling, as is planned, it will not be able to account for resources used by a hostPath
      3. 在underlying hosts创建的文件夹,只能被root写,你需要在一个特权容器中,使用root运行你的进程,或者更改host的文件权限,以便可以写入hostPath volume
       
      Example pod
       
      apiVersion: v1
      kind: Pod
      metadata:

        name: test-pdspec:
        containers:
        - image: gcr.io/google_containers/test-webserver
          name: test-container
          volumeMounts:
          - mountPath: /test-pd
            name: test-volume
        volumes:
        - name: test-volume
          hostPath:
            # directory location on host

            path: /data
      Example pod
       
      apiVersion: v1
      kind: Pod
      metadata:

        name: test-hostpathspec:
        containers:
        - image: myimage
          name: test-container
          volumeMounts:
          - mountPath: /test-hostpath
            name: test-volume
        volumes:
        - name: test-volume
          hostPath:
            path: /path/to/my/dir

       
      NFS
       
      一个nfs volume允许一个已存在的NFS(Network file system) 可以共享的挂载到你的pod, 不像emptyDir, 当一个Pod移除的时候,就会被擦出, nfs volume中的内容是保留的,volume仅仅是变为unmounted,这意味着一个NFS volume可以在其中预先放入一些数据。这些数据可以被"handed off" 在pod之间。 NFS可以被多个写入着同时挂载(  NFS can be mounted by multiple writers simultaneously)。
       
      重要: 在你可以使用share exports前,你必须让你自己的NFS 服务器运行起来。
      更多的细节请参考  NFS example
       
      NFS example
       
      这里的实例展示了如何创建一个前台的web服务,一个用GCE自动预分配持久存储,一个支持NFS的持久存储请求(an NFS-backed persistent claim)
       
      一些k8s的概念
      1. Persistent Volumes定义一个持久的disk(disk的生命周期不和Pod相关联)
      2. Services  to enable Pods to locate one another.
       
       
      就像上面图展示的一样,这个例子使用了两个PV
      1. 前台的web Pod使用一个基于NFS服务的PV
      2. NFS服务使用一个被GCE PD或者AWS EBS自动分配的  persistent volume
      注意:这个例子里使用的NFS container不支持NFSv4
       
      QuickStart
       
      $ kubectl create -f examples/volumes/nfs/provisioner/nfs-server-gce-pv.yaml
      $ kubectl create -f examples/volumes/nfs/nfs-server-rc.yaml
      $ kubectl create -f examples/volumes/nfs/nfs-server-service.yaml
      # get the cluster IP of the server using the following command
      $ kubectl describe services nfs-server
      # use the NFS server IP to update nfs-pv.yaml and execute the following
      $ kubectl create -f examples/volumes/nfs/nfs-pv.yaml
      $ kubectl create -f examples/volumes/nfs/nfs-pvc.yaml
      # run a fake backend
      $ kubectl create -f examples/volumes/nfs/nfs-busybox-rc.yaml
      # get pod name from this command
      $ kubectl get pod -l name=nfs-busybox
      # use the pod name to check the test file
      $ kubectl exec nfs-busybox-jdhf3 -- cat /mnt/index.html
       
      Example of NFS based persistent volume
       
      可以参考 NFS Service and Replication Controller中的在RC中如何使用NFS volume claim
       
      It relies on the NFS persistent volume and NFS persistent volume claim in this example as well
       
      Complete setup
      这下面的例子展示了如何从一个pod rc导出一个NFS share,并把它导入两个rc中
       
      NFS server part
      定义NFS Service、rc和NFS service( Define the NFS Service and Replication Controller and NFS service):
      NFS server导出一个自动预先分配的由GCE PD提供支持的持久存储
       
      $ kubectl create -f examples/volumes/nfs/provisioner/nfs-server-gce-pv.yaml(创建一个PVC)
      $ kubectl create -f examples/volumes/nfs/nfs-server-rc.yaml(创建以RC,在RC中指定了PVC的名称,来使用对应的PVC)
      $ kubectl create -f examples/volumes/nfs/nfs-server-service.yaml(创建一个service)
      这个目录包含虚拟的index.html。 等到Pod运行的时候,使用kubctl get pods -l role=nfs-server来查看
       
      Create the NFS based persistent volume claim
       
      刚开始的时候,NFS busybox controller使用一个简单的脚本来生成数据写入NFS server. 你需要找的找到server的cluster IP
      $ kubectl describe services nfs-server
       
      在nfs pv中替换无效的ip(未来,我们将会使用service names来把它们聚集到一起,但是现在,你不得不硬编码IP)
      用你的NFS server创建persistent volume和pvc, pv和pvc提供了一种迂回的方法来允许多个pod关联到NFS server, 那就是使用一个虚拟的名称,而不是硬编码的server address. 
      $ kubectl create -f examples/volumes/nfs/nfs-pv.yaml
      $ kubectl create -f examples/volumes/nfs/nfs-pvc.yaml
       
      Setup the fake backend
       NFS busybox controller在NFS server每10秒更新一次index.html。 
       
      $ kubectl create -f examples/volumes/nfs/nfs-busybox-rc.yaml
       
      这是一个busybox的pod, 所以我们可以很简单的查看到我们的挂载正在运行。 找到一个busybox pod,然后exec:
       
      $ kubectl get pod -l name=nfs-busybox
      NAME                READY     STATUS    RESTARTS   AGEnfs-busybox-jdhf3   1/1       Running   0          25mnfs-busybox-w3s4t   1/1       Running   0          25m
      $ kubectl exec nfs-busybox-jdhf3 -- cat /mnt/index.html
      Thu Oct 22 19:20:18 UTC 2015
      nfs-busybox-w3s4t
       
      如果一切正常的话,你可以看到和上面相似的输出。 如果不一样,请确认一下,你在NFS PV文件中是不是使用了无效的IP,确定一下上述的describe services命令已经在endpoint列出来( make sure the describe services command above had endpoints listed) (表明这个service和运行的Pod关联起来)。
       
      Setup the web server
       
       web server controller是另一个简单的RC ,展示了使用了在上面的NFS导出的作为一个NFS volume,并运行了一个简单的web server。
       
      定义Pod
       
      $ kubectl create -f examples/volumes/nfs/nfs-web-rc.yaml
       
      这将会创建两个pod, 每一个pod都对外提供上面提到的index.html,我们可以使用一个简单的server来放到pod的前面
      kubectl create -f examples/volumes/nfs/nfs-web-service.yaml
       
      我们可以使用busybos容器,然后检测nginx是否提供了适当的数据
       
      $ kubectl get pod -l name=nfs-busybox
      NAME                READY     STATUS    RESTARTS   AGEnfs-busybox-jdhf3   1/1       Running   0          1hnfs-busybox-w3s4t   1/1       Running   0          1h
      $ kubectl get services nfs-web
      NAME      LABELS    SELECTOR            IP(S)        PORT(S)
      nfs-web   <none>    role=web-frontend   10.0.68.37   80/TCP
      $ kubectl exec nfs-busybox-jdhf3 -- wget -qO- http://10.0.68.37
      Thu Oct 22 19:28:55 UTC 2015
      nfs-busybox-w3s4t
       
      rbd
       
      一个rdb存储允许一个 Rados Block Device volume挂载到你的pod,不像emptyDir当pod被移除后被擦除,rdb中的内容会被保留,volume的状态变为unmounted,这以为这RDB bolume可以预先存储一些数据,这些数据可以在pod之间"handed off"
       
      重要的是: 当你在使用RBD之前,你必须让你自己的Ceph installation运行 
      RBD的一个特点是,他只能同时被多个消费者同时挂载为只读的。这意味着你可以在一个volume中预先放入一些设置数据,然后让其并行的为多个你需要的pod提供数据。
       
      更多的详细信息参考  RBD example
       
      rdb example
       
      How to use it
       
      在你的k8s host上安装Ceph, 例如在Fedora 21上
      # yun -y install ceph-common
       
      如果你没有一个Ceph集群,你可以设置一个容器化的Ceph集群
      从Ceph得到keyring,并把它复制到/etc/ceph/keyring
       
      一旦你安装了新的Ceph和新的k8s,利用  rbd.json rbd-with-secret.json来创建一个pod
      在这个JSON中,你需要提供一下信息:
      1. monitors: ceph的monitors
      2. pool: RADOS pool的名称,如果没有提供的话,将会使用默认的rdb pool
      3. image: rdb创建的image的名称
      4. user: RADOS用户名称,如果没有提供,将会使用默认的admin
      5. keyring: keyring文件的路径,如果没有提供,将会使用默认的/etc/ceph/keyring
      6. secretName: 验证密码的名称,如果提供了,secretName将会重写keyring。注意: 看下面如何创建一个secret
      7. fsType: 文件系统的类型(ext4, xfs等),对应的是设备上的格式
      8. readOnly: 这个文件系统是不是被用作只读的
在容器中磁盘文件寿命是短暂的,当在容器中运行一些重要程序时,这会产生一些问题。 首先,当一个容器崩溃后,kubelet将重新启动该容器,但是文件将会丢失 - 容器将会以最初的状态启动。 第二,当在一个Pod中运行多个容器的时候,它需要在多个容器中共享文件。 k8s的Volume就是为了解决这些问题
 
 
Background
 
Docker也有  volumes的概念, 尽管它点失败和缺乏有效的管理。 在Docker里, 一个volume是一个简单的磁盘上的目录或者在其他容器中。 Lifetimes are not managed and until very recently there were only local-disk-backed volumes。 Docker现在开始提供新的存储驱动,但是这个功能是被限制的(例如,在Docker1.7中,每一个container只允许有一个volume,而且也没有什么办法向volume传递参数)
 
一个K8s的Volume,有一个明确的生命周期,和它所在的Pod一样。 因此,一个Volume和任何container无关,而是在Pod中存在,所以即使contaner重启了,数据也保存着。当然,当一个Pod不再存在,这个volume也不再存在。也许比这更重要的是,k8s支持多类型的volume,一个Pod可以同时使用任意数量的volume.
 
它的核心概念是,一个volume仅仅是一个目录,可能在其中有一些数据,这些数据对pod中的container是可访问的。这是目录是怎么来的,背后的媒介是什么,正在使用volume的特定类型所决定的内容是什么(  the contents of it are determined by the particular volume type used.)
 
为了使用volume,一个pod需要指定什么样的volume提供给pod(spec.volumes字段),把他们挂载到容器的哪里(在spec.containers.volumeMounts中设置)。
 
A process in a container sees a filesystem view composed from their Docker image and volumes。 Docker iamge位于文件系统的最低层, 在image中,任何volume都可以挂载到指定路径。Volume不能挂载到其他的volume(目录不可重复挂载volume),不能和其他的volume有hard link( Volumes can not mount onto other volumes or have hard links to other volumes)。每一个在pod中的container必须独立的指定每一个volume的挂载点。
 
Types of Volumes
 
k8s支持以下类型的volume:
 
 
  • emptyDir
  • hostPath
  • gcePersistentDisk
  • awsElasticBlockStore
  • nfs
  • iscsi
  • flocker
  • glusterfs
  • rbd
  • cephfs
  • gitRepo
  • secret
  • persistentVolumeClaim
  • downwardAPI
  • azureFileVolume
  • vsphereVolume
 
当一个pod指定到一个node的时候,一个emptyDir volumn就会被创建,只要pod在node上运行,该volume就会一直存在。就像他的名称一样,初始化的时候是个空的目录。在这个emptyDir中,该Pod中的所有容器可以读写到相同的文件
虽然,这个emptyDir会被挂载到每一个容器相同或者不同的目录。当一个Pod被从node移除后,对应的emptyDir中的数据会被永久删除。 注意:一个容器崩溃不会将pod从node上移除,所以一个container崩溃,在emptyDir中的数据是安全的。
 

Some uses for an emptyDir are:

  • scratch space, such as for a disk-based merge sort
  • checkpointing a long computation for recovery from crashes
  • holding files that a content-manager container fetches while a webserver container serves the data
默认情况下,emptyDir volume are stored 不论你后台机器的存储媒介是什么。媒介可能是磁盘或SSD,或者网络存储,这依赖于你的环境。你可以通过把emptyDir.medium设置成"memory"来告诉k8s, 挂载一个tmpfs(RAM-backed filesystem)。tmpfs非常快,但是它不像disk,当你的物理机重启后,tmpfs将会被清空,你所生成的任何文件,都会对你的container的内存限制造成影响。 
 
hostPath
 
一个hostPath Volume 挂载一个来自host node的文件系统的一个文件或者目录到你的pod,这里不需要pod做什么,  it offers a powerful escape hatch for some applications
 
下面是,一些使用hostPath的例子
  1. 运行一个容器,需要访问Docker的内部,则用hostPath挂载/var/lib/docker
  2. 在container中运行一个cAdvisor,使用hostPath挂载 /dev/cgroups
当使用hostPath的时候需要注意,因为:
  1. 因为在不同的node中,文件不同,所以使用相同配置的pod(比如,从podTemplate创建的)可能在不同的node上,有不同的行为。
  2. 当k8s添加 resource-aware scheduling,就不能认为资源是由hostPath使用( when Kubernetes adds resource-aware scheduling, as is planned, it will not be able to account for resources used by a hostPath
  3. 在underlying hosts创建的文件夹,只能被root写,你需要在一个特权容器中,使用root运行你的进程,或者更改host的文件权限,以便可以写入hostPath volume
 
Example pod
 
apiVersion: v1
kind: Pod
metadata:

  name: test-pdspec:
  containers:
  - image: gcr.io/google_containers/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /test-pd
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      # directory location on host

      path: /data
Example pod
 
apiVersion: v1
kind: Pod
metadata:

  name: test-hostpathspec:
  containers:
  - image: myimage
    name: test-container
    volumeMounts:
    - mountPath: /test-hostpath
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      path: /path/to/my/dir

 
NFS
 
一个nfs volume允许一个已存在的NFS(Network file system) 可以共享的挂载到你的pod, 不像emptyDir, 当一个Pod移除的时候,就会被擦出, nfs volume中的内容是保留的,volume仅仅是变为unmounted,这意味着一个NFS volume可以在其中预先放入一些数据。这些数据可以被"handed off" 在pod之间。 NFS可以被多个写入着同时挂载(  NFS can be mounted by multiple writers simultaneously)。
 
重要: 在你可以使用share exports前,你必须让你自己的NFS 服务器运行起来。
更多的细节请参考  NFS example
 
NFS example
 
这里的实例展示了如何创建一个前台的web服务,一个用GCE自动预分配持久存储,一个支持NFS的持久存储请求(an NFS-backed persistent claim)
 
一些k8s的概念
  1. Persistent Volumes定义一个持久的disk(disk的生命周期不和Pod相关联)
  2. Services  to enable Pods to locate one another.
 
 
就像上面图展示的一样,这个例子使用了两个PV
  1. 前台的web Pod使用一个基于NFS服务的PV
  2. NFS服务使用一个被GCE PD或者AWS EBS自动分配的  persistent volume
注意:这个例子里使用的NFS container不支持NFSv4
 
QuickStart
 
$ kubectl create -f examples/volumes/nfs/provisioner/nfs-server-gce-pv.yaml
$ kubectl create -f examples/volumes/nfs/nfs-server-rc.yaml
$ kubectl create -f examples/volumes/nfs/nfs-server-service.yaml
# get the cluster IP of the server using the following command
$ kubectl describe services nfs-server
# use the NFS server IP to update nfs-pv.yaml and execute the following
$ kubectl create -f examples/volumes/nfs/nfs-pv.yaml
$ kubectl create -f examples/volumes/nfs/nfs-pvc.yaml
# run a fake backend
$ kubectl create -f examples/volumes/nfs/nfs-busybox-rc.yaml
# get pod name from this command
$ kubectl get pod -l name=nfs-busybox
# use the pod name to check the test file
$ kubectl exec nfs-busybox-jdhf3 -- cat /mnt/index.html
 
Example of NFS based persistent volume
 
可以参考 NFS Service and Replication Controller中的在RC中如何使用NFS volume claim
 
It relies on the NFS persistent volume and NFS persistent volume claim in this example as well
 
Complete setup
这下面的例子展示了如何从一个pod rc导出一个NFS share,并把它导入两个rc中
 
NFS server part
定义NFS Service、rc和NFS service( Define the NFS Service and Replication Controller and NFS service):
NFS server导出一个自动预先分配的由GCE PD提供支持的持久存储
 
$ kubectl create -f examples/volumes/nfs/provisioner/nfs-server-gce-pv.yaml(创建一个PVC)
$ kubectl create -f examples/volumes/nfs/nfs-server-rc.yaml(创建以RC,在RC中指定了PVC的名称,来使用对应的PVC)
$ kubectl create -f examples/volumes/nfs/nfs-server-service.yaml(创建一个service)
这个目录包含虚拟的index.html。 等到Pod运行的时候,使用kubctl get pods -l role=nfs-server来查看
 
Create the NFS based persistent volume claim
 
刚开始的时候,NFS busybox controller使用一个简单的脚本来生成数据写入NFS server. 你需要找的找到server的cluster IP
$ kubectl describe services nfs-server
 
在nfs pv中替换无效的ip(未来,我们将会使用service names来把它们聚集到一起,但是现在,你不得不硬编码IP)
用你的NFS server创建persistent volume和pvc, pv和pvc提供了一种迂回的方法来允许多个pod关联到NFS server, 那就是使用一个虚拟的名称,而不是硬编码的server address. 
$ kubectl create -f examples/volumes/nfs/nfs-pv.yaml
$ kubectl create -f examples/volumes/nfs/nfs-pvc.yaml
 
Setup the fake backend
 NFS busybox controller在NFS server每10秒更新一次index.html。 
 
$ kubectl create -f examples/volumes/nfs/nfs-busybox-rc.yaml
 
这是一个busybox的pod, 所以我们可以很简单的查看到我们的挂载正在运行。 找到一个busybox pod,然后exec:
 
$ kubectl get pod -l name=nfs-busybox
NAME                READY     STATUS    RESTARTS   AGEnfs-busybox-jdhf3   1/1       Running   0          25mnfs-busybox-w3s4t   1/1       Running   0          25m
$ kubectl exec nfs-busybox-jdhf3 -- cat /mnt/index.html
Thu Oct 22 19:20:18 UTC 2015
nfs-busybox-w3s4t
 
如果一切正常的话,你可以看到和上面相似的输出。 如果不一样,请确认一下,你在NFS PV文件中是不是使用了无效的IP,确定一下上述的describe services命令已经在endpoint列出来( make sure the describe services command above had endpoints listed) (表明这个service和运行的Pod关联起来)。
 
Setup the web server
 
 web server controller是另一个简单的RC ,展示了使用了在上面的NFS导出的作为一个NFS volume,并运行了一个简单的web server。
 
定义Pod
 
$ kubectl create -f examples/volumes/nfs/nfs-web-rc.yaml
 
这将会创建两个pod, 每一个pod都对外提供上面提到的index.html,我们可以使用一个简单的server来放到pod的前面
kubectl create -f examples/volumes/nfs/nfs-web-service.yaml
 
我们可以使用busybos容器,然后检测nginx是否提供了适当的数据
 
$ kubectl get pod -l name=nfs-busybox
NAME                READY     STATUS    RESTARTS   AGEnfs-busybox-jdhf3   1/1       Running   0          1hnfs-busybox-w3s4t   1/1       Running   0          1h
$ kubectl get services nfs-web
NAME      LABELS    SELECTOR            IP(S)        PORT(S)
nfs-web   <none>    role=web-frontend   10.0.68.37   80/TCP
$ kubectl exec nfs-busybox-jdhf3 -- wget -qO- http://10.0.68.37
Thu Oct 22 19:28:55 UTC 2015
nfs-busybox-w3s4t
 
rbd
 
一个rdb存储允许一个 Rados Block Device volume挂载到你的pod,不像emptyDir当pod被移除后被擦除,rdb中的内容会被保留,volume的状态变为unmounted,这以为这RDB bolume可以预先存储一些数据,这些数据可以在pod之间"handed off"
 
重要的是: 当你在使用RBD之前,你必须让你自己的Ceph installation运行 
RBD的一个特点是,他只能同时被多个消费者同时挂载为只读的。这意味着你可以在一个volume中预先放入一些设置数据,然后让其并行的为多个你需要的pod提供数据。
 
更多的详细信息参考  RBD example
 
rdb example
 
How to use it
 
在你的k8s host上安装Ceph, 例如在Fedora 21上
# yun -y install ceph-common
 
如果你没有一个Ceph集群,你可以设置一个容器化的Ceph集群
从Ceph得到keyring,并把它复制到/etc/ceph/keyring
 
一旦你安装了新的Ceph和新的k8s,利用  rbd.json rbd-with-secret.json来创建一个pod
在这个JSON中,你需要提供一下信息:
  1. monitors: ceph的monitors
  2. pool: RADOS pool的名称,如果没有提供的话,将会使用默认的rdb pool
  3. image: rdb创建的image的名称
  4. user: RADOS用户名称,如果没有提供,将会使用默认的admin
  5. keyring: keyring文件的路径,如果没有提供,将会使用默认的/etc/ceph/keyring
  6. secretName: 验证密码的名称,如果提供了,secretName将会重写keyring。注意: 看下面如何创建一个secret
  7. fsType: 文件系统的类型(ext4, xfs等),对应的是设备上的格式
  8. readOnly: 这个文件系统是不是被用作只读的

最新文章

  1. Gif图片制作
  2. 使用Apache HttpClient
  3. 行为识别笔记:HOG,HOF与MBH特征(转载)
  4. Android体系结构
  5. 使用JAVA对字符串进行DES加密解密(修正问题)
  6. 用于软件包管理的21个Linux YUM命令
  7. Tcp/Ip协议族简单解读及网络数据包/报/帧数据格式及封装及解包;
  8. Eclipse启动报错Java was started but returned exit code=13
  9. Java语言基础(二)
  10. python简单小爬虫爬取易车网图片
  11. c语言-三字符组
  12. 运维之Linux基础知识(三)
  13. jdbc连接数据库以及crud(简单易懂,本人亲测可用 有源代码和数据库)
  14. [零] JavaIO入门简介 程序设计语言 为什么需要IO库
  15. kibana从入门到精通-Kibana安装
  16. socket 如何判断远端服务器的连接状态?连接断开,需重连
  17. PostgreSQL获取所有表名、字段名、字段类型、注释
  18. java.sql.SQLException: ORA-01578: ORACLE 数据块损坏问题解决办法
  19. leetcode-algorithms-17 Letter Combinations of a Phone Number
  20. SqlServer 全文索引指令大全(转载)

热门文章

  1. Reactjs的Controller View模式
  2. in_array,array_search的使用
  3. SLAM前端技术选择思考
  4. Vue2随笔
  5. Mac 下 PostgreSQL 的安装与使用
  6. ubuntu 14.04 java开发环境搭建 jdk 以及 inteliJ IDEA安装
  7. JavaScript中的防篡改对象
  8. Hibernate SQL方言 (hibernate.dialect) Spring配置文件applicationContext.xml
  9. SQLServer的数据存储结构01 文件与文件组
  10. C#: DataBase