实测在该环境下,容器热迁移可用,热迁移成功与否与 docker 和 criu 版本强相关。
- # Docker 安装
- $ sudo yum install -y yum-utils
- $ sudo yum-config-manager \
- --add-repo \
- https://download.docker.com/linux/centos/docker-ce.repo
- $ sudo yum list docker-ce --showduplicates | sort -r
- $ sudo yum install docker-ce-17.06.0.ce
- $ sudo systemctl start docker
-
- # 启动Docker实验特征
- vim **/etc/docker/daemon.json
- + { "experimental": true }**
-
- # criu 安装
- $ sudo yum install criu -y
-
- # Go安装(可选)
- wget https://golang.org/dl/go1.15.6.linux-amd64.tar.gz
- tar -C /usr/local -xzf go1.15.6.linux-amd64.tar.gz
- vim /etc/profile
- + export PATH=$PATH:/usr/local/go/bin
- source /etc/profile
- # On the host
- $ 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'
-
- # wait a few seconds to give the container an opportunity to print a few lines, then
- $ docker checkpoint create looper2 checkpoint2
-
- # check your container & print log file
- $ docker logs looper2
-
- # On the client
- $ docker create --name looper-clone --security-opt seccomp:unconfined busybox \
- /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'
-
- $ docker start --checkpoint=checkpoint2 looper-clone
-
- # check your container
- $ docekr ps
- $ docker logs looper-clone
以上步骤将容器 looper2 的状态迁移到 looper-clone ,可实现当前容器、跨容器的状态迁移,甚至可以实现跨主机的迁移,只需将该目录 /var/lib/docker/{docker id}/checnkpoints/ 下面与检查点同名的文件夹迁移即可。
- /*************************************************************************
- > File Name : fork_test.c
- > Author : TL Song
- > EMail : songtianlun@frytea.com
- > Created Time : Wed 23 Dec 2020 08:46:47 AM CST
- ************************************************************************/
-
- #include <stdio.h>
- #include <unistd.h>
- #include <time.h>
- #include <sys/types.h>
-
- int main(int arg,char* argv[]) {
-
- int i = 0;
- time_t t;
- struct tm *timeinfo;
- // int 被 typedef为 pid_t
- pid_t pid=fork();
-
- // 当pid==0时,是子进程代码运行区域。其他则是父进程运行区域。
- if(pid<0) {
- printf("Create child process failure ...\n");
- }else if(pid==0) {
- //子进程执行体
- printf("Hi i am child process ,my processId is %i \n",getpid());
- i = 0;
- while (1) {
- sleep(1);
- time(&t);
- timeinfo = localtime(&t);
- printf("Child: %d %s\n", i++, asctime(timeinfo));
- fflush(stdout);
- if(i>100)
- break;
- }
- }
- else{
- //父进程执行体
- printf("parent process is run ,myid is %i \n",getpid());
- i = 0;
- while (1) {
- sleep(1);
- time(&t);
- timeinfo = localtime(&t);
- printf("Main : %d %s\n", i++, asctime(timeinfo));
- fflush(stdout);
- if(i>100)
- break;
- }
- }
- // 执行体结束标志
- if(pid==0) {
- printf("pid=%i child process end ... \n",getpid());
- }
- else {
- // 睡眠5s,等待子先进程结束
- sleep(5);
- printf("pid=%i Parent process End ... \n",getpid());
- }
-
- return 0;
- }