# Volume
容器磁盤上的文件的生命周期是短暫的,這就使得在容器中運行重要應用時會出現一些問題。首先,當容器崩潰時,kubelet 會重啟它,但是容器中的文件將丟失——容器以干凈的狀態(鏡像最初的狀態)重新啟動。其次,在 `Pod` 中同時運行多個容器時,這些容器之間通常需要共享文件。Kubernetes 中的 `Volume` 抽象就很好的解決了這些問題。
建議先熟悉 [pod](https://kubernetes.io/docs/user-guide/pods)。
## 背景
Docker 中也有一個 [volume](https://docs.docker.com/engine/admin/volumes/) 的概念,盡管它稍微寬松一些,管理也很少。在 Docker 中,卷就像是磁盤或是另一個容器中的一個目錄。它的生命周期不受管理,直到最近才有了 local-disk-backed 卷。Docker 現在提供了卷驅動程序,但是功能還非常有限(例如Docker1.7只允許每個容器使用一個卷驅動,并且無法給卷傳遞參數)。
另一方面,Kubernetes 中的卷有明確的壽命——與封裝它的 Pod 相同。所f以,卷的生命比 Pod 中的所有容器都長,當這個容器重啟時數據仍然得以保存。當然,當 Pod 不再存在時,卷也將不復存在。也許更重要的是,Kubernetes 支持多種類型的卷,Pod 可以同時使用任意數量的卷。
卷的核心是目錄,可能還包含了一些數據,可以通過 pod 中的容器來訪問。該目錄是如何形成的、支持該目錄的介質以及其內容取決于所使用的特定卷類型。
要使用卷,需要為 pod 指定為卷(`spec.volumes` 字段)以及將它掛載到容器的位置(`spec.containers.volumeMounts` 字段)。
容器中的進程看到的是由其 Docker 鏡像和卷組成的文件系統視圖。[Docker 鏡像](https://docs.docker.com/userguide/dockerimages/)位于文件系統層次結構的根目錄,任何卷都被掛載在鏡像的指定路徑中。卷無法掛載到其他卷上或與其他卷有硬連接。Pod 中的每個容器都必須獨立指定每個卷的掛載位置。
## 卷的類型
Kubernetes 支持以下類型的卷:
- `awsElasticBlockStore`
- `azureDisk`
- `azureFile`
- `cephfs`
- `csi`
- `downwardAPI`
- `emptyDir`
- `fc` (fibre channel)
- `flocker`
- `gcePersistentDisk`
- `gitRepo`
- `glusterfs`
- `hostPath`
- `iscsi`
- `local`
- `nfs`
- `persistentVolumeClaim`
- `projected`
- `portworxVolume`
- `quobyte`
- `rbd`
- `scaleIO`
- `secret`
- `storageos`
- `vsphereVolume`
我們歡迎額外貢獻。
### awsElasticBlockStore
`awsElasticBlockStore` 卷將Amazon Web Services(AWS)EBS Volume 掛載到您的容器中。與 `emptyDir` 類型會在刪除 Pod 時被清除不同,EBS 卷的的內容會保留下來,僅僅是被卸載。這意味著 EBS 卷可以預先填充數據,并且可以在數據包之間“切換”數據。
**重要提示**:您必須使用 `aws ec2 create-volume` 或 AWS API 創建 EBS 卷,才能使用它。
使用 awsElasticBlockStore 卷時有一些限制:
- 運行 Pod 的節點必須是 AWS EC2 實例
- 這些實例需要與 EBS 卷位于相同的區域和可用區域
- EBS 僅支持卷和 EC2 實例的一對一的掛載
#### 創建 EBS 卷
在 pod 中使用的 EBS 卷之前,您需要先創建它。
```bash
aws ec2 create-volume --availability-zone=eu-west-1a --size=10 --volume-type=gp2
```
確保區域與您啟動集群的區域相匹配(并且檢查大小和 EBS 卷類型是否適合您的使用!)
### AWS EBS 示例配置
```yaml
apiVersion: v1
kind: Pod
metadata:
name: test-ebs
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-ebs
name: test-volume
volumes:
- name: test-volume
# This AWS EBS volume must already exist.
awsElasticBlockStore:
volumeID: <volume-id>
fsType: ext4
```
### azureDisk
`AzureDisk` 用于將 Microsoft Azure [Data Disk](https://azure.microsoft.com/zh-cn/documentation/articles/virtual-machines-linux-about-disks-vhds) 掛載到 Pod 中。
### azureFile
`azureFile` 用于將 Microsoft Azure File Volume(SMB 2.1 和 3.0)掛載到 Pod 中。
### cephfs
`cephfs` 卷允許將現有的 CephFS 卷掛載到您的容器中。不像 `emptyDir`,當刪除 Pod 時被刪除,`cephfs` 卷的內容將被保留,卷僅僅是被卸載。這意味著 CephFS 卷可以預先填充數據,并且可以在數據包之間“切換”數據。 CephFS 可以被多個寫設備同時掛載。
**重要提示**:您必須先擁有自己的 Ceph 服務器,然后才能使用它。
有關更多詳細信息,請參見[CephFS示例](https://github.com/kubernetes/examples/tree/master/staging/volumes/cephfs/)。
### csi
CSI 代表[容器存儲接口](https://github.com/container-storage-interface/spec/blob/master/spec.md),CSI 試圖建立一個行業標準接口的規范,借助 CSI 容器編排系統(CO)可以將任意存儲系統暴露給自己的容器工作負載。有關詳細信息,請查看[設計方案](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/storage/container-storage-interface.md)。
`csi` 卷類型是一種 in-tree 的 CSI 卷插件,用于 Pod 與在同一節點上運行的外部 CSI 卷驅動程序交互。部署 CSI 兼容卷驅動后,用戶可以使用 `csi` 作為卷類型來掛載驅動提供的存儲。
CSI 持久化卷支持是在 Kubernetes v1.9 中引入的,作為一個 alpha 特性,必須由集群管理員明確啟用。換句話說,集群管理員需要在 apiserver、controller-manager 和 kubelet 組件的 “`--feature-gates =`” 標志中加上 “`CSIPersistentVolume = true`”。
CSI 持久化卷具有以下字段可供用戶指定:
- `driver`:一個字符串值,指定要使用的卷驅動程序的名稱。必須少于 63 個字符,并以一個字符開頭。驅動程序名稱可以包含 “`.`”、“`-` ”、“`_`” 或數字。
- `volumeHandle`:一個字符串值,唯一標識從 CSI 卷插件的 `CreateVolume` 調用返回的卷名。隨后在卷驅動程序的所有后續調用中使用卷句柄來引用該卷。
- `readOnly`:一個可選的布爾值,指示卷是否被發布為只讀。默認是 false。
### downwardAPI
`downwardAPI` 卷用于使向下 API 數據(downward API data)對應用程序可用。它掛載一個目錄,并將請求的數據寫入純文本文件。
參考 [`downwardAPI` 卷示例](https://kubernetes.io/docs/tasks/inject-data-application/downward-api-volume-expose-pod-information/)查看詳細信息。
### emptyDir
當 Pod 被分配給節點時,首先創建 `emptyDir` 卷,并且只要該 Pod 在該節點上運行,該卷就會存在。正如卷的名字所述,它最初是空的。Pod 中的容器可以讀取和寫入 `emptyDir` 卷中的相同文件,盡管該卷可以掛載到每個容器中的相同或不同路徑上。當出于任何原因從節點中刪除 Pod 時,`emptyDir` 中的數據將被永久刪除。
**注意**:容器崩潰不會從節點中移除 pod,因此 `emptyDir` 卷中的數據在容器崩潰時是安全的。
`emptyDir` 的用法有:
- 暫存空間,例如用于基于磁盤的合并排序
- 用作長時間計算崩潰恢復時的檢查點
- Web服務器容器提供數據時,保存內容管理器容器提取的文件
#### Pod 示例
```yaml
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
```
### fc (fibre channel)
fc 卷允許將現有的 `fc` 卷掛載到 pod 中。您可以使用卷配置中的 `targetWWN` 參數指定單個或多個目標全球通用名稱(World Wide Name)。如果指定了多個 WWN,則 targetWWN 期望這些 WWN 來自多路徑連接。
**重要提示**:您必須配置 FC SAN 區域劃分,并預先將這些 LUN(卷)分配并屏蔽到目標 WWN,以便 Kubernetes 主機可以訪問它們。
參考 [FC 示例](https://github.com/kubernetes/examples/tree/master/staging/volumes/fibre_channel)獲取詳細信息。
### flocker
Flocker 是一款開源的集群容器數據卷管理器。它提供了由各種存儲后端支持的數據卷的管理和編排。
`flocker` 允許將 Flocker 數據集掛載到 pod 中。如果數據集在 Flocker 中不存在,則需要先使用 Flocker CLI 或使用 Flocker API 創建數據集。如果數據集已經存在,它將被 Flocker 重新連接到 pod 被調度的節點上。這意味著數據可以根據需要在數據包之間“切換”。
**重要提示**:您必須先運行自己的 Flocker 安裝程序才能使用它。
參考 [Flocker 示例](https://github.com/kubernetes/examples/tree/master/staging/volumes/flocker)獲取更多詳細信息。
### gcePersistentDisk
`gcePersistentDisk` 卷將 Google Compute Engine(GCE)[Persistent Disk](http://cloud.google.com/compute/docs/disks) 掛載到您的容器中。與刪除 Pod 時刪除的 `emptyDir` 不同,PD 的內容被保留,只是卸載了卷。這意味著 PD 可以預先填充數據,并且數據可以在 Pod 之間“切換”。
**重要提示**:您必須先使用 gcloud 或 GCE API 或 UI 創建一個 PD,然后才能使用它。
使用 `gcePersistentDisk` 時有一些限制:
- 運行 Pod 的節點必須是 GCE 虛擬機
- 那些虛擬機需要在與 PD 一樣在 GCE 項目和區域中
PD 的一個特點是它們可以同時被多個用戶以只讀方式掛載。這意味著您可以預先使用您的數據集填充 PD,然后根據需要給多個 Pod 中并行提供。不幸的是,只能由單個消費者以讀寫模式掛載 PD,而不允許同時寫入。
在由 ReplicationController 控制的 pod 上使用 PD 將會失敗,除非 PD 是只讀的或者副本數是 0 或 1。
#### 創建 PD
在您在 pod 中使用 GCE PD 之前,需要先創建它。
```bash
gcloud compute disks create --size=500GB --zone=us-central1-a my-data-disk
```
#### Pod 示例
```yaml
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
# This GCE PD must already exist.
gcePersistentDisk:
pdName: my-data-disk
fsType: ext4
```
### gitRepo
`gitRepo` 卷是一個可以演示卷插件功能的示例。它會掛載一個空目錄并將 git 存儲庫克隆到您的容器中。將來,這樣的卷可能會轉移到一個更加分離的模型,而不是為每個這樣的用例擴展 Kubernetes API。
下面是 gitRepo 卷示例:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: server
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- mountPath: /mypath
name: git-volume
volumes:
- name: git-volume
gitRepo:
repository: "git@somewhere:me/my-git-repository.git"
revision: "22f1d8406d464b0c0874075539c1f2e96c253775"
```
### glusterfs
`glusterfs` 卷允許將 [Glusterfs](http://www.gluster.org)(一個開放源代碼的網絡文件系統)卷掛載到您的集群中。與刪除 Pod 時刪除的 `emptyDir` 不同,`glusterfs` 卷的內容將被保留,而卷僅僅被卸載。這意味著 glusterfs 卷可以預先填充數據,并且可以在數據包之間“切換”數據。 GlusterFS 可以同時由多個寫入掛載。
**重要提示**:您必須先自行安裝 GlusterFS,才能使用它。
有關更多詳細信息,請參閱 [GlusterFS](https://github.com/kubernetes/examples/tree/master/staging/volumes/glusterfs) 示例。
### hostPath
`hostPath` 卷將主機節點的文件系統中的文件或目錄掛載到集群中。該功能大多數 Pod 都用不到,但它為某些應用程序提供了一個強大的解決方法。
例如,`hostPath` 的用途如下:
- 運行需要訪問 Docker 內部的容器;使用 `/var/lib/docker` 的 `hostPath`
- 在容器中運行 cAdvisor;使用 `/dev/cgroups` 的 `hostPath`
- 允許 pod 指定給定的 hostPath 是否應該在 pod 運行之前存在,是否應該創建,以及它應該以什么形式存在
除了所需的 `path` 屬性之外,用戶還可以為 `hostPath` 卷指定 `type`。
`type` 字段支持以下值:
| 值 | 行為 |
| :------------------ | :--------------------------------------- |
| | 空字符串(默認)用于向后兼容,這意味著在掛載 hostPath 卷之前不會執行任何檢查。 |
| `DirectoryOrCreate` | 如果在給定的路徑上沒有任何東西存在,那么將根據需要在那里創建一個空目錄,權限設置為 0755,與 Kubelet 具有相同的組和所有權。 |
| `Directory` | 給定的路徑下必須存在目錄 |
| `FileOrCreate` | 如果在給定的路徑上沒有任何東西存在,那么會根據需要創建一個空文件,權限設置為 0644,與 Kubelet 具有相同的組和所有權。 |
| `File` | 給定的路徑下必須存在文件 |
| `Socket` | 給定的路徑下必須存在 UNIX 套接字 |
| `CharDevice` | 給定的路徑下必須存在字符設備 |
| `BlockDevice` | 給定的路徑下必須存在塊設備 |
使用這種卷類型是請注意,因為:
- 由于每個節點上的文件都不同,具有相同配置(例如從 podTemplate 創建的)的 pod 在不同節點上的行為可能會有所不同
- 當 Kubernetes 按照計劃添加資源感知調度時,將無法考慮 `hostPath` 使用的資源
- 在底層主機上創建的文件或目錄只能由 root 寫入。您需要在特權容器中以 root 身份運行進程,或修改主機上的文件權限以便寫入 `hostPath` 卷
#### Pod 示例
```yaml
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
```
### iscsi
`iscsi` 卷允許將現有的 iSCSI(SCSI over IP)卷掛載到容器中。不像 `emptyDir`,刪除 Pod 時 `iscsi` 卷的內容將被保留,卷僅僅是被卸載。這意味著 iscsi 卷可以預先填充數據,并且這些數據可以在 pod 之間“切換”。
**重要提示**:必須先創建自己的 iSCSI 服務器,然后才能使用它。
iSCSI 的一個特點是它可以同時被多個用戶以只讀方式安裝。這意味著您可以預先使用您的數據集填充卷,然后根據需要向多個額 pod 同時提供。不幸的是,iSCSI 卷只能由單個使用者以讀寫模式掛載——不允許同時寫入。
### local
這個 alpha 功能要求啟用 `PersistentLocalVolumes` feature gate。
**注意**:從 1.9 開始,`VolumeScheduling` feature gate 也必須啟用。
`local` 卷表示掛載的本地存儲設備,如磁盤、分區或目錄。
本地卷只能用作靜態創建的 PersistentVolume。
與 HostPath 卷相比,local 卷可以以持久的方式使用,而無需手動將 pod 調度到節點上,因為系統會通過查看 PersistentVolume 上的節點關聯性來了解卷的節點約束。
但是,local 卷仍然受底層節點的可用性影響,并不適用于所有應用程序。
以下是使用 `local` 卷的示例 PersistentVolume 規范:
```yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: example-pv
annotations:
"volume.alpha.kubernetes.io/node-affinity": '{
"requiredDuringSchedulingIgnoredDuringExecution": {
"nodeSelectorTerms": [
{ "matchExpressions": [
{ "key": "kubernetes.io/hostname",
"operator": "In",
"values": ["example-node"]
}
]}
]}
}'
spec:
capacity:
storage: 100Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
storageClassName: local-storage
local:
path: /mnt/disks/ssd1
```
**注意**:本地 PersistentVolume 清理和刪除需要手動干預,無外部提供程序。
從 1.9 開始,本地卷綁定可以被延遲,直到通過具有 StorageClass 中的 `WaitForFirstConsumer` 設置為`volumeBindingMode` 的 pod 開始調度。請參閱示例。延遲卷綁定可確保卷綁定決策也可以使用任何其他節點約束(例如節點資源需求,節點選擇器,pod 親和性和 pod 反親和性)進行評估。
有關 `local` 卷類型的詳細信息,請參見[本地持久化存儲用戶指南](https://github.com/kubernetes-incubator/external-storage/tree/master/local-volume)。
### nfs
`nfs` 卷允許將現有的 NFS(網絡文件系統)共享掛載到您的容器中。不像 `emptyDir`,當刪除 Pod 時,`nfs` 卷的內容被保留,卷僅僅是被卸載。這意味著 NFS 卷可以預填充數據,并且可以在 pod 之間“切換”數據。 NFS 可以被多個寫入者同時掛載。
**重要提示**:您必須先擁有自己的 NFS 服務器才能使用它,然后才能使用它。
有關更多詳細信息,請參見 [NFS 示例](https://github.com/kubernetes/examples/tree/master/staging/volumes/nfs)。
### persistentVolumeClaim
`persistentVolumeClaim` 卷用于將 [PersistentVolume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) 掛載到容器中。PersistentVolumes 是在用戶不知道特定云環境的細節的情況下“聲明”持久化存儲(例如 GCE PersistentDisk 或 iSCSI 卷)的一種方式。
有關更多詳細信息,請參閱 [PersistentVolumes 示例](https://kubernetes.io/docs/concepts/storage/persistent-volumes/)。
### projected
`projected` 卷將幾個現有的卷源映射到同一個目錄中。
目前,可以映射以下類型的卷來源:
- [`secret`](#secret)
- [`downwardAPI`](#downwardapi)
- `configMap`
所有來源都必須在與 pod 相同的命名空間中。
#### 帶有 secret、downward API 和 configmap 的 pod
```yaml
apiVersion: v1
kind: Pod
metadata:
name: volume-test
spec:
containers:
- name: container-test
image: busybox
volumeMounts:
- name: all-in-one
mountPath: "/projected-volume"
readOnly: true
volumes:
- name: all-in-one
projected:
sources:
- secret:
name: mysecret
items:
- key: username
path: my-group/my-username
- downwardAPI:
items:
- path: "labels"
fieldRef:
fieldPath: metadata.labels
- path: "cpu_limit"
resourceFieldRef:
containerName: container-test
resource: limits.cpu
- configMap:
name: myconfigmap
items:
- key: config
path: my-group/my-config
```
#### 使用非默認權限模式設置多個 secret 的示例 pod
```yaml
apiVersion: v1
kind: Pod
metadata:
name: volume-test
spec:
containers:
- name: container-test
image: busybox
volumeMounts:
- name: all-in-one
mountPath: "/projected-volume"
readOnly: true
volumes:
- name: all-in-one
projected:
sources:
- secret:
name: mysecret
items:
- key: username
path: my-group/my-username
- secret:
name: mysecret2
items:
- key: password
path: my-group/my-password
mode: 511
```
每個映射的卷來源在 `sources` 下的規格中列出。除了以下兩個例外,參數幾乎相同:
- 對于 secret,`secretName` 字段已經被更改為 `name` 以與 ConfigMap 命名一致。
- `defaultMode` 只能在映射級別指定,而不能針對每個卷源指定。但是,如上所述,您可以明確設置每個映射的 `mode`。
### portworxVolume
`portworxVolume` 是一個與 Kubernetes 一起,以超融合模式運行的彈性塊存儲層。Portwork 指紋存儲在服務器中,基于功能的分層,以及跨多個服務器聚合容量。 Portworx 在虛擬機或裸機 Linux 節點上運行。
`portworxVolume` 可以通過 Kubernetes 動態創建,也可以在 Kubernetes pod 中預先設置和引用。
以下是一個引用預先配置的 PortworxVolume 的示例 pod:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: test-portworx-volume-pod
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /mnt
name: pxvol
volumes:
- name: pxvol
# This Portworx volume must already exist.
portworxVolume:
volumeID: "pxvol"
fsType: "<fs-type>"
```
**重要提示**:在 pod 中使用之前,請確保您有一個名為 `pxvol` 的現有 PortworxVolume。
### quobyte
`quobyte` 卷允許將現有的 [Quobyte](http://www.quobyte.com) 卷掛載到容器中。
**重要提示**:您必須先創建自己的 Quobyte 安裝程序,然后才能使用它。
### rbd
`rbd` 卷允許將 [Rados Block Device](http://ceph.com/docs/master/rbd/rbd/) 卷掛載到容器中。不像 `emptyDir`,刪除 Pod 時 `rbd `卷的內容被保留,卷僅僅被卸載。這意味著 RBD 卷可以預先填充數據,并且可以在 pod 之間“切換”數據。
**重要提示**:您必須先自行安裝 Ceph,然后才能使用 RBD。
RBD 的一個特點是它可以同時為多個用戶以只讀方式掛載。這意味著可以預先使用您的數據集填充卷,然后根據需要同時為多個 pod 并行提供。不幸的是,RBD 卷只能由單個用戶以讀寫模式安裝——不允許同時寫入。
### scaleIO
ScaleIO 是一個基于軟件的存儲平臺,可以使用現有的硬件來創建可擴展的共享塊網絡存儲集群。`scaleIO` 卷插件允許已部署的 pod 訪問現有的 ScaleIO 卷(或者它可以為持久性卷聲明動態調配新卷,請參閱 [ScaleIO 持久卷](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#scaleio))。
**重要提示**:您必須有一個已經配置好的 ScaleIO 集群,并和創建的卷一同運行,然后才能使用它們。
以下是使用 ScaleIO 的示例 pod 配置:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-0
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: pod-0
volumeMounts:
- mountPath: /test-pd
name: vol-0
volumes:
- name: vol-0
scaleIO:
gateway: https://localhost:443/api
system: scaleio
protectionDomain: sd0
storagePool: sp1
volumeName: vol-0
secretRef:
name: sio-secret
fsType: xfs
```
有關更多詳細信息,請參閱 [ScaleIO 示例](https://github.com/kubernetes/examples/tree/master/staging/volumes/scaleio)。
### secret
`secret` 卷用于將敏感信息(如密碼)傳遞到 pod。您可以將 secret 存儲在 Kubernetes API 中,并將它們掛載為文件,以供 Pod 使用,而無需直接連接到 Kubernetes。 `secret` 卷由 tmpfs(一個 RAM 支持的文件系統)支持,所以它們永遠不會寫入非易失性存儲器。
**重要提示**:您必須先在 Kubernetes API 中創建一個 secret,然后才能使用它。
### storageOS
`storageos` 卷允許將現有的 [StorageOS](https://www.storageos.com) 卷掛載到容器中。
StorageOS 在 Kubernetes 環境中以容器方式運行,使本地或附加存儲可以從 Kubernetes 集群中的任何節點訪問。可以復制數據以防止節點故障。精簡配置和壓縮可以提高利用率并降低成本。
StorageOS 的核心是為容器提供塊存儲,可以通過文件系統訪問。
StorageOS 容器需要 64 位 Linux,沒有額外的依賴關系。可以使用免費的開發者許可證。
**重要提示**:您必須在每個要訪問 StorageOS 卷的節點上運行 StorageOS 容器,或者為該池提供存儲容量。相關的安裝說明,請參閱 [StorageOS文檔](https://docs.storageos.com)。
```yaml
apiVersion: v1
kind: Pod
metadata:
labels:
name: redis
role: master
name: test-storageos-redis
spec:
containers:
- name: master
image: kubernetes/redis:v1
env:
- name: MASTER
value: "true"
ports:
- containerPort: 6379
volumeMounts:
- mountPath: /redis-master-data
name: redis-data
volumes:
- name: redis-data
storageos:
# The `redis-vol01` volume must already exist within StorageOS in the `default` namespace.
volumeName: redis-vol01
fsType: ext4
```
### vsphereVolume
**先決條件**:配置了 vSphere Cloud Provider 的 Kubernetes。有關云提供商的配置,請參閱 [vSphere 入門指南](https://vmware.github.io/vsphere-storage-for-kubernetes/documentation/)。
`vsphereVolume` 用于將 vSphere VMDK 卷掛載到 Pod 中。卷的內容在卸載時會被保留。支持 VMFS 和 VSAN 數據存儲。
**重要提示**:在 Pod 中使用它之前,您必須使用以下一種方法創建 VMDK。
#### 創建 VMDK 卷
選擇以下方法之一來創建 VMDK。
首先進入 ESX,然后使用以下命令創建一個 VMDK:
```bash
vmkfstools -c 2G /vmfs/volumes/DatastoreName/volumes/myDisk.vmdk
```
使用下列命令創建一個 VMDK:
```bash
vmware-vdiskmanager -c -t 0 -s 40GB -a lsilogic myDisk.vmdk
```
#### vSphere VMDK 示例配置
```yaml
apiVersion: v1
kind: Pod
metadata:
name: test-vmdk
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-vmdk
name: test-volume
volumes:
- name: test-volume
# This VMDK volume must already exist.
vsphereVolume:
volumePath: "[DatastoreName] volumes/myDisk"
fsType: ext4
```
更多的例子可以在[這里](https://github.com/kubernetes/examples/tree/master/staging/volumes/vsphere)找到。
## 使用 subPath
有時,在單個容器中共享一個卷用于多個用途是有用的。`volumeMounts.subPath` 屬性可用于在引用的卷內而不是其根目錄中指定子路徑。
下面是一個使用單個共享卷的 LAMP 堆棧(Linux Apache Mysql PHP)的示例。 HTML 內容被映射到它的 html 目錄,數據庫將被存儲在它的 mysql 目錄中:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: my-lamp-site
spec:
containers:
- name: mysql
image: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: "rootpasswd"
volumeMounts:
- mountPath: /var/lib/mysql
name: site-data
subPath: mysql
- name: php
image: php:7.0-apache
volumeMounts:
- mountPath: /var/www/html
name: site-data
subPath: html
volumes:
- name: site-data
persistentVolumeClaim:
claimName: my-lamp-site-data
```
## 資源
`emptyDir` 卷的存儲介質(磁盤、SSD 等)由保存在 kubelet 根目錄的文件系統的介質(通常是 `/var/lib/kubelet`)決定。 `emptyDir` 或 `hostPath` 卷可占用多少空間并沒有限制,容器之間或 Pod 之間也沒有隔離。
在將來,我們預計 `emptyDir` 和 `hostPath` 卷將能夠使用 [resource](https://kubernetes.io/docs/user-guide/compute-resources) 規范請求一定的空間,并選擇要使用的介質,適用于具有多種媒體類型的集群。
## Out-of-Tree 卷插件
除了之前列出的卷類型之外,存儲供應商可以創建自定義插件而不將其添加到 Kubernetes 存儲庫中。可以通過使用 `FlexVolume` 插件來實現。
`FlexVolume`使用戶能夠將供應商卷掛載到容器中。供應商插件是使用驅動程序實現的,該驅動程序支持由 `FlexVolume` API定義的一系列卷命令。驅動程序必須安裝在每個節點的預定義卷插件路徑中。
更多細節可以在[這里](https://github.com/kubernetes/community/blob/master/contributors/devel/flexvolume.md)找到。
## 掛載傳播
**注意**:掛載傳播是 Kubernetes 1.8 中的一個 alpha 特性,在將來的版本中可能會重新設計甚至刪除。
掛載傳播允許將由容器掛載的卷共享到同一個 Pod 中的其他容器上,甚至是同一節點上的其他 Pod。
如果禁用 MountPropagation 功能,則不會傳播 pod 中的卷掛載。也就是說,容器按照 [Linux內核文檔](https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt)中所述的 `private` 掛載傳播運行。
要啟用此功能,請在 `--feature-gates` 命令行選項中指定 `MountPropagation = true`。啟用時,容器的 `volumeMounts` 字段有一個新的 `mountPropagation` 子字段。它的值為:
- `HostToContainer`:此卷掛載將接收所有后續掛載到此卷或其任何子目錄的掛載。這是 MountPropagation 功能啟用時的默認模式。
同樣的,如果任何帶有 `Bidirectional` 掛載傳播的 pod 掛載到同一個卷上,帶有 `HostToContainer` 掛載傳播的容器將會看到它。
該模式等同于[Linux內核文檔](https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt)中描述的 `rslave` 掛載傳播。
- `Bidirectional` 卷掛載與 `HostToContainer` 掛載相同。另外,由容器創建的所有卷掛載將被傳播回主機和所有使用相同卷的容器的所有容器。
此模式的一個典型用例是帶有 Flex 卷驅動器或需要使用 HostPath 卷在主機上掛載某些內容的 pod。
該模式等同于 [Linux內核文檔](https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt)中所述的 `rshared` 掛載傳播。
**小心**:雙向掛載傳播可能是危險的。它可能會損壞主機操作系統,因此只能在特權容器中使用。強烈建議熟悉 Linux 內核行為。另外,容器在 Pod 中創建的任何卷掛載必須在容器終止時銷毀(卸載)。
## 參考
- https://kubernetes.io/docs/concepts/storage/volumes/
- [使用持久化卷來部署 WordPress 和 MySQL](https://kubernetes.io/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/)
- 序言
- 云原生
- 云原生(Cloud Native)的定義
- CNCF - 云原生計算基金會簡介
- CNCF章程
- 云原生的設計哲學
- Play with Kubernetes
- 快速部署一個云原生本地實驗環境
- Kubernetes與云原生應用概覽
- 云原生應用之路——從Kubernetes到Cloud Native
- 云原生編程語言
- 云原生編程語言Ballerina
- 云原生編程語言Pulumi
- 云原生的未來
- Kubernetes架構
- 設計理念
- Etcd解析
- 開放接口
- CRI - Container Runtime Interface(容器運行時接口)
- CNI - Container Network Interface(容器網絡接口)
- CSI - Container Storage Interface(容器存儲接口)
- Kubernetes中的網絡
- Kubernetes中的網絡解析——以flannel為例
- Kubernetes中的網絡解析——以calico為例
- 具備API感知的網絡和安全性管理開源軟件Cilium
- Cilium架構設計與概念解析
- 資源對象與基本概念解析
- Pod狀態與生命周期管理
- Pod概覽
- Pod解析
- Init容器
- Pause容器
- Pod安全策略
- Pod的生命周期
- Pod Hook
- Pod Preset
- Pod中斷與PDB(Pod中斷預算)
- 集群資源管理
- Node
- Namespace
- Label
- Annotation
- Taint和Toleration(污點和容忍)
- 垃圾收集
- 控制器
- Deployment
- StatefulSet
- DaemonSet
- ReplicationController和ReplicaSet
- Job
- CronJob
- Horizontal Pod Autoscaling
- 自定義指標HPA
- 準入控制器(Admission Controller)
- 服務發現
- Service
- Ingress
- Traefik Ingress Controller
- 身份與權限控制
- ServiceAccount
- RBAC——基于角色的訪問控制
- NetworkPolicy
- 存儲
- Secret
- ConfigMap
- ConfigMap的熱更新
- Volume
- Persistent Volume(持久化卷)
- Storage Class
- 本地持久化存儲
- 集群擴展
- 使用自定義資源擴展API
- 使用CRD擴展Kubernetes API
- Aggregated API Server
- APIService
- Service Catalog
- 資源調度
- QoS(服務質量等級)
- 用戶指南
- 資源對象配置
- 配置Pod的liveness和readiness探針
- 配置Pod的Service Account
- Secret配置
- 管理namespace中的資源配額
- 命令使用
- Docker用戶過度到kubectl命令行指南
- kubectl命令概覽
- kubectl命令技巧大全
- 使用etcdctl訪問kubernetes數據
- 集群安全性管理
- 管理集群中的TLS
- kubelet的認證授權
- TLS bootstrap
- 創建用戶認證授權的kubeconfig文件
- IP偽裝代理
- 使用kubeconfig或token進行用戶身份認證
- Kubernetes中的用戶與身份認證授權
- Kubernetes集群安全性配置最佳實踐
- 訪問Kubernetes集群
- 訪問集群
- 使用kubeconfig文件配置跨集群認證
- 通過端口轉發訪問集群中的應用程序
- 使用service訪問群集中的應用程序
- 從外部訪問Kubernetes中的Pod
- Cabin - Kubernetes手機客戶端
- Kubernetic - Kubernetes桌面客戶端
- Kubernator - 更底層的Kubernetes UI
- 在Kubernetes中開發部署應用
- 適用于kubernetes的應用開發部署流程
- 遷移傳統應用到Kubernetes中——以Hadoop YARN為例
- 最佳實踐概覽
- 在CentOS上部署Kubernetes集群
- 創建TLS證書和秘鑰
- 創建kubeconfig文件
- 創建高可用etcd集群
- 安裝kubectl命令行工具
- 部署master節點
- 安裝flannel網絡插件
- 部署node節點
- 安裝kubedns插件
- 安裝dashboard插件
- 安裝heapster插件
- 安裝EFK插件
- 生產級的Kubernetes簡化管理工具kubeadm
- 使用kubeadm在Ubuntu Server 16.04上快速構建測試集群
- 服務發現與負載均衡
- 安裝Traefik ingress
- 分布式負載測試
- 網絡和集群性能測試
- 邊緣節點配置
- 安裝Nginx ingress
- 安裝配置DNS
- 安裝配置Kube-dns
- 安裝配置CoreDNS
- 運維管理
- Master節點高可用
- 服務滾動升級
- 應用日志收集
- 配置最佳實踐
- 集群及應用監控
- 數據持久化問題
- 管理容器的計算資源
- 集群聯邦
- 存儲管理
- GlusterFS
- 使用GlusterFS做持久化存儲
- 使用Heketi作為Kubernetes的持久存儲GlusterFS的external provisioner
- 在OpenShift中使用GlusterFS做持久化存儲
- GlusterD-2.0
- Ceph
- 用Helm托管安裝Ceph集群并提供后端存儲
- 使用Ceph做持久化存儲
- 使用rbd-provisioner提供rbd持久化存儲
- OpenEBS
- 使用OpenEBS做持久化存儲
- Rook
- NFS
- 利用NFS動態提供Kubernetes后端存儲卷
- 集群與應用監控
- Heapster
- 使用Heapster獲取集群和對象的metric數據
- Prometheus
- 使用Prometheus監控kubernetes集群
- Prometheus查詢語言PromQL使用說明
- 使用Vistio監控Istio服務網格中的流量
- 分布式跟蹤
- OpenTracing
- 服務編排管理
- 使用Helm管理Kubernetes應用
- 構建私有Chart倉庫
- 持續集成與發布
- 使用Jenkins進行持續集成與發布
- 使用Drone進行持續集成與發布
- 更新與升級
- 手動升級Kubernetes集群
- 升級dashboard
- 領域應用概覽
- 微服務架構
- 微服務中的服務發現
- 使用Java構建微服務并發布到Kubernetes平臺
- Spring Boot快速開始指南
- Service Mesh 服務網格
- 企業級服務網格架構
- Service Mesh基礎
- Service Mesh技術對比
- 采納和演進
- 定制和集成
- 總結
- Istio
- 安裝并試用Istio service mesh
- 配置請求的路由規則
- 安裝和拓展Istio service mesh
- 集成虛擬機
- Istio中sidecar的注入規范及示例
- 如何參與Istio社區及注意事項
- Istio教程
- Istio免費學習資源匯總
- 深入理解Istio Service Mesh中的Envoy Sidecar注入與流量劫持
- 深入理解Istio Service Mesh中的Envoy Sidecar代理的路由轉發
- Linkerd
- Linkerd 使用指南
- Conduit
- Condiut概覽
- 安裝Conduit
- Envoy
- Envoy的架構與基本術語
- Envoy作為前端代理
- Envoy mesh教程
- SOFAMesh
- SOFAMesh中的Dubbo on x-protocol
- SOFAMosn
- 使用 SOFAMosn 構建 SOFAMesh
- 大數據
- Spark standalone on Kubernetes
- 運行支持Kubernetes原生調度的Spark程序
- Serverless架構
- 理解Serverless
- FaaS-函數即服務
- OpenFaaS快速入門指南
- 邊緣計算
- 人工智能