zoukankan      html  css  js  c++  java
  • 第8关 k8s架构师课程之持久化存储第一节

    https://www.toutiao.com/a6940591610598228483/?log_from=59d1fd47e1101_1630830822320

    https://www.bilibili.com/video/BV12h411Q7hu?spm_id_from=333.999.0.0

    大家好,我是博哥爱运维,K8s是如何来管理存储资源的呢?跟着博哥来会会它们吧!

    Volume

    我们这里先来聊聊K8s的存储模型Volume,来实践下如何将各种持久化的存储映射到Pod中的容器。

    在我们上面的实战中,大家如果细心的话,会发现把nginx服务pod内的默认页面改了,但当重启pod后,这个页面又恢复成nginx容器初始的状态了,所以这里要和大家说的是,在没有配置持久化存储前,任何新增的数据在pod发生重启时都是无法保留的,而在K8s上,Pod的生命周期可能是很短,它们会被频繁地销毁和创建,自然在容器销毁时,里面运行时新增的数据,如修改的配置及日志文件等也会被清除。

    那么怎么解决这一现象呢,我们可以用K8s volume来持久化保存容器的数据,Volume的生命周期独立于容器,Pod中的容器可能被销毁重建,但Volume会被保留。

    本质上,K8s volume是一个目录,这点和Docker volume差不多,当Volume被mount到Pod上,这个Pod中的所有容器都可以访问这个volume,在生产场景中,我们常用的类型有这几种:

    • emptyDir
    • hostPath
    • PersistentVolume(PV) & PersistentVolumeClaim(PVC)
    • StorageClass

    emptyDir

    我们先开始讲讲emptyDir,它是最基础的Volume类型,pod内的容器发生重启不会造成emptyDir里面数据的丢失,但是当pod被重启后,emptyDir数据会丢失,也就是说emptyDir与pod的生命周期是一致的,那么大家可能有个疑问,这个之前讲的没有配置它也没什么区别呀,实际上在某些时候,它的作用还是挺大的,在生产中它的最实际实用是提供Pod内多容器的volume数据共享,下面我会用一个实际的生产者,消费者的例子来演示下emptyDir的作用,相信大家动动手就会理解得更快了

    # 我们继续用上面的web服务的配置,在里面新增volume配置
    # cat web.yaml
    
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: web
      name: web
      namespace: default
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: web
      template:
        metadata:
          labels:
            app: web
        spec:
          containers:
          - image: nginx
            name: nginx
            resources:
              limits:
                cpu: "50m"
                memory: 20Mi
              requests:
                cpu: "50m"
                memory: 20Mi
            volumeMounts:         # 准备将pod的目录进行卷挂载
              - name: html-files  # 自定个名称,容器内可以类似这样挂载多个卷
                mountPath: "/usr/share/nginx/html"
    
          - name: busybox       # 在pod内再跑一个容器,每秒把当时时间写到nginx默认页面上
            image: busybox
            args:
            - /bin/sh
            - -c
            - >
               while :; do
                 if [ -f /html/index.html ];then
                   echo "[$(date +%F %T)] hello" > /html/index.html
                   sleep 1
                 else
                   touch /html/index.html
                 fi
               done
            volumeMounts:
              - name: html-files  # 注意这里的名称和上面nginx容器保持一样,这样才能相互进行访问
                mountPath: "/html"  # 将数据挂载到当前这个容器的这个目录下
          volumes:
            - name: html-files   # 最后定义这个卷的名称也保持和上面一样
              emptyDir:          # 这就是使用emptyDir卷类型了
                medium: Memory   # 这里将文件写入内存中保存,这样速度会很快,配置为medium: "" 就是代表默认的使用本地磁盘空间来进行存储
                sizeLimit: 10Mi  # 因为内存比较珍贵,注意限制使用大小
    更新这个web的配置
    
    # kubectl apply -f web.yaml 
    deployment.apps/web configured
    
    # 可以看到READY下面容器数量变为2了
    # kubectl get pod
    NAME                    READY   STATUS    RESTARTS   AGE
    ......
    web-5bf769fdfc-44p7h    2/2     Running   0          2m4s
    
    # 我们先直接用服务的IP来快速测试下效果
    # kubectl get svc
    NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
    ......
    web          ClusterIP   10.68.229.231   <none>        80/TCP    4h36m

    上面有两个容器,一个是nginx容器,nginx 容器的内部的目录/usr/share/nginx/html挂载到volume是html-files

    另外一个容器busybox的/html目录也是挂载到volume是html-files,容器busybox会在/html下面创建index.html会修改index/html中的内容

    nginx首先默认路径是/usr/share/nginx/html/index.html 因为busybox和nginx两个容器同享了html-files这个磁盘,所以当访问nginx的时候,首页的内容会不断发生变化

    volumes:
            - name: html-files   # 最后定义这个卷的名称也保持和上面一样
              emptyDir:          # 这就是使用emptyDir卷类型了
                medium: Memory   # 这里将文件写入内存中保存,这样速度会很快,配置为medium: "" 就是代表默认的使用本地磁盘空间来进行存储
                sizeLimit: 10Mi  # 因为内存比较珍贵,注意限制使用大小

    html-files默认情况下的挂载点会在当前的node节点上面临时创建一个文件夹用来存储数据,当pod重启之后会自动删除改临时文件,上面
     medium: Memory  是指定临时文件存储在内存中,这样效率比存储在文件中更高。

    一个pod下面有两个容器,我们要到具体的某个容器下面,需要使用-c参考来指定容器的名称,nginx就是容器的名称
    # 可以看到每次访问都是被写入当前最新时间的页面内容
    [root@node-1 ~]# curl 10.68.229.231
    [2020-11-27 07:21:34] hello
    [root@node-1 ~]# curl 10.68.229.231
    [2020-11-27 07:21:35] hello
    [root@node-1 ~]# curl 10.68.229.231
    [2020-11-27 07:21:36] hello
    [root@node-1 ~]# curl 10.68.229.231
    [2020-11-27 07:21:38] hello


    浏览器访问也是一样的

    我们来探究下原理

    # 看下这个web的pod的描述信息
    # kubectl describe pod web-5bf769fdfc-44p7h 
    ......
    Node:         10.0.1.203/10.0.1.203     # 找到这个pod运行在哪个node上
    ......
    Containers:
      nginx:
        Container ID:   docker://c1482a15f756ff3bc089973ec942a4e60f7ec34674ab8435a47a94d4b93411a7   # 找到pod内nginx容器的ID
    ......
      busybox:
        Container ID:  docker://ecedf3b0ffa6b5101e84a21f8dbf6188179875b5db61980bc93b65195f558c6f   # 找到pod内busybox容器的ID
        
        
    # 我们登陆10.0.1.203 这台node,查看pod内这两个容器的volume挂载信息,我们发现两个容器都 mount 了同一个目录
    [root@node-3 ~]# docker inspect c1482a15f756ff3bc089973ec942a4e60f7ec34674ab8435a47a94d4b93411a7|grep volume|grep html
                    "/var/lib/container/kubelet/pods/cc4832f3-c73c-479f-9088-12b079ff4608/volumes/kubernetes.io~empty-dir/html-files:/usr/share/nginx/html",
                    "Source": "/var/lib/container/kubelet/pods/cc4832f3-c73c-479f-9088-12b079ff4608/volumes/kubernetes.io~empty-dir/html-files",
                    
                    
    [root@node-3 ~]# docker inspect ecedf3b0ffa6b5101e84a21f8dbf6188179875b5db61980bc93b65195f558c6f|grep volume|grep html
                    "/var/lib/container/kubelet/pods/cc4832f3-c73c-479f-9088-12b079ff4608/volumes/kubernetes.io~empty-dir/html-files:/html",
                    "Source": "/var/lib/container/kubelet/pods/cc4832f3-c73c-479f-9088-12b079ff4608/volumes/kubernetes.io~empty-dir/html-files",   


    hostPath

    hostPath Volume 的作用是将容器运行的node上已经存在文件系统目录给mount到pod的容器。在生产中大部分应用是是不会直接使用hostPath的,因为我们并不关心Pod在哪台node上运行,而hostPath又恰好增加了pod与node的耦合,限制了pod的使用,这里我们只作一下了解,知道有这个东西存在即可,一般只是一些安装服务会用到,比如下面我截取了网络插件calico的部分volume配置:

     volumeMounts:
        - mountPath: /host/driver
          name: flexvol-driver-host
    ......
      volumes:
    ......
      - hostPath:
          path: /usr/libexec/kubernetes/kubelet-plugins/volume/exec/nodeagent~uds
          type: DirectoryOrCreate
        name: flexvol-driver-host
     


  • 相关阅读:
    vue响应式原理的实现
    手写 Promise
    模拟ATM机功能(C语言)
    打印空心菱形
    假设一对耗子每个月都可以生一对小耗子。小耗子生长3个月后,从第4个月开始也就能够生小耗子。问:假设所有的耗子都不死的话,那么20个月后一共有多少只耗子?
    判断一年中的第几天
    依次将10个数输入,要求打印出其中最大的数
    九九乘法表
    判断是否为闰年
    从键盘上接收一个字母,判断是否是大写字母,如果是则转换成小写字母输出 ,否则直接输出。
  • 原文地址:https://www.cnblogs.com/kebibuluan/p/15229993.html
Copyright © 2011-2022 走看看