暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

mac 上学习k8s系列(16)进入docker for mac 的宿主机linux kit

        我们知道docker 是基于linux 系统的namespace + cgroup实现的进程隔离技术,在mac下并不能很好的支持,因此需要运行在虚拟机上,虚拟机和docker的区别在于,虚拟机多了一层hypervisor。FreeBSD 下的虚拟技术 bhyve (The BSD Hypervisor) 包含在了 FreeBSD 10.0 发行版中。而这个 xhyve 是基于 bhyve 的 Mac OS X 移植版本

https://github.com/machyve/xhyve

        Docker for Mac 也是在本地跑了一个虚拟机来运行 Docker,不过 Hypervisor 采用的是 xhyve,而 xhyve 又基于 Mac 自带的虚拟化方案 Hypervisor.framework,虚拟机里运行的发行版是 Docker 自己打包的 LinuxKitHyperKit是一个具有hyperisor能力的工具集,包含了基于 xhyve - macOS平台的KVM/bhyve (轻量级虚拟机和容器部署) 的完整hypervisor。HyperKit设计成上层组件诸如 VPNKit 和 DataKit 的接口。

注解

  1.  VPNKit:嵌入式虚拟网络库,VPNKit 是一个工具和服务集合用于帮助HyperKit虚拟机和主机VPN配置协作。https://github.com/moby/vpnkit

  2. HyperKit:OSX上运行的轻量级虚拟化工具包https://github.com/moby/hyperkit

  3. DataKit:现代化分布式组件框架https://github.com/moby/datakit

linuxkit是一个docker自己打包的linux镜像,非常小有点类似apline

https://github.com/linuxkit/linuxkit

        总结起来:docker for mac 是运行在mac上的虚拟机xhyve里,linux镜像linuxkit的实例里

        那么我们如何进入linuxkit呢?整体上有两大类方法:1,通过宿主机的tty或者socket进入。2,在linuxkit上运行容器,通过enterns进入。

     

        在早期的docker for mac 版本中,我们看到虚拟机的文件路径是:

/Users/Kamus/Library/Containers/com.docker.docker/Data/vms/0/Docker.raw

进入到这个文件的所在目录。可以看到tty这个软链接文件。

$ cd Users/Kamus/Library/Containers/com.docker.docker/Data/vms/0
$ ls -l
total 31067864
srwxr-xr-x 1 Kamus staff 0 7 4 12:22 00000002.000005f4
srwxr-xr-x 1 Kamus staff 0 7 4 12:22 00000002.00001000
srwxr-xr-x 1 Kamus staff 0 7 4 12:22 00000002.00001001
srwxr-xr-x 1 Kamus staff 0 7 4 12:22 00000002.0000f3a5
srwxr-xr-x 1 Kamus staff 0 7 4 12:22 00000003.000005f5
srwxr-xr-x 1 Kamus staff 0 7 4 12:22 00000003.00000948
-rw-r--r--@ 1 Kamus staff 63999836160 7 7 12:51 Docker.raw
-rw-r--r-- 1 Kamus staff 215040 7 4 12:22 config.iso
srwxr-xr-x 1 Kamus staff 0 7 4 12:22 connect
lrwxr-xr-x 1 Kamus staff 17 7 4 12:22 guest.000005f5 -> 00000003.000005f5
lrwxr-xr-x 1 Kamus staff 17 7 4 12:22 guest.00000948 -> 00000003.00000948
-rw-r--r-- 1 Kamus staff 2303 7 4 12:22 hyperkit.json
-rw-r--r-- 1 Kamus staff 4 7 4 12:22 hyperkit.pid
drwxr-xr-x 2 Kamus staff 64 11 21 2018 log
-rw-r--r-- 1 Kamus staff 36 11 21 2018 nic1.uuid
lrwxr-xr-x 1 Kamus staff 12 7 4 12:22 tty -> dev/ttys000

screen该文件即可连接到虚拟机的输出窗口中。

$ screen tty

在新的版本里(20.10.5)版本以后,使用socket代替了:

I think the new version of docker (my version is 20.10.5) uses socket instead of TTY to communicate with the virtual machine so you can use the nc command instead of the screen command.

    nc -U ~/Library/Containers/com.docker.docker/Data/debug-shell.sock
      ?????uname -a
      Linux docker-desktop 5.10.47-linuxkit #1 SMP PREEMPT Sat Jul 3 21:50:16 UTC 2021 aarch64 Linux

      可以看到,运行的镜像是linuxkit

              还可以使用更优雅的方式,临时建一个最小化的debian容器,指定容器运行在pid=host命名空间下,然后该容器运行nsenter命令

      $ docker run -it --rm --privileged --pid=host debian nsenter -t 1 -m -u -n -i sh
      Unable to find image 'debian:latest' locally
      latest: Pulling from library/debian
      6f2f362378c5: Pull complete
      Digest: sha256:118cf8f3557e1ea766c02f36f05f6ac3e63628427ea8965fb861be904ec35a6f
      Status: Downloaded newer image for debian:latest

       # uname -a
      Linux linuxkit-025000000001 4.9.125-linuxkit #1 SMP Fri Sep 7 08:20:28 UTC 2018 x86_64 Linux

      详细解释一下这条命令为什么就会登录进macOS中作为宿主机的VM里面。
      –rm表示在退出的时候就自动删除该容器;
      –privileged表示允许该容器访问宿主机(也就是我们想要登录的VM)中的各种设备;
      –pid=host表示允许容器共享宿主机的进程命名空间(namespace),或者通俗点儿解释就是允许容器看到宿主机中的各种进程;
      这些是docker在启动容器时候的参数设置,但是仅仅依靠这些参数还无法让我们直接登录到宿主机VM中,接下来解释最主要的nsenter命令。

      nsenter是一个小工具允许我们进入一个指定的namespace然后运行指定的命令,ns=namespace,enter=进入。
      namespace是容器技术的根基,基本上可以认为namespace就是一组隔离的资源,不同的进程可以看到不同的系统资源这里和这里有比较详细的关于namespace的介绍。
      可以从操作系统的/proc/[pid]/ns目录下一窥全貌。比如我们进入pid=1的ns目录下。可以看到有一共8种namespace。

      # pwd
      /proc/1/ns
      # ls -l
      total 0
      lrwxrwxrwx 1 root root 0 Jul 8 12:51 cgroup -> cgroup:[4026531835]
      lrwxrwxrwx 1 root root 0 Jul 8 12:51 ipc -> ipc:[4026531839]
      lrwxrwxrwx 1 root root 0 Jul 8 12:51 mnt -> mnt:[4026531840]
      lrwxrwxrwx 1 root root 0 Jul 8 12:51 net -> net:[4026531889]
      lrwxrwxrwx 1 root root 0 Jul 8 12:51 pid -> pid:[4026531836]
      lrwxrwxrwx 1 root root 0 Jul 8 12:51 pid_for_children -> pid:[4026531836]
      lrwxrwxrwx 1 root root 0 Jul 8 12:51 user -> user:[4026531837]
      lrwxrwxrwx 1 root root 0 Jul 8 12:51 uts -> uts:[4026531838]

      最后解释一下nsenter命令的选项。回顾一下命令是:nsenter -t 1 -m -u -n -i sh
      -t 1: 表示要进入哪个pid,1表示整个操作系统的主进程id
      -m: 进入mount namespace,挂载点
      -u: 进入UTS namespace,也就是上面我们演示的那个namespace
      -n: 进入network namespace,网络
      -i: 进入IPC namespace,进程间通信
      sh: 表示运行/bin/sh



      文章转载自golang算法架构leetcode技术php,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

      评论