一、为什么需要健康检查
容器化应用就像住在公寓里的租客,虽然水电齐全,但房东(运维人员)得定期确认租客是否还活着。没有健康检查的容器,就像从不回消息的室友——你不知道它是在正常工作还是已经崩溃。
举个例子,你的电商网站用Docker部署了商品服务,但某个容器因为内存泄漏悄悄挂了。如果没有健康检查,流量还会继续往这个"僵尸容器"发送,用户看到的可能就是404错误页面。
二、健康检查的三种姿势
1. 命令检查(CMD)
最直接的方式就是让容器执行一条命令,返回0表示健康,非0则异常。比如用curl检查Web服务:
# Dockerfile示例(技术栈:Nginx)
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost/ || exit 1
参数说明:
--interval:每30秒检查一次--timeout:超过3秒没响应就算失败curl -f:静默模式,失败时返回非0状态码
2. HTTP端点检查
现代应用通常会有专门的健康检查API端点:
# 适用于Spring Boot应用(技术栈:Java)
HEALTHCHECK --start-period=40s \
CMD curl -s http://localhost:8080/actuator/health | grep -q '"status":"UP"'
技巧:
/actuator/health是Spring Boot Actuator的标准端点start-period给应用40秒启动时间,避免误判
3. TCP端口探测
适合那些没有HTTP接口的服务,比如数据库:
# Redis健康检查示例(技术栈:Redis)
HEALTHCHECK --retries=3 \
CMD nc -z localhost 6379 || exit 1
注意:
nc -z只测试TCP连接,不验证实际功能retries连续失败3次才标记为不健康
三、进阶玩法:组合检查
有时候简单的命令检查不够用,比如你的微服务需要同时满足:
- 能响应HTTP请求
- 能连接Redis
- 磁盘空间充足
这时候可以写个脚本:
#!/bin/bash
# 复合检查脚本(技术栈:Node.js)
curl -f http://localhost:3000/health || exit 1
redis-cli ping | grep -q PONG || exit 1
[ $(df / | awk 'NR==2{print $4}') -gt 1000000 ] || exit 1
然后在Dockerfile中引用:
COPY healthcheck.sh /usr/local/bin/
HEALTHCHECK CMD /usr/local/bin/healthcheck.sh
四、避坑指南
1. 检查频率要合理
- 太频繁(如1秒1次):浪费资源
- 间隔太长(如5分钟):故障发现延迟
- 推荐值:生产环境通常30秒-1分钟
2. 超时时间要设置
特别是网络检查,默认超时时间可能太长:
# 错误示范(超时未设置)
HEALTHCHECK CMD curl http://slow-service/
# 正确做法
HEALTHCHECK --timeout=5s CMD curl -f http://slow-service/
3. 注意启动缓冲期
刚启动的容器可能需要加载数据、初始化连接:
# 给Elasticsearch 2分钟启动时间(技术栈:Elasticsearch)
HEALTHCHECK --start-period=120s \
CMD curl -s http://localhost:9200/_cluster/health | grep -q '"status":"green"'
4. 不要过度依赖健康检查
以下情况健康检查会失效:
- 容器进程僵死(PID 1还在,但服务不响应)
- 内核级故障(如磁盘损坏)
- 网络隔离
五、实战案例:Kubernetes集成
在K8s中健康检查更关键,因为它是服务自愈的基础。看个Deployment配置片段:
# k8s健康检查示例(技术栈:Golang)
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
readinessProbe:
exec:
command:
- /bin/check-db-connection.sh
failureThreshold: 3
关键区别:
livenessProbe:失败会重启容器readinessProbe:失败只是从负载均衡摘除
六、监控与告警
健康状态应该被监控系统采集,比如Prometheus可以通过container_health_status指标收集数据。配合Grafana可以做出这样的看板:
UP状态的容器比例 = sum(container_health_status{state="healthy"})
/ sum(container_health_status)
当比例低于95%时触发告警,比等用户投诉更主动。
七、总结
健康的健康检查方案应该:
- 覆盖关键功能点,但不过度检查
- 设置合理的超时和间隔
- 区分"存活检查"和"就绪检查"
- 与编排系统(如K8s)深度集成
- 纳入统一监控体系
就像定期体检不能包治百病,但没有健康检查的容器化系统,就像蒙着眼睛走钢丝——掉下去是迟早的事。
评论