权衡轻重 發表於 2019-9-10 20:02:00

kubernetes 磁盘、PV、PVC

<h2>6.1.介绍卷</h2>
<h3>6.1.1.卷的类型</h3>
<p>emptyDir-用于存储临时数据的简单空目录</p>
<p>hostPath-用于将目录从工作节点的文件系统挂载到pod</p>
<p>nfs-挂载到pod中的NFS共享卷。</p>
<p>还有其他的如gitRepo、gcepersistenDisk</p>
<p>&nbsp;</p>
<h2>6.2.通过卷在容器间共享数据</h2>
<h3>6.2.1.使用emptyDir卷</h3>
<p>卷的生命周期与pod的生命周期项关联,所以当删除pod时,卷的内容就会丢失。</p>
<p>使用empty示例代码如下:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">apiVersion: v1
kind: Pod
metadata:
name: fortune
spec:
containers:
- image: luksa/fortune
    name: html-gener
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx
      readOnly: true
- image: nginx/aplin
    name: web-service
    volumeMounts:
    - name: html
      mountPath: /usr/share
      readOnly: true
volumes:
- name: html                        //一个名为html的单独emptyDir卷,挂载在上面的两个容器中
    emptyDir: {}
</pre>
</div>
<p>  </p>
<h2>6.3.访问工作节点文件系统上的文件</h2>
<h3>6.3.1.hostPath卷</h3>
<p>hostPath是持久性存储,emptyDir卷的内容随着pod的删除而删除。</p>
<p>使用hostPath会发现当删除一个pod,并且下一个pod使用了指向主机上相同路径的hostPath卷,则新pod将会发现上一个pod留下的数据,但前提是必须将其调度到与第一个pod相同的节点上。</p>
<p>所以当你使用hostPath时请务必考虑清楚,当重新起一个pod时候,必须要保证pod的节点与之前相同。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">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:
      # directory location on host
      path: /data
      # this field is optional
      type: Directory
</pre>
</div>
<p>&nbsp;</p>
<h2>6.4.使用持久化存储</h2>
<h3>怎样保证pod重新启动后调度到任意一个节点都有相同的数据可用,这就需要做到持久化存储。</h3>
<p>因此必须要将数据存储在某种类型的网络存储(NAS)中。</p>
<p>各种支持的方式不尽相同,例如 GlusterFS 需要创建 Endpoint,Ceph/NFS 之流就没这么麻烦了。</p>
<h3>6.4.1.使用NFS存储</h3>
<p>以NFS为例,yml代码如下:</p>
<p><img src="https://img2018.cnblogs.com/blog/1024482/201909/1024482-20190909233811117-1853230658.png" alt=""></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h3>6.4.2.configmap和secert</h3>
<p>secret和configmap可以理解为特殊的存储卷,但是它们不是给Pod提供存储功能的,而是提供了从集群外部向集群内部的应用注入配置信息的功能。ConfigMap扮演了K8S集群中配置中心的角色。ConfigMap定义了Pod的配置信息,可以以存储卷的形式挂载至Pod中的应用程序配置文件目录,从configmap中读取配置信息;也可以基于环境变量的形式,从ConfigMap中获取变量注入到Pod容器中使用。但是ConfigMap是明文保存的,如果用来保存数据库账号密码这样敏感信息,就非常不安全。一般这样的敏感信息配置是通过<code>secret</code>来保存。<code>secret</code>的功能和ConfigMap一样,不过secret是通过Base64的编码机制保存配置信息。</p>
<p>从ConfigMap中获取配置信息的方法有两种:</p>
<ul>
<li>一种是利用环境变量将配置信息注入Pod容器中的方式,这种方式只在Pod创建的时候生效,这就意味着在ConfigMap中的修改配置信息后,更新的配置不能被已经创建Pod容器所应用。</li>
<li>另一种是将ConfigMap做为存储卷挂载至Pod容器内,这样在修改ConfigMap配置信息后,Pod容器中的配置也会随之更新,不过这个过程会有稍微的延迟。</li>
</ul>
<p>ConfigMap当作存储卷挂载至Pod中的用法:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">apiVersion: v1
kind: Pod
metadata:
name: pod-configmap-vol-2
labels:
    name: pod-configmap-vol-2
spec:
containers:
- name: myapp
    image: ikubernetes/myapp:v1
    volumeMounts:
    - name: my-cm-www
      mountPath: /etc/nginx/conf.d/       # 将名为my-www的configmap挂载至Pod容器的这个目录下。
volumes:
- name: my-cm-www
    configMap:               # 存储卷类型选configMap

</pre>
</div>
<p>  secert的方法类似,只是secert对数据进行了加密</p>
<p>&nbsp;</p>
<h2>6.5.从底层存储技术解耦pod</h2>
<h3><span style="font-size: 1.17em">6.5.1.介绍持久卷和持久卷声明</span></h3>
<p>  当集群用户需要在其pod中使用持久化存储时,他们首先创建持久化声明(PVC)清单,指定所需要的最低容量要求,和访问模式,然后用户将持久卷声明清单提交给kubernetes API服务器,kubernetes将找到可以匹配的持久卷并将其绑定到持久卷声明。</p>
<p>  持久卷声明可以当做pod中的一个卷来使用,其他用户不能使用相同的持久卷,除非先通过删除持久卷声明绑定来释放。</p>
<h3>6.5.2.创建持久卷</h3>
<p>下面创建一个 PV&nbsp;<code>mypv1</code>,配置文件pv1<code>.yml</code>&nbsp;如下:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">apiVersion: v1
kind: PersistentVolume
metadata:
name: yh_pv1
spec:
capacity:
    storage: 1Gi                //capacity 指定 PV 的容量为 1G
accessModes:               //accessModes 指定访问模式为 ReadWriteOnce
    - ReadWriteOnce            
persistentVolumeReclaimpolicy: Recycle//persistentVolumeReclaimPolicy 指定当 PV 的回收策略为 Recycle
storageClassName: nfs         //storageClassName 指定 PV 的 class 为 nfs。相当于为 PV 设置了一个分类,PVC 可以指定 class 申请相应 class 的 PV。
nfs:
    path: /nfs/data             //指定 PV 在 NFS 服务器上对应的目录
    server: 10.10.0.11</pre>
</div>
<p><code>1.accessModes</code>&nbsp;指定访问模式为&nbsp;<code>ReadWriteOnce</code>,支持的访问模式有:</p>
<p>  ReadWriteOnce – PV 能以 read-write 模式 mount 到单个节点。<br>  ReadOnlyMany – PV 能以 read-only 模式 mount 到多个节点。<br>  ReadWriteMany – PV 能以 read-write 模式 mount 到多个节点。</p>
<p>2.<code>persistentVolumeReclaimPolicy</code>&nbsp;指定当 PV 的回收策略为&nbsp;<code>Recycle</code>,支持的策略有:<br>  Retain – 需要管理员手工回收。<br>  Recycle – 清除 PV 中的数据,效果相当于执行&nbsp;<code>rm -rf /thevolume/*</code>。<br>  Delete – 删除 Storage Provider 上的对应存储资源,例如 AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume 等。</p>
<p>&nbsp;</p>
<p><strong>创建&nbsp;<code>pv</code>:</strong></p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;"># kubectl apply -f pv1.yml
persistentvolume/yh-pv1 created
</pre>
</div>
<p>&nbsp;</p>
<p><strong>查看pv:</strong></p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;"># kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
yh-pv1   1Gi      RWO            Recycle          Available         nfs                     17m
</pre>
</div>
<p>  </p>
<p><code>STATUS</code>&nbsp;为&nbsp;<code>Available</code>,表示&nbsp;yh-pv1就绪,可以被 PVC 申请。</p>
<h3>6.5.3.通过持久卷声明来获取持久卷</h3>
<p>&nbsp;</p>
<p>接下来创建 PVC&nbsp;<code>mypvc1</code>,配置文件&nbsp;<code>pvc1.yml</code>&nbsp;如下:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: yh-pvc
spec:
accessModes:
    - ReadWriteOnce
resources:
    requests:
      storage: 1Gi
storageClassName: nfs
</pre>
</div>
<p>  </p>
<p>PVC 就很简单了,只需要指定 PV 的容量,访问模式和 class。</p>
<p>执行命令创建&nbsp;<code>mypvc1</code>:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;"># kubectl apply -f pvc1.yml
persistentvolumeclaim/yh-pvc created</pre>
</div>
<p>查看pvc</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;"># kubectl get pvc
NAME   STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
yh-pvc   Bound    yh-pv1   1Gi      RWO            nfs            64s
</pre>
</div>
<p>&nbsp;</p>
<p>从&nbsp;<code>kubectl get pvc</code>&nbsp;和&nbsp;<code>kubectl get pv</code>&nbsp;的输出可以看到 yh-<code>pvc1</code>&nbsp;已经 Bound 到yh-&nbsp;<code>pv1</code>,申请成功。</p>
<p>&nbsp;</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;"># kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM            STORAGECLASS   REASON   AGE
yh-pv1   1Gi      RWO            Recycle          Bound    default/yh-pvc   nfs                     47m
</pre>
</div>
<p>  </p>
<h3>6.5.4.在pod中使用持久卷声明</h3>
<p>上面已经创建好了pv和pvc,pod中直接使用这个pvc即可</p>
<p><img src="https://img2018.cnblogs.com/blog/1215197/201811/1215197-20181112000941263-134961896.png" alt=""></p>
<p>与使用普通 Volume 的格式类似,在&nbsp;<code>volumes</code>&nbsp;中通过&nbsp;<code>persistentVolumeClaim</code>&nbsp;指定使用&nbsp;<code>mypvc1</code>&nbsp;申请的 Volume。</p>
<p>&nbsp;通过命令创建<code>mypod1</code>:</p>
<p><img src="https://img2018.cnblogs.com/blog/1215197/201811/1215197-20181112001048694-922664654.png" alt=""></p>
<p><img src="https://img2018.cnblogs.com/blog/1215197/201811/1215197-20181112003213905-627552664.png" alt=""></p>
<p>可见,在 Pod 中创建的文件&nbsp;<code>/mydata/hello</code>&nbsp;确实已经保存到了 NFS 服务器目录&nbsp;<code>/nfsdata</code>中。</p>
<p>如果不再需要使用 PV,可用删除 PVC 回收 PV。</p>
<p>&nbsp;</p>
<h3>6.5.5.回收持久卷</h3>
<p>当 PV 不再需要时,可通过删除 PVC 回收。</p>
<p><img src="https://img2018.cnblogs.com/blog/1215197/201811/1215197-20181114140524904-1462205182.png" alt=""></p>
<p>未删除pvc之前&nbsp; pv的状态是Bound</p>
<p><img src="https://img2018.cnblogs.com/blog/1215197/201811/1215197-20181114140620468-1513256026.png" alt=""></p>
<p><strong><img src="https://img2018.cnblogs.com/blog/1215197/201811/1215197-20181114140643382-503979351.png" alt=""></strong></p>
<p>删除pvc之后pv的状态变为Available,,此时解除绑定后则可以被新的 PVC 申请。</p>
<p>/nfsdata文件中的文件被删除了</p>
<p><img src="https://img2018.cnblogs.com/blog/1215197/201811/1215197-20181114140816328-1594861053.png" alt=""></p>
<p>&nbsp;</p>
<p><img src="https://img2018.cnblogs.com/blog/1215197/201811/1215197-20181114141038825-733094704.png" alt=""></p>
<p>因为 PV 的回收策略设置为&nbsp;<code>Recycle</code>,所以数据会被清除,但这可能不是我们想要的结果。如果我们希望保留数据,可以将策略设置为&nbsp;<code>Retain</code>。</p>
<p><img src="https://img2018.cnblogs.com/blog/1215197/201811/1215197-20181114140944474-244523375.png" alt=""></p>
<p>通过&nbsp;<code>kubectl apply</code>&nbsp;更新 PV:</p>
<p>&nbsp;<img src="https://img2018.cnblogs.com/blog/1215197/201811/1215197-20181114141123152-1573323006.png" alt=""></p>
<p>回收策略已经变为&nbsp;<code>Retain</code>,通过下面步骤验证其效果:</p>
<p>&nbsp;<img src="https://img2018.cnblogs.com/blog/1215197/201811/1215197-20181114141846850-14718544.png" alt=""></p>
<p>① 重新创建&nbsp;<code>mypvc1</code>。</p>
<p>② 在&nbsp;<code>mypv1</code>&nbsp;中创建文件&nbsp;<code>hello</code>。</p>
<p>③&nbsp;<code>mypv1</code>&nbsp;状态变为&nbsp;<code>Released</code>。</p>
<p>④&nbsp;PV 中的数据被完整保留。</p>
<p>虽然&nbsp;<code>mypv1</code>&nbsp;中的数据得到了保留,但其 PV 状态会一直处于&nbsp;<code>Released</code>,不能被其他 PVC 申请。为了重新使用存储资源,可以删除并重新创建&nbsp;<code>mypv1</code>。删除操作只是删除了 PV 对象,存储空间中的数据并不会被删除。</p>
<p>&nbsp;<img src="https://img2018.cnblogs.com/blog/1215197/201811/1215197-20181114142318452-1082688967.png" alt=""></p>
<p>新建的&nbsp;<code>mypv1</code>&nbsp;状态为&nbsp;<code>Available</code>,已经可以被 PVC 申请。</p>
<p>PV 还支持&nbsp;<code>Delete</code>&nbsp;的回收策略,会删除 PV 在 Storage Provider 上对应存储空间。NFS 的 PV 不支持&nbsp;<code>Delete</code>,支持&nbsp;<code>Delete</code>&nbsp;的 Provider 有 AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume 等。</p>
<p>&nbsp;</p>
<h2>6.6.持久卷的动态配置</h2>
<h3>6.6.1.通过StorageClass资源定义可用存储类型</h3>
<p>前面的例子中,我们提前创建了 PV,然后通过 PVC 申请 PV 并在 Pod 中使用,这种方式叫做静态供给(Static Provision)。</p>
<p>与之对应的是动态供给(Dynamical Provision),即如果没有满足 PVC 条件的 PV,会动态创建 PV。相比静态供给,动态供给有明显的优势:不需要提前创建 PV,减少了管理员的工作量,效率高。</p>
<p>动态供给是通过 StorageClass 实现的,StorageClass 定义了如何创建 PV,下面是两个例子。</p>
<p>StorageClass&nbsp;<code>standard</code>:</p>
<p><img src="https://img2018.cnblogs.com/blog/1215197/201811/1215197-20181114142759910-1404134003.png" alt=""></p>
<p>StorageClass&nbsp;<code>slow</code>:</p>
<p><img src="https://img2018.cnblogs.com/blog/1215197/201811/1215197-20181114142818881-1657034993.png" alt=""></p>
<p>这两个 StorageClass 都会动态创建 AWS EBS,不同在于&nbsp;<code>standard</code>&nbsp;创建的是&nbsp;<code>gp2</code>&nbsp;类型的 EBS,而&nbsp;<code>slow</code>&nbsp;创建的是&nbsp;<code>io1</code>&nbsp;类型的 EBS。不同类型的 EBS 支持的参数可参考 AWS 官方文档。</p>
<p>StorageClass 支持&nbsp;<code>Delete</code>&nbsp;和&nbsp;<code>Retain</code>&nbsp;两种&nbsp;<code>reclaimPolicy</code>,默认是&nbsp;<code>Delete</code>。</p>
<p>与之前一样,PVC 在申请 PV 时,只需要指定 StorageClass 和容量以及访问模式,比如:</p>
<p>&nbsp;<img src="https://img2018.cnblogs.com/blog/1215197/201811/1215197-20181114142851545-262925360.png" alt=""></p>
<p>除了 AWS EBS,Kubernetes 支持其他多种动态供给 PV 的 Provisioner,完整列表请参考&nbsp;https://kubernetes.io/docs/concepts/storage/storage-classes/#provisioner</p>
<p>&nbsp;</p>
<h3>6.6.2.PV&amp;&amp;PVC在应用在mysql的持久化存储</h3>
<p>下面演示如何为 MySQL 数据库提供持久化存储,步骤为:</p>
<ol class=" list-paddingleft-2">
<li>
<p>创建 PV 和 PVC。</p>
</li>
<li>
<p>部署 MySQL。</p>
</li>
<li>
<p>向 MySQL 添加数据。</p>
</li>
<li>
<p>模拟节点宕机故障,Kubernetes 将 MySQL 自动迁移到其他节点。</p>
</li>
<li>
<p>验证数据一致性。</p>
</li>
</ol>
<p>&nbsp;</p>
<p>首先创建 PV 和 PVC,配置如下:</p>
<p>mysql-pv.yml</p>
<p>&nbsp;<img src="https://img2018.cnblogs.com/blog/1215197/201811/1215197-20181114164249311-815553434.png" alt=""></p>
<p>mysql-pvc.yml</p>
<p><img src="https://img2018.cnblogs.com/blog/1215197/201811/1215197-20181114164321137-1044555599.png" alt=""></p>
<p>创建&nbsp;<code>mysql-pv</code>&nbsp;和&nbsp;<code>mysql-pvc</code>:</p>
<p>&nbsp;<img src="https://img2018.cnblogs.com/blog/1215197/201811/1215197-20181114164423538-1248541390.png" alt=""></p>
<p>接下来部署 MySQL,配置文件如下:</p>
<p>&nbsp;<img src="https://img2018.cnblogs.com/blog/1215197/201811/1215197-20181114164556988-1613625971.png" alt=""></p>
<p>&nbsp;PVC&nbsp;<code>mysql-pvc</code>&nbsp;Bound 的 PV&nbsp;<code>mysql-pv</code>&nbsp;将被 mount 到 MySQL 的数据目录&nbsp;<code>var/lib/mysql</code>。</p>
<p><img src="https://img2018.cnblogs.com/blog/1215197/201811/1215197-20181114164706515-1715855365.png" alt=""></p>
<p>MySQL 被部署到&nbsp;<code>k8s-node2</code>,下面通过客户端访问 Service&nbsp;<code>mysql</code>:</p>
<div class="cnblogs_code">
<pre>kubectl run -it --rm --image=mysql:5.6 --restart=Never mysql-client -- mysql -h mysql -ppassword</pre>
</div>
<p>&nbsp;<img src="https://img2018.cnblogs.com/blog/1215197/201811/1215197-20181114165320049-1580108497.png" alt=""></p>
<p>更新数据库:</p>
<p><img src="https://img2018.cnblogs.com/blog/1215197/201811/1215197-20181114165947863-142820308.png" alt=""></p>
<p>① 切换到数据库 mysql。</p>
<p>② 创建数据库表 my_id。</p>
<p>③ 插入一条数据。</p>
<p>④ 确认数据已经写入。</p>
<p>&nbsp;关闭&nbsp;<code>k8s-node2</code>,模拟节点宕机故障。</p>
<p>&nbsp;<img src="https://img2018.cnblogs.com/blog/1215197/201811/1215197-20181114170125072-435593197.png" alt=""></p>
<p>验证数据的一致性:</p>
<p>&nbsp;由于node2节点已经宕机,node1节点接管了这个任务。</p>
<p><img src="https://img2018.cnblogs.com/blog/1215197/201811/1215197-20181114170806935-1324900057.png" alt=""></p>
<p>通过kubectl&nbsp;run&nbsp;命令&nbsp;进入node1的这个pod里,查看数据是否依旧存在</p>
<p><img src="https://img2018.cnblogs.com/blog/1215197/201811/1215197-20181114173251942-323542163.png" alt=""></p>
<p><img src="https://img2018.cnblogs.com/blog/1215197/201811/1215197-20181114173235264-1137808713.png" alt=""></p>
<p>&nbsp;</p>
<p>MySQL 服务恢复,数据也完好无损。</p><br><br>
来源:https://www.cnblogs.com/yaohong/p/11489164.html
頁: [1]
查看完整版本: kubernetes 磁盘、PV、PVC