近期接触容器技术时,经常看到各类比较容器与虚拟机区别的文章中会提到:容器是共享宿主机的内核,而虚拟机则是拥有自己独立的内核,所以不可能在Linux上用容器运行windows,但是用虚拟机则可以。
乍看下去,觉得Linux上无法运行windows是很自然的结论,然后突然升起一个疑问:Linux上无法运行windows容器,那Debian上可以运行Ubuntu容器吗?Ubuntu上又能运行CentOS容器吗?
从自己实际使用上看,Debian上确实有运行CentOS的docker容器,CentOS上确实也有运行Ubuntu的docker容器,那无法运行windows容器却能运行不同发行版Linux的根本原因是什么呢?
进一步探究:具体发行版Debian 10.0 Linux上能运行低版本如Debian 9.0的容器吗?能运行Debian11.0的容器吗?为什么?
这些的问题的底层其实都指向共享内核的确切含义,这里记录一下思考过程,以下观点均为个人分析推断,不一定准确,有疑义的小伙伴欢迎指正、探讨。
已经有很多文章对容器、虚拟机的区别进行了详细的对比,这里不再赘述,很多文章对比时都会引用类似如下图片:

左图中是在Host OS上运行Hypervisor(虚拟机监控器,virtual machine monitor),在Hypervisor提供的硬件模拟基础上运行有有多个Guest OS,每个Guest OS均有自己的独立内核,相当于为GuestOS提供了一个完全模拟的虚拟裸机,GuestOS其实无感知自身是运行在物理机上还是虚拟硬件上。
而右图中container是作为一个普通进程运行于Host OS上,所有进程共享Host OS的内核,而container的运行、编排则由中间的docker engine实现。
Linux® 内核是 Linux 操作系统(OS)的主要组件,也是计算机硬件与其进程之间的核心接口。它负责两者之间的通信,还要尽可能高效地管理资源。
之所以称为内核,是因为它在操作系统中就像果实硬壳中的种子一样,并且控制着硬件(无论是电话、笔记本电脑、服务器,还是任何其他类型的计算机)的所有主要功能,主要包括内存管理、进程管理、设备驱动程序、系统调用和安全防护,单纯的linux内核并不算我们传统意义上说的一个完整操作系统。
那么内核在整个系统中的具体作用到底是什么呢?
内核对上层屏蔽了底层硬件操作的细节,对其提供了统一的系统调用对硬件进行统一的操作。
但是系统调用接口一般比较原始,涉及和操作系统相关的细节,不同操作系统之间的系统调用基本完全不同,哪怕同系列的Linux与UNIX都不相同。
基于以上原因,一般应用程序是通过标准的运行库来使用系统调用,运行库的优点是本身是语言级别的,设计比较友好,标准、形式统一,不会随着操作系统或编译器的变化而变化。
Linux上的运行库即是glibc,其位于用户程序与系统调用之间,如下图:

Linux发行版就是一些组织和厂商将Linux内核、各类软件、库及文档组合起来,提供了完整各类常用工具、库(如gcc、dpkg、yum、glibc等),打包在一起作为一个完整的发行版操作系统提供给用户,其关系如下图:

由于不同发行版使用的都是同一个Linux内核,所以在内核的层面并不存在兼容性问题--具体来说对于运行在宿主机上的容器进程分三种情况:
回到文章一开始提出的几个问题:
Linux上为什么无法运行windows容器?
因为Linux内核与windows内核完全不是一个东西,windows程序不可能使用Linux内核的系统调用与硬件交互。
Debian上可以运行Ubuntu容器吗?Ubuntu容器又能运行CentOS容器吗?
根据发行版使用的具体内核版本,其可以基于其宿主机内核运行成功则可以,由于linux内核提供向后兼容(backward compatible),一般来说容器发行版内核<=宿主机内核版本的情况都是可以成功的,而>宿主机内核的情况下可能可以成功。
具体发行版Debian 10.0 Linux上能运行低版本如Debian 9.0的容器吗?能运行Debian11.0的容器吗?为什么?
和上面其实是一个分析思路。
转载请注明出处,原文地址:https://www.cnblogs.com/AcAc-t/p/linux_container_share_kernel_meaning.html
https://zh.wikipedia.org/zh-cn/Hypervisor
https://cloudacademy.com/blog/docker-vs-virtual-machines-differences-you-should-know/
https://www.redhat.com/zh/topics/linux/what-is-the-linux-kernel
https://book.douban.com/subject/3652388/
https://www.cnblogs.com/blog-yejy/p/9373850.html
https://stackoverflow.com/questions/32756988/what-is-meant-by-shared-kernel-in-docker
https://stackoverflow.com/questions/32841982/how-can-docker-run-distros-with-different-kernels
https://en.wikipedia.org/wiki/Linux_distribution
我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.
我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是
我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r
我是Google云的新手,我正在尝试对其进行首次部署。我的第一个部署是RubyonRails项目。我基本上是在关注thisguideinthegoogleclouddocumentation.唯一的区别是我使用的是我自己的项目,而不是他们提供的“helloworld”项目。这是我的app.yaml文件runtime:customvm:trueentrypoint:bundleexecrackup-p8080-Eproductionconfig.ruresources:cpu:0.5memory_gb:1.3disk_size_gb:10当我转到我的项目目录并运行gcloudprevie
我有一个存储主机名的Ruby数组server_names。如果我打印出来,它看起来像这样:["hostname.abc.com","hostname2.abc.com","hostname3.abc.com"]相当标准。我想要做的是获取这些服务器的IP(可能将它们存储在另一个变量中)。看起来IPSocket类可以做到这一点,但我不确定如何使用IPSocket类遍历它。如果它只是尝试像这样打印出IP:server_names.eachdo|name|IPSocket::getaddress(name)pnameend它提示我没有提供服务器名称。这是语法问题还是我没有正确使用类?输出:ge
我正在使用DMOZ的listofurltopics,其中包含一些具有包含下划线的主机名的url。例如:608609TheOuterHeaven610InformationandimagegalleryofMcFarlane'sactionfiguresforTrigun,Akira,TenchiMuyoandotherJapaneseSci-Fianimations.611Top/Arts/Animation/Anime/Collectibles/Models_and_Figures/Action_Figures612虽然此url可以在网络浏览器中使用(或者至少在我的浏览器中可以使用:
我正在关注Hartl的railstutorial.org并已到达11.4.4:Imageuploadinproduction.我做了什么:注册亚马逊网络服务在AmazonIdentityandAccessManagement中,我创建了一个用户。用户创建成功。在AmazonS3中,我创建了一个新存储桶。设置新存储桶的权限:权限:本教程指示“授予上一步创建的用户读写权限”。但是,在存储桶的“权限”下,未提及新用户名。我只能在每个人、经过身份验证的用户、日志传送、我和亚马逊似乎根据我的名字+数字创建的用户名之间进行选择。我已经通过选择经过身份验证的用户并选中了上传/删除和查看权限的框(而不
我正在尝试循环哈希数组。当我到达获取枚举器开始循环的位置时,出现以下错误:undefinedmethod`[]'fornil:NilClass我的代码如下所示:defextraireAttributs(attributsParam)classeTrouvee=falsescanTrouve=falseownerOSTrouve=falseownerAppTrouve=falseresultat=Hash.new(0)attributs=Array(attributsParam)attributs.eachdo|attribut|#CRASHESHERE!!!typeAttribut=a
在许多ruby类之间共享记录器实例的最佳(正确)方法是什么?现在我只是将记录器创建为全局$logger=Logger.new变量,但我觉得有更好的方法可以在不使用全局变量的情况下执行此操作。如果我有以下内容:moduleFooclassAclassBclassC...classZend在所有类之间共享记录器实例的最佳方式是什么?我是以某种方式在Foo模块中声明/创建记录器还是只是使用全局$logger没问题? 最佳答案 在模块中添加常量:moduleFooLogger=Logger.newclassAclassBclassC..
我正在尝试用Ruby(Rails)编写一个正则表达式,以便用户名的字符仅包含数字和字母(也没有空格)。我有这个正则表达式,/^[a-zA-Z0-9]+$/,但它似乎没有用,我在Rails中收到一个错误,说“The如果正则表达式使用多行anchor(^或$),这可能会带来安全风险。您是要使用\A和\z,还是忘记添加:multiline=>true选项?"我的user.rb模型中此实现的完整代码是:classUser我做错了什么以及如何修复此正则表达式,使其仅对数字和字母有效而不对空格有效?谢谢。 最佳答案 简短回答:使用/\A[a-z