Kubernetes 探针的工作原理
我将向您展示 Kubernetes 中探针的工作原理。它们如何使您的应用程序更具弹性,并帮助您防止可避免的错误,比如需要数小时才能恢复的重启循环以及在发布期间丢失请求。本帖中的每个互动演示都使用我的部分 Kubernetes TypeScript 移植项目 webernetes。它包含超过 100,000 行移植的 Kubernetes Go 代码,可以直接在浏览器中运行模拟集群。我验证了这些演示的行为与 k3s 的一致,并成功发现了 Kubernetes 中的一个 bug!稍后会详细介绍。您将学到的内容是没有探针的 Pod。我想运行一个只有一个容器的 Pod。这是它的清单 pod-a.yaml:pod-a.yaml 1 apiVersion: "v1" 2 kind: "Pod" 3 metadata: 4 name: "pod-a" 5 spec: 6 containers: 7 - name: "app" 8 image: "my-app:latest" 这个映像 my-app:latest 在监听端口 8080 之前花费了几秒钟进行初始化。当您点击重启以向容器发送信号时,您将看到下面的情况,这会导致它崩溃并重新被 Kubernetes 启动。您可以随时暂停或重置任何演示。node-1 0/2 重启容器 尚未完成。在第一次崩溃后,容器立即重新启动。在第二次崩溃后,Kubernetes 对它施加了 CrashLoopBackOff,然后再重新启动。默认情况下,这个延迟为 10 秒,每次崩溃后翻倍,最长等待时间为 5 分钟。为了这个演示,我将其缩短到 3 秒。在这两种情况下,Kubernetes 会认为容器一启动就 Ready,尽管我们知道它并不是。它仍在进行启动工作,还没有监听端口 8080。接下来我将添加 pod-b,每 2 秒向 pod-a 发送一个请求。在整篇文章中,您可以把 pod-b 看作是任何客户端流量的来源:入口控制器、负载均衡器、服务间请求等。如果您在下面的演示中重新启动 pod-a,而请求正在传输中,该请求将失败。node-1 使请求失败 尚未完成。从您重新启动容器的那一刻起,直到其启动工作完成,请求都会失败,即使容器被认为是 Ready!这不是我想要的。我需要 Kubernetes 知道 pod-a 何时准备好接收流量。为此,Kubernetes 给我们提供了探针。探针是定期发送到容器的检查,以确定它们的健康状况。它们有三种类型:启动探针确定容器内的应用程序是否已启动;就绪探针确定应用程序是否准备好接收流量;存活探针确定应用程序是否需要重启。我认为启动探针最适合我在上面的演示中展示的问题,因此我们从这里开始。启动探针 下面,我在 pod-a.yaml 中添加了一个启动探针:pod-a.yaml 1 apiVersion: "v1" 2 kind: "Pod" 3 metadata: 4 name: "pod-a" 5 spec: 6 containers: 7 - name: "app" 8 image: "my-app:latest" 9 startupProbe: 10 httpGet: 11 path: "/startup" 12 port: 8080 13 periodSeconds: 1 14 failureThreshold: 5 这是一个 httpGet 探针,它向 pod 发送 GET /startup 请求,端口是 8080。状态码 200-399 视为成功。每 periodSeconds 秒执行一次,并允许在 Kubernetes 杀死容器之前失败 failureThreshold 次。这为我的容器完成启动工作提供了大约 5 秒的时间。Kubernetes 还支持 tcpSocket、exec 和 grpc 探针。这些探针建立一个 TCP 连接、在容器内运行一个命令,或调用 gRPC 健康检查协议以确定容器健康。您可以在 Kubernetes 文档中阅读有关它们的内容。在整个文章中,我将使用 httpGet。探针是由一个叫做 kubelet 的进程发送的。集群中每个节点都有自己的 kubelet,kubelet 的职责是确保每个节点运行正确的 Pod 并进行探针检测。当您在下面重新启动 pod-a 时,它现在显示为 NotReady。Kubernetes 现在意识到 pod-a 尚未初始化。它只有在第一次启动探针成功后才会变为 Ready。node-1 0/2 重启容器 尚未完成。kubelet NotReady 是具有启动探针的 Pod 的默认状态。然而,即使在不 Ready 的情况下,pod-b 仍会向 pod-a 发送请求,并且在容器的启动周期中,这些请求仍会失败。这是因为我配置 pod-b 直接向 pod-a 的 IP 地址发送请求,这绕过了就绪机制。关于 NotReady 我有点撒谎 从技术上讲,Kubernetes 没有 NotReady 状态,它有一个 Ready 状态,可以是 True、False 或 Unknown。我称之为 NotReady,因为在演示中它比 Ready=True 或 Ready=False 短。要修复这些失败的请求,我需要升级到更具生产级别的设置:多个副本的 pod-a,相互之间进行负载均衡。我将创建一个配置为运行 2 个副本 pod-a 的 ReplicaSet 和一个在它们之间进行负载均衡的 Service。replica-set-a.yaml 1 api
本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。
☕请我喝杯咖啡