张春源
作者张春源2017-07-05 11:42
技术总监, 希云cSphere

Docker集群的两种模式K8s和Swarm究竟有何异同?未来哪种模式主流

字数 7127阅读 9325评论 0赞 13

活动简介:

Docker容器技术得以快速发展,核心技术是“镜像打包”使得上下游能友好地进行协助和标准化交付。“build onece run anywhere”构建一次到处运行的想法非常好,实践中发现系统在开发和测试以及生产环境之间部署时应用配置会发生变化,仅靠“环境变量-e”没法满足实际需求,另外“容器镜像”的架构使得应用配置文件变更困难,如容器已部署你的需求是更改应用配置文件中的一个参数,都需要重新修改Dockerfile文件来实现,体现不出用容器的优势反而感觉更加繁琐。

活动探讨精华汇总:

核心话题一、Docker集群的两种模式K8s和swarm究竟有何异同?未来企业应用哪个会更加广泛?

观点一:1、出生不同,Google根据其在Linux上容器管理经验,改造到docker管理上,就是kubernetes。他的在许多方面表现良好。最重要的是构造于Google多年的宝贵经验只上。kubernetes并不是为了docker写的,kubernetes把集群带到了一个全新的高度,代价是学习曲线比较陡。docker-swarm 使用了一个不同的方式。它是docker原生的集群工具。最方便的部分是它暴露了docker标准的编程接口,意味着你之前一直在使用的任何与docker沟通的工具(docker命令行接口,docker compose,dokku,krane等等),都可以无缝的在docker swarm上使用。

2、安装配置不同,安装设置swarm非常简单,简单明了并且很灵活。我们需要做的就是安装一个服务发现工具,然后在所有的节点上安装swarm容器。相比较而言,kubernetes的安装就有点复杂晦涩了。不同的操作系统上安装都不同。每个操作系统都有自己的独立安装指令。

3、运行方式不同,使用Swarm和使用容器没有什么不同。比如,你习惯于使用Docker CLI(命令行接口),你可以继续使用几乎相同的命令。如果你习惯于使用Docker Componse来运行容器,你可以继续在Swarm集群中使用。不管你之前习惯于怎么使用容器,你仍旧可以使用,只是在更大级别的集群中使用。Kubernetes要求你去学习它自己的CLI(命令行接口)和配置。你不能使用你之前创建的docker-compose.yml配置,你必须要去新建与Kubernetes对应的配置。你也不能使用之前学习的Docker CLI(命令行接口)。你必须要去学习 Kubernetes CLI(命令行接口)

最后,当需要在Docker Swarm 和 Kubernetes做出选择时,可以考虑如下几点。你是否想依赖于Docker自己来解决集群的问题。如果是,选择Swarm。如果某些功能在Docker中不支持,那它也非常可能在Swarm中找不到,因为Swarm是依赖于Docker API的。另外一方面,如果你想要一个工具可以解决Docker的限制,Kubernetes将是不错的选择。Kubernetes不是基于Docker,而是基于Google多年对于管理容器的经验。它是按照自己的方式来行事。

观点二:swarm:比较使用与轻量级的容器编排管理,学习起来比较容易,但是高可靠性无法保障
k8s:容器的高可用性,集群的精细管理,复杂的网络场景,个人觉得k8s功能更加强大,不需要二次开发,比较适合需要提供高可靠的服务;不过学习的门槛还是有一点高,需要了解里面的技术比较多;再者k8s是google公司十几年容器编排工具的borg的开源版本,具有更成熟、更可靠性。

可以参考这篇博客,感觉博主写的很到位: http://www.aixchina.net/Article/178601

观点三:各有所长,包括kb,swarm,mesos等都各有所长,相对来说kb提供完整解决方案,但自住可控性就差一些,mesos需要有实施人员有更多的去定制。swarm没有太深入的研究过。kb更多的推荐作为开发和持续交付中使用会比较好,生产上可能会增加故障定位的难度。

观点四:我觉得从自己需求出发,然后去选择技术方案。
swarm:比较使用与轻量级的容器编排管理, docker官网推荐三戟叉之一。
k8s:容器的高可用性,集群的管理等等这些特点,无疑就是一个容器平台的解决方案,功能大而全。但是相应的有更多的复杂精度。
如果,业务只是需要容器化docker+swarm足够解决。
如果,是需求一个容器管理平台,那k8s是个好选择。
例如我们kolla直接使用docker,编排使用ansible来做。安全简单高效。

这个问题得靠时间来回答,目前k8s势头很猛,但是真的能市场的考验,现在还不知道答案。

核心话题二:Docker应用配置文件的作用都有哪些?

观点一:我先来理一下问题的思路:
1.docker应用应该是指的在容器中运行的服务(tomcat);
2.应用配置文件那就是指的在容器中运行服务的配置文件(tomcat的配置文件);

问题理清楚后,那在用docker过程中管理应用配置文件的价值就比较大;
我列举几个:
1.容器镜像是只读的,构建完成之后如果发现配置文件的中想增加环境变量此时如果没有配置文件管理的功能就需要重新构建build镜像;有个配置文件以后,直接在配置文件中增加就行。

2.基于镜像部署容器后,后续运维过程中会对应用配置的参数做一些修整,那直接可以修改配置文件的内容即可;有的配置文件修改后是要重新启动服务的,但至少不需要再重新构建打包镜像了;有些配置文件修改后是不用重启服务的修改后应用即可很方便。
3.如果一个对Docker容器不懂或者是重心关注在应用层的人来说,我觉得有配置文件的话使用容器就更容易一些。此时我们就可以把镜像看成是一个程序包,基于容器的模式进行封装后,剩下的工作就是修改应用的配置文件,调整容器配额,日志文件、数据文件存储路径等事宜。能将重心从系统底层上升到应用层。
4.实践发现在应用迁移过程中调试成本会降低。
5.线上运维运营方便。

观点二:观点一回答的很好,Docker应用配置文件的作用就是给docker的服务提供配置
我就在他的基础之上,说说我的看法

应用配置文件应该需要做到以下几点
1.docker应用配置文件能够保持能够支持针对不同环境作出更改。
2.配置文件支持在线更改,重启就生效。

核心话题三:基于镜像部署容器后,应用配置文件如何做变更?

观点一:容器部署后配置文件变更是一个强需求;

以上2位专家回答的都很正确。我简单说一下我的分析:

1.使用docker自身带的环境变量方式
docker自身带的环境变量的方式如已部署完成后,再修改基本上就是重新创建容器了。我个人觉得比较生硬,对应用层不够友好。
2.程序自动去获取
这种模式有点类似springcloud微服务的实践方式,配置文件都存放到config server中,程序配置文件有更新后config server会将更新后的配置文件下发到容器中。如果没有config server实现起来比较困难一些。
3.容器管理平台自动下发
容器管理平台自动下发这种模式我觉得会比较通用,目前我接触的企业客户中,客户有很多业务系统不是基于微服务架构开发的但也想用容器来部署和管理。做个广告希云cSphere平台的配置文件管理我觉得做的挺不错的,哪位同事的公司有需求可以多沟通。

观点二:两种实现方式

  1. 对于需要变更的参数在启动容器时通过-e传入,相当于export 定义变量,然后在容器中读取这个变量;
  2. 专门制作一个config server,Spring Cloud Config可以满足你的需求

观点三:上面的各位解答的已经很全面了,我说一下我们的特殊做法,因为我们的场景比较特殊,要动态修改系统,web,中间件,消息服务等多种情况,我们采用了在build的镜像的时候在里面注入了agent通过它来修改容器中的各种配置文件和启动停止各种服务。

核心话题四:应用配置文件和docker环境变量的区别是什么?

观点一:1.docker环境变量是在制作镜像的时候就需要提前想好,有哪些参数是部署容器的时候会经常更改,然后把这些参数抽出来做成容器的环境变量,然后在部署的容器的时候填入不同的参数即可。
(如果后续发现有一些参数不同场景下部署的时候也会修改,那就需要再重新制作镜像了。)

2.应用配置文件可以有多种管理方法,上述的管理方式不太灵活。灵活的管理方式是将配置文件和镜像剥离开,这样就不会被镜像给绑定了。

观点二:应用配置文件如果配好后写到镜像,那么以后启动的每个实例都会有相同值,但是如果使用环境变量,则启动容器时直接通过-e输入,就无需在改变应用参数配置时重新制作镜像。

核心话题五:如何修改运行中容器的配置?
我开启一个docker容器:
容器中配置项目IP是:10.241.93.21。现在由于网络环境的问题,ip地址变化了。需要将容易的IP换成10.241.61.20。
ps:要求不删除现有的容器,下次重启后ip地址还是10.241.61.20。怎么配置?求方法?

观点一:你的使用方式错了。容器不应该是长久性的东西,要保持容器的可抛弃性,有问题就应该rm掉,数据保存在容器外,然后直接run新的容器。参数修改是那个时候进行的。

另外,你应该使用DNS,如果是内部的机器,则使用内部DNS也可以,而不应该写死IP。

这两个做法都有问题。至于说修改容器内的配置,这是不推荐的做法,容器不是虚拟机,不应该修改其内的配置。

观点二:docker就是一个容器引擎,类似kvm是虚拟机引擎。docker官方最厉害的地方是提出了镜像打包的概念,但想把容器用好还有很多问题要求解决,容器网络就是其中的一块。

一个企业想把容器用起来或者说是能基于容器来支持业务系统网络方面一般都要达到几个要求:

1.容器网络性能(我接触过的公司对网络要求都比较严格的)
2.容器固定ip地址(这个已经有很多种实现方式了)
3.容器跨主机之间通信(有很多中网络模式)
4.不同容器之间通信,这个场景中使用容器和vm是不一样的地方。容器对底层资源环境是解耦的,所以不要把容器的ip给固定死,不同环境的网络也不同,所以应用层要通过dns来解决。

核心话题六:修改无法启动的容器中的内容(如配置文件信息),应该如何处理?

观点一:方案一:创建新镜像

把这个问题容器用docker commit提交到一个新的镜像,然后用docker run -it 基于新镜像运行一个新的容器进去改变(修复)配置文件。
再通过新的容器再提交一个新的镜像,然后在基于新的镜像重新启动容器(同最初的容器)。
这个方法是可行的,但问题是步骤多,而且提交了新的镜像,对于后续维护增加了复杂性。

方案二:直接修改容器的文件
所有的容器数据都存在/var/lib/docker/aufs/diff/路径下。比如:
root@ubuntu:~# ls /var/lib/docker/aufs/diff/ -l
total 176
drwxr-xr-x 2 root root 4096 Mar 6 05:13 040bf8e0842564e26e62f3e3a30785bd9651c82c52ed99115cd5360ce979e680
drwxr-xr-x 6 root root 4096 Mar 6 05:13 04f7e78a2c8ac9664503f4ea5a1d94bf27b94620987f241cfb9fd6631f761113
drwxr-xr-x 2 root root 4096 Mar 11 01:07 0c666375883f81ba0fc3962368766e93710f59c072a4b80cdf5640323018ccdb
drwxr-xr-x 4 root root 4096 Mar 11 07:53 0d7fc1722e459b242140ec45faec754d4967d72ea2ddf321f8606c837f8e8d4f
drwxr-xr-x 6 root root 4096 Mar 11 07:53 0d7fc1722e459b242140ec45faec754d4967d72ea2ddf321f8606c837f8e8d4f-init
drwxr-xr-x 3 root root 4096 Mar 6 05:13 0dc5e226a795507723362cc16046cf16650f8f70dc7bb721b799a5f2a40512ce
drwxr-xr-x 2 root root 4096 Mar 6 05:13 0fd3b6e125673affc1f348cdb0c071782bde7d7ab4748bea3e30bc2d1d7ea7ab
......................

一个容器的数据对应这其中的一个或多个目录 。其中目录名的前几位就是容器的ID,通过这知道容器和目录的对应关系。
注意这个目录需要用root用户执行。

具体的操作步骤如下:

1、设置当前目录 cd /var/lib/docker/aufs/diff/
2、查找要修改的配置文件所在容器中的位置
find ./ -name 'nginx.conf'

假设我们要修改的是 nginx.conf文件,可能的结果如:

./eb531927ba243b59f0db78848809423f7debe148a9ef972088ea41be73c2aa81/etc/nginx/nginx.conf
./4975acfb30f3f729ac08a9c1bd642f735298a47057fc7c414c7479696b80f36a/etc/nginx/nginx.conf
./6fce3cb01e3c9b8cc4e1fc270c012b1d0b666fe49ad8b6bededb99e295c5da4c/etc/nginx/nginx.conf

这时我们通过比较要修改容器的ID 与上面几个目录的前缀,就知道是要修改哪个配置文件了。

如果我们进入类似 4975acfb30f3f729ac08a9c1bd642f735298a47057fc7c414c7479696b80f36a 目录,会发现这个目录下的内容和linux跟目录下的目录结构非常类似。我们可以找到相关的配置文件直接修改。

说明:因为一个容器的文件系统包括不可修改的镜像层和可修改的读写层,这个目录下其实就是读写层的内容。

3、修改完毕后用 docker start 容器名/ID 即可重新启动容器。

**核心话题七:基础镜像的继承管理和如何处理多个技术栈的应用版本?
有两个问题,基础镜像的继承管理和如何处理多个技术栈的应用版本。举个例子,我们对于CentOS 7,做了公司级别的基础OS镜像A,基于这个镜像加入了JDK成为镜像B,基于B加入了JBOSS成为C,在C的基础上再构建项目的APP镜像D。
问题来了:1,有没有办法针对A镜像修改了,B,C和D去级连更新。
2,由于是继承关系,各层软件的版本不同,导致镜像种类就特别多,例如JDK有3种,jboss有三种,那么镜像C就有九种,技术栈深了,命名又成为了问题。

求指导解决思路?**

观点一:由于镜像是分层管理,层级越深,IO性能会降低,因此最好的办法就是各种环境分别制作不同image,如果有一些类似需求的,比如所有环境都使用java7,那么在base先构建java7,再在此基础上建构更上层的技术,一个原则:越通用的东西越先构建
1.尽量将Dockerfile放在空目录中,如果目录中必须有其他文件,则使用.dockerignore文件。
2.避免安装不必须的包
3.每个容器尽量只关注一个功能点。
4.尽量减少最小化镜像层数

观点二:你的提的这个问题非常好,这个问题是每个企业中大量使用容器的时候都会遇到的。

第一个问题:针对A镜像修改了,B,C和D去级连更新。
提到容器大家都在提持续集成持续部署CI/CD,每个镜像都是由Dockerfile来定义,最终执行docker build命令来镜像构建。推荐选择1-2台服务器专门用来做应用镜像的构建,避免在运行业务容器的服务器上构建镜像影响业务。

系统架构:gitlab存放dockerfile--jenkins job1(A镜像)---jenkins job2(等A构建完成后构建B)--- jenkins job3(等B构建完成后构建C)依次类推......

第二个问题:由于是继承关系,各层软件的版本不同,导致镜像种类就特别多,例如JDK有3种,jboss有三种,那么镜像C就有九种,技术栈深了,命名又成为了问题。

镜像树是这样:baseos--jdk--jbosstomcatweblogic---applications,因为dockerfile在gitlab中进行管理,所以不妨你在增加一个文件IMAGE_VERSION=xx,docker build时可以取这个文件中的值,版本号你可以取jboss的版本号(在dockerfile中增加一个EVN jboss-version=xxx就行)。这样即使后面有再多的镜像命名都很好管理了,提前规划好是非常有必要的。

更多交流内容参看:更多交流内容参看:http://www.aixchina.net/Activity/?id=671

如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!

13

添加新评论0 条评论

Ctrl+Enter 发表

关于TWT  使用指南  社区专家合作  厂商入驻社区  企业招聘  投诉建议  版权与免责声明  联系我们
© 2019  talkwithtrend — talk with trend,talk with technologist 京ICP备09031017号-30