美文网首页
pv和pvc存储 - nfs

pv和pvc存储 - nfs

作者: Robin92 | 来源:发表于2022-05-02 22:52 被阅读0次

    RC、RS、Deployment 可以控制副本数量,但需要所有 Pod 副本使用的数据与 Pod 自身的生命周期分离,这就需要用额外的空间存储这些数据。

    PV(Persistent Volume),是一个全局资源,在创建之初定义了有多大的存储能力。
    PVC(Persistent Volume Claim),是 Namespace 中的资源,描述的是对 PV 的一个使用请求。
    每个需要使用的 Pod 需要有一个 PVC 与全局的 PV 相绑定,并且声明自己使用 PV 的多大空间。

    安装 nfs

    每个节点需要有 nfs 的客户端,nfs 的服务端可以只有一个。(C/S模式)

    yum install nfs-utils -y # 所有节点安装客户端
    

    配置 nfs 访问

    以下配置,共享 /data 目录,使用 192.168.208.0/24 段访问,读写,同步、指定不做 root 用户的 uid 映射,不做其他用户的 uid 映射。

    # vim /etc/exports
    /data 192.168.208.0/24(rw,async,no_root_squash,no_all_squash) # 
    

    重启 rpcbind 和 nfs

    systemctl restart rpcbind
    systemctl restart nfs #
    systemctl enable nfs # 记得设置为开机自启动
    

    nfs 启动状态错误


    image.png

    原来是因为括号中是逗号而不是空格,教程上没体现到变动。以上代码已经是修正版的了

    验证安装成功

    在任何一台机器上通过 showmount -e 192.168.208.130 查看是否能查到 nfs。

    image.png

    创建 pv

    # pv/test-pv.yml
    apiVersion: v1
    kind: PersistentVolume
    metadata: 
      name: test
      labels:
        type: test
    spec:
      capacity:
        storage: 10Gi # 提供 10G 的存储
      accessModes:
        - ReadWriteMany # 允许多个 Pod 同时读写
      persistentVolumeReclaimPolicy: Recycle # pvc 的策略,允许回收
      nfs:
        path: "/data/k8s"
        server: 192.168.208.130 # 
        readOnly: false # 取消只读,就是可写
    
    kubectl create -f pv/test-pv.yml # persistentvolume "test" created
    

    以下通过更改名字和空间大小,创建了三个 pv,查看 pv:

    image.png

    创建 pvc

    # test-pvc.yml
    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: nfs # pvc 的名字
    spec:
      accessModes:
        - ReadWriteMany # 模式允许多人读写访问
      resources:
        requests:
          storage: 1Gi # 需求资源 1G
    
    image.png

    更新 pvc 请求资源量,pvc 会对应使用容量最小能用的 pv 进行绑定。

    image.png

    实践 Pod 使用 nfs pv/pvc

    1. 写了一个向服务器文件目录中上传文件以及获取文件列表的程序
    2. 创建 k8s 资源配置文件,使用 pv、pvc、svc、deployment 资源
    3. 通过 postman 上传文件,通过浏览器查看列表

    制作程序:显示文件列表及上传文件

    用 go 写一个提供上传/访问文件系统的程序,代码如下:

    package main
    
    import (
        // ...
        "github.com/gin-gonic/gin"
    )
    
    var (
        filedir = flag.String("d", "./data", "the file dir for server")
        port    = flag.String("p", "8080", "the port which server is running on")
    )
    
    func main() {
        flag.Parse()
    
        abs, err := filepath.Abs(*filedir)
        if err != nil {
            abs = *filedir
        }
        fmt.Println("the file dir:", abs)
        fmt.Println("runing on port:", *port)
        fmt.Println()
    
        app := gin.New()
        app.GET("/", func(c *gin.Context) {
            c.Redirect(301, "/fs")
        })
        app.StaticFS("/fs", gin.Dir(*filedir, true)) // API:列表指定目录的内容
        app.POST("/upload", func(c *gin.Context) { // API 上传文件
            datafile, header, err := c.Request.FormFile("datafile")
            if err != nil {
                c.AbortWithError(400, err)
                return
            }
            defer datafile.Close()
    
            fd, err := os.Create(filepath.Join(*filedir, header.Filename))
            if err != nil {
                c.AbortWithError(500, err)
                return
            }
            defer fd.Close()
    
            io.Copy(fd, datafile)
        })
        if err := app.Run(":" + *port); err != nil {
            fmt.Println("service run failed:", err.Error())
        }
    }
    

    使用 CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build . 交叉编译出 linux 上二进制文件。(输出 fs-svr)

    构建 Docker

    创建 Dockerfile:

    FROM 192.168.208.130:5000/alpine:latest
    COPY fs-svr /service/
    WORKDIR /service
    RUN mkdir /data /service/data # RUN 在 build 阶段执行
    EXPOSE 9000
    ENTRYPOINT ["./fs-svr"] # ENTRYPOINT 的命令在 run 阶段执行,可以和 CMD 拼接到一块
    CMD ["-p", "9000", "-d", "/data"] # CMD 在 run 阶段执行,可以认为是默认的启动命令/参数,可以被传入的命令/参数覆盖
    

    注意:
    这里使用 alpine 作为基础镜像,注意先从网上下载这个基础镜像,然后改 tag 推到私有镜像库中。
    这里用服务名为 fs-svr,并且在服务本地目录位置有个 data 目录是服务内部默认用的目录

    通过一系列操作将镜像构建出来并 push 到私有库中:

    docker build . # 构建  
    docker tag 676d70bef0a7 192.168.208.130:5000/fs-svr:0.0.1 # 打私有仓库的标签
    docker push 192.168.208.130:5000/fs-svr:0.0.1 # 提交到私有仓库
    

    创建 k8s 资源

    编辑 k8s.yml 文件。创建 deployment 和 service 资源

    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      name: fs-deployment
    spec:
      replicas: 3
      template:
        metadata:
          labels:
            app: fs-svr 
        spec:
          containers:
            - name: fs-svr 
              image: 192.168.208.130:5000/fs-svr:0.0.1
              ports:
                - containerPort: 9000
              volumeMounts:
                - name: fsdata     # 绑定 template 定义的 volumes
                  mountPath: /data/
          volumes:                    # 与 containers 并级
            - name: fsdata            # 自定义一个名称,必须小写,用于 containers[].volumeMounts[].name
              persistentVolumeClaim:  # 
                claimName: nfs2       # 使用的 pvc 的名字
    ---
    apiVersion: v1
    kind: Service # 创建 service,允许通过宿主机访问
    metadata:
      name: fs-service
    spec:
      type: NodePort # 端口映射的方式,还有其他支持
      ports:
        - port: 80            # cluster IP 的端口
          nodePort: 30000     # 宿主机的端口(宿主机的端口在配置文件中指定)
          targetPort: 9000    # pod 地址的端口
      selector:       # 为哪些 Pod 做负载均衡是通过标签选择器选择的
        app: fs-svr   # 选择 app: fs-svr 的 Label
    

    通过 kubectl create -f k8s.yaml 创建资源。创建的资源列表:

    所有资源

    测试上传和显示

    • 通过浏览器地址 http://k8s-master:30000/fs/ 查看文件列表
    • 通过 postman 上传文件
    curl --location --request POST 'k8s-master:30000/upload' \
    --form 'datafile=@"/I:/workspace/k8s/kube-dns-svc.yml"'
    
    • 再次查看浏览器地址文件列表,查看 container 资源内文件列表及 pv 对应目录的文件列表(创建 pv 时有指定 /data/k8s
    • kubectl delete deployment fs-deployment 删除服务资源或进行更新等操作,查看 pv 对应资源是否持久化(是,成功)

    其他技巧

    限制重启后 deployment 资源的数量

    如上文中下图是因为重复了多次 kubectl apply 资源操作,导致遗留了很多无用的资源信息。

    所有资源

    可以通过 deployment.spec.revisionHistoryLimit 来进行限制:

    ➜  ~ kubectl explain deployment.spec.revisionHistoryLimit
    FIELD: revisionHistoryLimit <integer>
    
    DESCRIPTION:
         The number of old ReplicaSets to retain to allow rollback. This is a
         pointer to distinguish between explicit zero and not specified.
    

    shell 操作没有提示

    参考 k8s命令自动补全(只是 bash 使用的,在 zsh 或者说 Oh-my-zsh 上不好用)

    kubectl api-resources

    kubectl api-resources 可以显示所有 k8s 资源,但目前由于集群版本问题不显示。后面再了解。

    相关文章

      网友评论

          本文标题:pv和pvc存储 - nfs

          本文链接:https://www.haomeiwen.com/subject/iomzertx.html