0

AKS 如何使未准备好的 pod 无法接受对其的请求?仅当您在该部署之前有服务时才有效?

我想首先解释一下我在未配置 azure cni 的 aks 中注意到的内容,然后继续解释我在启用 azure cni 的 aks 中看到的内容。

在没有启用 cni 的 AKS 中,如果我在这样的服务后面的未准备好的 pod 上执行curlon url,curl -I some-pod.some-service.some-namespace.svc.cluster.local:8080我在响应中得到的响应是无法解析的主机名或类似的东西。这意味着据我了解 DNS 没有此条目。这就是在正常情况下,aks 处理未准备好的 pod 以不接收请求的方式。

在启用了 azure cni 的 AKS 中,如果我在未准备好的 pod 上执行相同的请求,它能够解析主机名并能够将请求发送到 pod。但是,有一个警告是,当我尝试通过该服务的外部私有 ip 执行请求时,该请求不会到达未准备好的 pod,这是预期的并且似乎工作正常。但是,当我尝试执行上面提到的请求时,它再次curl -I some-pod.some-service.some-namespace.svc.cluster.local:8080起作用,但它不应该。为什么在 azure cni 的情况下 DNS 具有该值?

我可以做些什么来将 azure cni 配置为更像 AKS 的默认行为,在这种行为中,这样的 curl 请求要么无法解析该主机名,要么会拒绝连接或其他什么?

4

1 回答 1

0

假设not ready pod引用就绪探针失败的 pod。kubelet 使用就绪探针来了解容器何时准备好开始接受流量。当 Pod 的所有容器都准备好时,就认为 Pod 准备好了。此信号的一种用途是控制哪些 Pod 用作服务的后端。当Pod 没有准备好时,它会从服务负载均衡器中移除。[参考]

但是,确定 pod 就绪的逻辑可能与 pod 是否可以服务请求有关,也可能无关,并且完全取决于用户。

例如,具有以下清单的 Pod:

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: readiness
  name: readiness-pod
spec:
  containers:
  - name: readiness-container
    image: nginx
    readinessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5
      periodSeconds: 5

/tmp/healthy无论 nginx 是否为应用程序服务,都根据文件的存在来决定是否准备就绪。因此,在运行应用程序并使用k run -readiness-svc上的服务公开它时:

kubectl exec readiness-pod -- /bin/bash -c 'if [ -f /tmp/healthy ]; then echo "/tmp/healthy file is present";else echo "/tmp/healthy file is absent";fi'
/tmp/healthy file is absent

kubectl get pods -o wide
NAME            READY   STATUS    RESTARTS   AGE    IP            NODE                                NOMINATED NODE   READINESS GATES
readiness-pod   0/1     Running   0          11m    10.240.0.28   aks-nodepool1-29819654-vmss000000   <none>           <none>
source-pod      1/1     Running   0          6h8m   10.240.0.27   aks-nodepool1-29819654-vmss000000   <none>           <none>

kubectl describe svc readiness-svc
Name:              readiness-svc
Namespace:         default
Labels:            test=readiness
Annotations:       <none>
Selector:          test=readiness
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.0.23.194
IPs:               10.0.23.194
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:
Session Affinity:  None
Events:            <none>

kubectl exec -it source-pod -- bash
root@source-pod:/# curl -I readiness-svc.default.svc.cluster.local:80
curl: (7) Failed to connect to readiness-svc.default.svc.cluster.local port 80: Connection refused
root@source-pod:/# curl -I 10-240-0-28.default.pod.cluster.local:80
HTTP/1.1 200 OK
Server: nginx/1.21.3
Date: Mon, 13 Sep 2021 14:50:17 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 07 Sep 2021 15:21:03 GMT
Connection: keep-alive
ETag: "6137835f-267"
Accept-Ranges: bytes

因此,我们可以看到,当我们尝试从80 端口source-pod连接到服务readiness-svc.default.svc.cluster.local时,连接被拒绝。这是因为 kubelet 没有在容器中找到执行 cat 操作的文件,因此将Pod标记为未准备好服务流量并将其从Service后端删除。但是,pod 上的 nginx 服务器仍然可以为 Web 应用程序提供服务,如果您直接连接到 pod,它将继续这样做。/tmp/healthyreadiness-pod readiness-pod readiness-svc

容器的就绪探测失败不会删除Pod的DNS 记录Pod的 DNS 记录与Pod本身共享其生命周期。

这种行为是 Kubernetes 的特征,不会随网络插件而改变。我们已尝试重现此问题,并观察到使用kubenetAzure CNI网络插件的 AKS 群集的相同行为。

于 2021-09-13T17:15:05.203 回答