繁体   English   中英

GKE - 在运行时绕过 Pod LoadBalancer(Pod 的外部 IP)到 Pod 的容器的 IP 以用于 WebSocket 目的

[英]GKE - Bypass Pod LoadBalancer (Pod's external IP) to Pod's container's IP at runtime for WebSocket purpose

我有以下情况:

我有几个微服务,现在只有 2 个是相关的。 - 网络套接字服务 API - 调度服务

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

在我们的情况下,我们将拥有以下“架构”:

在此处输入图片说明


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

在此处输入图片说明

如我们所见,Pod 的负载均衡器将用户的 Web 套接字连接转发到不同的容器。 每个容器,一旦获得新连接,就会通知 Dispatcher Service,而这个容器会将其保存在自己的数据库中。

现在,3 个用户连接到 2 个不同的容器,并且 Dispatcher 服务知道这一点。


用户 1 想给用户 2 发送消息。容器 A 将收到一条消息并告诉调度服务: Please, send this to the user 2

由于调度程序知道用户 2 连接到哪个容器,我想直接向我的容器发送请求,而不是将其发送到 Pod。 将它发送到 Pod 会导致向负载均衡器发送请求,负载均衡器实际上将请求分派到最可用的容器实例......

在此处输入图片说明

我怎样才能设法获得容器 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

调度器≈消息代理

就我对您的设计的理解而言,您的Dispatcher本质上是您的Websocket Service Pod 的消息代理。 让所有 Websocket pod 连接到代理并让代理路由消息。 这是一项有状态服务,您应该在 Kubernetes 中为此使用StatefulSet 根据您的要求,可能的解决方案是为此使用 MQTT 代理,例如mosquitto 大多数 MQTT 代理都支持 websocket。

横向扩展:Pod 的多个副本

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

这不是 Kubernetes 的使用方式。 使用 pod 的多个副本,而不是 pod 中的多个容器。 我建议您为您的Websocket 服务创建一个具有您想要的多个副本的部署

作为负载均衡器的服务

每个 pod 都有它的负载均衡器,这将是每次的入口点。

在Kubernetes你应该创建一个服务是负载均衡流量一套吊舱。

您的解决方案

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

是的,我基本同意。 这与我在这里描述的相似。 但我会让Websocket 服务建立到Broker/Dispatcher的连接。

任何 pod,都有一些关于它自己的信息。 其中一项信息是它自己的 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 将包含 pod 的 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 或容器发送请求也是一回事。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM