Kubernetes:服务路由到具有多个容器的Pod

时间:2020-06-25 07:47:03

标签: kubernetes containers kubernetes-pod kubernetes-service

我目前在Kubernetes集群中遇到问题。调试时,我想到的是一个我不知道答案的问题。

我正在使用1.15版的AWS EKS,但我不认为我的问题与任何特定的云或kubernetes版本有关

我有一个部署。它具有多个容器。有可以公开此部署的服务。

假设部署有2个容器C1和C2。 C1需要1秒才能启动,但C2需要30秒才能启动(疯狂!)。因此,当我在时间t1启动Pod时,发生的情况是,一旦C1立即启动并且Pod进入运行状态,但只有1/2个容器就绪。吊舱C2最终在时间t2(t1 + 30秒)开始。在时间t2,已经准备好2/2个容器。

还假定C1接受来自服务的传入请求,它执行某些操作,然后将请求转发到C2,C2执行某些操作,然后将其返回给C1。 C1最终恢复服务,并将响应提供给客户。

所以,我的问题是,在t2到t1之间的时间段内,当pod处于运行状态但只有1/2容器就绪时,服务会将请求转发到pod吗?

采用另一种方式,服务何时将请求转发到Pod?如果它们处于运行状态,则没关系准备好多少个容器?或者,如果它们处于运行状态并且所有容器都准备好了?

我的想法是,该服务将不会转发,因为如果所有Pod尚未准备就绪,但我没有任何证据/文件证明它正确,那么它将毫无意义。

5 个答案:

答案 0 :(得分:3)

为了使您的情况更易于理解,请将其称为网络 api 。这些是我们服务的组成部分,而网络将在几秒钟内准备就绪,而 api 组件将需要更多时间。

首先,我们需要确定我们的部署策略。如果我们将 web api 放在同一部署中,则此部署顶部的 service 对象将对这两个对象都进行定义。因此,如果您想在端口443上公开您的网络服务,那么 api 也将在端口443中公开。是的,您可以标记它们并设置不同的定义,但是这远非理想。

我们可以说Kubernetes世界中的 service 对象就像负载均衡器一样。因此,如果将两个不同的组件放在同一部署上,并在它们之上定义一个服务对象,那么当您从外部网络调用服务时,最终将到达 web api 端点。

您可以检出此图像以进行可视化:Kubernetes Service Example

在理想情况下,您需要在两个不同的部署中部署此应用程序,因为它们可以解耦并且可以用于不同的目的。部署这些服务之后,您要做的就是部署两个不同的服务以公开您的部署。据我了解, api 仅在内部网络中运行,因此可以为 headless-service

首先,让我们为应用程序创建一个名称空间(或项目)。

kubectl create ns myapp

并定义我们的部署因此,对于我们的 web 组件,让我们定义部署文件;

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-deployment
  labels:
    app: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 9376

以及将我们的Web部署公开到外部网络的服务

apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  selector:
    app: web
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

您可以看到 web-deployment 部署对象具有三个副本,并且 web-service 服务定义将相应地平衡传入的请求。

现在,让我们部署 api

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-deployment
  labels:
    app: api
spec:
  replicas: 5
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      containers:
      - name: api
        image: apirepo/api
        ports:
        - containerPort: 3000

api部署

的无头服务
apiVersion: v1
kind: Service
metadata:
  name: api-headless-service
spec:
  clusterIP: None 
  selector:
    app: api
  ports:
    - protocol: TCP
      port: 80
      targetPort: 3000 

仅此而已。现在,您可以根据请求扩大或缩小网络 api 部署,服务定义将自动对这些负载进行负载平衡并处理服务发现。

答案 1 :(得分:1)

...当pod处于运行状态但只有1/2容器准备就绪时,服务会将请求转发到pod吗?

否。

服务何时将请求转发到Pod? 如果它们处于运行状态,则没关系准备好多少个容器?或者,如果它们处于运行状态并且所有容器都准备好了?

我的想法是,该服务将不会转发,因为如果所有Pod尚未准备就绪,但我没有任何证据/文件证明它正确,那么它将毫无意义。

Here it is:)

官方文档说:“ ...小桶使用就绪探测器来了解容器何时准备开始接受流量。当Pod的所有容器准备就绪时,Pod被视为准备就绪。该信号的作用是控制将哪些Pod用作服务的后端。当Pod未准备好时,将从Service负载均衡器中将其删除...”

另外说:

“ ......应用程序暂时无法提供流量...一个应用程序可能取决于外部服务...在这种情况下,您不想杀死该应用程序,但又不想发送它Kubernetes提供了就绪性探针来检测和缓解这些情况。装有容器的容器报告其容器尚未准备就绪,不会通过Kubernetes Services接收流量...“

就绪探针用于检测流量不应发送到App的情况。

我的想法是服务不会转发,因为如果所有Pod尚未准备就绪,它将毫无意义

您绝对在这里。

我希望能帮上忙。

答案 2 :(得分:0)

从文档here

就绪:该Pod能够处理请求,应将其添加到 所有匹配服务的负载均衡池

因此,如果一个Pod为ready,则该Pod的IP将添加到endpoints对象,服务将开始向该Pod发送流量。稍后,如果更多的Pod变为ready,那么这些Pod IP也将添加到endpoints对象中,服务将开始在所有Pod之间进行负载平衡流量。

要检查添加到服务的Pod IP,可以运行kubectl describe service servicename并检查Endpoints部分。

为避免流量被发送到Pod中的容器但容器尚未准备好接受流量的情况,您可以使用container probe

当Pod内的所有容器都准备就绪时,只有服务Endpoints会填充Pod IP,流量开始流动。

答案 3 :(得分:0)

如果您通过Deployment.yaml文件浏览了下面提到的代码段-

spec:
  replicas: 4
    strategy:
        type: RollingUpdate
        rollingUpdate:
          maxUnavailable: 25%

对于一个金丝雀部署,这表明25%的标准表明,如果在deployment.yaml中设置了4个专用副本,则每当其中75%成功部署成功时,都将允许该服务为流量提供服务。

因此,基本上,您有3/4个副本处于活动状态,并且可以为流量提供服务。这是完全可配置的。

答案 4 :(得分:-1)

如果容器内的端口没有打开,则可能不会转发任何流量。不过,您可以在Pod内放入一个tcpdump,然后按照syn和reset标志进行操作