zoukankan      html  css  js  c++  java
  • linux运维、架构之路-K8s数据管理

    一、Volume介绍

    容器和Pod是短暂的,它们的生命周期可能很短,会被频繁的销毁和创建,存在容器中的数据会被清除,为了持久化保存容器的数据,k8s提供了Volume。
    Volume的生命周期独立于容器,它是一个目录,Volume会被mount到Pod,Pod中的所有容器都可以访问这个Volume,和Docker Volume类似。
    Volume支持的类型:emptyDir、hostPath、AWS Elastic Block Store、NFS、Ceph等。

    1、emptyDir

           emptyDir是最基础的Volume类型,它对于容器来说是持久的,对于Pod刚不是,当Pod从节点删除时Volume中的数据也会被删除,如果只是容器被销毁而Pod还在,则Volume不受影响。

    ①创建示例应用

    apiVersion: v1
    kind: Pod
    metadata:
      name: hello-world
    spec:
      containers:
      - image: busybox
        name: hello
        volumeMounts:
        - mountPath: /hello_dir   #②hello容器将shared-volume mount到/hello_dir目录 
          name: shared-volume
        args:
        - /bin/sh       #③hello通过echo将数据写到文件hello里
        - -c
        - echo "hello world" >/hello_dir/hello; sleep 30000
    
      - image: busybox
        name: world    #④world容器将 shared-volume mount到 /world_dir目录
        volumeMounts:
        - mountPath: /world_dir
          name: shared-volume
        args:
        - /bin/sh     #⑤world通过cat从文件hello读取数据
        - -c
        - cat /world_dir/hello; sleep 30000
    
      volumes:
      - name: shared-volume   #①定义了一个emptyDir类型的Volume shared-volume
        emptyDir: {}

    ②查看验证

    [root@k8s-node1 volume]# kubectl apply -f emptyDir.yaml 
    pod "hello-world" created
    
    [root@k8s-node1 volume]# kubectl get pod
    NAME          READY     STATUS    RESTARTS   AGE
    hello-world   2/2       Running   0          36s
    
    [root@k8s-node1 volume]# kubectl logs hello-world world 
    hello world

    上述显示容器world成功读到了hello容器写入的数据,验证了两个容器共享emptyDir Volume,其效果相当于执行了docker run -v /hello_dir 和/docker run -v /world_dir

    emptyDir是Host主机上创建的临时目录,其优点能够方便地为Pod中的容器提供共享存储,但不具有持久性,如果Pod不存在了,emptyDir也就没有了,适合Pod中容器需要临时共享存储空间的应用场景

    2、HostPath

            hostPath Volume的作用是将Docker Host文件系统中已经存在的目录mount给Pod的容器,大部分应用不会使用此类型,因为这实际上增加上了Pod与节点的耦合,有些需要访问k8s内部数据,比如配置文件和二进制库这样的应用需要使用hostPath,例如k8s自身的应用kube-apiserver和kube-controller-manager。

    3、外部Storage Provider

           如果k8s部署在AWS、GCE、Azure等公有云上,可以直接使用云盘作为Volume。因资源有限,此处无法演示。

    二、PV & PVC

    • PV是外部存储系统中的一块存储空间,由管理员创建,与Volume一样具有持久性,生命周期独立于Pod。
    • PVC刚是对PV的申请,PVC通常由普通用户创建,需要为Pod分配存储资源时,用户可以创建一个PVC,指明存储资源的容量大小和访问权限等,k8s会查找并提供满足条件的PV。
    • k8s支持多种类型的PV,比如AWS EBS、Ceph、NFS等

    1、NFS PV

    ①在k8s-master节点搭建一个NFS服务,目录为/nfsdata

    [root@k8s-node1 ~]# showmount -e
    Export list for k8s-node1:
    /nfsdata *

    NFS服务具体部署请参照https://www.cnblogs.com/yanxinjiang/p/7419469.html

    ②创建应用示例

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: mypv
    spec:
      capacity:
        storage: 1Gi    #指定PV的容量为1GB
      accessModes:
        - ReadWriteOnce  #表示PV能为read-write模式mount到单个节点,ReadOnlyMany表示只读,mount到多个节点,ReadWriteMany表示读写可以mount到多节点
      persistentVolumeReclaimPolicy: Recycle  #PV的回收策略,清除PV中的数据,Retain表示管理员手工回收
      storageClassName: nfs    #指定PV的class为nfs,相当于为PV设置了一个分类,PVC可以指定class申请相应的PV
      nfs:
        path: /nfsdata/pv1     #指定PV在NFS服务器上对应的目录
        server: 192.168.56.11
    [root@k8s-node1 nfs-pv]# kubectl apply -f nfs-pv1.yaml 
    persistentvolume "mypv1" created 
    [root@k8s-node1 nfs-pv]# kubectl get pv
    NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM     STORAGECLASS   REASON    AGE   #STATUS为Available,表示mypv1就绪,可以被PVC申请
    mypv1     1Gi        RWO            Recycle          Available             nfs                      4s       

    ③创建PVC

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: mypv
    spec:
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 1Gi
      storageClassName: nfs
    [root@k8s-node1 nfs-pv]# kubectl apply -f nfs-pvc1.yaml 
    persistentvolumeclaim "mypvc1" created
    [root@k8s-node1 nfs-pv]# kubectl get pvc
    NAME      STATUS    VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    mypvc1    Bound     mypv1     1Gi        RWO            nfs            13s
    [root@k8s-node1 nfs-pv]# kubectl get pv
    NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS    CLAIM            STORAGECLASS   REASON    AGE
    mypv1     1Gi        RWO            Recycle          Bound     default/mypvc1   nfs                      22m

    结果:mypvc1已经成功绑定到mypv1上面

    ④在Pod中使用存储

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

    ⑤测试验证

    [root@k8s-node1 nfs-pv]# kubectl apply -f pod1.yaml
    [root@k8s-node1 nfs-pv]# kubectl get pod -o wide
    NAME      READY     STATUS    RESTARTS   AGE       IP           NODE
    mypod1    1/1       Running   0          11m       10.2.83.14   192.168.56.12
    [root@k8s-node1 nfs-pv]# kubectl exec mypod1 touch /mydata/readme.md
    [root@k8s-node1 nfs-pv]# ls /nfsdata/pv1/
    readme.md

    在Pod中创建的文件/mydata已经存储到了NFS服务器目录/nfsdata/pv1中。

    ⑥回收PV

    • 当不需要使用PV时,可用删除PVC回收PV
    [root@k8s-node1 nfs-pv]# kubectl delete pvc mypvc1 
    persistentvolumeclaim "mypvc1" deleted

    因PV的回收策略设置为Recycle,所以数据会被清除,如想保存数据,可以将策略设置为Retain

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: mypv1
    spec:
      capacity:
        storage: 1Gi
      accessModes:
        - ReadWriteOnce
      persistentVolumeReclaimPolicy: Retain  #Recycle
      storageClassName: nfs
      nfs:
        path: /nfsdata/pv1
        server: 192.168.56.11
    [root@k8s-node1 nfs-pv]# kubectl apply -f nfs-pv1.yaml 
    persistentvolume "mypv1" configured 
    [root@k8s-node1 nfs-pv]# kubectl get pv
    NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS    CLAIM            STORAGECLASS   REASON    AGE
    mypv1     1Gi        RWO            Retain           Bound     default/mypvc1   nfs

    ⑦验证

    [root@k8s-node1 nfs-pv]# kubectl apply -f nfs-pvc1.yaml 
    [root@k8s-node1 nfs-pv]# kubectl exec mypod1 touch /mydata/hello.world
    [root@k8s-node1 nfs-pv]# ls /nfsdata/pv1/
    hello.world
    [root@k8s-node1 nfs-pv]# kubectl delete pvc mypvc1 
    persistentvolumeclaim "mypvc1" deleted
    [root@k8s-node1 nfs-pv]# ls /nfsdata/pv1/
    hello.world

    2、PV动态供给

    • 静态供给:我们提前创建PV,通过PVC申请PV并在Pod中使用
    • 动态供给:如果没有满足PVC条件的PV,会动态创建PV,不需要提前创建PV,效率高,通过StorageClass实现。     

    3、k8s中MySQL数据持久化存储

    ①创建PV和PVC

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: mysql-pv
    spec:
      capacity:
        storage: 2Gi
      accessModes:
        - ReadWriteOnce
      persistentVolumeReclaimPolicy: Retain
      storageClassName: nfs
      nfs:
        server: 192.168.56.11
        path: /data/k8s/mysql-pv
    
    ---
    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: mysql-pvc
    spec:
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 2Gi
      storageClassName: nfs

    查看pv,pvc状态

    [root@k8s-node1 mysql]# kubectl apply -f mysql_pv.yaml 
    persistentvolume "mysql-pv" created
    persistentvolumeclaim "mysql-pvc" created
     
    [root@k8s-node1 mysql]# kubectl get pv,pvc
    NAME                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS    CLAIM               STORAGECLASS   REASON    AGE
    persistentvolume/mysql-pv   2Gi        RWO            Retain           Bound     default/mysql-pvc   nfs                      4s
    
    NAME                              STATUS    VOLUME     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    persistentvolumeclaim/mysql-pvc   Bound     mysql-pv   2Gi        RWO            nfs            4s

    ②部署MySQL

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

    创建应用查看

    [root@k8s-node1 mysql]# kubectl apply -f mysql.yaml 
    deployment.apps "mysql" created
    [root@k8s-node1 k8s]# kubectl get pod -o wide
    NAME                     READY     STATUS    RESTARTS   AGE       IP          NODE
    mysql-57c44d9d5f-5v7qc   1/1       Running   0          7m        10.2.8.25   192.168.56.13

    ③进入MySQL数据库创建测试数据

    kubectl exec -it mysql-57c44d9d5f-5v7qc /bin/bash
    root@mysql-57c44d9d5f-5v7qc:/# mysql -uroot -p
    Enter password: 
    Welcome to the MySQL monitor.  Commands end with ; or g.
    Your MySQL connection id is 2
    Server version: 5.6.46 MySQL Community Server (GPL)
    
    Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
    
    Oracle is a registered trademark of Oracle Corporation and/or its
    affiliates. Other names may be trademarks of their respective
    owners.
    
    Type 'help;' or 'h' for help. Type 'c' to clear the current input statement.
    
    mysql> 
    mysql> 
    mysql> 
    mysql> show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mysql              |
    | performance_schema |
    mysql> create database test;
    Query OK, 1 row affected (0.01 sec)
    
    mysql> use test;
    Database changed
    
    mysql> create table my_id(id int(4));
    Query OK, 0 rows affected (0.03 sec)
    
    mysql> insert my_id values(111);
    Query OK, 1 row affected (0.01 sec)
    
    
    mysql> select * from my_id;
    +------+
    | id   |
    +------+
    |  111 |
    +------+
    1 row in set (0.00 sec)

    ④模拟k8s-node3节点故障

     此时node3节点变为不可用

    [root@k8s-node1 mysql]# kubectl get node
    NAME            STATUS     ROLES     AGE       VERSION
    192.168.56.12   Ready      <none>    6d        v1.10.3
    192.168.56.13   NotReady   <none>    6d        v1.10.3

    ⑤等待一段时间后,k8s会将MySQL迁移至node2节点

    [root@k8s-node1 mysql]# kubectl get pod -o wide
    NAME                     READY     STATUS    RESTARTS   AGE       IP           NODE
    mysql-57c44d9d5f-5v7qc   1/1       Unknown   0          47m       10.2.8.25    192.168.56.13
    mysql-57c44d9d5f-6gvh5   1/1       Running   0          18m       10.2.93.74   192.168.56.12
    [root@k8s-node1 mysql]# kubectl exec -it mysql-57c44d9d5f-6gvh5 /bin/bash

    ⑥再次登录MySQL验证数据的一致性

    root@mysql-57c44d9d5f-6gvh5:/# mysql -uroot -ppassword
    Warning: Using a password on the command line interface can be insecure.
    Welcome to the MySQL monitor.  Commands end with ; or g.
    Your MySQL connection id is 1
    Server version: 5.6.46 MySQL Community Server (GPL)
    
    Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
    
    Oracle is a registered trademark of Oracle Corporation and/or its
    affiliates. Other names may be trademarks of their respective
    owners.
    
    Type 'help;' or 'h' for help. Type 'c' to clear the current input statement.
    mysql> show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mysql              |
    | performance_schema |
    | test               |
    +--------------------+
    4 rows in set (0.02 sec)
    mysql> use test;
    Reading table information for completion of table and column names
    You can turn off this feature to get a quicker startup with -A
    mysql> show tables;
    +----------------+
    | Tables_in_test |
    +----------------+
    | my_id          |
    +----------------+
    1 row in set (0.00 sec)
    
    mysql> select * from my_id;
    +------+
    | id   |
    +------+
    |  111 |
    +------+
    1 row in set (0.00 sec)

    结果:MySQL服务恢复,数据无丢失

  • 相关阅读:
    2018CodeM复赛
    poj3683
    bzoj3991
    bzoj2809
    bzoj1001
    bzoj1412
    计蒜之道2018复赛
    HDU2255
    bzoj1010
    bzoj2006
  • 原文地址:https://www.cnblogs.com/yanxinjiang/p/12083970.html
Copyright © 2011-2022 走看看