【问题标题】:How OpenVZ boot OS?OpenVZ如何引导操作系统?
【发布时间】:2015-08-03 22:13:56
【问题描述】:

我购买了基于 OpenVZ 虚拟化的 VPS,并启用了 Debian 客户操作系统。

Guest /boot 目录为空。 /etc/inittab 为空。

操作系统初始化过程是如何进行的?

OpenVZ容器的reboot是什么意思?

【问题讨论】:

  • OpenVZ 是一种容器技术,很像 Docker。 OpenVZ 来宾只是一个进程树,其中包含与主主机操作系统隔离的资源(例如网络堆栈)。

标签: linux debian virtualization boot openvz


【解决方案1】:

经过研究,我将vzctl 工具克隆为有关启动/停止的主要工作:

git clone https://github.com/OpenVZ/vzctl.git
git clone https://github.com/OpenVZ/libvzctl.git

vzctl 使用libvzctl,您可以在其中找到https://github.com/OpenVZ/libvzctl/blob/master/lib/env.c#L783

int exec_init(struct start_param *param)
{
   char cid[STR_SIZE];
   char *argv[] = {"init", "-z", "      ", NULL};
   char *envp[] = {"HOME=/", "TERM=linux", cid, NULL};
   char **env;
   int errcode = 0;
   logger(1, 0, "Starting init");

   if (stat_file("/sbin/init") == 0 &&
                   stat_file("/ertc/init") == 0  &&
                   stat_file("/bin/init") == 0)
           errcode = VZCTL_E_BAD_TMPL;

   if (write(param->err_p[1], &errcode, sizeof(errcode)) == -1)
           logger(-1, errno, "exec_init: write(param->err_p[1]");

   snprintf(cid, sizeof(cid), "container="SYSTEMD_CTID_FMT, EID(param->h));
   env = makeenv(envp, &param->h->env_param->misc->ve_env);
   if (env == NULL)
           return VZCTL_E_NOMEM;

   execve("/sbin/init", argv, env);
   execve("/etc/init", argv, env);
   execve("/bin/init", argv, env);
   free_ar_str(env);
   free(env);

   return VZCTL_E_BAD_TMPL;
}

https://github.com/OpenVZ/libvzctl/blob/master/lib/env.c#L103停止:

int real_env_stop(int stop_mode)
{
  logger(10, 0, "* stop mode %d", stop_mode);
  close_fds(1, -1);
  /* Disable fsync. The fsync will be done by umount() */
  configure_sysctl("/proc/sys/fs/fsync-enable", "0");
  switch (stop_mode) {
  case M_HALT: {
          char *argv[] = {"halt", NULL};
          char *argv_init[] = {"init", "0", NULL};
          execvep(argv[0], argv, NULL);
          execvep(argv_init[0], argv_init, NULL);
          break;
  }
  case M_REBOOT: {
          char *argv[] = {"reboot", NULL};
          execvep(argv[0], argv, NULL);
          break;
  }
  case M_KILL:
          return syscall(__NR_reboot, LINUX_REBOOT_MAGIC1,
                  LINUX_REBOOT_MAGIC2,
                  LINUX_REBOOT_CMD_POWER_OFF, NULL);
  }
  return -1;
}

在调用/sbin/init vzctl 之前进行一些检查(例如系统是否已经运行或挂载,是否存在某些文件等),如果需要,请停止,挂载 fs,进行一些独立的 chroot 模拟,然后执行/sbin/init

结论 OpenVZ 不使用来自客户操作系统的grub/linux-image/initrd 并直接调用第一个找到的对象:

"/sbin/init"
"/etc/init"
"/bin/init"

在来宾操作系统中。为了阻止它使用

halt
init 0
reboot

来自来宾操作系统。从用户的角度来看,容器初始化(安全、隔离、挂载等)对来宾操作系统启动过程不感兴趣。

【讨论】:

    【解决方案2】:

    OpenVZ VPS 本质上是作为主机系统中的沙盒进程树运行的。因此,它没有自己的引导加载程序或内核,并且通常在 /boot 中没有任何文件。

    OpenVZ VPS 是通过让主机系统在特殊环境中运行/bin/init 来启动的,这样它就与主机系统隔离,因此它认为自己是 PID 1。我不完全确定详细信息,因为 Parallels 没有详细记录它。

    对于使用 systemd init 而不是 SysV init 的 Linux 系统,空的或丢失的 /etc/inittab 是正常的。当前版本的 Debian 默认使用 systemd;此行为并非特定于 OpenVZ。

    我不完全确定在 OpenVZ VPS 中运行 reboot 是如何工作的,但我想主机内核必须对容器内的 reboot() 系统调用进行一些特殊处理,以便它导致主机内核来停止或重新启动容器,而不是整个系统。

    【讨论】:

    • 似乎我在容器中的操作系统使用 upstart /sbin/init 并且该脚本在 OpenVZ 启动时执行。内核initrdgrub根本没有使用。
    猜你喜欢
    • 2015-09-24
    • 2014-09-01
    • 2019-01-30
    • 1970-01-01
    • 2011-09-16
    • 1970-01-01
    • 2010-10-24
    • 2013-03-25
    • 2011-03-18
    相关资源
    最近更新 更多