容器(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端口。

K8s中的多容器Pod和Pod内容器间通信的更多相关文章

  1. 【K8S学习笔记】Part3:同一Pod中多个容器间使用共享卷进行通信

    本文将展示如何使用共享卷(Volume)来实现相同Pod中的两个容器间通信. 注意:本文针对K8S的版本号为v1.9,其他版本可能会有少许不同. 0x00 准备工作 需要有一个K8S集群,并且配置好了 ...

  2. (译)Kubernetes中的多容器Pod和Pod内容器间通信

    原文:https://www.mirantis.com/blog/multi-container-pods-and-container-communication-in-kubernetes/Pave ...

  3. k8s中几个基本概念的理解,pod,service,deployment,ingress的使用场景

    k8s 总体概览 前言 Pod 副本控制器(Replication Controller,RC) 副本集(Replica Set,RS) 部署(Deployment) 服务(Service) ingr ...

  4. k8s 中的 Pod 细节了解

    k8s中Pod的理解 基本概念 k8s 为什么使用 Pod 作为最小的管理单元 如何使用 Pod 1.自主式 Pod 2.控制器管理的 Pod 静态 Pod Pod的生命周期 Pod 如何直接暴露服务 ...

  5. k8s 中的 service 如何找到绑定的 Pod 以及如何实现 Pod 负载均衡

    k8s 中的 service 如何找到绑定的 Pod 以及如何实现 Pod 负载均衡 前言 endpoint kube-proxy userspace 模式 iptables ipvs kernels ...

  6. k8s中初始化容器(init container)的作用及其使用方法

    概述 在容器的部署过程中,有的时候需要在容器运行之前进行一些预配置的工作,比如下载配置,判断某些服务是否启动,修改配置等一些准备的工作,想要实现这些功能,在k8s中可以使用初始化容器,在应用容器运行之 ...

  7. 在k8s中搭建可解析hostname的DNS服务

    2016-01-25更新 上篇文章总结k8s中搭建hbase时,遇到Pod中hostname的DNS解析问题,本篇将通过修改kube2sky源码来解决这个问题. 1 前言 kube2sky在Githu ...

  8. K8s中Pod健康检查源代码分析

    了解k8s中的Liveness和Readiness Liveness: 表明是否容器正在运行.如果liveness探测为fail,则kubelet会kill掉容器,并且会触发restart设置的策略. ...

  9. 如何为k8s中的pod配置QoS等级?

    1.概述 本文介绍如何为pod分配特定的QoS等级. 我们知道,在k8s的环境中,通过使用QoS等级来做决定,在资源紧张的时候,将哪些的pod进行驱逐,或者说如何对pod进行调度. OK,话不多说,让 ...

随机推荐

  1. 在MAX10上使用DDR3 IP的一个关于DQS/DQSn pin的错误解决办法

    MAX10 是Intel FPGA的CPLD中的一个特殊的芯片,因为它内部有CPLD的Flash结构,也有FPGA的Ram结构.具体的可以参考MAX10 Handbook文档. Max10 在外部存储 ...

  2. webpack打包时候去掉console.log配置

    new UglifyJsPlugin({ uglifyOptions: { compress: { warnings: false, drop_console: true,//console pure ...

  3. springcloud 连接docker中运行的RabbitMQ消息中间件。

    参考:https://blog.51cto.com/zero01/2173288 主要是记录几个坑: 第一个坑:开始订单服务中配置文件是: #配置rabbitmq 2019.5.17 added by ...

  4. 基于thinkphp5框架做一个可以区别开发、测试、生产三种环境的配置加载

    在日常的开发测试中我们经常会遇到本地开发和测试或者线上配置参数不同的场景,必要你要是使用一个三方的支付,它的本地测试和线上的key值或者账号存在不同.最基本的做法是本地用测试参数,提交到测试的时候再改 ...

  5. pyhton数据类型:字典、集合、列表、元组

    基本常识 元组 列表 字典 集合 初始化 tuple=(1,2,3,4) list=[1,2,3,4] dic={'a':12,'b':34} set={1,2,3,4} 元素索引 tuple[0] ...

  6. 图片url地址的生成获取方法

    在写博客插入图片时,许多时候需要提供图片的url地址.作为菜鸡的我,自然是一脸懵逼.那么什么是所谓的url地址呢?又该如何获取图片的url地址呢? 首先来看一下度娘对url地址的解释:url是统一资源 ...

  7. get merge --no-ff和git merge区别、git fetch和git pull的区别

    get merge --no-ff和git merge区别 git merge -–no-ff可以保存你之前的分支历史.能够更好的查看 merge历史,以及branch 状态. git merge则不 ...

  8. ffmpeg 速查手册

    ref : http://linux.51yip.com/search/ffmpeg ffmpeg是一个源于Linux的工具软件,是FLV视频转换器,可以轻易地实现FLV向其它格式avi.asf. m ...

  9. TypeScript之泛型

    什么是泛型,有什么用? 泛型字面意思就是广泛的类型,怎么样才算广泛呢?当然是能变的最广泛嘛, 所谓泛型就是类型的变量写法,让你的变量的类型是动态可变的,应用场景如官方文档描述的例子: 一个函数,输入什 ...

  10. 组件系列之RabbitMQ

    官网: https://www.rabbitmq.com/getstarted.html 1.四种交换机 TODO... 2.消费者获取消息方式:推 和 拉 拉取:每次拉取一条,循环拉取需要的条数在批 ...