在K8S中部署NFS服务器并在外部公开它

时间:2018-11-21 19:56:23

标签: docker kubernetes nfs nfsclient

我正在K8S集群上设置NFS服务器。我希望它充当外部实体的NFS服务器,即客户端将来自K8S群集之外的虚拟机。

Docker镜像的端口要求为:

==================================================================
      SERVER STARTUP COMPLETE
==================================================================
----> list of enabled NFS protocol versions: 4.2, 4.1, 4
----> list of container exports:
---->   /exports *(rw,no_subtree_check)
----> list of container ports that should be exposed:
---->   111 (TCP and UDP)
---->   2049 (TCP and UDP)
---->   32765 (TCP and UDP)
---->   32767 (TCP and UDP)

所以我创建了一个Debian Stretch码头工人形象。当我使用docker run运行它时,我可以成功公开/exports并将其从其他系统挂载。

docker run -v /data:/exports -v /tmp/exports.txt:/etc/exports:ro \
--cap-add SYS_ADMIN -p 2049:2049 -p 111:111 -p 32765:32765 \
-p 32767:32767 8113b6abeac

上面的命令启动我的docker容器,当我启动

mount.nfs4 <DOKCER_HOST_IP>:/exports /mount/

从另一个VM,我可以成功挂载该卷。

所以直到这里的一切都是确定

现在的任务是在K8S中部署它。

我的状态集定义是:

kind: StatefulSet
apiVersion: apps/v1
metadata:
  name: nfs-provisioner
spec:
  selector:
    matchLabels:
      app: nfs-provisioner
  serviceName: "nfs-provisioner"
  replicas: 1
  template:
    metadata:
      labels:
        app: nfs-provisioner
    spec:
      serviceAccount: nfs-provisioner
      terminationGracePeriodSeconds: 10
      imagePullSecrets:
      - name: artifactory
      containers:
        - name: nfs-provisioner
          image: repository.hybris.com:5005/test/nfs/nfs-server:1.2
          ports:
            - name: nfs
              containerPort: 2049
            - name: mountd
              containerPort: 20048
            - name: rpcbind
              containerPort: 111
            - name: rpcbind-udp
              containerPort: 111
              protocol: UDP
            - name: filenet
              containerPort: 32767
            - name: filenet-udp
              containerPort: 32767
              protocol: UDP
            - name: unknown
              containerPort: 32765
            - name: unknown-udp
              containerPort: 32765
              protocol: UDP
          securityContext:
            privileged: true
          env:
            - name: SERVICE_NAME
              value: nfs-provisioner
            - name: NFS_EXPORT_0
              value: '/exports *(rw,no_subtree_check)'
          imagePullPolicy: "IfNotPresent"
          volumeMounts:
            - name: export-volume
              mountPath: /exports
      volumes:
        - name: export-volume
          hostPath:
            path: /var/tmp

如您所见,我已经指定了所有端口(TCP和UDP)

现在将其暴露给外部世界而不只是暴露于群集中,我的service.yaml文件减速为:

kind: Service
apiVersion: v1
metadata:
  name: nfs-provisioner
  labels:
    app: nfs-provisioner
spec:
  type: NodePort
  ports:
    - name: nfs
      port: 2049
    - name: mountd
      port: 20048
    - name: rpcbind
      port: 111
    - name: rpcbind-udp
      port: 111
      protocol: UDP
    - name: filenet
      port: 32767
    - name: filenet-udp
      port: 32767
      protocol: UDP
    - name: unknown
      port: 32765
    - name: unknown-udp
      port: 32765
      protocol: UDP
  selector:
    app: nfs-provisioner

这将导致

kubectl get svc
NAME              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                                                                                                                      AGE
nfs-provisioner   NodePort    10.233.43.135   <none>        2049:30382/TCP,20048:31316/TCP,111:32720/TCP,111:32720/UDP,32767:30173/TCP,32767:30173/UDP,32765:31215/TCP,32765:31215/UDP   32m

现在,我尝试从外部的其他节点/ VM挂载/exports K8S集群。

我尝试过

mount.nfs4 <K8S_Node_IP>:/exports /mount/

我已经尝试

mount.nfs4 -o port=<NodePort> <K8S_Node_IP>:/exports /mount/

我一次尝试了每个NodePort。但是它们都不起作用。我收到错误消息:

mount.nfs4 -o port=31316 <K8S_Node_IP>:/exports /mount/
mount.nfs4: mount to NFS server '<K8S_Node_IP>:/exports' failed: RPC Error: Unable to receive

我不确定这里可能是什么问题。是否需要指定所有的nodePorts?如果是这样,我该怎么做?

1 个答案:

答案 0 :(得分:1)

这里的问题是,从外部看,所有NodePort都不相同:

---->   111 (TCP and UDP)
---->   2049 (TCP and UDP)
---->   32765 (TCP and UDP)
---->   32767 (TCP and UDP)

您可以尝试使用L4负载平衡器,该负载平衡器将确切暴露给定IP地址(内部或外部)上的那些端口,并将其转发到nodePorts(type=LoadBalancer也这样做)。

另一种选择是对服务中的NodePort进行硬编码,以使其与容器中的容器完全匹配:

kind: Service
apiVersion: v1
metadata:
  name: nfs-provisioner
  labels:
    app: nfs-provisioner
spec:
  type: NodePort
  ports:
    - name: nfs
      port: 2049
      nodePort: 2049
    - name: mountd
      port: 20048
      nodePort: 20048
    - name: rpcbind
      port: 111
      nodePort: 111
    - name: rpcbind-udp
      port: 111
      nodePort: 111
      protocol: UDP
    - name: filenet
      port: 32767
      nodePort: 32767
    - name: filenet-udp
      port: 32767
      nodePort: 32767
      protocol: UDP
    - name: unknown
      port: 32765
      nodePort: 32765
    - name: unknown-udp
      port: 32765
      nodePort: 32765
      protocol: UDP
  selector:
    app: nfs-provisioner

不过,您将不得不在kubelet上更改nodePort范围(--service-node-port-range)。这样便可以使用2049111

例如,您还可以更改NFS服务器为2049(nfs)和111(portmapper)侦听的端口,这样就不必更改--service-node-port-range