【kubernetes/k8s源码分析】 k8s emptydir storage 源码分析

       EmptyDir 类型:同一个pod内的容器都能读写 EmptyDir 中文件。一旦 pod 离开了宿主机,EmptyDir 中的数据就会被永久删除。所以目前 EmptyDir 类型的 volume主 要用作临时空间。

      缺省情况下,EmptyDir 是使用主机磁盘进行存储的,需要使用 tmpfs 作为 emptyDir 的可用存储资源也是可以的,只需要在创建 emptyDir 卷时增加一个 emptyDir.medium 字段的定义,并赋值为 "Memory" 即可。

 

根据官方给出的建议,emptyDir可以在以下几种场景下使用:

  • 临时空间,例如基于磁盘的合并排序
  • 设置检查点以从崩溃事件中恢复未执行完毕的长计算
  • 保存内容管理器容器从Web服务器容器提供数据时所获取的文件

 

$ cat emtptydir.yaml 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql-emptydir
  labels:
    app: wordpress-emptydir
    tier: mysql-emptydir
spec:
  selector:
    matchLabels:
      app: wordpress-emptydir
      tier: mysql-emptydir
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: wordpress-emptydir
        tier: mysql-emptydir
    spec:
      containers:
        - image: mysql:5.6
          name: mysql-emptydir
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: changeme
          ports:
            - containerPort: 3306
              name: mysql
          volumeMounts:
            - name: mysql-persistent-storage
              mountPath: /var/lib/mysql
      volumes:
        - name: mysql-persistent-storage
          emptyDir: {}

 

 operationExecutor.MountVolume

       -->  GenerateMountVolumeFunc

            --> volumePlugin.NewMounter (第 1 章节讲解)

            --> volumeMounter.SetUp (第 2 章节讲解)

 

       emptyDir 源码实现路径为: pkg/volume/emptydir 目录

       emptyDir 插件名称为 kubernetes.io/empty-dir

type emptyDirPlugin struct {
	host volume.VolumeHost
}

var _ volume.VolumePlugin = &emptyDirPlugin{}

const (
	emptyDirPluginName           = "kubernetes.io/empty-dir"
	hugePagesPageSizeMountOption = "pagesize"
)

func getPath(uid types.UID, volName string, host volume.VolumeHost) string {
	return host.GetPodVolumeDir(uid, stringsutil.EscapeQualifiedNameForDisk(emptyDirPluginName), volName)
}

func (plugin *emptyDirPlugin) Init(host volume.VolumeHost) error {
	plugin.host = host

	return nil
}

 

1. NewMounter 函数

     这个主要实例化 emptyDir 结构,medium数据存储在disk / memory / hugepages

     mounter接口实现了 mount umount等一大堆方法

StorageMediumDefault   StorageMedium = ""          // use whatever the default is for the node, assume anything we don't explicitly handle is this
StorageMediumMemory    StorageMedium = "Memory"    // use memory (e.g. tmpfs on linux)
StorageMediumHugePages StorageMedium = "HugePages" // use hugepages
func (plugin *emptyDirPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, opts volume.VolumeOptions) (volume.Mounter, error) {
	return plugin.newMounterInternal(spec, pod, plugin.host.GetMounter(plugin.GetPluginName()), &realMountDetector{plugin.host.GetMounter(plugin.GetPluginName())}, opts)
}

func (plugin *emptyDirPlugin) newMounterInternal(spec *volume.Spec, pod *v1.Pod, mounter mount.Interface, mountDetector mountDetector, opts volume.VolumeOptions) (volume.Mounter, error) {
	medium := v1.StorageMediumDefault

	if spec.Volume.EmptyDir != nil { // Support a non-specified source as EmptyDir.
		medium = spec.Volume.EmptyDir.Medium
	}

	return &emptyDir{
		pod:             pod,
		volName:         spec.Name(),
		medium:          medium,
		mounter:         mounter,
		mountDetector:   mountDetector,
		plugin:          plugin,
		MetricsProvider: volume.NewMetricsDu(getPath(pod.UID, spec.Name(), plugin.host)),
	}, nil
}

 

2. Setup函数

    就是创建目录,看看SetUpAt进行哪些操作

// SetUp creates new directory.
func (ed *emptyDir) SetUp(fsGroup *int64) error {
	return ed.SetUpAt(ed.GetPath(), fsGroup)
}

 

3. SetUpAt函数

    3.1 IsLikelyNotMountPoint函数验证是否已经mount上了

notMnt, err := ed.mounter.IsLikelyNotMountPoint(dir)
// Getting an os.IsNotExist err from is a contingency; the directory
// may not exist yet, in which case, setup should run.
if err != nil && !os.IsNotExist(err) {
	return err
}

    3.2 根据 medium 类型执行不同操作,分别分析

     default 直接 disk,memory hugepages三种

switch ed.medium {
case v1.StorageMediumDefault:
	err = ed.setupDir(dir)
case v1.StorageMediumMemory:
	err = ed.setupTmpfs(dir)
case v1.StorageMediumHugePages:
	err = ed.setupHugepages(dir)
default:
	err = fmt.Errorf("unknown storage medium %q", ed.medium)
}

 

4. setupDir函数

    创建目录,权限0777,比较简单就是验证权限

// setupDir creates the directory with the default permissions specified by the perm constant.
func (ed *emptyDir) setupDir(dir string) error {
	// Create the directory if it doesn't already exist.
	if err := os.MkdirAll(dir, perm); err != nil {
		return err
	}

  	// stat the directory to read permission bits
	fileinfo, err := os.Lstat(dir)
	if err != nil {
		return err
	}

 

5. setupTmpfs函数

    也需要创建目录,最后也是需要mount操作,将tmpfs挂载到 dir目录

// setupTmpfs creates a tmpfs mount at the specified directory.
func (ed *emptyDir) setupTmpfs(dir string) error {
	if ed.mounter == nil {
		return fmt.Errorf("memory storage requested, but mounter is nil")
	}
	if err := ed.setupDir(dir); err != nil {
		return err
	}
	// Make SetUp idempotent.
	medium, isMnt, err := ed.mountDetector.GetMountMedium(dir)
	if err != nil {
		return err
	}
	// If the directory is a mountpoint with medium memory, there is no
	// work to do since we are already in the desired state.
	if isMnt && medium == v1.StorageMediumMemory {
		return nil
	}

	klog.V(3).Infof("pod %v: mounting tmpfs for volume %v", ed.pod.UID, ed.volName)
	return ed.mounter.Mount("tmpfs", dir, "tmpfs", nil /* options */)
}

 

总结:

     比较简单,就是pod删除了,数据就没有了

     三种模式,默认直接存disk,创建目录

     memory 挂载 tmpfs

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值