【问题标题】:Pod receives traffic even Kubernetes readiness probe fails即使 Kubernetes 就绪探测失败,Pod 也能接收流量
【发布时间】:2020-03-17 07:12:36
【问题描述】:

我有一个应用程序,它为 REST 请求提供服务器,并且正在侦听 Kafka 主题。 我将应用程序部署到 Kubernetes 并像这样配置就绪探针

readinessProbe:
  exec:
    command:
    - cat
    - /tmp/healthy
  initialDelaySeconds: 5
  periodSeconds: 5

基本按照[configure-liveness-readiness-startup-probes]的指示

部署完成后,我可以看到 Pod 就绪探测失败

Readiness probe failed: cat: can't open '/tmp/healthy': No such file or directory

这是意料之中的。然后我向该主题发送了一条kafka消息。我观察到了

1) kafka 消息已被我的应用程序使用并保存到数据库。
2) 其余api无法访问。

我假设如果 pod 的就绪探测失败,应用程序既不能接收 kafka 消息也不能接收 rest 请求。但是为什么在我的测试中,REST 请求和 Kafka 消息的处理方式不同。

根据 Kubernetes 文档:

The kubelet uses readiness probes to know when a Container is ready to start accepting traffic

但它并没有明确说明它真正意味着什么样的流量。 如果就绪探测失败,kubernetes 是否只限制到 pod 的 http 流量,但不限制 tcp 流量(因为 Kafka 正在通过 tcp 工作)?

我的实际意图是让我的服务应用程序(kafka 消费者)能够控制何时接收 kafka 消息(以及 REST 请求)。例如。如果操作繁重,我的服务将删除 /tmp/healthy 文件,从而使 pod 无法准备好接收 kafka 消息和 Rest 请求。繁重的操作完成后,app 会写入健康文件,让 pod 准备好接收消息。

更多信息,在我的测试中,kubernetes 版本是 v1.14.3,并且 kafka broker 运行在 kubernetes 之外的一个单独的虚拟机中。

【问题讨论】:

  • 1. kafka 消息已被我的应用程序使用并保存到数据库> 你是如何发送消息的?如果您的 pod 前面有 k8s 服务(例如 kafka.kafka.svc.cluster.local),则失败的就绪探测会导致端点控制器从平衡中删除 pod
  • @KonstantinVustin,我使用另一个运行在同一个 kubernetes 中的生产者应用程序将 kafka 消息发送到主题。在 UI 中单击一个按钮后,它将使用 kafka producer lib 将 kafka 消息发送到主题。 kafka broker 和 zookeeper 安装在 kubernetes 集群之外的一个单独的 VM 中。如何检查我的 pod 前面是否运行了 k8s 服务?运行 kubectl get services 显示有集群 IP 类型的 kubernetes。
  • 您使用哪个 URL 发送?
  • Kafka Producer 对象使用“bootstrap.servers”属性向 kafka 主题发送消息。这些值类似于ip_of_service_vm:9092。服务 vm 的 ip 只是普通的 IPV4 地址。我的消费者应用程序使用相同的格式进行 kafka 消费者配置。生产者应用和消费者应用在不同的 Pod 中运行。

标签: kubernetes apache-kafka readinessprobe


【解决方案1】:

这是两件截然不同的事情:

  • 接收请求外部服务正在发送请求并期待响应。
  • 发送请求:您的服务正在发送请求并等待响应。

ReadinessProbe

当 ReadinessProbe 失败时,不会有新的请求被路由到 pod

卡夫卡消费者

如果您的 pod 是 Kafka 消费者,那么您的 pod 正在初始化对 Kafka 的请求,以从 topic 中检索消息。 p>

检查所需目录

无法打开“/tmp/healthy”:没有这样的文件或目录

如果您的服务需要目录/tmp/healthy 才能正常工作,您的服务应在启动时检查它,如果所需目录不可用,则应检查exit(1)(崩溃并显示错误消息)。这应该在连接到 Kafka 之前完成。如果您的应用程序不断使用该目录,例如写信给它,任何操作都应该检查并正确处理错误代码 - 根据你的情况记录和崩溃。

消费 Kafka 消息

我的实际意图是让我的服务应用程序(kafka 消费者)能够控制何时接收 kafka 消息(以及 REST 请求)。例如。如果操作繁重,我的服务将删除 /tmp/healthy 文件,从而使 pod 无法准备好接收 kafka 消息和 Rest 请求。

Kafka 消费者 poll Kafka 在消费者需要时获取更多数据。换句话说,当 Kafka 消费者准备好接收更多数据时,请求更多数据。

示例消费者代码:

 while (true) {
     ConsumerRecords<String, String> records = consumer.poll(100);
     for (ConsumerRecord<String, String> record : records) {
         // process your records
     }
 }

记住commit您已处理的记录,这样消息就不会被多次处理,例如崩溃后。

【讨论】:

  • 谢谢@Jonas。我的实际意图是让我的服务应用程序(kafka 消费者)能够控制何时接收 kafka 消息(以及 REST 请求)。例如。如果操作繁重,我的服务将删除 /tmp/healthy 文件,从而使 pod 无法准备好接收 kafka 消息和 Rest 请求。繁重的操作完成后,app 会写入健康文件,让 pod 准备好接收消息。
  • 我仍然不清楚的一点是,当我的消费者应用程序发送请求并等待响应时,如果 pod 尚未准备好,如何将响应路由回我的消费者应用程序?
  • @ShenghuaLiu “如果 pod 尚未准备好,如何将响应路由回我的消费者应用程序” - 请求应该路由到您服务的另一个副本。
  • 是的,到目前为止,您的回答最有帮助。非常感谢。所以基本上不可能阻止我的消费者应用程序由于 kafka 的轮询机制而收到 kafka 消息,即使 pod 还没有准备好,对吧?我从一些文章中读到,例如[链接] (dzone.com/articles/kafka-consumer-delivery-semantics),当消费者轮询消息时,它实际上是从主题的分区中读取消息。从消费者的角度来看,阅读是流量。但看起来 kubernetes 并没有阻止这个传入的流量,即使就绪探测失败。
  • 回到我之前所说的实际意图,那么当有大量操作正在进行时,我必须明确停止轮询kafka消息。你有什么建议吗?
猜你喜欢
  • 1970-01-01
  • 2019-12-05
  • 2021-11-04
  • 2018-07-10
  • 2021-02-06
  • 2023-03-11
  • 2021-08-29
  • 1970-01-01
  • 2021-01-01
相关资源
最近更新 更多