GKE-在运行时将Pod LoadBalancer(Pod的外部IP)绕过Pod的容器的IP,以实现WebSocket的目的

时间:2019-11-28 19:18:40

标签: docker kubernetes websocket kubernetes-pod

我有以下情况:

我有几个微服务,现在只有两个是相关的。 -Web套接字服务API -调度员服务

我们有3个用户,分别称为1、2和3。这些用户将自己连接到后端的Web套接字端点。我们的微服务在Kubernetes上运行,每个服务可以在Pods中多次复制。对于这种情况,我们有1个用于调度程序的运行容器,以及3个用于Web套接字api的运行容器。每个吊舱都有其负载均衡器,并且这将是每次进入点的时间。

在我们的情况下,我们将具有以下“模式”:

enter image description here


现在我们已经有了系统(和图例)的表示形式,我们的3个用户将要使用该应用程序并进行连接。

enter image description here

我们可以看到,我们的Pod的负载平衡器在不同的容器之间转发了用户的Web套接字连接。每个容器一旦建立了新的连接,就会知道Dispatcher Service,并将其保存在自己的数据库中。

现在,有3个用户连接到2个不同的容器,而Dispatcher服务知道了。


用户1要向用户2发送消息。容器A随后将收到一条消息,并通知调度程序服务:Please, send this to the user 2

因为调度员知道用户2连接到哪个容器,所以我想直接将请求发送到我的容器,而不是将请求发送到Pod。将其发送到Pod会导致向负载均衡器发送请求,该负载均衡器实际上会将请求分派给最可用的容器实例...

enter image description here

我如何设法获得容器IP?可以从另一个Pod的另一个容器访问它吗?

对我来说,最好的方法是,一旦应用启动,它将获取当前容器的IP,然后在注册请求中将其发送给调度程序,因此调度程序将知道ContainerID = IP

谢谢!

编辑1

有我的web-socket-service-api.yaml

apiVersion: v1
kind: Service
metadata:
  name: web-socket-service-api
spec:
  ports:
    # Port that accepts gRPC and JSON/HTTP2 requests over HTTP.
    - port: 8080
      targetPort: 8080
      protocol: TCP
      name: grpc
    # Port that accepts gRPC and JSON/HTTP2 requests over HTTP.
    - port: 8081
      targetPort: 8081
      protocol: TCP
      name: rest
    # Port that accepts WebSockets.
    - port: 8082
      targetPort: 8082
      protocol: TCP
      name: websocket
  selector:
    app: web-socket-service-api
  type: LoadBalancer
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: web-socket-service-api
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: web-socket-service-api
    spec:
      containers:
        - name: web-socket-service-api
          image: gcr.io/[PROJECT]/web-socket-service-api:latest
          ports:
            - containerPort: 8080
            - containerPort: 8081
            - containerPort: 8082

2 个答案:

答案 0 :(得分:1)

任何吊舱,都有一些有关其自身的信息。其中一项信息是它自己的IP地址。例如:

apiVersion: v1
kind: Pod
metadata:
  name: envars-fieldref
spec:
  containers:
    - name: test-container
      image: k8s.gcr.io/busybox
      command: [ "sh", "-c"]
      args:
      - while true; do
          echo -en '\n';
          printenv MY_POD_IP;
          sleep 10;
        done;
      env:
        - name: MY_POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP

在容器中,MY_POD_IP将包含容器的IP地址。您可以通知调度员。

$ kubectl logs envars-fieldref
10.52.0.3


$ kubectl get po -owide
NAME                             READY   STATUS    RESTARTS   AGE   IP           NODE                           NOMINATED NODE   READINESS GATES
envars-fieldref                  1/1     Running   0          31s   10.52.0.3    gke-klusta-lemmy-3ce02acd-djhm   <none>           <none>

请注意,依靠Pod IP地址不是一个好主意。但这应该可以解决问题。

此外,将请求发送到Pod或容器也完全相同。

答案 1 :(得分:0)

调度程序≈消息代理

据我了解您的设计,您的 Dispatcher 本质上是 Websocket服务吊舱的消息代理。让所有Websocket Pod连接到代理,并让代理路由消息。这是一个有状态服务,您应该在Kubernetes中使用StatefulSet。根据您的要求,可能的解决方案是为此使用MQTT经纪人。 mosquitto。大多数MQTT经纪人都支持websocket。

向外扩展:吊舱的多个副本

  

每个服务都可以在Pod中多次复制。对于这种情况,我们有1个用于调度程序的运行容器,以及3个用于Web套接字api的运行容器。

这不是打算使用Kubernetes的方式。使用多个容器副本,而不要使用容器中的多个容器。我建议您为 Websocket服务创建一个Deployment,其中包含所需数量的副本。

充当负载平衡器

  

每个吊舱都有其负载均衡器,这将是每次进入点的时间。

在Kubernetes中,您应该创建一个Service,以负载均衡一组Pod的流量。

您的解决方案

  

对我来说,最好的方法是,一旦应用启动,它将获取当前容器的IP,然后在注册请求中将其发送给调度程序,因此调度程序将知道ContainerID = IP

是的,我大都同意。这类似于我在这里描述的内容。但是我会让 Websocket服务建立与 Broker / Dispatcher 的连接。