系列目录

容器经常是为了解决单一的,窄范围的问题,比如说微服务.然而现实中,一些复杂问题的完成往往需要多个容器.这里我们讨论一下如何把多个容器放在同一个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. hihoCoder #1157 建造金字塔

    这道题我想了一天才想清楚做法.AC 了之后去看别人写的题解,都是三言两语意识流式描述,我并不能读懂.我觉得很自卑,为何人家解这道题如此轻松.不过,我还是决定把我的解法写下来,并且一定要写清楚. 思路 ...

  2. [luoguP2147] [SDOI2008]Cave 洞穴勘测(并查集 || lct)

    传送门 1.并查集骗分(数据太水,比正解还快...) 我们知道,并查集有一步操作叫“路径压缩”,但是本题的并查集我们不能路径压缩,否则就无法进行Destroy操作.那每一步操作我们应该怎么做呢? 对于 ...

  3. Unity 导出的android项目自动生成Private Libraries

    如果Unity里面Plugins/Android 添加了 jar 文件,则导出Android 项目时会自动生成 Private Libraries. 而且里面的项还删不掉 然后在网上搜了一下,找到了原 ...

  4. vue2 vuex 简单入门基础

    1.vuex中文文档 https://vuex.vuejs.org/zh-cn/api.html 2.我理解vuex 应用观察者模式 设置了全局的状态 state 状态变化即通知更新全局state 3 ...

  5. The disk contains an unclean file system

    Ubuntu : Status 14: The disk contains an unclean file system By mkyong | July 23, 2014 | Viewed : 10 ...

  6. PHP解码Json(json_decode)字符串返回NULL的原因及解决方法(转载)

    本文主要为大家讲解了php在使用json_decode函数解码json字符串时,解码不成功返回NULL的问题原因分析和解决方法,感兴趣的同学参考下. 一般来说,php对json字符串解码使用json_ ...

  7. Scanner用法

    先来看一个简单的例子: import java.util.*; public class ScannerTest { public static void main(String[] args){   ...

  8. hdu4635 有向图最多添加多少边使图仍非强连通

    思路:先缩点成有向无环图,则必然含有出度为0的点/入度为0的点,因为要使添加的边尽量多,最多最多也就n*(n-1)条减去原来的m条边,这样是一个强连通图,问题转化为最少去掉几条,使图不强连通,原来图中 ...

  9. AC日记——【模板】线段树 1 洛谷 P3372

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个 ...

  10. 天梯赛 - L2-002 链表去重

    GG思密达,第二个测试点的三分怎么也拿不上,我还是比较熟悉指针,用指针来写~,写完去上概率论 题目链接:https://www.patest.cn/contests/gplt/L2-002 #incl ...