【K8S in Action】第六章 卷:将磁盘挂载到容器
每个新容器都是通过在构建镜像时加入的详细配置文件来启动的。将此与pod 中容器重新启动的现象结合起来。存储卷是 pod 的一个组成部分。这意味着在 pod 启动时创建卷, 并在删除 pod时销毁卷。因此, 在容器重新启动期间, 卷的内容将保持不变, 在重新启动容器之后, 新容器可以识别前一个容器写入卷的所有文件。另外,如果一个 pod 包含多个容器, 那这个卷可以同时被所有的容器使用。
1. 介绍卷
每个新容器都是通过在构建镜像时加入的详细配置文件来启动的。 将此与pod 中容器重新启动的现象结合起来。
存储卷是 pod 的一个组成部分。这意味着在 pod 启动时创建卷, 并在删除 pod时销毁卷。 因此, 在容器重新启动期间, 卷的内容将保持不变, 在重新启动容器之后, 新容器可以识别前一个容器写入卷的所有文件。
另外,如果一个 pod 包含多个容器, 那这个卷可以同时被所有的容器使用。
1.1 卷类型
• emptyDir 用于存储临时数据的简单空目录。
• hostPath 用于将目录从工作节点的文件系统挂载到pod中。
• gitRepo 通过检出Git仓库的内容来初始化的卷。
• nfs 挂载到pod中的NFS共享卷。
2. 通过卷在容器之间共享数据
2.1 使用 emptyDir
关注它是如何用于在 pod 的多个容器之间共享数据的。卷从一个 目录开始,运行在 pod 内的应用程序可以写入它需要 的任何文件。pod 含两个容器和 个挂载在两个容器中的共用的卷,但在不同的路径上。
apiVersion: vl
kind: Pod
metadata:
name : fortune
spec:
containers:
-image: luksa/fortune
name: html generator
volumeMounts:
- name: html
mountPath: /var/htdocs 名为html的卷挂载在/var/htdocs
- image: nginx:alpine
name: web-server
volumeMounts :
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
ports:
- containerPort: 80
protocol: TCP
volumes
- name: html 叫html的emptyDir卷,挂载在上面的两个容器中
emptyDir: {}
将端口从本地机器转发到 pod 来实现,计算机的 808 端口来访问服务
kubectl port-forward fortune 8080:80
volumes:
- name: html
emptyDir
medium: Memory # 存在内存上
2.2 使用 Git 仓库作为存储卷
gitRepo 卷基本上也是 emptyDir 卷,它通过克隆 Git 仓库并在 pod时(但在创建容器之前 检出特定版本来填充数据。
注意:
- 在创建gitRepo 卷后,它并不能和对应 repo 保持同步。 当向库推送新增 的提交时,文件将不会被更新。
- 然而,如果所用 pod 是由ReplicationController 管理的,删除这个 pod 将触发新建一个新的 pod ,而这个新 pod
的卷中将包含最新的提交。
apiVersion : vl
kind: Pod
metadata:
name: gi trepo-volume-pod
spec:
containers:
- image: nginx:alpine
name: web -server
volumeMounts :
- name : html
mountPath: / usr/share/nginx/ html
readOnly: true
ports:
containerPort: 80
protocol: TCP
volumes
- name: html
gitRepo: https://githubo.com/...
revision: master github 库的mater分支下载
directory: . 创建在根目录
如果想要将私有的 Git repo 克隆到容器中, 则应该使用 gitsync sidecar 或类似的方法, 而不是使用 gitRepo 卷。
3 访问工作节点文件系统上的文件(hostPath卷)
大多数 pod 应该忽略它们的主机节点, 因此它们不应该访问节点文件系统上的任何文件。
hostPath 卷指向节点文件系统上的特定文件或目录。 在同一个节点上运行并在其 hostPath 卷中使用相同路径的 pod 可以看到相同的文件。
hostPath 卷是我们介绍的第 一种类型的持久性存储。切勿使用它们来持久化跨 pod的数据。
kubect1 get pod s --namespace kube-system
查看hostpaht 的使用, 切勿使用它们来持久化跨 pod的数据
kubectl describe po fluentd-kubia-4ebc2fle-9a3e --namespace kube-system
4 使用持久化存储
当运行在一个 pod 中的应用程序需要将数据保存到磁盘上, 并且即使该 pod 重新调度到另 一个节点时也要求具有相同的数据可用。此必须将其存储在某种类型的网络存储 (NAS) 中。
4.1 使用 GCE 持久磁盘作为底层存储机制。
同 一区域的 Kubemetes 集群中创建
gcloud container clusters list
NAME ZONE MASTER VERSION MASTER_IP
kubia europe-westl-b 1.2.5 104.155.84.137
在europe-westl-b 区域中创建了集群 创建GCE 持久磁盘。创建了一个 1GiB 容量并命名为 mongodb的GCE 待久磁盘。
gcloud compute disks create --size=lGiB --zone=europe-west-b mongodb
创建—个使用GCE持久磁盘卷的pod。 Pod 直接使用了持久磁盘卷。
apiVersion: vl
kind: Pod
metadata:
name: mongodb
spec:
volumes:
- name: mongodb-data 卷名, 与挂载卷一致
gcePersistentDisk: 类型是GCE持久磁盘
pdName: mongodb 名称需要与创建的PD一致
fsType: ext4 文件系统类型
containers:
- image: mongo
name: mongodb
volumeMountS:
- name: mongodb-data 挂载卷
mountPath: /data/db
ports:
- containerPort: 27017
protocol: TCP
4.2 通过底层持久化存储使用其他类型的卷
如果集群是运行在自有的一组服务器上,那么就有大量其他可移植的选项在卷内挂载外部存储。例如,要挂载一个简单的NFS 共享,只需指定NFS 服务器和共享路径,如下面的代码清单所示
mongodb-pod-aws.yaml
volumes:
- name: mongodb-data
nfs: 这个卷受NFS共享支持
server: 1.2.3.4 NFS 服务IP
path: /some/path 服务器提供的路径
要了解每个卷类型设置需要哪些属性的详细信息,可以转到KubemetesAPI引用中的KubernetesAPI定义,或者通过第三章展示的通过kubectl explain查找信息。
通过pod的卷来隐藏真实的底层基础设施,不就是Kubernetes存在的意义吗。研发人员来指定NFS 服务器的主机名会是一件感觉很糟糕的事情。
5 从底层存储技术解耦pod
Kubernetes 的基本理念, 这个理念旨在向应用程序及其开发人员隐藏真实的基础设施, 使他们不必担心基础设施的具体状态, 并使应用程序可在大量云服务商和数据企业之间进行功能迁移。 (每当有这种想法,就会创造出新的岗位,专门管理基础设施与集群配置。)
5.1 介绍持久卷和持久卷声明
由集群管理员设置底层存储, 然后通过Kubernetes API 服务器创建持久卷并注册。
持久卷声明可以当作 pod 中的一个卷来使用, 其他用户不能使用相同的持久卷。
创建持久卷
apiVersion: vl
kind: PersistentVolume
metadata:
name: mongodb-pv
spec:
capacity:
storage: lGi 对应的容量需求
accessModes:
- ReadWriteOnce 可以被单个客户端挂载为读写模
- ReadOnlyMany 可以被多个客户端挂载为只读
persistentVolumeReclaimPolicy: Retain 声明被释放后被保留(不清理和删除)
gcePersistentDisk: PV 指定为之前创建的GCE持久磁盘.
pdName: mongodb 持久卷支持的实际存储类型、 位置和其他属性。
fsType: ext4 与直接Pod 直接使用GCE 的配置一样
create 创建后, 查看所有的持久卷, 持久卷不属于任何命名空间,集群层面的资源。
kubectl get pv
NAME CAPACITY RECLAIMPOLICY ACCESSMODES STATUS
mongodb-pv lGi Retain RWO,ROX Available
创建持久卷声明
需要部署持久化存储的 pod ,将要用到之前创建的持久卷,但是不能直接在 pod 内使用,需要先声明一个。
创建好声明,k8s就会找到适当的持久卷并将其绑定到声明 :
- 持久卷的容量必须足够大以满足声明的需求,
- 并且卷的模式必须包含声明中指定的访模式 必须包含声明中的访问模式。
在该示例中,声明请求 1GiB 的存储空间和 ReadWriteOnce 访问模式。之前创建的持久卷符合刚刚声明中 的这两个条件,所以它被绑定到对应的声明中。
持久卷声明又只在特定的命名空间创建,所以持久卷和持久卷声明只能被同命名空间内的 pod 创建使用。
apiVersion: vl
kind: PersistentVolumeClaim
metadata:
name: mongodb-pvc 声明的名称,给pod 使用时需要用到
spec:
resources:
request:
storage: lGi 申请1G空间
accessModes:
- ReadWriteOnce 可以被单个客户端挂载为读写模
storageClassName :”” 动态配置章节介绍
kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESSMODES AGE
mongodb-pvc Bound mongodb-pvc l Gi RWO,ROX 3s
pod 中使用持久卷声明
apiVersion: vl
kind: Pod
metadata:
name: mogodb
spec:
containers:
- image: mongo
name: mongodb
volumeMounts:
- name : mogodb-data
mountPath: /data/db
ports:
- containerPort: 27017
protocol: TCP
volumes·
- name: mongodb data
persistentVolumeClaim:
claimName: mongodb-pvc 在 pod 的卷中引用持久卷声明名称
继续创建 pod ,现在检查这个 pod 是否确实在使用相同的持久卷和底层 GCEPD 。通过再次运行 MongoDB shell, 查看之前的数据
kubectl exec -it mongodb mongo
...
> use mystore
switched to db mystore
>db.foe.find()
{"_id ": Objectid ("7a6leb9deOcfd512374cc75"),"name":"fpp"}
回收持久卷
先 删除 pod 和 持久卷声明, 如果再次创建持久卷声明会怎样?持久卷声明的状态显示为 Pending。未清理前不可绑定到全新的声明中。
通过使用相同的持久卷,新 pod 可以读取由前一个 pod 存放的数据,即使声明和pod 是在不同的命名空间中创建的(因此有可能属于不同的集群租户)
$ kubectl delete pod mongodb
pod ” rnongodb" deleted
$ ubectl delete pvc ngodb-pvc
persistentvolurneclairn ” rnongodb pvc" deleted
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESSMODES AGE
mogodb-pvc Pending 13s
列出持久卷
NAME CAPACITY ACCESSMODES STATUS CLAIM REASON AGE
mogodb-pv lGi RWO,ROX Released default/rnongodb-pvc
手动回收持久卷:
persistentVolumeReclaimPolicy 设置为 Reta : 在持久卷从持久卷声明中释放后仍然能保留它的卷和数据内容。唯一方法是删除和 新创建 持久卷资源。
自动回收持久卷:
- Recycle 第一种删除卷的内容并使卷可用于再次声明
- Delete 策略删除底层存储
6 持久卷的动态卷配置
通过动态配置持久卷来自动执行此任务。集群管理员可以创建持久卷配置,并定义一个或多个 Storage Class, 从而让用户选择他们想要的持久卷类型而不仅仅只是创建持久卷。
创建 Storage Class资源后,用户可以在其持久卷声明中按名称引用存储类
apiVersion: storage.kBs.io/vl
kind: StorageClass
metadata :
name: fast
provisioner: kubernetes.io/gce-pd 置备程序, 配置持久卷的插件
parameters: 传达parameters的参数
type:pd-ssd
zone:europe-westl-b
apiVersion: vl
kind: PersistentVolumeClaim
metadata:
name: mongodb-pvc 声明的名称,给pod 使用时需要用到
spec:
storageClassName:fast PVC 请求自定义存储类
resources:
request:
storage: lGi 申请1G空间
accessModes:
- ReadWriteOnce 可以被单个客户端挂载为读写模
不指定存储类的动态配置
将看将持久卷附加到的最新和最简单的方法。SC 作为 storageclass 的简写。可以在不指定 storageClassName 属性的情况下创建 PVC,并且(在 Google K8s引擎上〉将为你提供 pd-standard 类型的 GCE 持久磁盘
列出存储类
$ kubectl get sc
NAME TYPE
fast kubernetes.io/gce-pd
standard (default) kubernetes.io/gce-pd
检查默认存储类
kubectl get sc standard -o yaml
annotations: 将存储类型标记为默认
storageclass.beta.kubernetes io/is-default-class:“true"
parameters:
type: pd-standard
provisi r: kubernetes.io/gce-pd
如果持久卷声明没有明确指出要使用哪个存储类, 默认存储类会用于动态提供持久卷的内容。
apiVersion: vl
kind: PersistentVolumeClaim
metadata:
name: mongodb-pvc2 声明的名称,给pod 使用时需要用到
spec:
resources: 没有指定PVC 请求自定义存储类
request:
storage: lGi 申请1G空间
accessModes:
- ReadWriteOnce 可以被单个客户端挂载为读写模
kubect1 getpvc mongodb-pvc2
NAME STATUS VOLUME CAPACITY ACCESSMODES STORAGECLASS
mongodb-pvc2 Bound pvc-95a5ecl2 lGi RWO standard
强制将持久卷声明绑定到预配置的其中一个持久卷
kind: PersistentVolumeClaim
spec:
StorageClassName: ""
为什么将 storageClassNarne 设置为一个空字符串,当你想让 PVC 绑定到你手动配置的 PV 时。
如果尚未将 storageClassName 属性设置为空字符串, 则尽管已存在适当的预配置待久卷, 但动态卷置备程序仍将配置新的持久卷。
更多推荐
所有评论(0)