docker容器如何可靠地表示它们';你不只是跑,而是准备好了吗?

docker容器如何可靠地表示它们';你不只是跑,而是准备好了吗?,docker,Docker,我有一个Docker容器,它运行一个提供微服务的小型TCP服务器 一旦容器化进程启动,进程开始侦听其端口需要几毫秒的时间。如果在此之前尝试连接,则任何客户端的连接都将因连接被拒绝而终止 忙着等待容器状态更改为running不足以防止这种情况发生,因为在进程启动后需要一段时间才能启动服务 容器进程向主机表明其已真正准备就绪可供使用的好方法/常规方法是什么?Id取决于容器的运行方式/位置。DockerFile和Docker Compose/Swarm有一个HEALTHCHECK命令: 这是一个简单的

我有一个Docker容器,它运行一个提供微服务的小型TCP服务器

一旦容器化进程启动,进程开始侦听其端口需要几毫秒的时间。如果在此之前尝试连接,则任何客户端的连接都将因
连接被拒绝而终止

忙着等待容器状态更改为
running
不足以防止这种情况发生,因为在进程启动后需要一段时间才能启动服务


容器进程向主机表明其已真正准备就绪可供使用的好方法/常规方法是什么?Id取决于容器的运行方式/位置。DockerFile和Docker Compose/Swarm有一个
HEALTHCHECK
命令:

这是一个简单的脚本,如果容器未准备好,它将返回一个错误

在Kubernetes中,POD还可以定义运行状况检查和就绪检查:

它们看起来一样,但有一点不同:如果容器不健康,它将重新启动,而就绪检查失败将不会重新启动容器。如果检查失败了预定义的次数(可配置),则将其标记为“失败”


Dockerfile中的运行状况检查,因此如果部署在Dockerfile中,则应使用Kubernetes。Id取决于容器的运行方式/位置。DockerFile和Docker Compose/Swarm有一个
HEALTHCHECK
命令:

这是一个简单的脚本,如果容器未准备好,它将返回一个错误

在Kubernetes中,POD还可以定义运行状况检查和就绪检查:

它们看起来一样,但有一点不同:如果容器不健康,它将重新启动,而就绪检查失败将不会重新启动容器。如果检查失败了预定义的次数(可配置),则将其标记为“失败”

Dockerfile中的运行状况检查,因此如果部署在Dockerfile中,则应使用Kubernetes。轮询服务是常规方法。不要在意Docker在说什么;尝试建立连接,如果确实出现连接被拒绝错误,请重试,直到连接成功或等待时间过长

大多数容器只有在实际准备好接受流量时才真正开始侦听其TCP端口。客户机通常通过轮询套接字来处理此问题,通常使用专门构建的工具,如。一种非常合理的替代方法是,客户机在初始启动时尝试连接,如果连接失败,则崩溃,并让编排器重新启动pod(即使只有足够小的部分可以使其工作)

由于容器与其主机系统是隔离的,因此没有其他路径可以让容器发布“我准备好了!”。例如,如果一个容器创建了一个文件来公布准备情况,那么它将需要一些与主机系统共享的存储来创建该文件,并且编排器(例如Docker Compose)需要知道这一点。这不是任何普通编曲的标准部分

轮询方法的另一个重要方面是,问题和解决方案都不是Docker特有的。如果您只是在Ubuntu主机上运行
服务mysql start
,而不涉及Docker,那么仍然需要一分钟左右的时间,同样的轮询方法也会起作用。如果数据库位于其他主机或云提供商上的某个位置,则您没有共享的文件系统,但您可以再次轮询它,直到它准备就绪。像这样的工具可以基于轮询已知服务来构建服务目录。提到Kubernetes健康检查,它也有类似的方法(“尝试连接,或崩溃”绝对是管理Kubernetes托管客户端的正常方法)。

轮询服务是传统方法。不要在意Docker在说什么;尝试建立连接,如果确实出现连接被拒绝错误,请重试,直到连接成功或等待时间过长

大多数容器只有在实际准备好接受流量时才真正开始侦听其TCP端口。客户机通常通过轮询套接字来处理此问题,通常使用专门构建的工具,如。一种非常合理的替代方法是,客户机在初始启动时尝试连接,如果连接失败,则崩溃,并让编排器重新启动pod(即使只有足够小的部分可以使其工作)

由于容器与其主机系统是隔离的,因此没有其他路径可以让容器发布“我准备好了!”。例如,如果一个容器创建了一个文件来公布准备情况,那么它将需要一些与主机系统共享的存储来创建该文件,并且编排器(例如Docker Compose)需要知道这一点。这不是任何普通编曲的标准部分

轮询方法的另一个重要方面是,问题和解决方案都不是Docker特有的。如果您只是在Ubuntu主机上运行
服务mysql start
,而不涉及Docker,那么仍然需要一分钟左右的时间,同样的轮询方法也会起作用。如果数据库位于其他主机或云提供商上的某个位置,则您没有共享的文件系统,但您可以再次轮询它,直到它准备就绪。像这样的工具可以基于轮询已知服务来构建服务目录。提到Kubernetes健康检查,它也有类似的方法(并且“尝试连接,或崩溃”绝对是管理Kubernetes托管客户端的正常方法)。

这是一个很好的信息,但是(1)我没有运行Kubernetes,并且(2)对于我的应用程序来说,多秒轮询时间太长。理想的解决方案是容器一知道就可以执行一些通知(创建/写入文件、发送信号等)
HEALTHCHECK --interval=5s --timeout=3s CMD curl --fail http://localhost:8091/pools || exit
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-exec
spec:
  containers:
  - name: liveness
    image: k8s.gcr.io/busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5
      periodSeconds: 5