k8s 1.28.2 集群部署 NFS server 和 NFS Subdir External Provisioner

### 文章目录

  • [@[toc]](#文章目录 @[toc] 前言 部署 NFS server 镜像准备 节点打标签 启动 NFS server 创建 pv 验证 创建 pvc 创建 pod 挂载验证 部署 NFS Subdir External Provisioner 创建 pod 验证 提前创建 pvc 的方式 使用 volumeClaimTemplates 的方式)
  • [前言](#文章目录 @[toc] 前言 部署 NFS server 镜像准备 节点打标签 启动 NFS server 创建 pv 验证 创建 pvc 创建 pod 挂载验证 部署 NFS Subdir External Provisioner 创建 pod 验证 提前创建 pvc 的方式 使用 volumeClaimTemplates 的方式)
  • [部署 NFS server](#文章目录 @[toc] 前言 部署 NFS server 镜像准备 节点打标签 启动 NFS server 创建 pv 验证 创建 pvc 创建 pod 挂载验证 部署 NFS Subdir External Provisioner 创建 pod 验证 提前创建 pvc 的方式 使用 volumeClaimTemplates 的方式)
  • [镜像准备](#文章目录 @[toc] 前言 部署 NFS server 镜像准备 节点打标签 启动 NFS server 创建 pv 验证 创建 pvc 创建 pod 挂载验证 部署 NFS Subdir External Provisioner 创建 pod 验证 提前创建 pvc 的方式 使用 volumeClaimTemplates 的方式)
  • [节点打标签](#文章目录 @[toc] 前言 部署 NFS server 镜像准备 节点打标签 启动 NFS server 创建 pv 验证 创建 pvc 创建 pod 挂载验证 部署 NFS Subdir External Provisioner 创建 pod 验证 提前创建 pvc 的方式 使用 volumeClaimTemplates 的方式)
  • [启动 NFS server](#文章目录 @[toc] 前言 部署 NFS server 镜像准备 节点打标签 启动 NFS server 创建 pv 验证 创建 pvc 创建 pod 挂载验证 部署 NFS Subdir External Provisioner 创建 pod 验证 提前创建 pvc 的方式 使用 volumeClaimTemplates 的方式)
  • [创建 pv 验证](#文章目录 @[toc] 前言 部署 NFS server 镜像准备 节点打标签 启动 NFS server 创建 pv 验证 创建 pvc 创建 pod 挂载验证 部署 NFS Subdir External Provisioner 创建 pod 验证 提前创建 pvc 的方式 使用 volumeClaimTemplates 的方式)
  • [创建 pvc](#文章目录 @[toc] 前言 部署 NFS server 镜像准备 节点打标签 启动 NFS server 创建 pv 验证 创建 pvc 创建 pod 挂载验证 部署 NFS Subdir External Provisioner 创建 pod 验证 提前创建 pvc 的方式 使用 volumeClaimTemplates 的方式)
  • [创建 pod 挂载验证](#文章目录 @[toc] 前言 部署 NFS server 镜像准备 节点打标签 启动 NFS server 创建 pv 验证 创建 pvc 创建 pod 挂载验证 部署 NFS Subdir External Provisioner 创建 pod 验证 提前创建 pvc 的方式 使用 volumeClaimTemplates 的方式)
  • [部署 NFS Subdir External Provisioner](#文章目录 @[toc] 前言 部署 NFS server 镜像准备 节点打标签 启动 NFS server 创建 pv 验证 创建 pvc 创建 pod 挂载验证 部署 NFS Subdir External Provisioner 创建 pod 验证 提前创建 pvc 的方式 使用 volumeClaimTemplates 的方式)
  • [创建 pod 验证](#文章目录 @[toc] 前言 部署 NFS server 镜像准备 节点打标签 启动 NFS server 创建 pv 验证 创建 pvc 创建 pod 挂载验证 部署 NFS Subdir External Provisioner 创建 pod 验证 提前创建 pvc 的方式 使用 volumeClaimTemplates 的方式)
  • [提前创建 pvc 的方式](#文章目录 @[toc] 前言 部署 NFS server 镜像准备 节点打标签 启动 NFS server 创建 pv 验证 创建 pvc 创建 pod 挂载验证 部署 NFS Subdir External Provisioner 创建 pod 验证 提前创建 pvc 的方式 使用 volumeClaimTemplates 的方式)
  • [使用 volumeClaimTemplates 的方式](#文章目录 @[toc] 前言 部署 NFS server 镜像准备 节点打标签 启动 NFS server 创建 pv 验证 创建 pvc 创建 pod 挂载验证 部署 NFS Subdir External Provisioner 创建 pod 验证 提前创建 pvc 的方式 使用 volumeClaimTemplates 的方式)

前言

NFS Subdir External Provisioner 可以使用现有的 NFS 服务器动态创建 pv 和 pvc

部署 NFS server

镜像准备

这块可以看我之前的博客,这里就不啰嗦了

节点打标签

采用 hostpath 的方式来持久化 NFS 的共享目录,需要绑定节点不让 NFS 飘移

复制代码
k label node 192.168.22.124 nfs-server=true

启动 NFS server

  • 这里记录两个问题
    • NFS 的配置文件,根目录或者说第一个共享目录,需要加上 fsid=0 ,然后挂载的时候直接使用 / ,如果不加 fsid=0,挂载会报错找不到文件或目录,细节什么的,可以看一下官方的手册:exports
    • 因为需要本地宿主机挂载 NFS 共享目录到 kubelet 的目录下面,宿主机就没办法使用 svc 的方式来挂载,除非本地 DNS 服务器包含了 k8s 集群内的 DNS,我这边就暂时使用指定的 clusterIP 地址来创建 svc,集群内直接使用 svc 的 ip 地址来挂载 NFS
      • 关于 clusterip 的 ip 范围,需要看 apiserver 的 --service-cluster-ip-range 参数,一般都是 10.96.0.0/12,可用的范围在 10.96.0.010.111.255.255 之间,找一个集群内不存在的 ip 来用就行
      • Service ClusterIP 分配
      • exports 里面要把 node 节点的 ip 网段,svc 的网段和 pod 的网段都写进去,如果嫌烦,也可以直接写 * ,只要不是对外暴露的,问题不是很大
yaml 复制代码
---
apiVersion: v1
data:
  exports: |
    /nfs-share-data 192.168.22.0/24(rw,fsid=0,sync,no_subtree_check,no_auth_nlm,insecure,no_root_squash)
    /nfs-share-data 10.96.0.0/12(rw,fsid=0,sync,no_subtree_check,no_auth_nlm,insecure,no_root_squash)
    /nfs-share-data 172.22.0.0/16(rw,fsid=0,sync,no_subtree_check,no_auth_nlm,insecure,no_root_squash)
kind: ConfigMap
metadata:
  name: nfs-server-cm
  namespace: storage
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/name: nfs-server
  name: nfs-server-svc
  namespace: storage
spec:
  clusterIP: 10.111.111.111
  ports:
  - name: tcp
    port: 2049
    targetPort: tcp
  selector:
    app.kubernetes.io/name: nfs-server
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/name: nfs-server
  name: nfs-server
  namespace: storage
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: nfs-server
  strategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        app.kubernetes.io/name: nfs-server
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: nfs-server
                operator: In
                values:
                - "true"
      containers:
      - env:
        - name: SHARED_DIRECTORY
          value: /nfs-share-data
        image: nfs-server-2.6.4:alpine-3.20
        imagePullPolicy: IfNotPresent
        name: nfs-server
        ports:
        - containerPort: 2049
          name: tcp
          protocol: TCP
        resources:
          limits:
            cpu: 1000m
            memory: 1024Mi
          requests:
            cpu: 100m
            memory: 100Mi
        securityContext:
          capabilities:
            add:
            - SYS_ADMIN
        volumeMounts:
        - mountPath: /nfs-share-data
          name: nfs-share-data
        - mountPath: /etc/exports
          name: nfs-config
          subPath: exports
      volumes:
      - hostPath:
          path: /approot/k8s_data/nfs-share-data
          type: DirectoryOrCreate
        name: nfs-share-data
      - configMap:
          name: nfs-server-cm
        name: nfs-config
创建 pv 验证
yaml 复制代码
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteMany
  nfs:
    server: 10.111.111.111
    path: "/"
创建 pvc
yaml 复制代码
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
创建 pod 挂载验证
yaml 复制代码
---
apiVersion: v1
kind: Pod
metadata:
  name: nfs-client
spec:
  containers:
  - name: app
    image: m.daocloud.io/busybox:1.37
    command: ["sh", "-c", "while true; do sleep 3600; done"]
    volumeMounts:
    - name: nfs-storage
      mountPath: /mnt/nfs
  volumes:
  - name: nfs-storage
    persistentVolumeClaim:
      claimName: nfs-pvc

如果 pod 启动有类似如下的报错,可以在 k8s 节点上安装一下 nfs-utils

复制代码
  Warning  FailedMount  1s (x7 over 33s)  kubelet            MountVolume.SetUp failed for volume "nfs-pv" : mount failed: exit status 32
Mounting command: mount
Mounting arguments: -t nfs nfs-server-svc.storage.svc.cluster.local:/nfs-share-data /var/lib/kubelet/pods/9e7abc6f-573c-4c3f-b023-cdceee95722a/volumes/kubernetes.io~nfs/nfs-pv
Output: mount: /var/lib/kubelet/pods/9e7abc6f-573c-4c3f-b023-cdceee95722a/volumes/kubernetes.io~nfs/nfs-pv: bad option; for several filesystems (e.g. nfs, cifs) you might need a /sbin/mount.<type> helper program.

部署 NFS Subdir External Provisioner

官方也有 helm 的文档,需要用 helm 的,可以直接看官方的:NFS Subdirectory External Provisioner Helm Chart

我这边采用 yaml 编排来部署

yaml 复制代码
---
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    app: nfs-subdir-external-provisioner
  name: nfs-subdir-external-provisioner-sa
  namespace: storage
---
allowVolumeExpansion: true
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  labels:
    app: nfs-subdir-external-provisioner
  name: nfs-client
parameters:
  archiveOnDelete: "true"
  pathPattern: /
provisioner: cluster.local/nfs-subdir-external-provisioner
reclaimPolicy: Retain
volumeBindingMode: Immediate
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    app: nfs-subdir-external-provisioner
  name: nfs-subdir-external-provisioner-runner
rules:
- apiGroups:
  - ""
  resources:
  - nodes
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - persistentvolumes
  verbs:
  - get
  - list
  - watch
  - create
  - delete
- apiGroups:
  - ""
  resources:
  - persistentvolumeclaims
  verbs:
  - get
  - list
  - watch
  - update
- apiGroups:
  - storage.k8s.io
  resources:
  - storageclasses
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - events
  verbs:
  - create
  - update
  - patch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  labels:
    app: nfs-subdir-external-provisioner
  name: run-nfs-subdir-external-provisioner
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: nfs-subdir-external-provisioner-runner
subjects:
- kind: ServiceAccount
  name: nfs-subdir-external-provisioner-sa
  namespace: storage
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  labels:
    app: nfs-subdir-external-provisioner
  name: leader-locking-nfs-subdir-external-provisioner
  namespace: storage
rules:
- apiGroups:
  - ""
  resources:
  - endpoints
  verbs:
  - get
  - list
  - watch
  - create
  - update
  - patch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    app: nfs-subdir-external-provisioner
  name: leader-locking-nfs-subdir-external-provisioner
  namespace: storage
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: leader-locking-nfs-subdir-external-provisioner
subjects:
- kind: ServiceAccount
  name: nfs-subdir-external-provisioner-sa
  namespace: storage
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nfs-subdir-external-provisioner
  name: nfs-subdir-external-provisioner
  namespace: storage
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nfs-subdir-external-provisioner
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-subdir-external-provisioner
    spec:
      containers:
      - env:
        - name: PROVISIONER_NAME
          value: cluster.local/nfs-subdir-external-provisioner
        - name: NFS_SERVER
          value: 10.111.111.111
        - name: NFS_PATH
          value: /
        image: docker.m.daocloud.io/registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
        imagePullPolicy: IfNotPresent
        name: nfs-subdir-external-provisioner
        volumeMounts:
        - mountPath: /persistentvolumes
          name: nfs-subdir-external-provisioner-root
      serviceAccountName: nfs-subdir-external-provisioner-sa
      volumes:
      - name: nfs-subdir-external-provisioner-root
        nfs:
          path: /
          server: 10.111.111.111

创建 pod 验证

提前创建 pvc 的方式

创建 pvc

yaml 复制代码
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: test-claim
spec:
  storageClassName: nfs-client
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Mi

创建 pod

由于 NFS 这块是直接走的共享目录的根目录,会比较乱,因此 pod 增加了变量,再通过 volumeMounts.subPathExpr 将共享数据存到 pod 名字的目录下

yaml 复制代码
---
kind: Pod
apiVersion: v1
metadata:
  name: test-pod
spec:
  containers:
  - name: test-pod
    image: m.daocloud.io/busybox:1.37
    command:
      - "/bin/sh"
    args:
      - "-c"
      - "touch /mnt/hello && exit 0 || exit 1"
    env:
    - name: POD_NAME
      valueFrom:
        fieldRef:
          apiVersion: v1
          fieldPath: metadata.name
    volumeMounts:
      - name: nfs-pvc
        mountPath: "/mnt"
        subPathExpr: $(POD_NAME)
  restartPolicy: "Never"
  volumes:
    - name: nfs-pvc
      persistentVolumeClaim:
        claimName: test-claim

可以通过之前创建的 nfs-client 来验证是否创建了 hello 这个文件

shell 复制代码
kubectl exec -it nfs-client -- ls /mnt/nfs/test-pod/
使用 volumeClaimTemplates 的方式
yaml 复制代码
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: test-sts
spec:
  replicas: 1
  selector:
    matchLabels:
      app: test-sts
  template:
    metadata:
      labels:
        app: test-sts
    spec:
      containers:
      - name: test-sts
        image: m.daocloud.io/busybox:1.37
        command:
          - "/bin/sh"
        args:
          - "-c"
          - "touch /mnt/SUCCESS && exit 0 || exit 1"
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: metadata.name
        volumeMounts:
          - name: nfs-sts-pvc
            mountPath: "/mnt"
            subPathExpr: $(POD_NAME)
      restartPolicy: "Always"
  volumeClaimTemplates:
  - metadata:
      name: nfs-sts-pvc
    spec:
      storageClassName: nfs-client
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 10Gi

同样可以通过之前创建的 nfs-client 来验证是否创建了 SUCCESS 这个文件

yaml 复制代码
kubectl exec -it nfs-client -- ls /mnt/nfs/test-sts-0
相关推荐
布吉岛的石头19 小时前
Docker Compose编排实战:多容器应用从开发到生产
运维·docker·容器
SPC的存折1 天前
19-2、K8s 三种 QoS 等级 & 与 Resources(requests_limits)的核心关联
云原生·容器·kubernetes
SPC的存折1 天前
1、K8S-组件介绍
云原生·容器·kubernetes
狼与自由1 天前
微服务网关演化
微服务·云原生·架构
SPC的存折1 天前
20、K8S-Pod驱逐
java·docker·kubernetes
sbjdhjd1 天前
02 (中)| K8s Pod 生产化落地:从配置到优化全流程
linux·运维·云原生·kubernetes·开源·podman·kubelet
皓月盈江1 天前
Linux Ubuntu系统如何编辑Docker容器内的文件
linux·ubuntu·docker·容器·靶场·vulhub·编辑docker内文件
China_Yanhy1 天前
【云原生实战】从零构建无节点 EKS:Karpenter 极简注入与全自动算力接管指南
linux·运维·云原生
蜀道山老天师1 天前
从零搭建 Prometheus 监控 MySQL:含二进制安装、授权、exporter 配置全流程
运维·数据库·mysql·adb·云原生·prometheus
珂玥c1 天前
添加node节点到k8s集群+配置网络插件flannel
云原生·容器·kubernetes