【问题标题】:Using UDP broadcast for pods/peers discovery in Kubernetes在 Kubernetes 中使用 UDP 广播进行 pods/peers 发现
【发布时间】:2019-12-27 04:38:50
【问题描述】:

我需要使用 UDP 广播进行对等发现。

环境:

  • docker-desktop 单节点 Kubernetes 集群

我的代码如下:

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MainApp {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        int inPort = Integer.parseInt(System.getenv("IN_PORT"));
        int outPort = Integer.parseInt(System.getenv("OUT_PORT"));
        String name = System.getenv("NAME");
        Client client = new Client(name, outPort);
        Server server = new Server(name, inPort);

        ExecutorService service = Executors.newFixedThreadPool(2);
        service.submit(client);
        service.submit(server).get();
    }


    static class Client implements Runnable {
        final String name;
        final int port;

        Client(String name, int port) {
            this.name = name;
            this.port = port;
        }

        @Override
        public void run() {
            System.out.println(name + " client started, port = " + port);
            try (DatagramSocket socket = new DatagramSocket()) {
                socket.setBroadcast(true);
                while (!Thread.currentThread().isInterrupted()) {
                    byte[] buffer = (name + ": hi").getBytes();

                    DatagramPacket packet = new DatagramPacket(buffer, buffer.length,
                            InetAddress.getByName("255.255.255.255"), port);
                    socket.send(packet);
                    Thread.sleep(1000);
                    System.out.println("packet sent");
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }


    static class Server implements Runnable {
        final String name;
        final int port;

        Server(String name, int port) {
            this.name = name;
            this.port = port;
        }

        @Override
        public void run() {

            System.out.println(name + " server started, port = " + port);

            try (DatagramSocket socket = new DatagramSocket(port)) {

                byte[] buf = new byte[256];
                while (!Thread.currentThread().isInterrupted()) {
                    DatagramPacket packet = new DatagramPacket(buf, buf.length);
                    socket.receive(packet);
                    String received = new String(packet.getData(), 0, packet.getLength());

                    System.out.println(String.format(name + " received '%s' from %s:%d", received,
                            packet.getAddress().toString(),
                            packet.getPort()));
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

    }

}

Kubernetes pod 设置:

对于peer-1

    spec:
      containers:
        - name: p2p
          image: p2p:1.0-SNAPSHOT
          env:
          - name: NAME
            value: "peer-1"
          - name: IN_PORT
            value: "9996"
          - name: OUT_PORT
            value: "9997"

对于peer-2

    spec:
      containers:
        - name: p2p-2
          image: p2p:1.0-SNAPSHOT
          env:
          - name: NAME
            value: "peer-2"
          - name: IN_PORT
            value: "9997"
          - name: OUT_PORT
            value: "9996"

为简单起见,我使用了不同的输入/输出端口。实际上应该是同一个端口,例如:9999

我看到每个 pod 都有一个唯一的 IP 地址

kubectl get pods -o wide

NAME                                READY   STATUS    RESTARTS   AGE     IP          NODE             NOMINATED NODE   READINESS GATES
p2p-deployment-2-59bb89f9d6-ghclv   1/1     Running   0          2m26s   10.1.0.38   docker-desktop   <none>           <none>
p2p-deployment-567bb5bd77-5cnsl     1/1     Running   0          2m29s   10.1.0.37   docker-desktop   <none>           <none>

来自peer-1的日志:

peer-1 received 'peer-2: hi' from /10.1.0.1:57565

来自peer-2的日志:

peer-2 received 'peer-1: hi' from /10.1.0.1:44777

问题:为什么peer-1 接收来自10.1.0.1 而不是10.1.0.37 的UDP 数据包?

如果我登录到peer-2 容器:kubectl exec -it p2p-deployment-2-59bb89f9d6-ghclv -- /bin/bash

然后

socat - UDP-DATAGRAM:255.255.255.255:9996,broadcast
test
test
...

peer-1 日志中我看到peer-1 received 'test' from /10.1.0.1:43144。 再次说明为什么网络地址是10.1.0.1 而不是10.1.0.37

你能告诉我我做错了什么吗?

注意:当使用同一端口发送/接收 UDP 数据包时,某些对等方可以从其自己的 IP 地址接收数据包。换句话说,对等点只能发现自己的 IP 地址,但对于从其他对等点/pod 接收到的数据包,总是会得到10.1.0.1

【问题讨论】:

  • 这确实是错误的做法。您对此类事情使用多播。让对等方订阅特定的多播组。使用多播不会中断 LAN 上的所有其他主机(路由器、打印机、其他 PC 等)。使用广播是一个错误,如果您使用它,您将无法添加或转换为 IPv6,因为它没有广播。多播旨在仅与订阅多播组的特定感兴趣的主机组对话,但广播会中断 LAN 上的所有主机,无论是否感兴趣。

标签: docker networking kubernetes udp peer-discovery


【解决方案1】:

由于某种原因,UDP broadcast 在 Kubernetes 基础架构中无法正常工作,但 multicast 工作正常。

感谢Ron Maupin 建议多播。

Here你可以找到java代码+kube配置

【讨论】:

    猜你喜欢
    • 2014-05-16
    • 2016-07-30
    • 1970-01-01
    • 1970-01-01
    • 2010-09-25
    • 2017-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多