前言

最近呢也是在一直研究docker容器热迁移,在网上查阅了大量相关的资料,并且参照网上例子自己在去实现,这个过程中出现很多问题,就比如按照很多教程操作,最后没有达到预期效果。所有在这写了一篇总结,也是对自己学习的巩固。

技术:Checkpoint/Restore

一、本地环境

1.系统环境

Centos7.6 $ lsb_release -a                                           
LSB Version:	:core-4.1-amd64:core-4.1-noarch
Distributor ID:	CentOS
Description:	CentOS Linux release 7.8.2003 (Core)
Release:	7.8.2003
Codename:	Core

实测 CentOS Linux release 7.9.2009也行

2.内核版本

Centos7.6 $ uname -a
Linux bogon 5.10.2-1.el7.elrepo.x86_64 #1 SMP Sun Dec 20 09:53:23 EST 2020 x86_64 

实测 3.10版本也行

3.Docker版本

Centos7.6 $ docker version
Client:
 Version:      17.06.0-ce
 API version:  1.30
 Go version:   go1.8.3
 Git commit:   02c1d87
 Built:        Fri Jun 23 21:20:36 2017
 OS/Arch:      linux/amd64
 
Server:
 Version:      17.06.0-ce
 API version:  1.30 (minimum version 1.12)
 Go version:   go1.8.3
 Git commit:   02c1d87
 Built:        Fri Jun 23 21:21:56 2017
 OS/Arch:      linux/amd64
 Experimental: true
 
实测 17.12.1-ce不行

4.CRIU版本

Centos7.6 $ criu -V
Version: 3.12

在这里插入图片描述

此时CRIU有内存快照不可用的警告,最好可以将其解决,不过不影响本次热迁移实现。

5.daemon.json

Centos7.6 $ cat /etc/docker/daemon.json 
{
"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"] ,
"experimental": true
}

以上环境皆为本次实现所用环境,其他环境除上述提到过的都没有去验证。(软件安装或者内核更新可以自行查阅资料)

Docker卸载与重装
Centos更新内核

重启docker服务

systemctl daemon-reload
systemctl restart docker

二、容器自身迁移

先使用bash脚本进行验证

//创建容器
docker run -d --name looper2 --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'

在这里插入图片描述

//新建检查点
docker checkpoint create looper2 checkpoint1

在这里插入图片描述
此时容器状态从Up变为Exited
在这里插入图片描述

此时程序已经运行到当前状态

在这里插入图片描述

//还原检查点
docker start --checkpoint checkpoint1 looper2

还原后日志能够重新续接上次的打印,符合预期。
在这里插入图片描述
在这里插入图片描述

三、跨容器迁移

此时用相同的命令创建一个容器looper2-clone,创建之后马上暂停,避免写入太多日志

docker run -d --name looper2-clone --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'
docker stop looper2-clone

在这里插入图片描述
在这里插入图片描述
将容器looper2的检查点文件,拷贝到looper2-clone,要不然looper2-clone找不到检查点会迁移失败
在这里插入图片描述

//迁移
docker start --checkpoint checkpoint1 looper2-clone

此时日志直接跳到了checkpoint1检查点运行的地方,然后继续运行,符合预期。
在这里插入图片描述

四、多个进程运行时容器迁移

先正常创建个容器,然后将在容器里写几个程序,为了方便查看热迁移是否生效,我都是采用写文件的方式来观察执行情况。

docker run -id --security-opt=seccomp:unconfined --name test -h test test:1222 /usr/sbin/init

/root/app.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

int main()
{
    int i = 0;
    int j = 0;
    char buff[128] = {'\0'};
    char tmp[128] = {'\0'};
    pid_t fpid;
    fpid=fork();
    if (fpid == 0) {
        while(j < 100000)
        {
            memset(tmp,0,sizeof(tmp));
            sprintf(tmp,"echo \"fork:%d\">>/root/1",j);
            system(tmp);
            j++;
            sleep(1.5);
        }
    }
    while(i < 200000)
    {
        memset(buff,0,sizeof(buff));
        sprintf(buff,"echo \"count:%d\">>/root/1",i);
        system(buff);
        i++;
        sleep(1);
    }
    return 0;
}

编译:gcc -o app app.c

test.sh

#/bin/bash
/root/app &

for a in {1..1000000}
do
    echo "count:$a">>/root/2
    sleep 1
done

/etc/rc.local

#!/bin/bash
# THIS FILE IS ADDED FOR COMPATIBILITY PURPOSES
#
# It is highly advisable to create own systemd services or udev rules
# to run scripts during boot instead of using this file.
#
# In contrast to previous versions due to parallel execution during boot
# this script will NOT be run after all other services.
#
# Please note that you must run 'chmod +x /etc/rc.d/rc.local' to ensure
# that this script will be executed during boot.

touch /var/lock/subsys/local

sleep 1
/root/test.sh &
/bin/bash

exit 0

chmod +x /etc/rc.d/rc.local

//提交成镜像
docker commit -p test test:1122

先将当前运行容器全部删除,方便观察

docker kill $(docker ps -q)
docker rm $(docker ps -a)"

开始进行容器热迁移实现

//容器创建
docker run -id --security-opt=seccomp:unconfined --name test -h test test:1222 /etc/rc.local

进入容器查看运行情况:
在这里插入图片描述

//创建检查点
docker checkpoint create test checkpoint2

在这里插入图片描述
实际操作过程中因为创建检查点之前时程序依然还在执行,所有上上图仅供参考

//迁移
docker start --checkpoint checkpoint2 test

在这里插入图片描述
在这里插入图片描述

迁移后程序能接着上次检查点继续执行,符合预期。

回滚

我们可以迁移后让容器内程序继续运行一段时间,然后重新用检查点checkpoint2进行迁移,这样可以实现程序运行状态的回滚。

docker start --checkpoint checkpoint2 test

休息一段时间

docker stop test
//重新进行迁移
docker start --checkpoint checkpoint2 test

此时程序运行状态:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
迁移后容器实现了回滚的功能,程序运行状态回滚到之前的运行状态,符合预期。

至此,容器热迁移基本实现。容器内进程加速,容器内进程回退满足要求。

跨主机容器热迁移我也验证通过,和上面跨容器迁移类似,需要将检查点文件拷贝到另一个主机存放检查点的目录
需要保证两个主机容器环境一下,宿主机环境一样,避免出现其他问题

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐