郑昀编著,文字资料来自于张帆、白俊华、刘飞宇以及网络资料 创建于2015/10/21 最后更新于2015/10/29
关键词:Docker,容器,持续集成,持续发布,CI,私有云
本文档适用人员:广义上的技术人员
提纲:
- 集装箱还是卷挂载?
- Host Networking 还是 Bridge Networking?
- 容器要固定IP吗?
- 容器内部如何获取宿主机的IP?
- 待续
首先,你要明白容器并不是虚拟机,虽然它可以解决虚拟机能够解决的问题,同时也能够解决虚拟机由于资源要求过高而无法解决的问题,但它真的不是虚拟机。以往我们的开发、配置管理、部署发布、监控报警思路都要跟着变。
其次,一开始注定只有一少部分工程迁移到容器私有云上,既然还有大多数应用服务还在虚拟机或物理机上,那么它们之间如何通讯就成了一个必须解决的问题。
那么,我们在构建基于容器的私有云以及相应的持续发布时,遇到并解决了哪些问题呢?
0x00 集装箱还是卷挂载?
先抛出问题,下面这个选择题你怎么选:
|
一艘鲸鱼大船,载着无数集装箱。操作系统就是这艘货轮,每一个容器就是一个集装箱,交付运行环境如同海运。大家知道吗,集装箱的英文单词就是 container!
集装箱有什么好处?
- 规格标准,在港口和船上可以层叠摆放,节省大量空间,
- 可以进行快速装卸,并可从一种运输工具方便地换装到另一种运输工具,
- 途中转运不用移动箱内货物,就可以直接换装,
- 货物的装满和卸空很方便。
那么,上面的选择题如何回答呢?
触控科技运维负责人萧田国认为,把代码放在宿主机上,让容器通过卷组映射来读取,不建议采用这种方案,原因是,将代码拆分出容器,这违背了 Docker 的集装箱原则:
- 从货运工人角度考虑,整体才是最经济的。
- 这也导致装卸复杂度增加。
或者说,容器时代,一切版本化,抛弃过去文件分发的思想,才是正途,这样也才能实现真正意义上的容器级迁移。
我们是怎么考虑的呢?
假定是代码和 Image 分开的场景,主要有两种实现方式:
- 代码放到 slave 节点的本地磁盘:那么必须要有一种机制,来确保每台 slave 上代码包版本的一致性,而且对于磁盘空间和网络分发来讲也是一种浪费(考虑一下 100 台 slave,其中可能只有 10 台需要运行这个版本的代码)
- 代码放到分布式共享文件系统(如 ceph):它倒是解决了数据过度冗余以及一致性的问题,但分布式共享文件系统本身成为了『单点』,虽然可以设置多个副本。它的性能和可靠性都必须得到充分保障才行。
在容器云之前,我们采用的是基于 OpenStack 的虚拟机管理方案。在线下环境用 OpenStack 时,我们将所有的虚拟机放置到 ceph(注:Linux PB 级分布式文件系统) 上,但是由于线下 ceph 节点太少,单节点出问题时影响较大。每次 ceph 出现问题,所有的虚拟机都特别慢。
来到了容器时代,如果还把代码放置到 ceph 上,对 ceph 的依赖太高了,ceph 一旦有问题,有可能使用了 ceph 的所有容器都会出问题 。线上业务主要考虑的是性能(容器本地运行代码 vs 通过网络获取代码)和可靠性(每个 slave 都本地运行容器 vs 所有容器依赖共享文件系统),结论不言而喻。所以一开始决策时,没敢把代码放在 ceph 上,而是放在镜像里。所以我们选的是方案2,代码在镜像里。
在我们的场景里,镜像会被下载到 mesos slave 物理机的本地磁盘上,所以启动容器时读的是本地磁盘。
多说一句,Qunar 等公司在2014年选择的是卷挂载方案,业界也有人认为,这事儿得分环境具体问题具体分析,开发集成环境和生产环境可能就不一样。
0x01 Host Networking 还是 Bridge Networking?
网络基础
Docker 现有的网络模型主要是通过使用 Network namespace、Linux Bridge、iptables、veth pair 等技术实现的。(出处8)- Network namespace:它主要提供了网络资源的隔离,包括网络设备、IPv4/IPv6 协议栈、IP 路由表、防火墙、/proc/net 目录、/sys/class/net 目录、端口(socket)等。
- Linux Bridge:功能相当于物理交换机,为连在其上的设备(容器)转发数据帧,如 docker0 网桥。
- Iptables:主要为容器提供 NAT 以及容器网络安全。
- veth pair:两个虚拟网卡组成的数据通道。在 Docker 中,用于连接 Docker 容器和 Linux Bridge。一端在容器中作为 eth0 网卡,另一端在 Linux Bridge 中作为网桥的一个端口。
容器的网络模式
用来设置网络接口的 docker run --net 命令,它的可用参数有四个:
- none:关闭了 container 内的网络连接。容器有独立的 Network namespace,但并没有对其进行任何网络设置,如分配 veth pair 和网桥连接,配置 IP 等。
- bridge:通过 veth 接口来连接其他 container。这是 docker 的默认选项。
- host:允许 container 使用 host 的网络堆栈信息。容器和宿主机共享 Network namespace。
- container:使用另外一个 container 的网络堆栈信息。kubernetes 中的 pod 就是多个容器共享一个 Network namespace。
在 docker 默认的网络环境下,单台主机上的容器可以通过 docker0 网桥直接通信,如下图(图作者冯明振)所示:
而不同主机上的容器之间只能通过在主机上做端口映射进行通信。这种端口映射方式对集群应用来说极不方便。(出处8)我们重点要解决这个问题。
先看一下其他学生怎么做这道选择题的:
公司
|
网络方案
|
备注
|
网易(2014)
|
tinc+quagga+pipework
|
Pipework 是对 Docker Bridge 的扩展,它由 200 多行 shell 脚本实现。通过使用 ip、brctl、ovs-vsctl 等命令来为 Docker 容器配置自定义的网桥、网卡、路由等。
|
CoreOS(2014)
|
flannel
|
flannel 属于隧道方案,UDP 广播,VxLan。
|
大众点评网(2015) |
Bridge Networking 工作在 level 2 的模式,使公共 IP 得以暴露出来,这部分是做了定制的
|
|
汽车之家(2015) |
Bridge Networking
|
|
去哪儿(2015)
|
Host Networking
|
『大吞吐量平台下,bridge 模式性能测试都偏低,于是选择了 host 模式』——20150915,徐磊
|
芒果TV(2015)
|
Macvlan
|
属于路由方案。『从逻辑和 Kernel 层来看隔离性和性能最优的方案,基于二层隔离,所以需要二层路由器支持,大多数云服务商不支持,所以混合云上比较难以实现』——20150505,彭哲夫
|
新浪微博(2015)
|
Host Networking
|
|
先说一下 host 模式。
容器的网络直接和外部网络打通,解决了不同 slave 物理机之间容器互联互通的问题,减少了 NAT 转换的损耗,但需要自行来维护容器的 IP 地址和端口,否则会冲突,这增加了管理上的复杂度。请考虑这个场景:在同一个 slave 物理机上运行两个 80 端口 Nginx 容器的情况,除非分配两个不同的 IP 地址,这种方案我们之前在 shipyard 方案中使用过。
新浪微博在《大规模Docker集群助力微博迎接春晚峰值挑战》一文中曾经介绍过:
Docker 部署被诟病最多就是网络,平台目前采用的是 host 模式,为什么没有采用 NAT 或者 Bridge 呢?由于涉及的技术细节比较繁冗,这里仅分享一些踩过的坑。例如 NAT 使用 iptables 底层流量转发依靠内核 netfilter 模块,其默认仅保持 65536 个链接,在服务有大量链接的场景下,会出现大量拒绝链接的现象。再如 Bridge 的 MAC 地址默认是选择其子接口中最先的一个,这样就会导致一个宿主机下多个容器启停时出现网络瞬断。还有很多问题不一一列举,平台未来计划采用 vlanif 的方案来解决容器网络部署难题。
再看 bridge 模式,它是 docker 默认的网络模式,为了解决容器间互通问题,通常有两种解决方案:
- 采用 SDN(软件定义网络) 技术,如 flannel,weave 等,直接将容器内网打通;
- 采用 NAT(网络地址转换) 技术,直接使用 slave 主机的 IP 地址互通。
我们认为,bridge 模式加 NAT 方式,是当前 mesos+marathon 支持的最好的模式(采用的是 container port,host port,service port 的对应关系)。我们的容器云主要构建于 mesos+marathon 之上,封装了我们的业务逻辑,采用一些方式解决了容器与现存非容器架构之间的互通问题, 如 consul 的服务注册和发现机制,dubbo 的应用注册和发现机制等。
最终我们选择了 Bridge Networking。
Docker网络模型以后如何发展
Libnetwork 是 Docker 官方 2015年初推出的项目,旨在将 Docker 的网络功能从 Docker 核心代码中分离出去,形成一个单独的库。 Libnetwork 以插件的形式为 Docker 提供网络功能,使得用户可以根据自己的需求实现自己的 Driver 来提供不同的网络功能。 Libnetwork 所要实现的网络模型基本是这样的: 用户可以创建一个或多个网络(一个网络就是一个网桥或者一个 VLAN ),一个容器可以加入一个或多个网络。 同一个网络中容器可以通信,不同网络中的容器隔离。 Docker 网络的发展以后就都在这个项目上了。
0x02 容器要固定IP吗?
默认情况下,当 docker 启动时,它会在宿主机器上创建一个名为 docker0 的虚拟网络接口。它会从 RFC 1918 定义的私有地址中随机选择一个主机不用的地址和子网掩码,并将它分配给 docker0。(出处9)所以,容器的 IP 是动态变化的。
于是乎大家一开始接触 Docker 就纷纷提出给容器分配静态 IP 的需求。看一下各大公司容器云技术栈对比,几家历史包袱较重的公司都选择不让上层应用感知到底层是 VM 还是容器,如360/点评/汽车之家,都改了docker 代码,固定了容器 IP。
docker 官方对此需求的态度是,Docker maintainers prefers a more abstract way to separate user intent from operational intent. Based on this feedback and various other discussions on a flexible ip address management, we feel that having a pluggable IPAM will help a great deal.
If you’re using named Docker instances, then adding the IP address 10.40.33.21 to a Docker instance bind is as simple as:
pipework br0 bind 10.40.33.21/24
If you want to route out of 10.40.33.1, change it to:
pipework br0 bind 10.40.33.21/24@10.40.33.1
(出处:https://opsbot.com/advanced-docker-networking-pipework/)
这样的话,需要在容器启动后在宿主机上运行 pipework 来设置容器的 ip,这样就增加了自动化的难度。
我们的考虑是,第一,容器应该是无状态的,分配固定 IP 违背了这个理念,第二,Docker 刚出来一两年,还在飞速发展中,现在你改了内核代码,将来它大版本升级,你怎么跟随?第三,使用固定 IP 很大程度上是为了让技术人员能像以前一样直接登录虚拟机操作,但我们的持续集成管理平台里使用 webconsole 也能登到容器里面操作。
我们的实践是:首先,我们内部调用都走内部域名,有专门的 DNS Server,其次,我们很早以前就引入了服务治理框架 Dubbo,基本做到了服务的注册和发现。再次,我们在容器云里引入了 consul 的注册和发现服务,配合 slave 节点上的 registrator 容器,以及 haproxy 和 consul-template 组件,实现了完整的容器服务的注册和发现架构。
第一,dubbo 能帮我们解决什么容器问题:
进驻容器云后 java 工程之间的调用:直接将物理机的 ip 和容器 java 工程对外提供的随机端口,注册到 dubbo 里。例如, 容器 javaA 要调用容器 javaB,容器 javaB 已经将它对外提供的 ip 和随机端口注册到了 dubbo 里,容器 javaA 可以从 dubbo 里找到容器 javaB 相关的信息直接调用。
第二,dubbo 不能解决的问题有:
- 我们的线上还有 php 或者其他开发语言的应用,它怎么调用容器化的 java 工程呢?
- 容器化的工程如何对外网提供服务 ,如何把它放入 nginx 和 F5中呢?
基于以上两个需求、以及同一个工程的容器也要做负载均衡 ,我们引入了 consul + consul-template + registrator + haproxy,来做服务注册和发现。
实施详细流程如下:
第一步,每一台 slave 节点上都会启动一个 registrator 的容器,该容器检测 docker 引擎的 unix socket 地址:/var/run/docker.sock,从中获得该 slave 上所有容器的启动、停止以及其他运行时相关的信息;
第二步,registrator 容器同时会把它获取的其他容器的信息(IP、端口等)注册到 consul 集群中,服务信息如下面的输出:
curl 172.28.128.3:8500/v1/catalog/service/python-micro-service[{"Node":"host-1","Address":"172.28.128.3","ServiceID":"registrator:service1:5000","ServiceName":"python-micro-service","ServiceTags":null,"ServicePort":49154}]
第三步,consul-template 组件从 consul 中获得所有容器注册的服务信息,应用相应的规则(如,区分为镜像环境和生产环境)后,将容器提供的服务信息写入 haproxy 中,并 reload haproxy 以生效配置。
第四步,client 端通过 DNS 中注册的域名指向 haproxy 的地址,访问到具体提供服务的容器。
0x03 容器内部如何获取宿主机的IP?
容器启动后,宿主机 IP 会被写入容器的环境变量里。
容器内的程序可以从环境变量里读取。
——未完待续——
附录A:参考资源
1,知乎Docker话题,http://www.zhihu.com/topic/19950993;
2,2015,Docker终极指南(原作者German Jaber);
3,2015,Docker持续部署图文详解;
4,2015,使用Docker搭建Java Web运行环境;
5,2015,dockone上对代码放里面还是外面的讨论;
6,2013,dockerfile最佳实践;
7,2015,集群规模下日志处理和网络方案;
8,2015,Docker网络详解及Libnetwork前瞻;
附录C:
目前,我们容器管理集群的技术栈包括以下内容:
- mesos(资源调度)
- marathon(服务编排)
- chronos(分布式计划任务)
- docker(容器引擎)
- consul+registrator(服务注册和发现)
- haproxy(负载均衡)
- prometheus(服务监控)
- nagios/zabbix(节点监控)
- salt(节点配置管理)
- cobbler(节点自动化装机)
- ELK(日志收集分析)
窝窝持续集成管理平台在这些技术的基础上,实现了我们的集群管理、容器管理、应用管理等业务流程。
欢迎订阅我的微信订阅号『老兵笔记』,请扫描二维码关注:
-EOF-
相关推荐
5. **混合云**:企业往往需要在公有云和私有云之间进行灵活切换,因此混合云解决方案成为必要,以保证数据安全和合规性。 在"阿里谐云联合容器云解决方案"中,重点介绍了以下几个方面: 1. **稳定的阿里云底座**:...
此外,容器云平台还能提高数据一致性,通过私有云建设和通用数据模型,确保数据安全和业务稳定性。业务层实现服务共享,可以加速新业务应用的构建和发布,提升客户体验。 然而,项目实施也面临难点,如技术选型、...
企业容器云的应用正在成为现代IT基础设施的核心组成部分,它为企业提供了高度可扩展、灵活且高效的解决方案。私有PaaS(Platform as a Service)平台是企业转向容器云的关键驱动力,主要出于对混合云策略、现有及新...
私有云和容器技术在其中发挥关键作用,确保了开发、测试和生产环境的一致性。通过使用Docker,可以构建开发环境、功能测试环境、集成测试环境和生产环境,确保每个阶段的环境一致性。 **持续集成/持续部署(CI/CD)...
【网易蜂巢公有容器云架构之路】是一个深入探讨云架构和容器技术的专题,主要关注如何通过容器云架构提升DevOps效率和实现微服务化的转型。以下是对该主题的详细解析: ### 1. 背景说明 在2012年,网易开始建设...
标题:中国容器云市场研究报告精品报告2020 描述:本报告由艾瑞咨询研究院自主研究及绘制,详细...随着容器技术的进一步成熟和安全问题的解决,以及Kubernetes等编排工具的发展,容器云市场有望保持快速增长的态势。
在云原生架构下实现持续交付需要面对一系列的挑战和机遇,其中包括服务爆炸、复杂拓扑、环境规模庞大、联调测试成本高昂以及高频发布带来的回归工作量大等问题。同时,标准化的技术架构、业务和基础设施解耦、易观测...
本周的TMT行业周报聚焦了2020年第30期的重要动态,主要关注了阿里巴巴集团发布的“云电脑”这一创新技术,以及持续升温的云计算领域。这两大话题不仅展示了科技巨头在技术领域的最新探索,也揭示了未来IT行业的趋势...
在架构方面,文档提出了一个多层次的服务架构,包括协作层、基础服务层、基础设施层和容器层。为了适应不同云环境,文档强调了公有云与私有云技术选型的一致性,列举了阿里云、EC2、Docker、Kubernetes、Flannel、...
### 金蝶云苍穹V1.5系统部署手册_非容器版_V1.0 #### 一、系统概述 金蝶云苍穹V1.5系统是一款基于云原生架构设计的企业级管理软件,其核心特点...此外,持续关注官方发布的最新文档和技术支持信息也是非常重要的。
本文将深入探讨如何利用Kubernetes构建和管理容器服务,以及其在360私有云平台HULK中的实践。 **一、容器服务介绍** 容器服务是基于Kubernetes构建的一种云服务,它能够快速部署和管理容器化的应用程序,提供弹性...
该平台的核心特点是采用“2+1”模式,即结合私有云、公有云和专有云,输出全栈云服务,以满足不同客户在不同场景下的需求。通过这种模式,平安云实现了多元化的服务发展,构建了丰富的云生态系统。 容器技术在平安...
随着公有云和私有云的普及,云原生已成为构建现代应用架构的主流方式,不仅适用于Java应用,也适用于各种编程语言和架构。 CNCF(Cloud Native Computing Foundation)等组织推动了云原生生态的发展,Kubernetes...
【容器技术】是一种轻量级的虚拟化技术,它通过操作系统级别的隔离,使得应用程序可以在独立的容器中运行,而无需关心底层操作系统和其他应用的干扰。容器技术极大地提升了软件的部署速度和灵活性,使得企业能够更加...
Rancher 1.0支持目前流行的容器编排和调度框架,包括Docker Swarm和Kubernetes,旨在为企业提供一个开箱即用的解决方案,使得开发者和运维人员能专注于应用的开发和业务的改善,而无需关注底层基础设施的集成和管理...
云原生的概念强调轻量级的封装、松散耦合以及高效的自动化流程,这使得应用程序能够在各种云环境中无缝运行,包括私有云、公有云、混合云和多云场景。 云原生技术的核心组成部分包括: 1. 容器(Containers):...
从物理环境到虚拟环境,再到私有云和托管云,最后到公有云,这些变化都是由业务模式驱动的技术转型所驱动的。在容器化的环境中,应用编排变得至关重要,用于管理服务发现、配置管理、健康检查、弹性伸缩和灰度发布等...
- 该公司的目标是建立一个通用性的容器云平台,整合CaaS(容器即服务)和IaaS(基础设施即服务)。 - 平台采用了Rancher来管理容器服务,与Docker和 CentOS 7操作系统相结合,提供了一体化的云服务,包括主机、...