Использование UDP-трансляции для обнаружения подов / пиров в Kubernetes
Мне нужно использовать широковещательную рассылку 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:
За 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
Я вижу, что у каждого модуля уникальный 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
получает UDP-пакеты от 10.1.0.1
вместо того 10.1.0.37
?
Если я войду в 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-адрес, но всегда получает10.1.0.1
для пакетов, полученных от других пиров / подов
1 ответ
По какой-то причине широковещательная рассылка UDP не работает должным образом в инфраструктуре Kubernetes, однако многоадресная рассылка работает нормально.
Спасибо Ron Maupin за предложение многоадресной рассылки.
Здесь вы можете найти java-код + конфигурацию kube