上一篇介绍创建存储pv的流程,那个有个存储需要挂载到容器里面才能被使用,下面还需要一个通用的接口felx去将存储挂载到容器里面。
kubernetes存储的使用和协助需要分别实现挂载和解挂的接口
kubernetes下面pkg/volume/volume.go
type Attacher interface {
// 挂载存储到主机
Attach(spec *Spec, nodeName types.NodeName) (string, error)
// 检查存储是否以及挂载
VolumesAreAttached(specs []*Spec, nodeName types.NodeName) (map[*Spec]bool, error)
// 等待存储被挂载
WaitForAttach(spec *Spec, devicePath string, pod *v1.Pod, timeout time.Duration) (string, error)
// 获取挂载路径
GetDeviceMountPath(spec *Spec) (string, error)
// 格式化并挂载到pod下的目录
MountDevice(spec *Spec, devicePath string, deviceMountPath string) error
}
下面解挂的接口
type Detacher interface {
// 从主机上面解挂
Detach(deviceName string, nodeName types.NodeName) error
// 解挂pod下的目录
UnmountDevice(deviceMountPath string) error
}
介绍完接口了,那么第三方的存储如何对接呢,那就是flexvolume,它就是通过调用第三方存储的二进制可执行文件去使用存储
具体看它的代码实现pkg/volume/flexvolume/attacher.go,
这是加载的例子
func (a *flexVolumeAttacher) Attach(spec *volume.Spec, hostName types.NodeName) (string, error) {
call := a.plugin.NewDriverCall(attachCmd)
call.AppendSpec(spec, a.plugin.host, nil)
call.Append(string(hostName))
status, err := call.Run()
if isCmdNotSupportedErr(err) {
return (*attacherDefaults)(a).Attach(spec, hostName)
} else if err != nil {
return "", err
}
return status.DevicePath, err
}
这是一个挂载的例子
func (a *flexVolumeAttacher) MountDevice(spec *volume.Spec, devicePath string, deviceMountPath string) error {
// Mount only once.
alreadyMounted, err := prepareForMount(a.plugin.host.GetMounter(a.plugin.GetPluginName()), deviceMountPath)
if err != nil {
return err
}
if alreadyMounted {
return nil
}
call := a.plugin.NewDriverCall(mountDeviceCmd)
call.Append(deviceMountPath)
call.Append(devicePath)
call.AppendSpec(spec, a.plugin.host, nil)
_, err = call.Run()
if isCmdNotSupportedErr(err) {
// Devicepath is empty if the plugin does not support attach calls. Ignore mountDevice calls if the
// plugin does not implement attach interface.
if devicePath != "" {
return (*attacherDefaults)(a).MountDevice(spec, devicePath, deviceMountPath, a.plugin.host.GetMounter(a.plugin.GetPluginName()))
} else {
return nil
}
}
return err
}
如果对driver感兴趣看,pkg/volume/flexvolume/driver-call.go,就是通过golang的os/exec去调用二进制文件。
这样我们的第三放存储实现这些接口就可以被k8s调用了。那么kubelet怎么知道你的存储插件在那里呢?答案是通过
–volume-plugin-dir指定你存储插件的位置,默认值是/usr/libexec/kubernetes/kubelet-plugins/volume/exec/。把你的二进制文件放到这个目录下面,这个和cni的执行是一样的。