IT 铁人赛 k8s 入门30天 -- day12 Persisting Data in K8s with Volumes

前言

这篇文章主要介绍在 k8s 如何建立能够保存资料的服务

当我们需要让运行的服务资料状态能够在服务重开後也能保存

就需要以下 3种元件

Persistent Volume, Persistent Volume Claim, Storage Class

接下来的章节会更细部的去说明每个元件如何建立运作

Storage 在 k8s 的需求

在 k8s 丛集里, 对於 storage 会有以下需求

1 Storage 不会被 Pod 的生命周期影响, 也就是与 Pod 不同生命周期

2 可以被所有结点都可以存取

3 需要能够保存下来, 即使 k8s 丛集毁损

k8s 透过 PersistentVolume 元件来符合3个条件

Persistent Volume

Persistent Volume 是 k8s 设计来与实际 Storage 互动的介面

实体连接的类型可以是 k8s 丛集所在本机实体硬碟, 可以远端的网路硬碟系统例如 nfs server, 或是云端硬碟

使用 NFS storage 的设定档案如下:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-name
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessMode:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: slow
  mountOptions:
    - hard
    - nfsvers=4.0
  nfs:
    path: /dir/path/on/nfs/server
    server: nfs-server-ip-address

使用 google cloud storage 设定如下:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: test-volume
  labels:
    failure-domain.beta.kubernetes.io/zone: us-central1-a__us-central1-b
spec:
  capacity:
    storage: 400Gi
  accessModes:
  - ReadWriteOnce
  gcePersistentDisk:
    pdName: my-data-disk
    fsType: ext4

而使用 local storage 的设定档案如下:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: example-pv
spec:
  capacity:
    storage: 100Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete
  storageClassName: local-storage
  local:
    path: /mnt/disks/ssd1
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - example-node

可以看到, 关键在於 spec 部份

除了 capacity 设定是类似的

其他选项会根据实际连结的 Storage 不同而改变

k8s 支援的 Storage 可以在官网 查到

这边不做细部解说

而关於 PersistentVolume 设定档细节会铁人30天後续的章节讲到, 这边只说概念性的讲解

这边要注意的是 PersistentVolume 不属於 namespace 之内

所以基本上在 k8s 丛集, 所有 namespace 都可以存取的到 PersistentVolume 的资源

Local vs Remote Volume Types

把 k8s 支援的 Volume 类型把实连接的储存实体是否在cluster本机来分

可分为 Local 跟 Remote

其中 Local 类的不符合一开始所说的 Storage 需求第2, 3项

因此如果要建制资料库类的资料建议使用 Remote 类型较好

k8s Administrator & k8s User

k8s Administrator 负责架设 k8s 丛集, 并且负责维护 k8s 丛集的人

k8s User 指的是使用 k8s 丛集建立应用资源 ,发布应用在 k8s 丛集上的人, 通常会是应用开发者

而 Storage 资源必须要在发布应用之前就设定好, 因此建立 Storage 配置跟建制 PersistentVolume 是 k8s Administractor 的工作

PersistentVolumeClaim

这个元件是用来跟丛集宣告应用需要哪些 Storage 资源

以下是 PersistentVolumeClaim 的设定档范例

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: pvc-name
spec:
  storageClassName: manual
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

一旦 PersistentVolumeClaim 设定好

k8s 丛集就会自动分配符合需求的 PersistentVolume 给那个使用对应 PersistentVolumeClaim 的 Pod

而在 Pod 设定档里可以指定要使用哪个 PersistentVolumeClaim

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: myfronennd
      image: nginx
      volumeMounts:
      - mountPath: "/var/www/html"
        name: mypd
  volumes:
    - name: mypd
      persistentVolume:
        claimName: pvc-name

整个 Volume 对应流程如下图:

特别要注意的是 Pod 跟 PersistentVolumeClaim 需要在同一个 Namespace

而 PersistentVolume 则是丛集内的全域物件

二阶段的挂载

从以下的设定档

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: myfronennd
      image: nginx
      volumeMounts:
      - mountPath: "/var/www/html"
        name: mypd
  volumes:
    - name: mypd
      persistentVolume:
        claimName: pvc-name

可以知道挂载的部份

分为两个阶段

第一阶段, 透过 PersistentVolumeClaim 的名称 pvc-name

k8s 丛集会把 Volume 挂载到 Pod

第二阶段, 在 Container 的 volumeMount 透过名称 mypd

k8s 丛集会把挂载到 Pod 的 Volume 挂载到 Container 上

把 Volume 做抽象分层的好处

对开发应者来说, 可以专注在应用层的开发, 不需要去担忧 Storage 的来源或是设定

只要在应用端写出应用所需的 Storage 资源给 k8s 资源及可

ConfigMap 以及 Secret

在前面有提过这两个元件

这两个元件属於 Local Volume

而不是透过 PersistentVolume 与 PersistentVolumeClaim 产生出来的

由 k8s 丛集自行管理

对於 prometheus 这类需要设定档跟机敏资料档的应用

假设需要一个在运行去时去存取

就是使用 ConfigMap 跟 Secret

然後挂载到 Pod 跟 Container 内

而挂载范例如下:

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec: 
  containers:
    - name: busybox-container
      image: busybox
      volumeMounts:
        - name: config-dir
          mountPath: /etc/config
  volumes:
    - name: config-dir
      configMap:
        name: bb-configmap

另外, 可以同时在一个同时使用多种类型的 Volume

Storage Class

如前面所述, 每当 k8s User 需要 Storage

需要跟 k8s Administractor 去要求开出需要的 PersistentVolume

给次都要这样做会变成很烦琐的过程

因此, k8s 提供一个选项 Storage Class

让 PersistentVolume 能够动态新增当 k8s User 发出 PersistentVolumeClaim 时

以下是 StorageClass 的范例

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: storage-class-name
provisioner: kubernetes.io/aws-ebs
parameters:
  type: io1
  iopsPerGB: "10"
  fsType: ext4

注意的是 provisioner 是代表 Storage 的後台服务器

每个 Storage 後台服务都有属於自己的 provisioner, 可以查询k8s 官网文件

当有 PersistentVolumeClaim 发出时, StorageClass 就会跟 provisioner 发请求新增 PersistentVolume

provisioner 分为两种一种是 internal provisioner(只要是 kubernete.io 开头的)

另一种则是 external provisioner

parameter 部份则是对於 storage 的一些需求规格

StorageClass 使用范例

基本上会在 PersistentVolumeClaim 宣告

范例如下:

apiVersion: v1
kind: PersistenVolumeClaim
metadata:
  name: mypvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 100Gi
    storageClassName: storage-class-name

实际运作flow 如下图:


<<:  轻松排序!sort 的延伸用法,Ruby 30 天刷题修行篇第十一话

>>:  Day 11 ROS Cpp Parameter Server

Day29 javascript RegExp介绍

今天要来看的是JavaScript RegExp 对象,因为刚好最近做表单要用到,因此就来顺便做点笔...

Day 18 AWS云端实作起手式第八弹 让开机器变得很自动自发Auto Scaling-WriteNode设置

Auto-Scaling设置内容较多,我们快速回顾一下昨天的架构图: 针对外面的流量,我们提供使用者...

Day10 OLED进化成Micro OLED後来找Micro LED报仇了!?

上一期说到Micro LED的厉害之处,不过今天要说的是Micro OLED,Micro OLED继...

JavaScript学习日记 : Day5 - 基本型别(三)

1. 物件的引用 在讨论物件引用前先探讨call by value与call by referenc...

Day19 不使用JSX开发React的方式

当你在开发时若不想使用编译器的话,不使用JSX也是可以开发react的。 每个JSX元素都只是呼叫 ...