此‘容器’非彼容器
很多人可能曾经晓得了这一点:其实并不存在真正的Linux“container”,在Linux中没有所谓的“容器”。 家喻户晓,容器是应用Linux内核的两个个性(称为namespaces和cgroups)运行的惯例过程。 namespace能够为过程提供“视图”用来暗藏namespace之外的所有内容,从而为本人提供一个独立的运行环境,在其中运行的过程将无奈看到或烦扰其余过程。
命名空间蕴含以下这些:
• Hostname
• Process IDs
• File System
• Network interfaces
• Inter-Process Communication (IPC)
尽管我在下面说过,在名称空间中运行的过程不会烦扰到其余过程,然而一个过程实践上能够应用其所在的物理计算机上的所有资源,从而使其余过程无奈应用资源。 为了限度这一点,Linux推出了称为cgroups的个性。 过程能够像命名空间一样在cgroup中运行,然而cgroup限度了该过程能够应用的资源。 这些资源包含CPU,RAM,块设施I/O,网络I/O等,CPU通常受毫核(内核的千分之一)限度,而内存则受RAM字节数限度。 该过程自身能够失常运行,然而将只能应用cgroup限度范畴内的最大CPU,并且如果过程超出cgroup上设置的内存限度,则会呈现内存不足谬误。
对于namespace和cgroups能够参考之前的文章 什么是容器:namespces和cgroups
我想在这里指出的是cgroups和每个namespce类型都是独立的个性, 下面列出的命名空间的某些子集能够应用或基本不应用,你只能应用cgroup或两者的某种其余组合(好吧,你仍在应用名称空间和cgroup,但仅应用根目录cgroup)。命名空间和cgroup也可用于过程组(一个命名空间中运行的多个过程),这样的话,过程之间就能够看到彼此并进行交互,或者在单个cgroup中运行它们,这样这些过程将一起被限度在特定数量的CPU和RAM中。
组合的组合
当在Docker上以通常形式运行容器时,Docker会为每个容器创立namespace和cgroup并让它们一一映射, 这就是开发人员对容器的通常认识。
容器实质上是独立的孤岛,但它们可能具备映射到宿主机的存储卷或端口,以便它们能够进行通信。然而,通过一些额定的命令行参数,你能够应用单个namespace组合Docker容器。 首先,咱们创立一个nginx容器。
$ cat <<EOF >> nginx.conf> error_log stderr;> events { worker_connections 1024; }> http {> access_log /dev/stdout combined;> server {> listen 80 default_server;> server_name example.com www.example.com;> location / {> proxy_pass http://127.0.0.1:2368;> }> }> }> EOF$ docker run -d --name nginx -v `pwd`/nginx.conf:/etc/nginx/nginx.conf -p 8080:80 nginx
接着,在其中运行ghost容器,增加额定的参数以使其退出到nginx容器的命名空间之中。
$ docker run -d --name ghost --net=container:nginx --ipc=container:nginx --pid=container:nginx ghost
当初,nginx容器能够将本地主机上的申请间接代理到咱们的ghost容器,拜访http://localhost:8080/,可能... 这些命令创立一组在同一命名空间中运行的容器,在此命名空间中运行的Docker容器能够发现彼此并进行通信。
Pod是某种容器吗?
当初看到能够将namespace和cgroup与多个过程联合应用,而这,正是Kubernetes Pods的实质。 Pod容许指定要运行的容器,Kubernetes会以正确的形式主动设置namespace和cgroup,然而比上述形式要简单得多,因为Kubernetes不应用Docker网络(它应用CNI)
一旦以这种形式设置了容器,每个过程就会“感觉”在同一台机器上运行一样。 它们能够在localhost上相互通信,能够应用共享卷,甚至能够应用IPC或相互发送信号,例如HUP或TERM(在Kubernetes 1.7中具备共享的PID名称空间,Docker> = 1.13)。
假如当初要运行nginx并应用confd,confd会在每次增加/删除应用程序服务器时更新nginx配置并重新启动nginx。 假如有一个etcd服务器,其中蕴含后端应用程序服务器的IP地址,当列表更改时,confd能够失去告诉并写出新的nginx配置,并向Nginx发送HUP信号,从而使得nginx可能从新加载配置。
仅应用Docker时的形式是将nginx和confd都放在一个容器中,因为Docker只有一个入口点,所以须要使两个过程都运行在诸如supervisor之类的条件下,这是不太现实的,因为须要应用supervisord运行每个nginx正本。 更重要的是,Docker仅“理解”supervisord,因为这是entrypoint,它不理解每个过程,这意味着其余工具无奈通过Docker API获取该信息,Nginx可能会解体,然而Docker并不知道。
Kubernetes借助Pod来治理每个过程,从而洞悉每个过程的状态,这样,它能够通过API向用户提供相干状态信息,当服务解体时还能够提供重启或自动记录日志等服务。
Pod是伪装成API的容器
通过以这种形式将容器组合到Pod中,咱们本质上能够创立其他人能够应用的“ API”增加到Pods中的容器。 从失常的Web API角度来看,这不是API,而是其余Pod能够应用的形象API。
以下面的nginx + confd为例,confd对nginx过程无所不知,它所晓得的仅仅只是监督etcd中的值并将HUP信号发送到过程或运行命令,它运行的应用程序不应该是nginx,而能够是任意一种应用程序,这样就能够应用confd容器镜像和配置,并将其与任意数量不同类型的Pod替换。 能够在其中执行操作的pod通常称为“sidecar(边车)容器”,能够设想一下摩托车上边车的图像。
你还能够设想其余类型的形象,诸如istio之类的服务网格能够作为边车固定,无需更改主应用程序即可提供服务路由,遥测和策略执行。也能够应用多个sidecar,没有什么能够阻止你同时应用confd sidecar和istio sidecar。通过这种形式组合的应用程序,能够构建更加简单和牢靠的零碎,同时使单个app放弃简洁。