赞
踩
最近呢也是在一直研究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服务
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
此时程序运行状态:
迁移后容器实现了回滚的功能,程序运行状态回滚到之前的运行状态,符合预期。
至此,容器热迁移基本实现。容器内进程加速,容器内进程回退满足要求。
跨主机容器热迁移我也验证通过,和上面跨容器迁移类似,需要将检查点文件拷贝到另一个主机存放检查点的目录
需要保证两个主机容器环境一下,宿主机环境一样,避免出现其他问题
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。