因爲容器自己是非持久化的,所以須要解決在容器中運行應用程序遇到的一些問題。首先,當容器崩潰時,kubelet將從新啓動容器,可是寫入容器的文件將會丟失,容器將會以鏡像的初始狀態從新開始;第二,在經過一個Pod中一塊兒運行的容器,一般須要共享容器之間一些文件。Kubernetes經過存儲卷解決上述的兩個問題。php
在Docker有存儲卷的概念卷,但Docker中存儲卷只是磁盤的或另外一個容器中的目錄,並無對其生命週期進行管理。Kubernetes的存儲卷有本身的生命週期,它的生命週期與使用的它Pod生命週期一致。所以,相比於在Pod中運行的容器來講,存儲卷的存在時間會比的其中的任何容器都長,而且在容器從新啓動時會保留數據。固然,當Pod中止存在時,存儲卷也將再也不存在。在Kubernetes支持多種類型的卷,而Pod能夠同時使用各類類型和任意數量的存儲卷。html
在Pod中經過指定下面的字段來使用存儲卷:mysql
emptyDir類型的Volume在Pod分配到Node上時被建立,Kubernetes會在Node上自動分配一個目錄,所以無需指定宿主機Node上對應的目錄文件。 這個目錄的初始內容爲空,當Pod從Node上移除時,emptyDir中的數據會被永久刪除。web
emptyDir Volume主要用於某些應用程序無需永久保存的臨時目錄,多個容器的共享目錄等。redis
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類型的存儲卷用於將宿主機的文件系統的文件或目錄掛接到Pod中,除了須要指定path字段以外,在使用hostPath類型的存儲卷時,也能夠設置type,type支持的枚舉值由下表。另外在使用hostPath時,sql
須要注意下面的事項:docker
值 | 行爲 |
---|---|
空字符串(默認)是用於向後兼容,這意味着在掛接主機路徑存儲卷以前不執行任何檢查。 | |
DirectoryOrCreate |
若是path指定目錄不存在,則會在宿主機上建立一個新的目錄,並設置目錄權限爲0755,此目錄與kubelet擁有同樣的組和擁有者。 |
Directory |
path指定的目標必需存在 |
FileOrCreate |
若是path指定的文件不存在,則會在宿主機上建立一個空的文件,設置權限爲0644,此文件與kubelet擁有同樣的組和擁有者。 |
File |
path指定的文件必需存在 |
Socket |
path指定的UNIX socket必需存在 |
CharDevice |
path指定的字符設備必需存在 |
BlockDevice |
在path給定路徑上必須存在塊設備。 |
下面是使用hostPath做爲存儲卷的YAML文件,此YAML文件定義了一個名稱爲test-pd的Pod資源。它經過hostPath類型的存儲卷,將Pod宿主機上的/data掛接到容器中的/teset-pd目錄。數據庫
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: # 宿主機上的目錄 path: /data # this field is optional type: Directory
在Kubernetes中,能夠經過nfs類型的存儲卷將現有的NFS(網絡文件系統)到的掛接到Pod中。在移除Pod時,NFS存儲卷中的內容被不會被刪除,只是將存儲卷卸載而已。這意味着在NFS存儲卷總能夠預先填充數據,而且能夠在Pod之間共享數據。NFS能夠被同時掛接到多個Pod中,並能同時進行寫入。須要注意的是:在使用nfs存儲卷以前,必須已正確部署和運行NFS服務器,並已經設置了共享目錄。api
下面是一個redis部署的YAML配置文件,redis在容器中的持久化數據保存在/data目錄下;存儲卷使用nfs,nfs的服務地址爲:192.168.8.150,存儲路徑爲:/k8s-nfs/redis/data。容器經過volumeMounts.name的值肯定所使用的存儲卷安全
# for versions before 1.9.0 use apps/v1beta2 apiVersion: apps/v1 kind: Deployment metadata: name: redis spec: selector: matchLabels: app: redis revisionHistoryLimit: 2 template: metadata: labels: app: redis spec: containers: # 應用的鏡像 - image: redis name: redis imagePullPolicy: IfNotPresent # 應用的內部端口 ports: - containerPort: 6379 name: redis6379 env: - name: ALLOW_EMPTY_PASSWORD value: "yes" - name: REDIS_PASSWORD value: "redis" # 持久化掛接位置,在docker中 volumeMounts: - name: redis-persistent-storage mountPath: /data volumes: # 宿主機上的目錄 - name: redis-persistent-storage nfs: path: /k8s-nfs/redis/data server: 192.168.8.150
persistentVolumeClaim類型存儲卷將PersistentVolume掛接到Pod中做爲存儲卷。使用此類型的存儲卷,用戶並不知道存儲卷的詳細信息。
此處定義名爲busybox-deployment的部署YAML配置文件,使用的鏡像爲busybox。基於busybox鏡像的容器須要對/mnt目錄下的數據進行持久化,在YAML文件指定使用名稱爲nfs的PersistenVolumeClaim對容器的數據進行持久化。
# This mounts the nfs volume claim into /mnt and continuously # overwrites /mnt/index.html with the time and hostname of the pod. apiVersion: v1 kind: Deployment metadata: name: busybox-deployment spec: replicas: 2 selector: name: busybox-deployment template: metadata: labels: name: busybox-deployment spec: containers: - image: busybox command: - sh - -c - 'while true; do date > /mnt/index.html; hostname >> /mnt/index.html; sleep $(($RANDOM % 5 + 5)); done' imagePullPolicy: IfNotPresent name: busybox volumeMounts: # name must match the volume name below - name: nfs mountPath: "/mnt" volumes: - name: nfs persistentVolumeClaim: claimName: nfs-pvc
有時,能夠在一個pod中,將同一個卷共享,使其有多個用處。volumeMounts.subPath
特性能夠用來指定卷中的一個子目錄,而不是直接使用卷的根目錄。
這裏有一個使用LAMP棧(Linux Apache Mysql PHP)的pod示例,該pod使用了一個共享的卷。HTML內容映射在它的html子目錄,而數據庫則保存在它的mysql目錄
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
Kubemetes提供了Secret來處理敏感數據,好比密碼、Token和密鑰,相比於直接將敏感數據配置在Pod的定義或者鏡像中,Secret提供了更加安全的機制(Base64加密),防止數據泄露。Secret的建立是獨立於Pod的,以數據卷的形式掛載到Pod中,Secret的數據將以文件的形式保存,容器經過讀取文件能夠獲取須要的數據。
yaml示例以下:
apiVersion: v1 kind: Secret metadata: name: mysecret type: Opaque data: username: emhlbnl1 password: eWFvZGlkaWFv -- apiVersion: v1 kind: Pod metadata: labels: name: test-secret role: master name: test-secret spec: containers: - name: test-secret image: registry:5000/back_demon:1.0 volumeMounts: - name: secret mountPath: /home/laizy/secret readOnly: true command: - /run.sh volumes: - name: secret secret: secretName: mysecret