负载分配在 Kubernetes 中不起作用,请求将发送到单个 pod

Posted

技术标签:

【中文标题】负载分配在 Kubernetes 中不起作用,请求将发送到单个 pod【英文标题】:Load Distribution not working in Kubernetes, Request is going to single pod 【发布时间】:2021-03-02 16:48:14 【问题描述】:

我使用 Minikube 进行 kubernetes 部署,我使用的操作系统是 Ubuntu 18.04

我有一个包含 3 个副本的应用程序部署。因此,当我部署 3 个 pod 时,就会部署。 当我增加 http 请求的数量时,所有请求都被转发到单个 pod,而其他两个副本中没有记录日志。

关于负载如何分布到所有 pod 的任何想法。

我在下面有 deployment.yaml 和相应的 service.yaml 文件

    deployment.yaml


    apiVersion: apps/v1
    kind: Deployment
    metadata:
          name: master
      labels:
       app: master-container
    spec:
     selector:
       matchLabels:
         app: master-container
     replicas: 3
     template:
       metadata:
         labels:
           app: master-container
       spec:
         volumes:
         - name: logs-dir
           hostPath:
            path: /data/logs/
            type: DirectoryOrCreate
         containers:
          - name: master-container
            image: image:1
            volumeMounts:
            - mountPath: /data/workspace/logs/
              name: logs-dir

    service.yaml
    
apiVersion: v1
kind: Service
metadata:
  name: master-container
  labels:
    app: master-container
spec:
  selector:
    app: master-container
  ports:
  - port: 2000
    protocol: TCP
    targetPort: 2000
    name: can-port
    nodePort: 32000
  - port: 2002
    protocol: TCP
    targetPort: 2002
    name: can-ajp-port
    nodePort: 32002
  - port: 2003
    protocol: TCP
    targetPort: 2003
    name: cas-port
    nodePort: 32003
  - port: 2005
    protocol: TCP
    targetPort: 2005
    name: cas-ajp-port
    nodePort: 32005
  - port: 31900
    protocol: TCP
    targetPort: 31900
    name: cas-master-port
    nodePort: 31900
  type: NodePort

看看下图,这是命令的输出

kubectl 描述 svc canmastercontainer

我们可以看到服务已经启动并且所有端口都可以访问。我面临的唯一问题是负载分布没有跨 pod 发生

我尝试将类型指定为 NodePort 、 LoadBalancer 和 ClusterIp ,这三个都没有成功。 所有的 http 请求都被转移到单个 pod 中。

如有任何解决方案,谢谢

【问题讨论】:

您是否确认所有选定的 pod 都工作正常? 您能提供一个测试场景的信息吗?您的清单包括app: master-container,但在屏幕选择器和标签中是app: canmasterconainer。屏幕和清单之间的类型也不同。您是否使用 helm 部署此应用程序(看到 Helm 注释),如果是,您可以分享图表吗?您是否考虑过使用nginx Ingress Patch Matching?您能在 pod 日志中看到任何问题吗? @slashpai 所有 pod 都工作正常,pod 日志中没有问题。这里唯一的问题是每当我从浏览器发出请求时,请求都会转移到单个 pod 中,而其他两个 pod 中没有生成日志。 @PjoterS :在我的部署中匹配的所有选择器和所有 pod 都在运行。对于 helm 部分,我使用 helm 进行部署,上述文件是我一直用于部署的文件。我在这里面临的问题是,即使我有多个 pod 副本,也不会在 pod 上发生负载分布。当我从浏览器发出 http 请求时,所有请求都会转移到单个 pod,而 pod 的其他副本保持空闲,即请求没有命中这些 pod。我想知道负载分配是如何工作的。 你能确保kube-proxyiptables 设置适当的规则吗?还要检查 `iptables 规则是否按预期工作?您是否考虑过使用 Ingress? 【参考方案1】:

如果您使用端口转发,则负载不会分布在所有 pod(端点)上。

请参阅此link 了解更多信息。

【讨论】:

【参考方案2】:

Kubernetes 集群中的每个节点都运行一个kube-proxykube-proxy 负责为非ExternalName 类型的Services 实现virtual IP 的形式。

kube-proxy 可以在几种模式下工作:

User space proxy mode iptables proxy mode IPVS proxy mode

但是,您可以使用内置的 Kubernetes 方法,例如 Nginx Ingress。

测试场景

Nginx Ingress,GCP Ubuntu VM 上的裸机考虑。

Hello world YAML

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-1
spec:
  replicas: 1
  selector:
    matchLabels:
      key: application-1
  template:
    metadata:
      labels:
        key: application-1
    spec:
      containers:
      - name: hello1
        image: gcr.io/google-samples/hello-app:1.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080

服务 Yaml:

apiVersion: v1
kind: Service
metadata:
  name: service-one
spec:
  selector:
    key: application-1
  ports:
    - port: 80
      targetPort: 8080

入口 Yaml:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"      
spec:
  rules:
  - http:
      paths:
      - path: /one
        backend:
          serviceName: service-one
          servicePort: 80
      - path: /two
        backend:
          serviceName: service-two
          servicePort: 80

入口描述:

Rules:
  Host        Path  Backends
  ----        ----  --------
  *           
              /one   service-one:80 (192.168.243.80:8080,192.168.243.84:8080,192.168.243.85:8080)
              /two   service-two:80 (192.168.243.81:8080,192.168.243.82:8080,192.168.243.83:8080)
          

测试

$ curl 34.89.244.41:31337/one
Hello, world!
Version: 1.0.0
Hostname: deployment-1-77ddb77d56-4x4pd
$ curl 34.89.244.41:31337/one
Hello, world!
Version: 1.0.0
Hostname: deployment-1-77ddb77d56-vq72x
$ curl 34.89.244.41:31337/one
Hello, world!
Version: 1.0.0
Hostname: deployment-1-77ddb77d56-v5826
$ curl 34.89.244.41:31337/one
Hello, world!
Version: 1.0.0
Hostname: deployment-2-fb984955c-xk5h9
$ curl 34.89.244.41:31337/two
Hello, world!
Version: 2.0.0
Hostname: deployment-2-fb984955c-lw74g
$ curl 34.89.244.41:31337/two
Hello, world!
Version: 2.0.0
Hostname: deployment-2-fb984955c-xk5h9
$ curl 34.89.244.41:31337/two
Hello, world!
Version: 2.0.0
Hostname: deployment-2-fb984955c-lw74g
$ curl 34.89.244.41:31337/two
Hello, world!
Version: 2.0.0
Hostname: deployment-2-fb984955c-8pfls
$ curl 34.89.244.41:31337/two
Hello, world!
Version: 2.0.0
Hostname: deployment-2-fb984955c-8pfls

如您所见,每个请求都被重定向到不同的 pod。

如果这不起作用,请提供在您的问题下提出的更多详细信息。

【讨论】:

以上是关于负载分配在 Kubernetes 中不起作用,请求将发送到单个 pod的主要内容,如果未能解决你的问题,请参考以下文章

为啥最近的主机名负载平衡配置在 ClickHouse 中不起作用?

多个保护级别在 WCF 中不起作用

指针分配在递归函数中不起作用

在弹性 beantalk 和 kubernetes 之间分配的应用程序负载均衡器

为啥正常的 for 循环允许为结构字段分配值,而 for range 在 Golang 中不起作用? [复制]

为啥请求 http 在 Kotlin 中不起作用?