使用NFS作为k8s的持久化存储
来源:原创
时间:2020-06-25
作者:脚本小站
分类:Linux
nfs-subdir-external-provisioner
先在任意主机上创建好nfs服务,然后在k8s中部署如下几个资源,这里用到的是nfs-client-provisioner,官方文档如下:
https://github.com/kubernetes-retired/external-storage/tree/master/nfs-client
新地址:
https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner
helm部署:
helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/ helm install nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \ --set nfs.server=192.168.0.12 \ --set nfs.path=/data/nfs
手动部署:
需要部署的几个文件。
cat > nfs-storageclass.yaml <<EOF apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: managed-nfs-storage provisioner: fuseim.pri/ifs # or choose another name, must match deployment's env PROVISIONER_NAME' parameters: archiveOnDelete: "false" EOF
rbac.yaml
cat > rbac.yaml <<EOF apiVersion: v1 kind: ServiceAccount metadata: name: nfs-client-provisioner # replace with namespace where provisioner is deployed namespace: default --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: nfs-client-provisioner-runner rules: - 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"] --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: run-nfs-client-provisioner subjects: - kind: ServiceAccount name: nfs-client-provisioner # replace with namespace where provisioner is deployed namespace: default roleRef: kind: ClusterRole name: nfs-client-provisioner-runner apiGroup: rbac.authorization.k8s.io --- kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: name: leader-locking-nfs-client-provisioner # replace with namespace where provisioner is deployed namespace: default rules: - apiGroups: [""] resources: ["endpoints"] verbs: ["get", "list", "watch", "create", "update", "patch"] --- kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: leader-locking-nfs-client-provisioner # replace with namespace where provisioner is deployed namespace: default subjects: - kind: ServiceAccount name: nfs-client-provisioner # replace with namespace where provisioner is deployed namespace: default roleRef: kind: Role name: leader-locking-nfs-client-provisioner apiGroup: rbac.authorization.k8s.io EOF
deployment.yaml:注意修改nfs服务地址和目录
cat > deployment.yaml <<EOF apiVersion: apps/v1 kind: Deployment metadata: name: nfs-client-provisioner labels: app: nfs-client-provisioner # replace with namespace where provisioner is deployed namespace: default spec: replicas: 1 strategy: type: Recreate selector: matchLabels: app: nfs-client-provisioner template: metadata: labels: app: nfs-client-provisioner spec: serviceAccountName: nfs-client-provisioner containers: - name: nfs-client-provisioner image: quay.io/external_storage/nfs-client-provisioner:latest volumeMounts: - name: nfs-client-root mountPath: /persistentvolumes env: - name: PROVISIONER_NAME value: fuseim.pri/ifs # 如果有多个storageclass和多个nfs这里的值要不一样 - name: NFS_SERVER value: 192.168.0.71 - name: NFS_PATH value: /opt/nfs volumes: - name: nfs-client-root nfs: server: 192.168.0.71 path: /opt/nfs EOF
注意:
在k8s 1.21之后的版本中使用nfs需要在kube-apiserver.yaml中添加如下参数,selfLink功能在这个版本之后被移除了,会导致pv创建不了。
spec: containers: - command: - kube-apiserver - --feature-gates=RemoveSelfLink=false # 添加这个
或者使用如下不依赖selfLink功能的镜像:这样就不用在apiserver中添加参数了
gcr.io/k8s-staging-sig-storage/nfs-subdir-external-provisioner:v4.0.0 registry.cn-beijing.aliyuncs.com/pylixm/nfs-subdir-external-provisioner:v4.0.0
csi-driver-nfs
github地址:
https://github.com/kubernetes-csi/csi-driver-nfs
k8s1.8版本可以使用3.1.0版本的,4.0+版本需要fsGroupPolicy,fsGroupPolicy功能是 Kubernetes 1.20 的 Beta 版才有的,默认禁用,而且需要手动开启,这里使用3.1版本的。
安装文档:
https://github.com/kubernetes-csi/csi-driver-nfs/blob/master/docs/install-csi-driver-v3.1.0.md
资源文件:或者直接应用资源文件即可。
kind: Deployment apiVersion: apps/v1 metadata: name: csi-nfs-controller namespace: kube-system spec: replicas: 2 selector: matchLabels: app: csi-nfs-controller template: metadata: labels: app: csi-nfs-controller spec: hostNetwork: true # controller also needs to mount nfs to create dir dnsPolicy: ClusterFirstWithHostNet serviceAccountName: csi-nfs-controller-sa nodeSelector: kubernetes.io/os: linux # add "kubernetes.io/role: master" to run controller on master node priorityClassName: system-cluster-critical tolerations: - key: "node-role.kubernetes.io/master" operator: "Exists" effect: "NoSchedule" - key: "node-role.kubernetes.io/controlplane" operator: "Exists" effect: "NoSchedule" containers: - name: csi-provisioner image: registry.k8s.io/sig-storage/csi-provisioner:v2.2.2 args: - "-v=2" - "--csi-address=$(ADDRESS)" - "--leader-election" env: - name: ADDRESS value: /csi/csi.sock volumeMounts: - mountPath: /csi name: socket-dir resources: limits: memory: 400Mi requests: cpu: 10m memory: 20Mi - name: liveness-probe image: registry.k8s.io/sig-storage/livenessprobe:v2.5.0 args: - --csi-address=/csi/csi.sock - --probe-timeout=3s - --health-port=29652 - --v=2 volumeMounts: - name: socket-dir mountPath: /csi resources: limits: memory: 100Mi requests: cpu: 10m memory: 20Mi - name: nfs image: registry.k8s.io/sig-storage/nfsplugin:v3.1.0 securityContext: privileged: true capabilities: add: ["SYS_ADMIN"] allowPrivilegeEscalation: true imagePullPolicy: IfNotPresent args: - "-v=5" - "--nodeid=$(NODE_ID)" - "--endpoint=$(CSI_ENDPOINT)" env: - name: NODE_ID valueFrom: fieldRef: fieldPath: spec.nodeName - name: CSI_ENDPOINT value: unix:///csi/csi.sock ports: - containerPort: 29652 name: healthz protocol: TCP livenessProbe: failureThreshold: 5 httpGet: path: /healthz port: healthz initialDelaySeconds: 30 timeoutSeconds: 10 periodSeconds: 30 volumeMounts: - name: pods-mount-dir mountPath: /var/lib/kubelet/pods mountPropagation: "Bidirectional" - mountPath: /csi name: socket-dir resources: limits: memory: 200Mi requests: cpu: 10m memory: 20Mi volumes: - name: pods-mount-dir hostPath: path: /var/lib/kubelet/pods type: Directory - name: socket-dir emptyDir: {} --- apiVersion: storage.k8s.io/v1 kind: CSIDriver metadata: name: nfs.csi.k8s.io spec: attachRequired: false volumeLifecycleModes: - Persistent - Ephemeral --- # This YAML file contains driver-registrar & csi driver nodeplugin API objects # that are necessary to run CSI nodeplugin for nfs kind: DaemonSet apiVersion: apps/v1 metadata: name: csi-nfs-node namespace: kube-system spec: updateStrategy: rollingUpdate: maxUnavailable: 1 type: RollingUpdate selector: matchLabels: app: csi-nfs-node template: metadata: labels: app: csi-nfs-node spec: hostNetwork: true # original nfs connection would be broken without hostNetwork setting dnsPolicy: ClusterFirstWithHostNet nodeSelector: kubernetes.io/os: linux tolerations: - operator: "Exists" containers: - name: liveness-probe image: registry.k8s.io/sig-storage/livenessprobe:v2.5.0 args: - --csi-address=/csi/csi.sock - --probe-timeout=3s - --health-port=29653 - --v=2 volumeMounts: - name: socket-dir mountPath: /csi resources: limits: memory: 100Mi requests: cpu: 10m memory: 20Mi - name: node-driver-registrar image: registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.4.0 args: - --v=2 - --csi-address=/csi/csi.sock - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH) livenessProbe: exec: command: - /csi-node-driver-registrar - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH) - --mode=kubelet-registration-probe initialDelaySeconds: 30 timeoutSeconds: 15 env: - name: DRIVER_REG_SOCK_PATH value: /var/lib/kubelet/plugins/csi-nfsplugin/csi.sock - name: KUBE_NODE_NAME valueFrom: fieldRef: fieldPath: spec.nodeName volumeMounts: - name: socket-dir mountPath: /csi - name: registration-dir mountPath: /registration resources: limits: memory: 100Mi requests: cpu: 10m memory: 20Mi - name: nfs securityContext: privileged: true capabilities: add: ["SYS_ADMIN"] allowPrivilegeEscalation: true image: registry.k8s.io/sig-storage/nfsplugin:v3.1.0 args: - "-v=5" - "--nodeid=$(NODE_ID)" - "--endpoint=$(CSI_ENDPOINT)" env: - name: NODE_ID valueFrom: fieldRef: fieldPath: spec.nodeName - name: CSI_ENDPOINT value: unix:///csi/csi.sock ports: - containerPort: 29653 name: healthz protocol: TCP livenessProbe: failureThreshold: 5 httpGet: path: /healthz port: healthz initialDelaySeconds: 30 timeoutSeconds: 10 periodSeconds: 30 imagePullPolicy: "IfNotPresent" volumeMounts: - name: socket-dir mountPath: /csi - name: pods-mount-dir mountPath: /var/lib/kubelet/pods mountPropagation: "Bidirectional" resources: limits: memory: 300Mi requests: cpu: 10m memory: 20Mi volumes: - name: socket-dir hostPath: path: /var/lib/kubelet/plugins/csi-nfsplugin type: DirectoryOrCreate - name: pods-mount-dir hostPath: path: /var/lib/kubelet/pods type: Directory - hostPath: path: /var/lib/kubelet/plugins_registry type: Directory name: registration-dir --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-nfs-dynamic spec: accessModes: - ReadWriteMany resources: requests: storage: 10Gi storageClassName: nfs-csi --- apiVersion: v1 kind: ServiceAccount metadata: name: csi-nfs-controller-sa namespace: kube-system --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: nfs-external-provisioner-role rules: - 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: ["get", "list", "watch", "create", "update", "patch"] - apiGroups: ["storage.k8s.io"] resources: ["csinodes"] verbs: ["get", "list", "watch"] - apiGroups: [""] resources: ["nodes"] verbs: ["get", "list", "watch"] - apiGroups: ["coordination.k8s.io"] resources: ["leases"] verbs: ["get", "list", "watch", "create", "update", "patch"] - apiGroups: [""] resources: ["secrets"] verbs: ["get"] --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: nfs-csi-provisioner-binding subjects: - kind: ServiceAccount name: csi-nfs-controller-sa namespace: kube-system roleRef: kind: ClusterRole name: nfs-external-provisioner-role apiGroup: rbac.authorization.k8s.io --- apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: nfs-csi provisioner: nfs.csi.k8s.io parameters: server: 192.168.1.80 # nfs地址 share: /data # nfs共享出来的目录 # csi.storage.k8s.io/provisioner-secret is only needed for providing mountOptions in DeleteVolume # csi.storage.k8s.io/provisioner-secret-name: "mount-options" # csi.storage.k8s.io/provisioner-secret-namespace: "default" reclaimPolicy: Delete volumeBindingMode: Immediate mountOptions: - nfsvers=4.1