K8s中的多容器Pod和Pod内容器间通信
容器(Container)常被⽤来解决⽐如微服务的单个问题,但在实际场景中,问题的解决往往需要多容器⽅案。本⽂会讨论将多个容器整合进单个Kubernetes Pod 中,以及Pod中的容器之间是如何通信的。
Kubernetes Pod 是什么?
⾸先我们来探讨下什么是Pod。Pod是Kubernetes中最⼩的可部署和管理单元。换句话讲,如果需要在Kubernetes中运⾏单个容器,那么你就得为这个容器创建⼀个Pod。同时,⼀个Pod可以包含多个容器,这些容器往往是紧耦合的。怎么样个紧耦合法呢?试着想象这么⼀个场景,⼀个Pod中的多个容器代表需要运⾏在同⼀个服务器上的多个进程。这种类⽐是合理的,因为在许多⽅⾯,Pod就类似于⼀台服务器。⽐如,通过localhost每个容器可以访问它所在Pod中的其它容器。
为什么Kubernetes将Pod⽽不是单个容器作为最⼩可部署单元呢?
进程间通信 共享内存尽管直接部署单个容器也许会更容易,但增加Pod这个新的抽象层会带来新的好处。容器是⼀个真实存在的实体,它代表⼀个具体的东西。这个“东西”可以是⼀个Docker容器,也可以是⼀个rkt容器。每种“东西”都有不同的⽤途。为了管理容器,Kubernetes需要更多的信息,⽐如重启策略(restart policy),它定义了当容器终⽌了时怎样重启容器;还有活性检测(liveness probe),它定义了如何从应⽤视⾓去检测容器中的进程是否活着,⽐如Web服务器进程是否能响应HTTP请求。
为了避免在容器这个已有的实体上增加这些新的属性,Kubernetes架构师们决定使⽤⼀个新的实体,那就是Pod。它逻辑地包含⼀个或多个容器。
为什么Kubernetes允许Pod中存在⼀个或多个容器?
Pod中的容器们运⾏在⼀个逻辑“主机”上。他们使⽤同⼀个⽹络命名空间(network namespace,换句话讲,就是同样的IP地址和端⼝空间),以及同样的IPC(inter-process communication,进程间通信)命名空间,他们还使⽤共享卷(shared volume)。这些特征使得Pod 内的容器能互相⾼效地通信。同时,Pod使得你可以将多个紧耦合的应⽤容器当做⼀个实体来管理。
那么,如果⼀个应⽤需要在同⼀台服务器上运⾏多个容器,为什么不把所有东西放在⼀个容器⾥⾯呢?好吧,⾸先,这会违反“⼀个容器⼀个进程”规范。这个规范很重要,因为当⼀个容器中有多个进程时,调试会变得⾮常困难,因为不同进程的⽇志会混在⼀起,⽽且很难去管理这些进程的⽣命周期。其次,为⼀个应⽤使⽤多个容器会更简单、更直接、能解耦软件依赖。⽽且,更细粒度的容器可以在团队间复⽤。
多容器Pod的⽤例
多容器Pod的主要⽬的是为了⽀持同时存在的(co-located)及同时被管理的(co-managed)帮助进程(helper process)。帮助进程有⼏种通⽤场景:
边车容器(sidecarcontainer):⽐如⽇志或数据变化监视器等。⼀个团队创建⽇志监视器(log watcher)后,它可以被各种应⽤使⽤。另⼀个边车容器的例⼦是⽂件或数据加载器,它负责为主容器产⽣数据。
代理(Proxy)、桥(bridge)和适配器(adapter):它们将主容器连接到外部世界。⽐如,Apache HTTP 服务器或nginx 会读取静态⽂件。它们还能被⽤作主容器中的web应⽤的反向代理(reverseproxy)。
当你在Pod中运⾏多层应⽤(⽐如WordPress)时,推荐的⽅式是为每层使⽤单独的Pod。最简单的理由是这样你就可以独⽴地扩展每层,并将他们分布在不同节点上。
Pod 中容器间的通信
在Pod中运⾏多个容器,使得它们之间的通信⾮常直接。他们⾃⼰的通信有⼏种⽅法。
通过共享卷通信
在Kubernetes中,Pod中的容器可以将共享卷当做⼀种简单和⾼效的共享数据⽅式。在⼤多数场景中,使⽤主机上的⼀个⽬录,并在多个容器间共享,是⼀种⾼效的⽅式。
Kubernetes volume(卷)使得在容器重启后数据能被保存下来。卷具有和Pod⼀样的⽣命周期。这意味着,只要Pod存在,卷就存在。如果Pod被删除了,即使⼀模⼀样的Pod被创建出来,原来Pod的共享卷也会被销毁,⼀个新的共享卷会被创建出来。
进程间通信(Inter-processCommunication,IPC)
Pod中的容器共享同⼀个IPC命名空间,这意味着它们可以使⽤标准的进程间通信⽅式来互相通信,⽐如SystemV信号量和POSIX共享内存。
容器间的⽹络通信
Pod中的容器可以通过“localhost”来互相通信,因为他们使⽤同⼀个⽹络命名空间。⽽且,对容器来说,hostname就是Pod的名称。因为Pod中的所有容器共享同⼀个IP地址和端⼝空间,你需要为每个需要接收连接的容器分配不同的端⼝。也就是说,Pod中的应⽤需要⾃⼰协调端⼝的使⽤。
在下⾯的例⼦中,我们会创建⼀个多容器Pod,其中⼀个容器中运⾏Nginx,它作为另⼀个容器中运⾏的web应⽤的反向代理。
(1)步骤1,为nginx配置⽂件创建⼀个ConfigMap。从80端⼝进来的HTTP请求会被转发到localhost上的5000端⼝。
(2)步骤2:创建⼀个两容器Pod,⼀个容器运⾏nginx,另⼀个容器运⾏简单的web应⽤。注意我们只为Pod定义了80端⼝。端⼝5000不能被从Pod外部访问到。
查看pod中的端⼝空间,能看到有80 和 5000端⼝。
(3)步骤3:将Pod暴露为⼀个 NodePort服务
(4)步骤4:确认服务
现在,就可以使⽤浏览器或者curl⼯具来访问这个web应⽤了。
nginx容器的80端⼝上收到的HTTP请求会被转发到web应⽤容器的5000端⼝。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论