runC的checkpoint功能模塊源碼分析

runC是什么?

RunC 是一個輕量級的工具鸥咖,它是用來運(yùn)行容器的燕鸽,只用來做這一件事,并且這一件事要做好啼辣。我們可以認(rèn)為它就是個命令行小工具啊研,可以不用通過 docker 引擎,直接運(yùn)行容器鸥拧。事實(shí)上党远,runC 是標(biāo)準(zhǔn)化的產(chǎn)物,它根據(jù) OCI 標(biāo)準(zhǔn)來創(chuàng)建和運(yùn)行容器富弦。而 OCI(Open Container Initiative)組織沟娱,旨在圍繞容器格式和運(yùn)行時制定一個開放的工業(yè)化標(biāo)準(zhǔn)。

概述

本文對runC的checkpoint功能模塊源碼進(jìn)行分析腕柜,主要包括:

  1. 梳理checkpoint功能模塊源碼的調(diào)用流程济似;
  2. 梳理checkpoint功能模塊源碼中用到的struct矫废、method和第三方庫;
  3. 梳理checkpoint功能模塊源碼中涉及的專業(yè)知識(需要學(xué)習(xí)的部分)砰蠢;

checkpoint功能模塊源碼的調(diào)用流程

runC源碼入口為:

runc/main.go

func main() {
    app := cli.NewApp()
    app.Name = "runc"
    app.Usage = usage
        ...

        app.Flags = []cli.Flag{
        ...
    }
    app.Commands = []cli.Command{
        checkpointCommand,
        ...
    }
    ...
}

由main()函數(shù)可知蓖扑,checkpointCommand是checkpoint功能模塊的入口,進(jìn)入checkpointCommand定義:

runc/checkpoint.go

var checkpointCommand = cli.Command{
    ...
    Flags: []cli.Flag{
        ...
    },
    Action: func(context *cli.Context) error {
        ...
        container, err := getContainer(context)
        ...
        
        options := criuOptions(context)
        ...
        return container.Checkpoint(options)
    },
}

由checkpointCommand定義可知台舱,checkpointCommand核心內(nèi)容由Flags和Action組成赵誓,F(xiàn)lags中各個flag的作用通過定義可以一目了然,接下來深入分析Action中定義的函數(shù)柿赊。

Action函數(shù)

由checkpointCommand定義可知俩功,Action函數(shù)核心內(nèi)容包括:container, err := getContainer(context) 、options := criuOptions(context)和container.Checkpoint(options)三個函數(shù)調(diào)用碰声,接下來逐個函數(shù)深入分析诡蜓。

container, err := getContainer(context)

函數(shù)getContainer(...)的作用是獲取需要checkpoint的容器實(shí)例,進(jìn)入函數(shù)getContainer(...)的定義:

runc/utils_linux.go

func getContainer(context *cli.Context) (libcontainer.Container, error) {
    ...
    factory, err := loadFactory(context)
    ...
    return factory.Load(id)
}

由getContainer(...)函數(shù)的定義可知胰挑,其作用是通過從狀態(tài)加載指定的容器實(shí)例并返回蔓罚,整個過程是由factory, err := loadFactory(context)和factory.Load(id)聯(lián)合完成的,接下來對它們的實(shí)現(xiàn)進(jìn)行深入分析瞻颂。

factory, err := loadFactory(context)

進(jìn)入loadFactory(context)函數(shù)定義:

runc/utils_linux.go

func loadFactory(context *cli.Context) (libcontainer.Factory, error) {
    ...
    return libcontainer.New(abs, cgroupManager, intelRdtManager,
        libcontainer.CriuPath(context.GlobalString("criu")),
        libcontainer.NewuidmapPath(newuidmap),
        libcontainer.NewgidmapPath(newgidmap))
}

由 loadFactory(...)函數(shù)的定義可知豺谈,該函數(shù)的主要作用就是根據(jù)指定配置創(chuàng)建一個容器實(shí)例并返回,該功能主要由libcontainer.New(...)函數(shù)完成贡这,進(jìn)入其定義:

runc/libcontainer/factory_linux.go

func New(root string, options ...func(*LinuxFactory) error) (Factory, error) {
    ...
    l := &LinuxFactory{
        Root:      root,
        InitPath:  "/proc/self/exe",
        InitArgs:  []string{os.Args[0], "init"},
        Validator: validate.New(),
        CriuPath:  "criu",
    }
    ...
    return l, nil
}

由New(...)函數(shù)的定義可知茬末,創(chuàng)建factory實(shí)例最終是由struct LinuxFactory{...}(runc/libcontainer/factory_linux.go)來實(shí)現(xiàn)的,該struct實(shí)現(xiàn)了Factory interface {...}(runc/libcontainer/factory_linux.go)盖矫。

factory.Load(id)

進(jìn)入factory.Load(id)函數(shù)定義:

runc/libcontainer/factory_linux.go

func (l *LinuxFactory) Load(id string) (Container, error) {
    ...
    c := &linuxContainer{
        ...
    }
    c.state = &loadedState{c: c}
    ...
    return c, nil
}

由factory.Load(id)函數(shù)的定義可知丽惭,創(chuàng)建容器實(shí)例最終是由linuxContainer struct{...}(runc/libcontainer/container_linux.go)來實(shí)現(xiàn)的,該struct實(shí)現(xiàn)了Container interface {...}(runc/libcontainer/container_linux.go)辈双。

至此责掏,就分析完了getContainer(context)函數(shù)的整個實(shí)現(xiàn)流程,接下來分析options := criuOptions(context)湃望。

options := criuOptions(context)

函數(shù)criuOptions(context)用來獲取checkpoint的配置項實(shí)例换衬,進(jìn)入函數(shù) criuOptions(context)的定義:

runc/restore.go

func criuOptions(context *cli.Context) *libcontainer.CriuOpts {
    imagePath := getCheckpointImagePath(context)
    ...
    }
    return &libcontainer.CriuOpts{
        ImagesDirectory:         imagePath,
        WorkDirectory:           context.String("work-path"),
        ParentImage:             context.String("parent-path"),
        LeaveRunning:            context.Bool("leave-running"),
        TcpEstablished:          context.Bool("tcp-established"),
        ExternalUnixConnections: context.Bool("ext-unix-sk"),
        ShellJob:                context.Bool("shell-job"),
        FileLocks:               context.Bool("file-locks"),
        PreDump:                 context.Bool("pre-dump"),
        AutoDedup:               context.Bool("auto-dedup"),
        LazyPages:               context.Bool("lazy-pages"),
        StatusFd:                context.Int("status-fd"),
    }
}

由criuOptions(context)函數(shù)定義可知,該函數(shù)就是用來獲取checkpoint的各配置項证芭,并最終創(chuàng)建一個CriuOpts實(shí)例
返回瞳浦。

container.Checkpoint(options)

函數(shù)container.Checkpoint(options)負(fù)責(zé)執(zhí)行容器的checkpoint操作,進(jìn)入其定義:

runc/libcontainer/container_linux.go

func (c *linuxContainer) Checkpoint(criuOpts *CriuOpts) error {
    ...
    if err := os.Mkdir(criuOpts.ImagesDirectory, 0700); err != nil && !os.IsExist(err) {
        return err
    }
    ...
        rpcOpts := criurpc.CriuOpts{
        ...
    }

    c.handleCriuConfigurationFile(&rpcOpts)

    ...
    var t criurpc.CriuReqType
    if criuOpts.PreDump {
        ...
    } else {
        ...
    }

    if criuOpts.LazyPages {
        ...
    }

    req := &criurpc.CriuReq{
        Type: &t,
        Opts: &rpcOpts,
    }

    // no need to dump all this in pre-dump
    if !criuOpts.PreDump {
        
        ...
    }

    err = c.criuSwrk(nil, req, criuOpts, nil)
    ...
    return nil
}

由container.Checkpoint(options)函數(shù)的定義可知檩帐,容器實(shí)例根據(jù)配置項將運(yùn)行的容器checkpoint出來术幔。

至此,就梳理完了runC的checkpoint功能模塊源碼的調(diào)用流程湃密。

checkpoint功能模塊源碼中用到的struct诅挑、method和第三方庫

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末四敞,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子拔妥,更是在濱河造成了極大的恐慌忿危,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件没龙,死亡現(xiàn)場離奇詭異铺厨,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)硬纤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門解滓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人筝家,你說我怎么就攤上這事洼裤。” “怎么了溪王?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵腮鞍,是天一觀的道長。 經(jīng)常有香客問我莹菱,道長移国,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任道伟,我火速辦了婚禮迹缀,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘皱卓。我一直安慰自己裹芝,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布娜汁。 她就那樣靜靜地躺著,像睡著了一般兄朋。 火紅的嫁衣襯著肌膚如雪掐禁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天颅和,我揣著相機(jī)與錄音傅事,去河邊找鬼。 笑死峡扩,一個胖子當(dāng)著我的面吹牛蹭越,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播教届,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼响鹃,長吁一口氣:“原來是場噩夢啊……” “哼驾霜!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起买置,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤粪糙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后忿项,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蓉冈,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年轩触,在試婚紗的時候發(fā)現(xiàn)自己被綠了寞酿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡脱柱,死狀恐怖伐弹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情褐捻,我是刑警寧澤掸茅,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站柠逞,受9級特大地震影響昧狮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜板壮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一逗鸣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧绰精,春花似錦撒璧、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至硫椰,卻和暖如春繁调,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背靶草。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工蹄胰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人奕翔。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓裕寨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子宾袜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評論 2 353