容器中的磁盤文件生命週期比較短暫,在一些比較複雜的容器應用中會產生一些問題。1、容器crash後,kubelet會重啓該容器,但這些文件會丟失掉。2、pod中的多個容器常常須要共享文件。所以,Kubernetes的Volume應然而生,用於解決這些問題。php
在Docker中,也有volumes這個概念,volume只是磁盤上一個簡單的目錄,或者其餘容器中的volume。生命週期也不受管理,而且直到最近他們都是基於本地後端存儲的。Docker如今也提供了volume driver,可是如今來講功能也較弱(好比官網提到的Ceph volume driver,如今已經沒有維護了)。
Kubernetes的volume,有着明顯的生命週期——和使用它的pod生命週期一致。所以,volume生命週期就比運行在pod中的容器要長久,即便容器重啓,volume上的數據依然保存着。固然,pod再也不存在時,volume也就消失了。更重要的是,Kubernetes支持多種類型的volume,而且pod能夠同時使用多種類型的volume。
內部實現中,volume只是一個目錄,目錄中可能有一些數據,pod的容器能夠訪問這些數據。這個目錄是如何產生的,它後端基於什麼存儲介質,其中的數據內容是什麼,這些都由使用的特定volume類型來決定。
要使用volume,pod須要指定volume的類型和內容(spec.volumes
字段),和映射到容器的位置(spec.containers.volumeMounts
字段)。
容器中的進程能夠看到Docker image和volumes組成的文件系統。Docker image處於文件系統架構的root,任何volume都映射在鏡像的特定路徑上。Volume不能映射到其餘volume上,或者硬連接到其餘volume。容器中的每一個容器必須堵路地指定他們要映射的volume。html
Kubernetes支持不少種類的volume,包括:emptyDir、hostPath、gcePersistentDisk、awsElasticBlockStore、nfs、iscsi、flocker、glusterfs、rbd、cephfs、gitRepo、secret、persistentVolumeClaim、downwardAPI、azureFileVolume、azureDisk、vsphereVolume、Quobyte、PortworxVolume、ScaleIO。node
當Pod被分配到一個Node上時,emptyDir
volume就第一次被建立,只要Pod還運行在該Node上,該volume就一直存在。就像它名字裏介紹的同樣,它初始化時是空的。pod中的容器都可以徹底讀寫emptyDir
volume中相同文件,即便volume可能被映射到每一個容器中不一樣的路徑下。任何狀況下,一旦pod從該Node上移除了,emptyDir
volume中的數據就被永久刪除了。注意:容器crash並不會在Node上刪除pod,所以emptyDir
volume中的數據依然是安全的。
emptyDir
volume的使用場景有:
1) 臨時空間,如基於磁盤的排序場景等;
2) 從crash中經過checkpointing作長時間的計算恢復;
默認的,emptyDir
volume能夠存儲在任何後端介質之上——普通磁盤、ssd或網絡存儲,這都取決於你的環境。然而,你也能夠設置emptyDir.medium
字段爲Memory
,告訴Kubernetes映射tmpfs(基於RAM的文件系統)。tmpfs速度很是快,但要當心它和磁盤不一樣,一旦機器重啓,tmpfs就會被清空,而且,tmpfs上寫文件會受到容器內存的限制。
pod示例:mysql
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
volume映射node文件系統中的文件或者目錄到pod裏。大多數Pod都不須要這個功能,但對於一些特定的場景,該特性仍是頗有做用的。這些場景包括:
1) 運行的容器須要訪問Docker內部結構:使用hostPath
映射/var/lib/docker
2) 在容器中運行cAdvisor,使用hostPath
映射/dev/cgroups
不過,使用這種volume要當心,由於:
1) 配置相同的pod(如經過podTemplate建立),可能在不一樣的Node上表現不一樣,由於不一樣節點上映射的文件內容不一樣
2) 當Kubernetes增長了資源敏感的調度程序,hostPath
使用的資源不會被計算在內
3) 宿主機下建立的目錄只有root有寫權限。你須要讓你的程序運行在privileged container上,或者修改宿主機上的文件權限。
pod示例:git
apiVersion: v1 kind: Pod metadata: name: test-pd spec: 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
rbd
卷能夠將Rados Block Device設備映射到pod中。當Pod被移除時,emptyDir
卷的內容會被清空,和emptyDir
不一樣,rbd
卷的內容還存在着,僅僅是卷被卸載掉而已。也就是說,rbd
卷能夠其上的數據一塊兒,再次被映射,數據也能夠在pod之間傳遞。
重要:在使用rbd
卷以前,你必須先安裝Ceph環境。
RBD的一個特性就是可以以只讀的方式同時映射給多個用戶使用。不幸的是,rbd
卷只能被一個用戶已可讀寫的模式映射——不能同時容許多個可寫的用戶使用。
查看RBD example獲取更多細節。github
cephfs
卷能夠將已經存在的CephFS卷映射到pod中。與rbd
卷相同,當pod被移除時,cephfs
卷的內容還存在着,僅僅是卷被卸載掉而已。另一點不一樣的是,CephFS能夠同時以可讀寫的方式映射給多個用戶。
查看CephFS example獲取更多細節。web
有時,能夠在一個pod中,將同一個卷共享,使其有多個用處。volumeMounts.subPath
特性能夠用來指定卷中的一個子目錄,而不是直接使用卷的根目錄。
這裏有一個使用LAMP棧(Linux Apache Mysql PHP)的pod示例,該pod使用了一個共享的卷。HTML內容映射在它的html
子目錄,而數據庫則保存在它的mysql
目錄。sql
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
emptyDir
或者hostPath
卷的存儲介質(磁盤,SSD等)取決於kubelet根目錄(如/var/lib/kubelet
)所處文件系統的存儲介質。如今沒有限制emptyDir
或者hostPath
卷能使用的空間大小,也沒有對容器或者pod的資源隔離。
將來,咱們指望emptyDir
或者hostPath
卷可以經過resource屬性,來請求指定大小的空間,而且選擇存儲介質類型。docker
Kubernetes的volume用於pod內部的數據存儲,pod容器內部數據是能夠共享的,其生命週期與所屬pod生命週期相同。其用處通常是pod生命週期的臨時數據存儲等。數據庫