【kubernetes/k8s源码分析】 csi driver nfs 源码分析

https://github.com/kubernetes-csi/csi-driver-nfs

 

    nfs csi 的实现,其实这里不支持动态storageclass,只支持 mount 操作,看看怎么实现的

 

  •     endpoint:csi socket
  •     nodeid: node id 也很好理解

Usage:
  NFS [flags]

Flags:
      --alsologtostderr                  log to standard error as well as files
      --endpoint string                  CSI endpoint
  -h, --help                             help for NFS
      --log_backtrace_at traceLocation   when logging hits line file:N, emit a stack trace (default :0)
      --log_dir string                   If non-empty, write log files in this directory
      --logtostderr                      log to standard error instead of files (default true)
      --nodeid string                    node id
      --stderrthreshold severity         logs at or above this threshold go to stderr (default 2)
  -v, --v Level                          log level for V logs
      --vmodule moduleSpec               comma-separated list of pattern=N settings for file-filtered logging

 

 1. NewDriver 函数

    实例化 driver,包括设置 AddVolume权限,AddController权限(这里未实现,可以修改这些实现动态Provision功能)

func NewDriver(nodeID, endpoint string) *driver {
	glog.Infof("Driver: %v version: %v", driverName, version)

	d := &driver{}

	d.endpoint = endpoint

	csiDriver := csicommon.NewCSIDriver(driverName, version, nodeID)
	csiDriver.AddVolumeCapabilityAccessModes([]csi.VolumeCapability_AccessMode_Mode{csi.VolumeCapability_AccessMode_MULTI_NODE_MULTI_WRITER})
	// NFS plugin does not support ControllerServiceCapability now.
	// If support is added, it should set to appropriate
	// ControllerServiceCapability RPC types.
	csiDriver.AddControllerServiceCapabilities([]csi.ControllerServiceCapability_RPC_Type{csi.ControllerServiceCapability_RPC_UNKNOWN})

	d.csiDriver = csiDriver

	return d
}

 

2. Run 函数

    初始化 Identity Controller Node这三个RPC实现

func (d *driver) Run() {
	s := csicommon.NewNonBlockingGRPCServer()
	s.Start(d.endpoint,
		csicommon.NewDefaultIdentityServer(d.csiDriver),
		// NFS plugin has not implemented ControllerServer
		// using default controllerserver.
		getControllerServer(d.csiDriver),
		NewNodeServer(d))
	s.Wait()
}

 

3. 启动GRPC 服务

func (s *nonBlockingGRPCServer) Start(endpoint string, ids csi.IdentityServer, cs csi.ControllerServer, ns csi.NodeServer) {

	s.wg.Add(1)

	go s.serve(endpoint, ids, cs, ns)

	return
}

 

4. DefaultIdentityServer

    实现了这三个方法,执行操作会查看插件有没有设置权限

  • func (ids *DefaultIdentityServer) GetPluginInfo
  • func (ids *DefaultIdentityServer) Probe
  • func (ids *DefaultIdentityServer) GetPluginCapabilities

 

5. ControllerServer

    这里未实现,这里可以做一些文章,实现动态provision功能,可以这样这样修改,创建目录,然后让pod去挂载吧

type ControllerServer struct {
	*csicommon.DefaultControllerServer
}

func (cs ControllerServer) ControllerExpandVolume(ctx context.Context, req *csi.ControllerExpandVolumeRequest) (*csi.ControllerExpandVolumeResponse, error) {
	return nil, status.Error(codes.Unimplemented, "")
}

func getControllerServer(csiDriver *csicommon.CSIDriver) ControllerServer {
	return ControllerServer{
		csicommon.NewDefaultControllerServer(csiDriver),
	}
}

 

6. nodeServer

    这里实现也是如此简单,只是进行了mount操作

type nodeServer struct {
   *csicommon.DefaultNodeServer
}

 

 7. NodePublishVolume

      这个是 attacher 那个 csi 插件发送 GRPC 请求

      这个是查看挂载目录是否存在,存在就不处理了

targetPath := req.GetTargetPath()
notMnt, err := mount.New("").IsLikelyNotMountPoint(targetPath)
if err != nil {
	if os.IsNotExist(err) {
		if err := os.MkdirAll(targetPath, 0750); err != nil {
			return nil, status.Error(codes.Internal, err.Error())
		}
		notMnt = true
	} else {
		return nil, status.Error(codes.Internal, err.Error())
	}
}

if !notMnt {
	return &csi.NodePublishVolumeResponse{}, nil
}

    拿到挂载权限,rw / ro,server 与 share等

mo := req.GetVolumeCapability().GetMount().GetMountFlags()
if req.GetReadonly() {
	mo = append(mo, "ro")
}

s := req.GetVolumeContext()["server"]
ep := req.GetVolumeContext()["share"]
source := fmt.Sprintf("%s:%s", s, ep)

    啥也不说了,直接进行 mount操作,注意容器需要有权限去挂载

- name: nfs
  securityContext:
    privileged: true
    capabilities:
      add: ["SYS_ADMIN"]
    allowPrivilegeEscalation: true
mounter := mount.New("")
err = mounter.Mount(source, targetPath, "nfs", mo)
if err != nil {
	if os.IsPermission(err) {
		return nil, status.Error(codes.PermissionDenied, err.Error())
	}
	if strings.Contains(err.Error(), "invalid argument") {
		return nil, status.Error(codes.InvalidArgument, err.Error())
	}
	return nil, status.Error(codes.Internal, err.Error())
}

 

8. NodeUnpublishVolume

    这个操作更简单,如果已经mount上的,那就 umount呗

func (ns *nodeServer) NodeUnpublishVolume(ctx context.Context, req *csi.NodeUnpublishVolumeRequest) (*csi.NodeUnpublishVolumeResponse, error) {
	targetPath := req.GetTargetPath()
	notMnt, err := mount.New("").IsLikelyNotMountPoint(targetPath)

	if err != nil {
		if os.IsNotExist(err) {
			return nil, status.Error(codes.NotFound, "Targetpath not found")
		} else {
			return nil, status.Error(codes.Internal, err.Error())
		}
	}
	if notMnt {
		return nil, status.Error(codes.NotFound, "Volume not mounted")
	}

	err = mount.CleanupMountPoint(req.GetTargetPath(), mount.New(""), false)
	if err != nil {
		return nil, status.Error(codes.Internal, err.Error())
	}

	return &csi.NodeUnpublishVolumeResponse{}, nil
}

 

总结

    实现了csi nfs 插件,原型比较简单,只实现了 mount 与 umount 操作

    可以修改 controller那块,实现动态 provision 功能

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值