Docker健康检查为什么不要用curl或iwr

Docker健康检查为什么不要用curl或iwr

健康检查是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 }
</code></pre>
<pre><code>这两个选项都不是很好。相反,你应该考虑编写一个自定义的健康检查应用程序。
</code></pre>
<p>curl/iwr选项很好,也很简单,但当你在生产级Docker镜像上工作时,它有一些相当明显的缺点。</p>
<ol>
<li>
<p>在Linux镜像中,你需要有curl可用。你可以从Alpine开始,有一个4MB的基本镜像。但那并没有安装curl,只要你运行apk --update --no-cache add curl,就会给镜像增加2.5MB。而且所有的攻击面都是curl的。</p>
</li>
<li>
<p>在Windows镜像中,你需要安装PowerShell。最新的Nano Server镜像失去了PowerShell,而倾向于镜像的大小和攻击面,如果只是为了得到iwr而失去PowerShell,那就太可惜了。</p>
</li>
<li>
<p>如果你依赖一个特定的工具,你的Docker文件就会变得不那么便携。如果你的应用程序是跨平台的,而且你使用的是多架构的镜像,那么依赖于操作系统特定工具的健康检查会破坏你的跨平台性。最好的情况是,你的镜像无法构建。最坏的情况是--镜像建立了,但它的健康检查在一个平台上总是失败(因为它试图在Windows上使用curl或反之亦然)。</p>
</li>
<li>
<p>你用一个简单的HTTP工具能做的事情是有限的。为了灵活运用你的应用程序并证明关键功能的工作,你可以最终写一个/diagnostics 的端点,然后用curl。诊断端点是个好东西,但你需要确保该端点保持私有。</p>
</li>
</ol>
<p>通过使用外部工具来支持你的健康检查,你承担了在你的镜像中安装该工具的成本,并维护该工具--如果健康检查工具得到更新,你突然需要修补你的应用镜像。</p>
<p>相反,你应该考虑编写你自己的健康检查应用程序,使用与你自己的应用程序相同的应用程序运行时间。</p>
<p>自定义健康检查程序克服了使用外部工具的所有问题。你使用的是与你的实际应用相同的运行时间,所以你的健康检查没有额外的先决条件</p>
<p>如果你的应用程序运行时间是跨平台的,那么你的健康检查也是跨平台的, 你可以在健康检查中加入任何你想要的逻辑,而且它可以保持隐私,所以只有Docker平台可以执行这些代码。</p>
<p>缺点是,你现在有一个单独的东西需要编写、维护,并与你的应用程序一起打包。但这将是一个用相同语言编写的东西,而且应该比编写复杂的curl语句更简单。</p>
<blockquote></blockquote>
<pre><code>var http = require("http");

var options = {
    host : "localhost",
    port : "2368",
    timeout : 2000
};

var request = http.request(options, (res) => {
    console.log(: ${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,企业信息化, 团队管理 资讯,请关注我的微信订阅号:

Original: https://www.cnblogs.com/wintersun/p/16366209.html
Author: PetterLiu
Title: Docker健康检查为什么不要用curl或iwr

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/534190/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球