系列目录

容器经常是为了解决单一的,窄范围的问题,比如说微服务.然而现实中,一些复杂问题的完成往往需要多个容器.这里我们讨论一下如何把多个容器放在同一个pod里以及容器间的通信

什么是pod

pod是kubernetes里的一个基本概念,可能我们从一开始接触kubernetes的时候就开始接触pod,并被灌输pod是kubernetes里最小的不可分割的工作单元,这里再从多容器的角度对其进行一些基本阐释.

简言之,pod是kubernetes可以部署和管理的最小单元,换言之也就是说如果你想要运行一个容器,你先要为这个容器创建一个pod.同时,一个pod也可以包含多个容器,之所以多个容器包含在一个pod里,前面讲到过的初始容器为普通应用容器准备环境是一种使用场景,往往由于业务上的紧密耦合,一组容器也需要放在同一个pod里.

需要注意的是,以上场景都非必须把不同的容器放在同一个pod里,但是这样往往更便于管理,甚至后面会讲到的,紧密耦合的业务容器放置在同一个容器里通信效率更高.具体怎么使用还要看实际情况,综合权衡.

kubernetes为什么使用pod作为最小单元,而不是container

直接部署一个容器看起来更简单,但是这里也有更好的原因为什么在容器基础上抽象一层.容器是一个存在的实体,并指向一个具体的事物.这个具体的事物可能是一个docker容器,但也可能是一个rtk容器,或者一个Virtlet管理的虚拟机.它们有不同的要求.

更深层的原因是为了管理容器,kubernetes需要更多的信息,比如重启策略,它定义了容器终止后要采取的策略;或者是一个可用性探针,从应用程序的角度去探测是否一个进程还存活着.

基于这些原因,kubernetes架构师决定使用一个新的实体,也就是pod,而不是重载容器的信息添加更多属性,用来在逻辑上包装一个或者多个容器的管理所需要的信息

kubernetes为什么允许一个pod里有多个容器

pod里的容器运行在一个逻辑上的"主机"上,它们使用相同的网络名称空间(也就是说,同一pod里的容器使用相同的ip和相同的端口段区间)和相同的IPC名称空间.它们也可以共享存储卷.这些特性使它们可以更有效的通信.并且pod可以使你把紧密耦合的应用容器作为一个单元来管理.

因此一个应用如果需要多个运行在同一主机上的容器时,为什么为把它们放在同一个容器里呢?首先,这样何故违反了一个容器只负责一个应用的原则.这点非常重要,如果我们把多个应用放在同一个容器里,这将使解决问题变得非常麻烦因为它们的日志记录混合在了一起,并且它们的生命周期也很难管理.因此一个应用使用多个容器将更简单,更透明,并且使应用依赖解偶.并且粒度更小的容器更便于不同的开发团队共享和复用.

这里说到为了解偶把应用分别放在不同容器里,前面我们也强调为了便于管理管紧耦合的应用把它们的容器放在同一个pod里.一会强调耦合,一个强调解偶看似矛盾,实际上普遍存在,高内聚低耦合是我们的追求,然而一个应用的业务逻辑模块不可能完全完独立不存在耦合,这就需要我们从实际上来考量,做出决策.

多容器pod的使用场景举例

  • Sidecar containers "帮助"主容器,比如日志文件监视器.一个日志监视器构建完成以后,可以由不同的应用来使用.另一个示例是sidecar 容器为主容器加载文件和运行需要的数据

  • 代理,桥接和适配器 使主容器与外部世界联通.比如Apache http服务器或者nginx可承载静态文件.也可以做为一个web的反向代理服务器.

你可以使用一个pod来承载一个多层应用(比如wordpress),但是更建议使用不同的pod来承载不同的层,因这这样你可以为每一个层单独扩容并且把它们分布到集群的不同节点上.

同一pod间的容器通信

把不同的容器放在同一个pod里让它们之间的通信变得非常直接和简单,它们可以通过以下几种方法达到通信目的.

同一pod内的容器共识存储卷

你可以使用一个共享的存储卷来简单高效的地在容器间共享数据.大多数情况下,使用一个共享目录在同一pod里的不同容器间共享数据就够了.

一个标准的同一pod内容器共享存储卷的用例是一个容器往共享存储卷里写入数据,其它的则从共享目录里读取数据

apiVersion: v1
kind: Pod
metadata:
name: mc1
spec:
volumes:
- name: html
emptyDir: {}
containers:
- name: 1st
image: nginx
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
- name: 2nd
image: debian
volumeMounts:
- name: html
mountPath: /html
command: ["/bin/sh", "-c"]
args:
- while true; do
date >> /html/index.html;
sleep 1;
done

这个示例里我们定义了一个存储卷叫作html,它是emptyDir类型的.当一个pod在一个节点上创建的时候,它就被分配,只要pod一直运行在这个节点上它就一直存在(emptyDir生命周期和pod相同).就像它的名字所暗示的一样,它是一个空的目录,第一个容器运行了一个nginx server并且把它挂载到/usr/share/nginx/html,第二个容器使用了一个Debian镜像并把emptyDir挂载到 /html.每一秒钟,第二个容器就会把当前日期写入到index.html里,它位于共享存储卷里.当用户发起一个http请求,nginx就会读取它并响应给用户.

你可以通过把nginx的端口暴露出去然后通过浏览器查看或者查看共享目录里的文件来检测以上是否有效果

 kubectl exec mc1 -c 1st -- /bin/cat /usr/share/nginx/html/index.html
...
Fri Aug 25 18:36:06 UTC 2017 $ kubectl exec mc1 -c 2nd -- /bin/cat /html/index.html
...
Fri Aug 25 18:36:06 UTC 2017
Fri Aug 25 18:36:07 UTC 2017

进程间通信(IPC)

同一个pod里的容器共享IPC名称空间,这就意味着他们可以通过进程间通信的手段来进行通信,比如使用SystemV semaphores或者POSIX 共享内存

以下示例中,我们定义一个包含了两个容器的pod.它们使用相同的docker镜像,第一个容器是一个生产者,创建一个标准的linux消息队列,写一些随机的消息,然后写一个特殊的退出消息.第二个容器是一个消费者,打开同一个消息队列来读取数据直到读到退出消息,我们把重启策略设置为Never,这样当两个pod都中止的时候pod就会停止.

apiVersion: v1
kind: Pod
metadata:
name: mc2
spec:
containers:
- name: producer
image: allingeek/ch6_ipc
command: ["./ipc", "-producer"]
- name: consumer
image: allingeek/ch6_ipc
command: ["./ipc", "-consumer"]
restartPolicy: Never

然后通过kubectl create来创建pod,用下面命令来查看状态

$ kubectl get pods --show-all -w
NAME READY STATUS RESTARTS AGE
mc2 0/2 Pending 0 0s
mc2 0/2 ContainerCreating 0 0s
mc2 0/2 Completed 0 29

这时候你可以检测每一个容器的日志来检测第二个队列是否消费了第一个队列生产的所有消息包括退出消息

$ kubectl logs mc2 -c producer
...
Produced: f4
Produced: 1d
Produced: 9e
Produced: 27
$ kubectl logs mc2 -c consumer
...
Consumed: f4
Consumed: 1d
Consumed: 9e
Consumed: 27
Consumed: done

这里面存在一个问题,就是生产者所在容器要早于消费者所在容器,我们必须处理容器的启动顺序问题

容器的依赖关系和启动顺序

当前,同一个pod里的所有容器都是并行启动并且没有办法确定哪一个容器必须早于哪一个容器启动.就上面的IPC示例,我们不能总保证第一个容器早于第二个容器启动.这时候就需要使用到初始容器(init container)来保证启动顺序,关于初始容器,可以查看官方文档,本系列也对其进行了翻译,以便查看.

同一pod的容器间网络通信

同一pod下的容器使用相同的网络名称空间,这就意味着他们可以通过'localhost'来进行通信,它们共享同一个Ip和相同的端口空间

同一个pod暴露多个容器

通常pod里的容器监听不同的端口,想要被外部访问都需要暴露出去.你可以通过在一个服务里暴露多个端口或者使用不同的服务来暴露不同的端口来实现

kubernetes之多容器pod以及通信的更多相关文章

  1. 基于Kubernetes构建企业容器云

    前言 团队成员有DBA.运维.Python开发,由于需要跨部门向公司私有云团队申请虚拟机, 此时我在思考能否在现有已申请的虚拟机之上,再进行更加细粒度的资源隔离和划分,让本团队的成员使用, 也就是在私 ...

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

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

  3. K8s中的多容器Pod和Pod内容器间通信

    容器(Container)常被用来解决比如微服务的单个问题,但在实际场景中,问题的解决往往需要多容器方案.本文会讨论将多个容器整合进单个Kubernetes Pod 中,以及Pod中的容器之间是如何通 ...

  4. Kubernetes容器之间的通信浅谈

    公众号关注 「开源Linux」 回复「学习」,有我为您特别筛选的学习资料~ 作者: Matt Zand 和 Jim Sullivan 译者: 穿过生命散发芬芳F Kubernetes是一个容器化的解决 ...

  5. kubernetes进阶之三:Pod

    一:Pod 是什么 Pod是Kubernetes的最重要最基本的概念.它是能够被创建,调度和管理的最小部署单元.一个Pod代表集群中一个运行的进程. 二:Pod的组成 一个Pod由一个特殊的根容器Pa ...

  6. Kubernetes — 为什么我们需要Pod?

    不过,我相信你在学习和使用 Kubernetes 项目的过程中,已经不止一次地想要问这样一个问题:为什么我们会需要 Pod? 是啊,我们在前面已经花了很多精力去解读 Linux 容器的原理.分析了 D ...

  7. 三、Kubernetes之深入了解Pod

      1.yaml格式的Pod配置文件内容及注解 深入Pod之前,首先我们来了解下Pod的yaml整体文件内容及功能注解. 如下: # yaml格式的pod定义文件完整内容: apiVersion: v ...

  8. Kubernetes+Docker+Istio 容器云实践

    随着社会的进步与技术的发展,人们对资源的高效利用有了更为迫切的需求.近年来,互联网.移动互联网的高速发展与成熟,大应用的微服务化也引起了企业的热情关注,而基于Kubernetes+Docker的容器云 ...

  9. 026.[转] 基于Docker及Kubernetes技术构建容器云平台 (PaaS)

    [编者的话] 目前很多的容器云平台通过Docker及Kubernetes等技术提供应用运行平台,从而实现运维自动化,快速部署应用.弹性伸缩和动态调整应用环境资源,提高研发运营效率. 本文简要介绍了与容 ...

随机推荐

  1. HDU——1106排序(istringstream的使用、STLvector练习)

    排序 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submiss ...

  2. [luoguP1963] [NOI2009]变换序列(二分图最大匹配)

    传送门 根据公式xjb推一下,然后就可以连边. 考虑到字典序最小,和匈牙利算法的实现过程,要倒序匹配. #include <cmath> #include <cstdio> # ...

  3. 网络流(自行理解的Dinic)

    自行理解的Dinic 注释即讲解 #include<bits/stdc++.h> ; using namespace std; int read() { ,w=; ;ch=getchar( ...

  4. sqlite 使用

    '''SQLite数据库是一款非常小巧的嵌入式开源数据库软件,也就是说 没有独立的维护进程,所有的维护都来自于程序本身. 在python中,使用sqlite3创建数据库的连接,当我们指定的数据库文件不 ...

  5. 查看公网IP信息的方法

    有时候我们想知道自己的外网ip,推荐几个好用的方法 windows 用百度搜索“ip”就会显示 用浏览器访问getip.name 或者 ifconfig.me linux 使用curl命令  curl ...

  6. Python入门--16--模块

    模块的定义: 模块是一个包含所有你定义的函数和变量的文件,其后缀是.py.模块可以被别的程序引入,以使用该模块中的函数等功能 比如 import random secret=random.randin ...

  7. 在Eclipse中打开Hadoop工程

    1. 安装虚拟机,我用的是VMware Workstation 12 Player 2. 在VM中安装Ubuntu,我用的镜像文件是ubuntu-15.10-desktop-amd64.iso 3. ...

  8. luogu U10783 名字被和谐了

    链接 https://www.luogu.org/problem/show?pid=U10783 题目背景 众所周知,我们称g是a的约数,当且仅当g是正数且a mod g = 0. 众所周知,若g既是 ...

  9. RabbitMQ 核心概念

    目录 RabbitMQ 特点 AMQP 协议 RabbitMQ 消息传递机制 Message Exchange 1. 简介 2. 类型 3. 属性 RabbitMQ 特点 RabbitMQ 相较于其他 ...

  10. Oracle if else 、case when 判断示例

    declare -- 声明奖金的变量 v_comm emp.comm%type; begin -- 查询出员工的奖金 select comm into v_comm from emp where em ...