使用Docker,Chef和Amazon OpsWorks进行集群范围的Java / Scala应用程序部署

Docker非常适合在单个节点上运行隔离的容器。 但是,大多数软件系统都在多个节点上运行,因此,除了Docker之外,我们还需要某种方法来指定哪些容器应在哪些节点上运行。

MQPerf-deployment-blog-logos-1-300x216

我要解决的特定问题如下:我有两个Scala守护程序,我想在多个节点上运行(取决于配置,每个节点可以运行一个或两个守护程序)。 我想要一种在集群中部署修改后的二进制文件的快速方法。 我也不想花费太多时间来设置服务器。 (我的Gentoo日子已经过去了。)

我到达的最终解决方案涉及Docker , OpsWorks , Chef和Vagrant 。 但是,一步一步来。

顺便说一句-您将如何解决上述问题? 请评论。

打包Java / Scala应用程序

首先,我需要能够打包和上传二进制文件。 在这里,Docker非常完美。 我编写了一个简单的Dockerfile ,其中:

  • 基于受信任的ubuntu + java7映像–无需在服务器上安装Java!
  • 将胖子从我的磁盘复制到映像
  • 指定使用复制的jar运行Java的入口点

完整的Dockerfile可以在这里找到: https ://gist.github.com/adamw/166b82ec04c9c0f67453。

有了这样的映像,我可以将其推送到(公共或私有) Docker注册表中 ,群集中的节点可以将其下载。

如果需要,我还可以安装我的应用程序需要的任何其他操作系统级别的依赖项,而不必担心版本冲突并在实际服务器上进行设置。

如果看一下Dockerfile,您可能会注意到有两个jar。 这样做是为了最小化每次代码更改后必须上传的Docker映像的大小。 第一个jar仅包含依赖项(Scala库,日志记录库,框架等)。 第二个jar包含已编译的应用程序代码。 从Dockerfile构建Docker映像时,将创建一系列中间映像,每个步骤之后一个。 对于涉及相同文件的相同命令,不会创建新映像,但会从Docker缓存中重新使用映像。

依赖关系很少更改,因此通常dep-jar保持不变,因此缓存的版本会被重用(并且中间映像会上传一次)。 另一方面,应用程序代码始终会更改。 重要的是,首先将依赖项jar添加到映像,以便中间映像包含deps,但不包含应用程序代码(更改后的代码)。 最后,通常只需要上传2-3MB。

不过,这里要注意一件事。 在确定是否可以在ADD命令(该命令将文件从本地磁盘复制到该映像)之后重新使用该映像时,Docker仅检查该文件的最后修改时间戳。 这将导致依赖项fat-jar在每次重新构建时都被重新添加,即使它们是相同的。 因此,我创建了一个简单的bash脚本,仅当其md5校验和发生更改时,该脚本才会复制dockerfile旁边的fat-jar(作为Docker上下文的一部分从该文件上传): https : //gist.github.com/adamw/ ba5d8b79ff553fba83fd 。

如何用SBT创建这样两个单独的jar? 非常简单。 只需使用SBT Assembly插件并更改其设置即可:

assemblyOption in assembly ~= { _.copy(includeBin = true, includeScala = false, includeDependency = false) }

然后, assemblyPackageDependency目标将创建仅依赖项的jar,而assembly将创建仅应用程序的jar。

设置服务器

随着包含我们应用程序的Docker映像在云中(在Docker集线器上)等待,现在是时候设置服务器了,Docker守护程序将在其中运行容器。

为了配置服务器,我选择了Amazon OpsWorks的Chef,这有两个原因:可以使用Stacks和Layers清楚地分离和组织EC2实例,这些服务器与Chef具有现成的集成,并且使用自定义厨师食谱非常容易。 完全不需要手动实例设置!

以下步骤部分是摘要,部分是ShopIgniter博客上描述的内容的扩展。

Chef安装程序(由OpsWorks运行)将是最少的,并且仅包含运行Docker所需的内容。

首先,我们需要创建一个具有更新内核的基于Ubuntu 12.04的AMI(14.04尚不能与OpsWorks配合使用)–有关详细信息,请参阅ShopIgniter的博客。

其次,我们将使用自定义的厨师食谱; 为此,您需要创建一个专用的存储库(例如在GitHub上)。 食谱非常基本和简单: https : //gist.github.com/adamw/792f8c22abb09699b6d5 。

总结一下:

  • docker::setup安装Docker
  • docker::kill_containers杀死并删除所有正在运行的容器
  • docker::myapp从Docker注册表中提取myapp映像并运行一个容器,该容器具有例如Chef-JSON配置文件的每个应用程序部分中指定的命令行参数和环境变量(此处我们的应用程序使用单个命令-line参数,并且需要环境中的AWS凭证):
{"myapp": {"image": "adamw/myapp:latest","cmdline": [ "com.softwaremill.myapp.Main", "10" ],"env": {"AWS_ACCESS_KEY_ID": “...","AWS_SECRET_ACCESS_KEY": “..."}}
}

配置OpsWorks

要配置OpsWorks,我们需要使用自定义Chef食谱和自定义配置JSON创建一个Stack,例如上面的示例(对于要运行的每个应用程序/容器类型,我们需要在配置JSON中有一个部分)。 其次,对于我们要部署的每个应用程序(容器),我们需要创建一个图层。 由于这些层将仅运行Docker,因此我们不使用任何预先配置的层,而使用“自定义”层。

该层将包含我们的自定义配方:在Setup阶段,我们需要使用docker::setup配方,在Deploy阶段,我们需要使用docker::kill_containersdocker::kill_containers docker::myapp配方。

现在,每次在该层上运行Deploy阶段时,Docker都会提取映像并运行指定的容器! 通过创建具有适当配方的图层,我们可以在任何节点上启动容器的任何组合。

opsworks1-300x233

运行部署阶段

要一次单击即可实际运行“ Deploy阶段,我们需要创建一个虚拟的OpsWorks应用程序:只需选择“类型:其他”和“存储库类型:其他”。 现在,每次要在服务器上部署应用程序(运行更新的Docker容器)时,只需将此虚拟应用程序部署在所需的实例或层上即可。

这也可以通过API调用来完成(就像AWS上的一切一样)! 因此,构建应用程序,创建Docker映像,推送该映像以及在OpsWorks上运行部署的整个过程可以非常容易地实现自动化-例如在成功构建之后。

一切就绪后,我们现在可以将新实例添加到图层,启动和停止它们,并让多节点集群运行我们的应用程序! 要更新应用程序,只需将二进制文件推送到注册表即可。

在本地测试厨师

虽然Chef的食谱非常少,但仍然可以在本地对其进行测试仍然很有用。 使用Vagrant可以轻松实现。 使用Vagrant,我们可以轻松地创建安装了Chef的VM,该VM可以运行我们的配方,从而可以运行Docker容器。 此特定情况的Vagrantfile在这里: https ://gist.github.com/adamw/bf6fa803b6b13fd7430b。

Vagrantfile包含对我们正在开发的Chef食谱的引用(通过chef.cookbooks_path ),并且具有与我们在OpsWorks中使用的相同的配置JSON。

发布vagrant up ,我们将运行虚拟机。 更改食谱或上载新容器后,我们可以通过使用vagrant provision --provision-with chef_solo轻松地重新运行Chef食谱。

加起来

我们最终得到以下关注点分离:

  • Docker-在隔离的容器中运行应用程序,具有所有必需的依赖项
  • Chef –在定义的节点上设置docker,运行并链接具有指定参数/环境的容器
  • OpsWorks –管理实例,触发部署
  • 流浪汉–整个设置的本地测试

尽管在上述整个过程中肯定有一些事情需要简化(我希望Atomic项目能够做到这一点!)最后,在集群中轻松地部署新版本的修改后的应用程序非常容易,而且很轻松,开发环境。

翻译自: https://www.javacodegeeks.com/2014/06/cluster-wide-javascala-application-deployments-with-docker-chef-and-amazon-opsworks.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/363540.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

根据输入成绩显示成绩等级(新手)

//导入包。 import java.util.Scanner; //定义一个类。 public class zy238{    //公共静态的主方法。 public static void main(String[] args){ //打印提示。     System.out.println("请你输入成绩"); //为其创建变量。     Scanner sc new Scanner(Sy…

Tmux: 打造精致与实用并存的终端

由于最近需要经常 ssh 到远程环境,遂趁此折腾了一番 tmux。毕竟 工欲善其事,必先利其器 以下是我的配置文件地址,并在不断摸索与更新中。特别喜欢 solarized 主题,于是参考它配了状态栏的主题。在后边我会列出一些平时使用的技巧&…

8、路由 router

路由:router 用户功能 /user ----> index.html /user/login ----> login.html /user/reg ----> reg.html /user userRouter > express.Router(); app.use("/user",userRouter); 新闻功能 /news ----> index.html /news/edit ----> edit.ht…

服务器装虚拟化平台,vmware服务器虚拟化方案(vmware虚拟化平台部署)

服务器虚拟化平台方案主要的有三种,特点分别如下:1、思杰Citrix XenServer :XenCenter是Citrix的虚拟化图形接口管理工具,可在同一界面,管理多台的XenServer服务。以前见过一台服务器安装虚拟服务器,然后可以装N个系统…

一个逐步“优化”的范例程序(转)

reference URL:http://www.tracefact.net/Software-Design/A-Sample-Design.aspx本文是《Object-Oriented Analysis and Design》一书第一章和第五章的读书笔记。我对书中提供的一个范例程序进行了总结和整理,通过逐步优化这个乐器管理的范例程序&#x…

Java SE 8新特性导览:使用Lambda Expression进行函数式编程

“ Java SE 8新功能浏览 ”系列的这篇文章将深入了解Lambda表达式 。 我将向您展示Lambda表达式的几种不同用法。 它们都具有功能接口的共同实现。 我将解释编译器如何从代码中推断信息,例如特定类型的变量以及后台实际发生的情况。 在上一篇文章“ Java SE 8新功能…

JS 数据转换

转换成字符串类型 toString() var num 5;console.log(num.toString()); String() String()函数存在的意义:有些值没有toString(),这个时候可以使用String()。比如:undefined和null 拼接字符串方式 num "",当 两边一…

凭借K2 SmartObject框架,在SharePoint中集成数据

随着SharePoint 2013的发布,Microsoft已提供Business Connectivity Services(BCS)增强功能以及外部列表功能,确保您可以更简单地在SharePoint环境下从外部数据源提取数据。针对诸如服务台票务应用或销售仪表盘等实施解决方案&…

浙大计算机专硕培养方案,浙江大学硕士研究生培养方案

《浙江大学硕士研究生培养方案》由会员分享,可在线阅读,更多相关《浙江大学硕士研究生培养方案(3页珍藏版)》请在人人文库网上搜索。1、浙江大学硕士研究生培养方案医 学院 肿瘤学 专业(代码: 100214 )(一级学科: 临床医学 )一、培…

停止尝试使用内部DB框架模拟SQL OFFSET分页!

我敢肯定,到目前为止,您已经以多种方式弄错了。 而且您可能很快将无法正确处理。 那么,当您可以实施业务逻辑时,为什么还要在SQL调整上浪费您的宝贵时间呢? 让我解释… 直到最近的SQL:2008标准 &#xff0…

leetcode 20. Valid Parentheses 、32. Longest Valid Parentheses 、301. Remove Invalid Parentheses

20. Valid Parentheses 错误解法&#xff1a; "[])"就会报错&#xff0c;没考虑到出现)、]、}时&#xff0c;stack为空的情况&#xff0c;这种情况也无法匹配 class Solution { public:bool isValid(string s) {if(s.empty())return false;stack<char> st;st.…

和朱晔一起复习Java并发(五):并发容器和同步器

和朱晔一起复习Java并发&#xff08;五&#xff09;&#xff1a;并发容器和同步器 本节我们先会来复习一下java.util.concurrent下面的一些并发容器&#xff0c;然后再会来简单看一下各种同步器。 ConcurrentHashMap和ConcurrentSkipListMap的性能 首先&#xff0c;我们来测试一…

树莓派3显示服务器SSH拒绝了密码,脚本封杀尝试树莓派SSH密码的来源IP

树莓派整天开着&#xff0c;如果用缺省SSH端口对外开放&#xff0c;就会经常遇到扫描SSH密码的肉鸡。虽然密码不是很简单&#xff0c;但还是感觉很不安全的。系统的ssh登录日志文件在&#xff1a;/var/log/auth.log&#xff0c;登录失败时会记录以下格式的日志&#xff1a;Mar …

6-1 数组函数练习

1、引用 /* var num 10;function show(num){num ;alert(num);}alert(num); //10show(num); //11 num numalert(num); //10*//*引用*//*var arr [1, 2, 3, 4];function show(arr){arr.push("hello");alert(arr);}alert(arr); //[1, 2, 3, 4]show(arr)…

整理任务

昨晚帮师姐整理测试&#xff0c;没有时间写日志&#xff0c;今天一大早补上。 十一长假之后的第一个工作日&#xff0c;老师回来了。详细汇报了整个假期的学习之后&#xff0c;老师整理了以后我的学习任务。本来觉得没多少事情&#xff0c;可是细数了一下&#xff0c;竟然光论文…

Hive:使用Apache Hive查询客户最喜欢的搜索查询和产品视图计数

这篇文章涵盖了使用Apache Hive查询存储在Hadoop下的搜索点击数据。 我们将以示例的方式生成有关总产品浏览量的客户排名靠前的搜索查询和统计信息。 继续之前的文章 使用大数据分析客户产品搜索点击次数 &#xff0c; Flume&#xff1a;使用Apache Flume收集客户产品搜索点…

expdp错误案例

转自:https://www.cnblogs.com/kerrycode/p/3960328.html Oracle数据泵(Data Dump)使用过程当中经常会遇到一些奇奇怪怪的错误案例&#xff0c;下面总结一些自己使用数据泵(Data Dump)过程当中遇到的问题以及解决方法。都是在使用过程中遇到的问题&#xff0c;以后陆续遇到数据…

HashSet源码分析:JDK源码系列

1.简介 继续分析源码&#xff0c;上一篇文章把HashMap的分析完毕。本文开始分析HashSet简单的介绍一下。 HashSet是一个无重复元素集合&#xff0c;内部使用HashMap实现&#xff0c;所以HashMap的特征耶继承了下来。存储的元素是无序的并且HashSet允许使用空的元素。 HashSet是…

修改左侧导航显示样式(转载自Sunmoonfire's artistic matrix)

这是一片非常好的文章&#xff0c;修改下CSS就可以改变左侧导航栏的样式&#xff0c;在网上找了一些都是要写代码的。怕连接失效&#xff0c;所以直接将文章考了过来&#xff0c;希望作者原谅&#xff0c;如有不妥&#xff0c;请通知一声&#xff0c;我会将文章删掉&#xff01…

tf.argmax()以及axis

tf.argmax()表示返回最大值的索引号&#xff0c;axis为0 &#xff0c;表示返回每列最大值索引号。axis为1 &#xff0c;表示返回每行最大值索引号 结果为 转载于:https://www.cnblogs.com/san333/p/10507402.html