中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

k8s之數據存儲

發布時間:2020-07-20 09:57:01 來源:網絡 閱讀:337 作者:wuseeger 欄目:云計算
Kubernetes 如何管理存儲資源。

首先我們會學習 Volume,以及 Kubernetes 如何通過 Volume 為集群中的容器提供存儲;然后我們會實踐幾種常用的 Volume 類型并理解它們各自的應用場景;最后,我們會討論 Kubernetes 如何通過 Persistent Volume 和 Persistent Volume Claim 分離集群管理員與集群用戶的職責,并實踐 Volume 的靜態供給和動態供給。

Volume

本節我們討論 Kubernetes 的存儲模型 Volume,學習如何將各種持久化存儲映射到容器。

我們經常會說:容器和 Pod 是短暫的。
其含義是它們的生命周期可能很短,會被頻繁地銷毀和創建。容器銷毀時,保存在容器內部文件系統中的數據都會被清除。

為了持久化保存容器的數據,可以使用 Kubernetes Volume。

Volume 的生命周期獨立于容器,Pod 中的容器可能被銷毀和重建,但 Volume 會被保留。

本質上,Kubernetes Volume 是一個目錄,這一點與 Docker Volume 類似。當 Volume 被 mount 到 Pod,Pod 中的所有容器都可以訪問這個 Volume。Kubernetes Volume 也支持多種 backend 類型,包括 emptyDir、hostPath、GCE Persistent Disk、AWS Elastic Block Store、NFS、Ceph 等,完整列表可參考 https://kubernetes.io/docs/concepts/storage/volumes/#types-of-volumes

Volume 提供了對各種 backend 的抽象,容器在使用 Volume 讀寫數據的時候不需要關心數據到底是存放在本地節點的文件系統中呢還是云硬盤上。對它來說,所有類型的 Volume 都只是一個目錄。

我們將從最簡單的 emptyDir 開始學習 Kubernetes Volume。

emptyDir

emptyDir 是最基礎的 Volume 類型。正如其名字所示,一個 emptyDir Volume 是 Host 上的一個空目錄。

emptyDir Volume 對于容器來說是持久的,對于 Pod 則不是。當 Pod 從節點刪除時,Volume 的內容也會被刪除。但如果只是容器被銷毀而 Pod 還在,則 Volume 不受影響。

也就是說:emptyDir Volume 的生命周期與 Pod 一致。

Pod 中的所有容器都可以共享 Volume,它們可以指定各自的 mount 路徑。下面通過例子來實踐 emptyDir,配置文件如下:

apiVersion: v1
kind: Pod
metadata:
  name: producer-consumer
spec:
  containers:
  - image: busybox
    name: producer
    volumeMounts:
    - mountPath: /producer_dir
      name: shared-volume
    args:
    - /bin/sh
    - -c
    - echo "hello world"> /producer_dir/hello ; sleep 30000

  - image: busybox
    name: consumer
    volumeMounts:
    - mountPath: /consumer_dir
      name: shared-volume
    args:
    - /bin/sh
    - -c
    - cat /consumer_dir/hello ; sleep 30000

  volumes:
  - name: shared-volume
    emptyDir: {}

這里我們模擬了一個 producer-consumer 場景。Pod 有兩個容器 producer和 consumer,它們共享一個 Volume。producer 負責往 Volume 中寫數據,consumer 則是從 Volume 讀取數據。

① 文件最底部 volumes 定義了一個 emptyDir 類型的 Volume shared-volume。

② producer 容器將 shared-volume mount 到 /producer_dir 目錄。

③ producer 通過 echo 將數據寫到文件 hello 里。

④ consumer 容器將 shared-volume mount 到 /consumer_dir 目錄。

⑤ consumer 通過 cat 從文件 hello 讀數據。

執行如下命令創建 Pod:

# kubectl apply -f emptyDir.yaml
pod/producer-consumer created

# kubectl get pod
NAME                READY   STATUS    RESTARTS   AGE
producer-consumer   2/2     Running   0          87s

# kubectl logs producer-consumer consumer 
hello world

kubectl logs 顯示容器 consumer 成功讀到了 producer 寫入的數據,驗證了兩個容器共享 emptyDir Volume。

因為 emptyDir 是 Docker Host 文件系統里的目錄,其效果相當于執行了 docker run -v /producer_dir 和 docker run -v /consumer_dir。通過 docker inspect 查看容器的詳細配置信息,我們發現兩個容器都 mount 了同一個目錄:

 {
                "Type": "bind",
                "Source": "/var/lib/kubelet/pods/188767a3-cf18-4bf9-a89b-b0c4cf4124bb/volumes/kubernetes.io~empty-dir/shared-volume",
                "Destination": "/consumer_dir",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }

"Mounts": [
            {
                "Type": "bind",
                "Source": "/var/lib/kubelet/pods/188767a3-cf18-4bf9-a89b-b0c4cf4124bb/volumes/kubernetes.io~empty-dir/shared-volume",
                "Destination": "/producer_dir",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            },

這里 /var/lib/kubelet/pods/3e6100eb-a97a-11e7-8f72-0800274451ad/volumes/kubernetes.io~empty-dir/shared-volume 就是 emptyDir 在 Host 上的真正路徑。

emptyDir 是 Host 上創建的臨時目錄,其優點是能夠方便地為 Pod 中的容器提供共享存儲,不需要額外的配置。但它不具備持久性,如果 Pod 不存在了,emptyDir 也就沒有了。根據這個特性,emptyDir 特別適合 Pod 中的容器需要臨時共享存儲空間的場景,比如前面的生產者消費者用例。

hostPath Volume。

hostPath Volume 的作用是將 Docker Host 文件系統中已經存在的目錄 mount 給 Pod 的容器。大部分應用都不會使用 hostPath Volume,因為這實際上增加了 Pod 與節點的耦合,限制了 Pod 的使用。不過那些需要訪問 Kubernetes 或 Docker 內部數據(配置文件和二進制庫)的應用則需要使用 hostPath。

比如 kube-apiserver 和 kube-controller-manager 就是這樣的應用,通過

kubectl edit --namespace=kube-system pod kube-apiserver-k8s-master
查看 kube-apiserver Pod 的配置,下面是 Volume 的相關部分:

   volumeMounts:
    - mountPath: /etc/ssl/certs
      name: ca-certs
      readOnly: true
    - mountPath: /etc/pki
      name: etc-pki
      readOnly: true
    - mountPath: /etc/kubernetes/pki
      name: k8s-certs
      readOnly: true

  volumes:
  - hostPath:
      path: /etc/ssl/certs
      type: DirectoryOrCreate
    name: ca-certs
  - hostPath:
      path: /etc/pki
      type: DirectoryOrCreate
    name: etc-pki
  - hostPath:
      path: /etc/kubernetes/pki
      type: DirectoryOrCreate
    name: k8s-certs

這里定義了三個 hostPath volume k8s、certs 和 pki,分別對應 Host 目錄 /etc/kubernetes、/etc/ssl/certs 和 /etc/pki。

如果 Pod 被銷毀了,hostPath 對應的目錄也還會被保留,從這點看,hostPath 的持久性比 emptyDir 強。不過一旦 Host 崩潰,hostPath 也就沒法訪問了。

真正持久性的 Volume。

外部 Storage Provider

如果 Kubernetes 部署在諸如 AWS、GCE、Azure 等公有云上,可以直接使用云硬盤作為 Volume,下面是 AWS Elastic Block Store 的例子:

要在 Pod 中使用 ESB volume,必須先在 AWS 中創建,然后通過 volume-id 引用。其他云硬盤的使用方法可參考各公有云廠商的官方文檔。

Kubernetes Volume 也可以使用主流的分布式存,比如 Ceph、GlusterFS 等,下面是 Ceph 的例子:

Ceph的 /some/path/in/side/cephfs 目錄被 mount 到容器路徑 /test-ceph。

相對于 emptyDir 和 hostPath,這些 Volume 類型的最大特點就是不依賴 Kubernetes。Volume 的底層基礎設施由獨立的存儲系統管理,與 Kubernetes 集群是分離的。數據被持久化后,即使整個 Kubernetes 崩潰也不會受損。

當然,運維這樣的存儲系統通常不是項簡單的工作,特別是對可靠性、高可用和擴展性有較高要求時。

Volume 提供了非常好的數據持久化方案,不過在可管理性上還有不足。下一節我們將學習具有更高管理性的存儲方案:PersistentVolume & PersistentVolumeClaim。

PV & PVC

Volume 提供了非常好的數據持久化方案,不過在可管理性上還有不足。

拿前面 AWS EBS 的例子來說,要使用 Volume,Pod 必須事先知道如下信息:

  • 當前 Volume 來自 AWS EBS。
  • EBS Volume 已經提前創建,并且知道確切的 volume-id。

Pod 通常是由應用的開發人員維護,而 Volume 則通常是由存儲系統的管理員維護。開發人員要獲得上面的信息:

  • 要么詢問管理員。
  • 要么自己就是管理員。

這樣就帶來一個管理上的問題:應用開發人員和系統管理員的職責耦合在一起了。如果系統規模較小或者對于開發環境這樣的情況還可以接受。但當集群規模變大,特別是對于生成環境,考慮到效率和安全性,這就成了必須要解決的問題。

Kubernetes 給出的解決方案是 PersistentVolume 和 PersistentVolumeClaim。

PersistentVolume (PV) 是外部存儲系統中的一塊存儲空間,由管理員創建和維護。與 Volume 一樣,PV 具有持久性,生命周期獨立于 Pod。

PersistentVolumeClaim (PVC) 是對 PV 的申請 (Claim)。PVC 通常由普通用戶創建和維護。需要為 Pod 分配存儲資源時,用戶可以創建一個 PVC,指明存儲資源的容量大小和訪問模式(比如只讀)等信息,Kubernetes 會查找并提供滿足條件的 PV。

有了 PersistentVolumeClaim,用戶只需要告訴 Kubernetes 需要什么樣的存儲資源,而不必關心真正的空間從哪里分配,如何訪問等底層細節信息。這些 Storage Provider 的底層信息交給管理員來處理,只有管理員才應該關心創建 PersistentVolume 的細節信息。

Kubernetes 支持多種類型的 PersistentVolume,比如 AWS EBS、Ceph、NFS 等,完整列表請參考 https://kubernetes.io/docs/concepts/storage/persistent-volumes/#types-of-persistent-volumes

NFS PersistentVolume

通過 NFS 實踐PV和PVC。

作為準備工作,我們已經在 k8s-master 節點上搭建了一個 NFS 服務器,目錄為 /nfsdata:

[root@k8s-master ~]# showmount -e
Export list for k8s-master:
/nfsdata 192.168.168.0/24

下面創建一個 PV mypv1,配置文件 nfs-pv1.yml 如下:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mypv1
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /nfsdata/pv1
    server: 192.168.168.10

① capacity 指定 PV 的容量為 1G。

② accessModes 指定訪問模式為 ReadWriteOnce,支持的訪問模式有:
ReadWriteOnce – PV 能以 read-write 模式 mount 到單個節點。
ReadOnlyMany – PV 能以 read-only 模式 mount 到多個節點。
ReadWriteMany – PV 能以 read-write 模式 mount 到多個節點。

③ persistentVolumeReclaimPolicy 指定當 PV 的回收策略為 Recycle,支持的策略有:
Retain – 需要管理員手工回收。
Recycle – 清除 PV 中的數據,效果相當于執行 rm -rf /thevolume/*。
Delete – 刪除 Storage Provider 上的對應存儲資源,例如 AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume 等。

④ storageClassName 指定 PV 的 class 為 nfs。相當于為 PV 設置了一個分類,PVC 可以指定 class 申請相應 class 的 PV。

⑤ 指定 PV 在 NFS 服務器上對應的目錄。

創建 mypv1:

[root@k8s-master ~]# kubectl apply -f nfs-pv1.yml 
persistentvolume/mypv1 created
[root@k8s-master ~]# kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
mypv1   1Gi        RWO            Recycle          Available           nfs                     7s

STATUS 為 Available,表示 mypv1 就緒,可以被 PVC 申請。

接下來創建 PVC mypvc1,配置文件 nfs-pvc1.yml 如下:

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: mypvc1
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: nfs

PVC 就很簡單了,只需要指定 PV 的容量,訪問模式和 class。

創建 mypvc1:

[root@k8s-master ~]# kubectl apply -f nfs-pvc1.yml 
persistentvolumeclaim/mypvc1 created
[root@k8s-master ~]# kubectl get pvc
NAME     STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mypvc1   Bound    mypv1    1Gi        RWO            nfs            6s
[root@k8s-master ~]# kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM            STORAGECLASS   REASON   AGE
mypv1   1Gi        RWO            Recycle          Bound    default/mypvc1   nfs                     2m18s
[root@k8s-master ~]# 

從 kubectl get pvc 和 kubectl get pv 的輸出可以看到 mypvc1 已經 Bound 到 mypv1,申請成功。

接下來就可以在 Pod 中使用存儲了,Pod 配置文件 pod1.yml 如下:

kind: Pod
apiVersion: v1
metadata:
  name: mypod1
spec:
  containers:
    - name: mypod1
      image: busybox
      args:
      - /bin/sh
      - -c
      - sleep 30000
      volumeMounts:
      - mountPath: "/mydata"
        name: mydata
  volumes:
    - name: mydata
      persistentVolumeClaim:
        claimName: mypvc1

與使用普通 Volume 的格式類似,在 volumes 中通過 persistentVolumeClaim 指定使用 mypvc1 申請的 Volume。

創建 mypod1:

[root@k8s-master ~]# kubectl apply -f pod1.yml
pod/mypod1 created

[root@k8s-master ~]# kubectl get pod -o wide     
NAME     READY   STATUS    RESTARTS   AGE     IP           NODE        NOMINATED NODE   READINESS GATES
mypod1   1/1     Running   0          3m19s   10.244.1.2   k8s-node1   <none>           <none>

驗證 PV 是否可用:

[root@k8s-master ~]# kubectl exec mypod1 touch /mydata/hello
[root@k8s-master ~]# ll /nfsdata/pv1/
total 0
-rw-r--r-- 1 root root 0 Oct 12 16:36 hello

可見,在 Pod 中創建的文件 /mydata/hello 確實已經保存到了 NFS 服務器目錄 /nfsdata/pv1 中。

如果不再需要使用 PV,可用刪除 PVC 回收 PV。

MySQL 如何使用 PV 和 PVC?

本節演示如何為 MySQL 數據庫提供持久化存儲,步驟為:

創建 PV 和 PVC。

部署 MySQL。

向 MySQL 添加數據。

模擬節點宕機故障,Kubernetes 將 MySQL 自動遷移到其他節點。

驗證數據一致性。

首先創建 PV 和 PVC,配置如下:

mysql-pv.yml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv
spec:
  accessModes:
    - ReadWriteOnce
  capacity:
    storage: 1Gi
  persistentVolumeReclaimPolicy: Retain
  storageClassName: nfs
  nfs:
    path: /nfsdata/mysql-pv
    server: 192.168.77.10

mysql-pvc.yml

kind: PersistentVolumeClaim
apiVersion: v1
metadata: 
  name: mysql-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: nfs

創建 mysql-pv 和 mysql-pvc:

接下來部署 MySQL,配置文件如下:

apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  ports:
  - port: 3306
  selector:
    app: mysql

---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - image: mysql:5.6
        name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: password
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pvc  

PVC mysql-pvc Bound 的 PV mysql-pv 將被 mount 到 MySQL 的數據目錄 var/lib/mysql。

MySQL 被部署到 k8s-node2,下面通過客戶端訪問 Service mysql:

# kubectl run -it --rm --image=mysql:5.6 --restart=Never mysql-client -- mysql -h mysql -ppassword 

更新數據庫:

[root@k8s-master ~]# kubectl run -it --rm --image=mysql:5.6 --restart=Never mysql-client -- mysql -h mysql -ppassword
If you don't see a command prompt, try pressing enter.

mysql> use mysql 
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> create table my_id(id int(4));
Query OK, 0 rows affected (0.09 sec)

mysql> insert into my_id values(111);
Query OK, 1 row affected (0.00 sec)

mysql> select * from my_id;
+------+
| id   |
+------+
|  111 |
+------+
1 row in set (0.00 sec)

① 切換到數據庫 mysql。

② 創建數據庫表 my_id。

③ 插入一條數據。

④ 確認數據已經寫入。

關閉 k8s-node2,模擬節點宕機故障。

# systemctl poweroff 

一段時間后,Kubernetes 將 MySQL 遷移到 k8s-node1。

[root@k8s-master ~]# kubectl get pod
NAME                     READY   STATUS        RESTARTS   AGE
mysql-84bdf65dd5-bjz8b   1/1     Terminating   0          22m
mysql-84bdf65dd5-ddlhc   1/1     Running       0          34s

驗證數據的一致性:

[root@k8s-master ~]# kubectl run -it --rm --image=mysql:5.6 --restart=Never mysql-client -- mysql -h mysql -ppassword           If you don't see a command prompt, try pressing enter.

mysql> use mysql
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed

mysql> select * from my_id;
+------+
| id   |
+------+
|  111 |
+------+
1 row in set (0.01 sec)

mysql> quit

MySQL 服務恢復,數據也完好無損。

emptyDir 和 hostPath 類型的 Volume 很方便,但可持久性不強,Kubernetes 支持多種外部存儲系統的 Volume。

PV 和 PVC 分離了管理員和普通用戶的職責,更適合生產環境。。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

仁布县| 嫩江县| 襄城县| 西城区| 鹤壁市| 开原市| 秦皇岛市| 大理市| 丹江口市| 广丰县| 隆化县| 图木舒克市| 寿阳县| 松潘县| 罗城| 谷城县| 兴义市| 长兴县| 柞水县| 肃北| 桃源县| 彭阳县| 汤原县| 尉氏县| 怀化市| 巫山县| 广宁县| 新安县| 襄城县| 上犹县| 宝清县| 吉林市| 泾阳县| 巩义市| 大名县| 镇巴县| 建平县| 犍为县| 德惠市| 府谷县| 石家庄市|