我有两台虚拟机使用内部IP地址互相交谈,而外界只通过外部IP地址了解这些虚拟机。
我有一个使用两个VM的分布式缓存 - 每个都有一个必须与另一个进行通信的Erlang节点。我还在其他机器上拥有现金的Erlang客户端,需要与VM上的一个(或两个)Erlang缓存节点进行通信。
因此,如果我使用内部IP地址命名的缓存节点,那么它们可以相互通信,但没有其他Erlang节点可以与它们交互。但是,如果我使用VM的外部IP地址命名缓存节点,那么外部Erlang节点可以与缓存节点通信,但缓存节点不能相互通信。
除了使用不依赖于将节点连接到网格的基于http或套接字的接口之外,我能做些什么吗?
答案 0 :(得分:10)
你想要达到的目标是绝对可行。
Erlang的分发地址分为两部分:节点名称和主机名。它们由@
符号分隔。
主机名可以是数字IPv4地址。它们也可以是域名。有两种不同的模式,其中主机名很短(单个词,例如vm1
),它们很长(几个词,例如vm1.domain.com
)。 IP地址是长名称。以一种模式(短或长)启动的节点只能与以相同模式启动的节点通信。节点也受cookie保护:节点只接受带有匹配cookie的传入连接。最简单的方法是使用相同的cookie启动给定集群的所有节点。
当Erlang节点尝试连接到另一个Erlang节点时,它需要找到远程节点的IP地址。如果它与它自己相同,它将只是尝试连接本地主机。如果不同,它将尝试将此主机名解析为IP地址。
然后它将连接到该主机上的epmd
守护进程,以告知Erlang正在运行哪个端口。 epmd
以及Erlang节点监听所有接口(默认情况下)。
基于此机制,您可以使用短名称或长名称,但可以利用解析机制。 Unix上最简单的方法是在你机器的每个/etc/hosts
上配置不同的IP(特别是在两台虚拟机上),这样它们就可以通过私有地址相互连接,同时通过公共地址访问。
假设虚拟机A(VM A)具有私有IP地址10.0.0.2,公共IP地址123.4.5.2,VM B具有私有IP地址10.0.0.3和公共IP地址123.4.5.3。我们也说你决定选择短名。
您可以在/etc/hosts
:
10.0.0.3 vmb
您可以将匹配条目放在VM B的/etc/hosts
:
10.0.0.2 vma
在所有外部客户端上,您可以输入:
123.4.5.2 vma
123.4.5.3 vmb
您可以按如下方式启动节点:
# Node foo on VM A:
erl -sname foo@vma -cookie RANDOMCOOKIE
# Node foo on VM B:
erl -sname foo@vmb -cookie RANDOMCOOKIE
# Client nodes:
erl -sname client -cookie RANDOMCOOKIE
如果您拥有域名(例如/etc/hosts
),则可以避免在客户端节点上进行yourdomain.com
编辑,并且可以让vma.yourdomain.com
解析为123.4.5.2。您还可以使用特定的Erlang Inet configuration file。
Erlang分发机制并不意味着面向公众。此外,所有通信都是未加密的。我强烈建议在每台主机上配置防火墙,只允许来自其他群集服务器的连接和使用SSL分发。
对于防火墙:Erlang发行版为epmd
使用端口4369以及每个节点使用随机端口。您可以使用Erlang内核应用程序环境设置inet_dist_listen_min
和inet_dist_listen_max
来限制这些随机端口的范围。您将需要允许这些端口上的传入TCP连接,但仅允许来自群集的其他主机。
SSL分发设置非常复杂,但well documented。您的主要缺点是所有连接都应该通过SSL,包括其专用网络上的两个虚拟机之间的连接,以及打开远程shell的本地连接。
答案 1 :(得分:3)
在回答问题之前,我想指出,Distributed Erlang不安全,您不应在受信任的局域网之外使用它。 (在我看到"外部IP地址"后,我不得不离开那个评论,我认为它并不意味着公开)。下面列出了4个重要的事项,你应该知道:
当你启动一个节点时,最好给它一个这样的名字:
erl -name myname@192.168.0.1
当您尝试从其他计算机连接到该节点时,您可以在erlang shell中使用类似的内容:
net_kernel:connect('myname@192.168.0.1').
重要的部分是节点名称:'myname@192.168.0.1'
是一个原子。它不是" name和ip" - 这是一回事。即使如果您的第二个节点在同一台机器上,也无法使用:
net_kernel:connect('myname@127.0.0.1').
因为它是不同的节点名称。
这意味着,要连接两个节点,只有一个节点必须看到另一个节点。
示例:您有:
比:
在第二种情况下,连接就像它们在同一网络上一样。您只需要考虑谁应该初始化连接。
如果您不想这样做 - 请使用hidden nodes。
但我认为,如果你能够连接其他节点,那么你就可以了。
最简单的解决方案是在任何地方使用外部IP地址,因为Erlang发行版旨在在本地网络上运行。更难的解决方案涉及确保您从本地网络中的节点连接到具有外部IP的节点。