iT邦幫忙

2022 iThome 鐵人賽

DAY 20
0

可愛鯨魚

鯨魚也是會翻船的,先把重要的東西存起來~

圖片來源:Docker (@Docker) / Twitter

來介紹一下 Kubernetes 的各種 volume~

Volume

Pod 裡的 container 可能隨時重啟或重建,為了避免重要檔案跟著被刪除,就必須要使用 volume 讓裡面的檔案能被保留

Kubernetes 的 volume 類型分為 Ephemeral Volume, Projected Volume, Persistent Volume

簡單列出幾個 volume:

  • emptyDir: 建立空目錄儲存暫時性資料
  • hostPath: 掛 node 的目錄到 pod 內
  • local: 掛 node 的 local storage device 到 pod 內
  • nfs: 掛外部 NFS (Network File System) share
  • awsElasticBlockStore, azureDisk, azureFile, gcePersistentDisk: 雲端提供的儲存區
  • cinder, cephfs, iscsi: network storage
  • configMap, secret, downwardAPI: 特殊 volume 用來存 Kubernetes resource 相關資訊

如果 container 掛了 volume,原本 container 的檔案會被清空,僅留存掛上去 volume 的檔案

Ephemeral Volume

生命週期短暫相依於 pod,用來儲存暫時性資料

支援的類型: emptyDir, configMap, downwardAPI, secret, CSI ephemeral volumes, generic ephemeral volumes

emptyDir, configMap, downwardAPI, secret 資料是由各 node 的 kubelet 管理的

emptyDir

emptyDir 會建立一個空目錄,可讓 container 儲存龐大的暫時性資料

分享一下目前遇過的案例~
在架 gitlab 會需要配置 shm,這裡改成使用 emptyDir 設定 Memory

apiVersion: v1
kind: Pod
...
spec:
  containers:
  - image: gitlab/gitlab-ee:15.0.1-ee.0
    name: gitlab
    volumeMounts:
     - mountPath: /dev/shm
       name: cache-volume
    ...
  volumes:
  - name: cache-volume
    emptyDir:
      medium: Memory
      sizeLimit: 512Mi

configMap

用來存設定相關的值(key-value)或直接存成檔案

例如前面設定 Traefik 就有偷偷用到~

apiVersion: v1
kind: ConfigMap
metadata:
  name: traefik-config
  labels:
    name: traefik-config
  namespace: traefik
data:
  dyn.yaml: |
    tls:
      options:
        default:
          minVersion: VersionTLS12
      stores:
        default:
          defaultCertificate:
            certFile: '/certs/tls.pem'
            keyFile: '/certs/tls.key'

secret

用來存較為隱密的資料,所有存在裡面的資料會使用 base64 encode,注意並非加密!

例如用在設定 tls 憑證

kubectl create secret generic tls-secret -n traefik \
    --from-file=ca.pem \
    --from-file=tls.pem=fullchain.pem \
    --from-file=tls.key=example.domain.com.key

產生出來會像下面這樣...

apiVersion: v1
kind: Secret
metadata:
  creationTimestamp: "2022-10-02T20:04:31Z"
  name: tls-secret
  namespace: traefik
  resourceVersion: "682517"
  uid: bc1c5822-715e-4082-8c55-363ca350a8bd
type: Opaque
data:
  ca.pem: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t...
  tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVk...
  tls.pem: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t...

downwardAPI

可以用來直接取得 cluster 相關資訊

這個我目前還沒實際用過...
先拿官網的範例~ 取用 Pod 本身的 label

apiVersion: v1
kind: Pod
metadata:
  name: kubernetes-downwardapi-volume-example
  labels:
    zone: us-est-coast
    cluster: test-cluster1
    rack: rack-22
spec:
  containers:
    - name: client-container
      image: registry.k8s.io/busybox
      command: ["sh", "-c"]
      args:
      - while true; do
          if [[ -e /etc/podinfo/labels ]]; then
            echo -en '\n\n'; cat /etc/podinfo/labels; fi;
          sleep 5;
        done;
      volumeMounts:
        - name: podinfo
          mountPath: /etc/podinfo
  volumes:
    - name: podinfo
      downwardAPI:
        items:
          - path: "labels"
            fieldRef:
              fieldPath: metadata.labels

generic ephemeral volumes

透過 StorageClass 動態配置一個 volume 給 Pod,只有 Pod 在運行時才會掛載,通常用於快照或是需要動態調整容量的 volume

以下是官網的使用範例

kind: Pod
apiVersion: v1
metadata:
  name: my-app
spec:
  ...
  volumes:
    - name: scratch-volume
      ephemeral:
        volumeClaimTemplate:
          metadata:
            labels:
              type: my-frontend-volume
          spec:
            accessModes: [ "ReadWriteOnce" ]
            storageClassName: "scratch-storage-class"
            resources:
              requests:
                storage: 1Gi

感覺比較像 StatefulSet 需要的 volume 配置
以下是從 harbor redis 看到 StatefulSet 的例子

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: harbor-redis
  namespace: harbor
  ...
spec:
  ...
  volumeClaimTemplates:
  - apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      labels:
        app: harbor
        chart: harbor
        heritage: Helm
        release: harbor
      name: data
    spec:
      accessModes:
      - ReadWriteMany
      resources:
        requests:
          storage: 1Gi
      storageClassName: nfs-client

Persistent Volume

PV 獨立於 Namespace 外,由 admin 配置一塊儲存區 (PersistentVolume, PV),user 能夠請求使用 (PersistentVolumeClaim, PVC)

範例格式...

apiVersion: v1
kind: PersistentVolume
metadata:
  name: <pv_name>
spec:
  capacity:
    storage: 1Gi       # define pv size
  accessModes:
    - ReadWriteOnce
    - ReadOnlyMany
    persistentVolumeReclaimPolicy: Retain
    gcePersistentDisk:    # pv type
      pdName: mongodb
      fsType: ext4

accessModes

volume 存取權限

  • RWO, ReadWriteOnce: 限同一 node 以 read-write 方式 mount volume。
  • ROX, ReadOnlyMany: 多個不同 node 能以 read-only 方式 mount volume。
  • RWX, ReadWriteMany: 多個不同 node 能以 read-write 方式 mount volume。
  • RWOP, ReadWriteOncePod: 限定一個 pod 以 read-write 方式 mount volume。僅支援 CSI 和 Kubernetes v1.22^

要注意不同的 volume plugin 支援度不同!
volume accessmode
圖片來源:Persistent Volumes | Kubernetes

persistentVolumeReclaimPolicy

當 PVC 被移除時要怎麼回收釋出空間

  • Retain: 不會更動 PV,若要移除資料需要手動處理
  • Recycle: 自動回收 rm -rf /thevolume/*,支援 NFShostPath
  • Delete: 將 PersistentVolume 移除也會移除關聯的存儲區,用於 AWS EBS, GCE PD, Azure Disk, OpenStack Cinder, ...

接著就來看看幾種 PV 吧~


hostPath

mount Node 的目錄到 Pod 內,要注意 Pod 部署在哪個 Node,hostPath 無法跨 Node 共用

hostPath
圖片來源:Book Kubernetes in Action (ISBN 9781617293726)

local

mount node 的 local storage device,例如 disk, partition

nfs

mount 外部 NFS (Network File System) share

範例:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: "nfs-client"
  resources:
    requests:
      storage: 1Gi
  volumeName: nfs
  mountOptions:
    - nfsvers=4
  nfs:
    path: /cluster
    server: 169.254.0.1

雲端儲存區

雲端平台提供的儲存區 awsElasticBlockStore, azureDisk, azureFile, gcePersistentDisk

network storage

其他 network storage cinder, cephfs, iscsi

有試用過 iscsi...
iscsi 可以選擇以 block 或 filesystem 掛載,但 block 實用性不高...

apiVersion: v1
kind: PersistentVolume
metadata:
  name: iscsi1-target1-lun1
  labels:
    volume: iscsi
    host: iscsi1
    target: target1
    lun: "1"
spec:
  storageClassName: iscsi-storage
  capacity:
    storage: 1Ti
  accessModes:
    - ReadWriteOnce
    - ReadOnlyMany
  # volumeMode: Block   # change Filesystem to Block?
  persistentVolumeReclaimPolicy: Retain
  iscsi:
    iqn: iqn.2004-04.com.qnap:ts-h1283xu-rp:iscsi.target1.tbw9d
    lun: 1
    targetPortal: 169.254.0.2:3260
    initiatorName: iqn.1993-08.org.debian:01:754b4f5fdd
    chapAuthDiscovery: true
    chapAuthSession: true
    secretRef:    # 有設定 chap 的話要額外建立 secret
      name: chap-secret
      namespace: iscsi
---
apiVersion: v1
kind: Secret
metadata:
  name: chap-secret
  namespace: iscsi
type: "kubernetes.io/iscsi-chap"
data:
  node.session.auth.username: ...
  node.session.auth.password: ...

Projected Volume

將已存在的 volume 一次映射到同一個目錄上
(所有 resource 必須在同一個 namespace 才可使用)

支援的類型: secret, downwardAPI, configMap, serviceAccountToken

直接看官網的 all-in-one 例子~

apiVersion: v1
kind: Pod
metadata:
  name: volume-test
spec:
  containers:
  - name: container-test
    image: busybox:1.28
    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

Ref


明天接續介紹 StoargeClass 之後會以 NFS 為使用範例~ /images/emoticon/emoticon07.gif


上一篇
Day 19 — 艦隊自我認同:Ingress 套用 OpenSSL 自簽憑證
下一篇
Day 21 — 鯨魚的萬應儲物小間:StorageClass (使用 NFS)
系列文
前端轉生~到了實驗室就要養幾隻可愛鯨魚:自架 Kubernetes 迷航日記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言