最近要上云,所以在自己的机器上自己先用一下;估计步骤是使用  docker -- > k8s ;

虽然在windwos机器上也装了 Docker Desktop,总觉得和安装在linux下的docker有所差异,但不知道是哪里差异,直到看了一篇文章才清楚:

Docker使用:  Namespace、Cgroups、以及 rootfs 三大技术构建出来的隔离环境,在linux环境上,docker其实是起到了一个启动代理,通过设置一大堆启动参数,给应用进程配置好运行环境;其实docker本身并没有一个独立的运行环境。

  • Namespace:作用是“隔离”,让应用进程只看到该Namespace内的“世界”;
    • 实现方式:
      在创建进程时(clone),增加Namespace参数
      查看进程的namespace: /proc/pid/ns/*
      目前linux实现了六种namespace(https://blog.csdn/shichaog/article/details/41378145):
      • mount命名空间(CLONE_NEWS, Linux2.4.19) :

        用于隔离一组进程看到的文件系统挂载点集合,即处于不同mount 命名空间的进程看到的文件系统层次很可能是不一样的。mount()和umount()系统调用的影响不再是全局的而只影响其调用进程指向的命名空间。mount命名空间的一个应用类似chroot,然而和chroot()系统调用相比,mount 命名空间在安全性和扩展性上更好

      • UTS命名空间(CLONE_NEWUTS, Linux2.6.19):
        隔离了两个系统变量,系统节点名和域名;UTS赋予了每个容器各自的主机名和 网络信息服务名(NIS) (Network Information Service),这使得初始化和配置脚本能够根据不同的名字进行裁剪。

      • IPC namespaces (CLONE_NEWIPC, Linux 2.6.19):
        隔离进程间通信资源,具体来说就是System V IPC objects and (since Linux2.6.30) POSIX message queues;这些机制的共同特点是由其特点而非文件系统路径名标识。每一个IPC命名空间尤其自己的System V IPC标识符和POSIX 消息队列文件系统。

      • PID namespaces (CLONE_NEWPID, Linux 2.6.24):
        隔离进程ID号命名空间,话句话说就是位于不同进程ID命名空间的进程可以有相同的进程ID号,PID命名空间的最大的好处是在主机之间移植container时,可以保留container内的ID号,PID命名空间允许每个container拥有自己的init进程(ID=1),init进程是所有进程的祖先,负责系统启动时的初始化和作为孤儿进程的父进程
        从特殊的角度来看PID命名空间,就是一个进程有两个ID,一个ID号属于PID命名空间,一个ID号属于PID命名空间之外的主机系统,此外,PID命名空间能够被嵌套

      • Network namespaces (CLONE_NEWNET, Linux2.6.24开始结束于 Linux 2.6.29)
        用于隔离和网络有关的资源,这就使得每个网络命名空间有其自己的网络设备、IP地址、IP路由表、/proc/net目录、端口号等等。
        从网络命名空间的角度看,每个container拥有其自己的网络设备(虚拟的)和用于绑定自己网络端口号的应用程序。主机上合适的路由规则可以将网络数据包和特定container相关的网络设备关联。例如,可以有多个web 服务器,分别存在不同的container中,这就使得这些web 服务器可以在其命名空间中绑定80端口号。

      • User namespaces (CLONE_NEWUSER, 起始于 Linux2.6.23 完成于 Linux 3.8) :
        隔离用户和组ID空间,换句话说,一个进程的用户和组ID在用户命名空间之外可以不同于命名空间之内的ID,最有趣的是一个用户ID在命名空间之外非特权,而在命名空间内却可以是具有特权的。这就意味着在命名空间内拥有全部的特权权限,在命名空间之外则不是这样。
        自Linux3.8开始,非特权进程可以创建用户命名空间,由于非特权进程在user命名空间内具有root权限,命名空间内非特权应用程序可以使用以前只有root能够使用的一些功能。

  • Cgroups:作用是“限制”,限制应用进程可以使用到的资源;
    • 实现方式:
      /sys/fs/cgroup 中配置对应用进程的限制,目前常用的是cpu和内存,对磁盘的限制比较麻烦不常用;
    • 问题:给系统监控带来的问题:
      系统监控,是从/proc/中获取资源数据的,应用程序缺省是从/proc下读取数据的,而不是限制后的资源配置;
      所以要把/var/lib/lxcfs/proc/*  挂接到 容器中的 /proc/* 下,这样容器内才会看到的是实际限制后的资源配置;
      ---- 譬如没有对java启动参数做限制,让java根据系统资源自动设置,如果看到的是宿主机的资源,java使用的资源就会大大超过docker的限制;
       
  • rootfs:为应用进程创建一个独立的文件系统;
    • 实现
      通过pivot_root/chroot来实现;
      在切换前,可以mount本地目录进来,这样这些目录的读写,其实是在宿主机的目录中进行读写,容器中生成的数据,在宿主机上能直接看到;
    • 问题:
      由于mount本地目录,是在docker里进行mount的,因此在宿主机上是看不到这个mount的;
      如果采用 docker commit进行打包,在宿主机上看到的还是原来的这些目录,打包的还是mount之前的目录,而不是mount以后的内容;
       

这样,其实docker启动的应用,还是直接运行在宿主机上,和普通的程序一样,直接调用宿主机的内核;---- 在宿主机上,通过ps可以看到docker启动的应用进程 (这也就是为什么说,docker只启动一个进程的原因);

而在windows系统中,linux程序是无法调用windows的内核的,所以Docker Desktop是做了一层虚拟机,真正的虚拟机来支持linux程序的运行;

既然这样,那就自己安装一个虚拟机(准备采用virtualbox,不用Docker Desktop来模拟了),安装linux系统(CentOS或Ubuntu),这样能更好的模拟docker在linux环境下的运行(包括要安装k8s,也需要linux环境)

 

注:

还有一些资源,namespace无法隔离的,譬如时间;在容器里修改的时间,是对整个宿主机都起作用的;

更多推荐

windowns上的DockerDesktop 和 Linux下docker的差别