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

      健康检查是Docker的一个重要功能。它们让你告诉平台如何测试你的应用程序是健康的,而这样做的指示被捕获为应用程序包的一部分。

     当Docker启动一个容器时,它会监控该容器运行的进程。如果进程结束,容器就退出。这只是一个基本的有效性检查,因为Docker不知道也不关心你的应用程序实际上在做什么。容器进程可能正在运行,但它可能已经达到了极限--所以网络进程可能对每一个请求都做出503个回应,但它仍然在运行,所以容器保持着。

     健康检查是你告诉Docker测试你的应用程序是否真正健康的方式,所以如果你的网络进程已经达到极限,Docker可以将容器标记为不健康,并采取规避措施(在swarm模式下,Docker通过旋转替换来取代不健康的容器)。


听起来不错,让我们用curl来做吧


      健康检查是通过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的问题


     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。诊断端点是个好东西,但你需要确保该端点保持私有。

通过使用外部工具来支持你的健康检查,你承担了在你的镜像中安装该工具的成本,并维护该工具--如果健康检查工具得到更新,你突然需要修补你的应用镜像。

相反,你应该考虑编写你自己的健康检查应用程序,使用与你自己的应用程序相同的应用程序运行时间。

R


编写一个自定义的健康检查器


     自定义健康检查程序克服了使用外部工具的所有问题。你使用的是与你的实际应用相同的运行时间,所以你的健康检查没有额外的先决条件

如果你的应用程序运行时间是跨平台的,那么你的健康检查也是跨平台的, 你可以在健康检查中加入任何你想要的逻辑,而且它可以保持隐私,所以只有Docker平台可以执行这些代码。

缺点是,你现在有一个单独的东西需要编写、维护,并与你的应用程序一起打包。但这将是一个用相同语言编写的东西,而且应该比编写复杂的curl语句更简单。


Node.js中的健康检查示例


     前端是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文件的一部分,并将其与你的应用镜像捆绑在一起。



今天先到这儿,希望对云原生,技术领导力, 企业管理,系统架构设计与评估,团队管理, 项目管理, 产品管管,团队建设 有参考作用 , 您可能感兴趣的文章:
领导人怎样带领好团队
构建创业公司突击小团队
国际化环境下系统架构演化
微服务架构设计
视频直播平台的系统架构演化
微服务与Docker介绍
Docker与CI持续集成/CD
互联网电商购物车架构演变案例
互联网业务场景下消息队列架构
互联网高效研发团队管理演进之一
消息系统架构设计演进
互联网电商搜索架构演化之一
企业信息化与软件工程的迷思
企业项目化管理介绍
软件项目成功之要素
人际沟通风格介绍一
精益IT组织与分享式领导
学习型组织与企业
企业创新文化与等级观念
组织目标与个人目标
初创公司人才招聘与管理
人才公司环境与企业文化
企业文化、团队文化与知识共享
高效能的团队建设
项目管理沟通计划
构建高效的研发与自动化运维
某大型电商云平台实践
互联网数据库架构设计思路
IT基础架构规划方案一(网络系统规划)
餐饮行业解决方案之客户分析流程
餐饮行业解决方案之采购战略制定与实施流程
餐饮行业解决方案之业务设计流程
供应链需求调研CheckList
企业应用之性能实时度量系统演变

如有想了解更多软件设计与架构, 系统IT,企业信息化, 团队管理 资讯,请关注我的微信订阅号:

MegadotnetMicroMsg_thumb1_thumb1_thu[2]

作者:Petter Liu
出处:http://www.cnblogs.com/wintersun/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 该文章也同时发布在我的独立博客中-Petter Liu Blog。

posted on 2022-06-11 16:32  PetterLiu  阅读(358)  评论(0编辑  收藏  举报