健康检查是Docker的一个重要功能。它们让你告诉平台如何测试你的应用程序是健康的,而这样做的指示被捕获为应用程序包的一部分。
当Docker启动一个容器时,它会监控该容器运行的进程。如果进程结束,容器就退出。这只是一个基本的有效性检查,因为Docker不知道也不关心你的应用程序实际上在做什么。容器进程可能正在运行,但它可能已经达到了极限--所以网络进程可能对每一个请求都做出503个回应,但它仍然在运行,所以容器保持着。
健康检查是你告诉Docker测试你的应用程序是否真正健康的方式,所以如果你的网络进程已经达到极限,Docker可以将容器标记为不健康,并采取规避措施(在swarm模式下,Docker通过旋转替换来取代不健康的容器)。
健康检查是通过Docker文件中的HEALTHCHECK指令在镜像中捕获的。有一些关于使用健康检查的优秀博文,典型的例子是这样的。
HEALTHCHECK CMD curl --fail http://localhost || exit 1
它使用curl命令在容器内发出HTTP请求,检查容器内的网络应用是否有响应。如果响应是好的,它就以0退出,如果不是,就以1退出--这告诉Docker容器是不健康的。
Windows有一个Invoke-WebRequest的curl别名,但它并不完全相同。而且PowerShell处理退出代码的方式略有不同,所以在Windows的Docker文件中,相当于这样。
HEALTHCHECK CMD powershell -command ` try { ` $response = iwr http://localhost; ` if ($response.StatusCode -eq 200) { return 0} ` else {return 1}; ` } catch { return 1 }
这两个选项都不是很好。相反,你应该考虑编写一个自定义的健康检查应用程序。
curl/iwr选项很好,也很简单,但当你在生产级Docker镜像上工作时,它有一些相当明显的缺点。
1. 在Linux镜像中,你需要有curl可用。你可以从Alpine开始,有一个4MB的基本镜像。但那并没有安装curl,只要你运行apk --update --no-cache add curl,就会给镜像增加2.5MB。而且所有的攻击面都是curl的。
2. 在Windows镜像中,你需要安装PowerShell。最新的Nano Server镜像失去了PowerShell,而倾向于镜像的大小和攻击面,如果只是为了得到iwr而失去PowerShell,那就太可惜了。
3. 如果你依赖一个特定的工具,你的Docker文件就会变得不那么便携。如果你的应用程序是跨平台的,而且你使用的是多架构的镜像,那么依赖于操作系统特定工具的健康检查会破坏你的跨平台性。最好的情况是,你的镜像无法构建。最坏的情况是--镜像建立了,但它的健康检查在一个平台上总是失败(因为它试图在Windows上使用curl或反之亦然)。
4. 你用一个简单的HTTP工具能做的事情是有限的。为了灵活运用你的应用程序并证明关键功能的工作,你可以最终写一个/diagnostics 的端点,然后用curl。诊断端点是个好东西,但你需要确保该端点保持私有。
通过使用外部工具来支持你的健康检查,你承担了在你的镜像中安装该工具的成本,并维护该工具--如果健康检查工具得到更新,你突然需要修补你的应用镜像。
相反,你应该考虑编写你自己的健康检查应用程序,使用与你自己的应用程序相同的应用程序运行时间。
自定义健康检查程序克服了使用外部工具的所有问题。你使用的是与你的实际应用相同的运行时间,所以你的健康检查没有额外的先决条件
如果你的应用程序运行时间是跨平台的,那么你的健康检查也是跨平台的, 你可以在健康检查中加入任何你想要的逻辑,而且它可以保持隐私,所以只有Docker平台可以执行这些代码。
缺点是,你现在有一个单独的东西需要编写、维护,并与你的应用程序一起打包。但这将是一个用相同语言编写的东西,而且应该比编写复杂的curl语句更简单。
前端是Nginx,运行在Azure的Docker swarm上。这里是一个Node.js应用,容器的健康检查使用一个非常简单的脚本healthcheck.js:
var http = require("http"); var options = { host : "localhost", port : "2368", timeout : 2000 }; var request = http.request(options, (res) => { console.log(`STATUS: ${res.statusCode}`); if (res.statusCode == 200) { process.exit(0); } else { process.exit(1); } }); request.on('error', function(err) { console.log('ERROR'); process.exit(1); }); request.end();
这里没有大量的代码,但我对检查的运行方式有很大的控制权。我为请求调用设置了一个超时,我检查了响应的HTTP状态代码,并在成功或失败时写了日志条目(Docker会记录这些日志,你可以在docker容器检查中看到它们)。
在Docker文件中,健康检查只是运行该脚本:
HEALTHCHECK --interval=12s --timeout=12s --start-period=30s CMD node /healthcheck.js
HEALTHCHECK指令非常清楚。CMD很简单,所以检查的配置不会被实际的检查代码所淹没。
Node.js是一种解释型语言,但对于编译型语言,你可以将健康检查器编译为多阶段Docker文件的一部分,并将其与你的应用镜像捆绑在一起。
如有想了解更多软件设计与架构, 系统IT,企业信息化, 团队管理 资讯,请关注我的微信订阅号:
作者:Petter Liu
出处:http://www.cnblogs.com/wintersun/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
该文章也同时发布在我的独立博客中-Petter Liu Blog。
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife
我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?
我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案
我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查
我的日期格式如下:"%d-%m-%Y"(例如,今天的日期为07-09-2015),我想看看是不是在过去的七天内。谁能推荐一种方法? 最佳答案 你可以这样做:require"date"Date.today-7 关于ruby-检查日期是否在过去7天内,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/32438063/