探讨一下,docker/compose 中关于 link 的设计怎么样?


compose中,对于link的处理是这样的(以 A -> B 为例 )——
  1. A的hosts中写入B的地址,便于地址访问
  2. 在A中设定B的环境变量,为了避免名字冲突,添加前缀 B_ENV_
  3. 根据 B 容器对应镜像的 EXPOSE 指令,在A中添加一组 ADDR、PORT 环境变量
  4. 在A中添加一个环境变量指明B的容器全名称,类似这样: /<compose name>_A_run_1/B


但是试用时速云的时候发现不兼容compose的做法,沟通后的回答是这样的——

我们的确实跟docker compose不一样,不过一个服务的非接口信息,另外一个服务也需要拿到,不知道这个应用场景是什么?这种环境变量应该是那个服务独享吧。在Kubernetes里面没有docker 的 --link 的概念,两个关系紧密的容器可以放到一个Pod里面,通过localhost和共享存储进行通信。

这样就变成了 docker compose 和 k8s 的设计取舍问题,哪个设计更合理呢?
已邀请:

小飞侠 - TenxCloud合伙人

赞同来自: tenxcloud


Kubernetes在Pod 层面(多容器组合,保证容器组合部署到同一节点,适用于某些场景),容器之间可以通过localhost互相访问服务,也可以共享数据存储);Pod之间通过自组网络进行互联,支持跨主机通信,相当于跨主机的link,通过内网地址或者域名通信。docker的 --link 和Pod有些类似,compose 会优先支持自己的 --link 的概念,就看用户的实际场景更适合哪种理念了,隔热感觉--link 这种用处不是很大。

fsword - 程序员,搞java出身,喜欢ruby on rails、erlang和js,专注web 不相信中医理论 反对美化拔高传统文化 接受自由主义经济学观点,关注云计算和比特币

赞同来自:


先说说我自己的观点——

docker/compose还不完善,不过方向是对的。

我是从使用者角度看容器之间编排的时候应该使用什么机制,docker/compose的做法是hosts+环境变量,k8s据说是利用 localhost和共享存储,感觉后者的设计不是很好。

有一个大前提,docker是能梳理整条研发线路的技术,凡是能帮助实现这个目标的设计就是好设计(拿集装箱作比较,如果技术仅限于码头到码头,不能上公路,那就是集装箱的失败)。

比如有同学建议用etcd解耦,但是这个要应用自己去etcd读,即要依赖etcd基础设施。这在开发环境中基本是不可能实现的,于是这个解决办法给开发和线上建立了一个壁垒,这不是好主意

fsword - 程序员,搞java出身,喜欢ruby on rails、erlang和js,专注web 不相信中医理论 反对美化拔高传统文化 接受自由主义经济学观点,关注云计算和比特币

赞同来自:


补充,据说有团队在开发环节就引入了k8s,这个倒是没想到,如果实施没问题,确实可以解决开发线上一致性的问题。

求有这样经历的同学分享一下经验

苦逼少侠 - 去哪儿网互联网研发工程师,docker爱好

赞同来自:


本质是一个服务发现和通信的问题,感觉两者都不好,最好还是注册中心那种。不过成本大很多。

jolestar

赞同来自:


个人认为k8s的机制更先进。

k8s本身是兼容docker的link机制的
  1. 通过内置dns服务的短域名解析替代docker的修改host文件机制
  2. 通过一定命名规则,给pod注入service ip的环境变量,兼容docker规则。
    具体参看 k8s services environment-variables


主要区别在于:
1. dns便于修改 这样重新部署服务后,服务ip变化,k8s的dns监听到service变更,自动修改dns解析,依赖服务的应用方不需要做任何变更。如果是host文件模式就必须同时部署相关依赖的应用方。
2. 环境变量的缺点在于部署的时候是顺序相关的,必须先部署地层服务,再部署依赖上层应用。并且部署后环境变量是不会自动变更的,地层服务变更需要重新部署整个依赖链。 而k8s在pod上面抽象了一层service。pod可能经常变更,而service定义一般很少变更。环境变量里注入的是service的ip。这样最大程度的降低了依赖环境变量的缺陷。

fsword - 程序员,搞java出身,喜欢ruby on rails、erlang和js,专注web 不相信中医理论 反对美化拔高传统文化 接受自由主义经济学观点,关注云计算和比特币

赞同来自:


看了一下大家的讨论,觉得有些收获,我现在的想法是这样的:
  • 让一个容器可以看到另一个容器内部的环境变量在大多数情况下是不正确的作法,少数情况下,这些环境变量应该不随着重新部署而变化(其实质是image实例化的时候针对线上环境的参数化,因此只要还在线上,参数值不变)
  • 重新部署时会发生变化的应该只有link信息,对应服务寻址的需要,这个解决方案应该尽可能使用dns,应用本身应该使用名字服务
  • 名字服务的具体实现可以有所不同,比如研发环境使用compose直接修改hosts文件,而线上使用mDNS更好些
  • 根本问题是要尽量确保研发环境和线上一致,这能最大限度发挥docker在标准化上的价值
  • k8s确实可以模仿link,这为k8s对docker环境的支持提供了便利

tifayuki - Tutum 工程师

赞同来自:


目前tutum是用Docker link,但是采用DNS作为服务发现。
虽然底层服务的重新部署不会改变现有上层服务的容器内的环境变量,但是通过tutum的API,可以查找到新服务的新的环境变量,而且因为采用DNS做服务发现,上层服务也不用重新部署。

要回复问题请先登录注册