具有WiFi以太网桥接和Nginx反向代理的4堆栈rPI集群(译文)
By robot-v1.0
本文链接 https://www.kyfws.com/pi/a-4-stack-rpi-cluster-with-wifi-ethernet-bridging-zh/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 14 分钟阅读 - 6837 个词 阅读量 0具有WiFi以太网桥接和Nginx反向代理的4堆栈rPI集群(译文)
原文地址:https://www.codeproject.com/Articles/1394735/A-4-Stack-rPI-Cluster-with-WiFi-Ethernet-Bridging
原文作者:Marc Clifton
译文由本站 robot-v1.0 翻译
前言
Bonus - Group chat with your rPI’s using SlackBot
奖励-使用SlackBot与您的rPI进行群聊
内容(Contents)
介绍(Introduction)
上图显示了我们正在构建的内容.(What we’re building is illustrated by the diagram above.)
- 4 rPi堆栈(A 4 rPi stack)
- WiFi到以太网桥(A WiFi to Ethernet Bridge)
- 带有反向代理的nginx到每个rPi(nginx with reverse proxy to each rPi) 在物理上,它看起来像这样:(Physically, it looks like this:)
这个想法是:(The idea is:)
- 给定域名(或在本文中,为路由器的公共IP:端口)…(Given domain names (or in this article, a public IP:port to your router)…)
- 通过WiFi将TCP/IP数据包路由到顶部rPi …(Route the TCP/IP packets to the top rPi over WiFi…)
- 然后nginx通过以太网路由到4个rPi中的任何一个…(Which then nginx routes to any of the 4 rPi’s over Ethernet…)
- 通过" DNS Masquerade",用于实现WiFi到以太网桥.(Via “DNS Masquerade” which is used to implement a WiFi to Ethernet bridge.)
DNS伪装(DNS Masquerade)
我们使用DNS伪装来创建WiFi到以太网桥.物理连接的rPi的IP地址将为10.1.1.1至1.1.1.4.使用两个博客文章来了解如何执行此操作:(We use DNS Masquerade to create a WiFi to Ethernet bridge. The IP addresses of the physically wired rPi’s will be 10.1.1.1 through 1.1.1.4. Two blog posts were used to figure out how to do this:)
- 5/5/2017:(5/8/2017:) https://pimylifeup.com/raspberry-pi-wifi-bridge/(https://pimylifeup.com/raspberry-pi-wifi-bridge/)
- 2018年4月14日:(4/14/2018:) https://willhaley.com/blog/raspberry-pi-wifi-ethernet-bridge/(https://willhaley.com/blog/raspberry-pi-wifi-ethernet-bridge/) 自2017年以来,似乎dnsmasq的配置方式发生了一些变化.关于初始设置的大多数步骤(创建静态无线IP会破坏我在rPI上的无线功能除外)都很好.对于dnsmasq的其余步骤(特别是配置文件),我必须遵循2018年博客文章中的步骤.(It seems that since 2017, the way dnsmasq is configured has changed a bit. Most of the steps (except creating a static wireless IP, which broke my wireless on the rPI) regarding the initial setup were fine. For the rest of the dnsmasq steps (specifically the config files), I had to follow the steps in the 2018 blog post.)
脚步(Steps)
执行这些命令以获取所有最新信息并安装(Execute these commands to get everything up to date and install) dnsmasq
.(.)
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install dnsmasq
验证您的WiFi是否已设置.该文件应包含以下内容:(Verify that your WiFi is set up. This file should have contents:)
sudo nano /etc/wpa_supplicant/wpa_supplicant.conf
如果没有,请运行(If not, run) raspi-config
,即使您的rPi可能已经设置为使用Wifi,并从无线配置菜单选项配置WiFi(可能再次配置).(, even though your rPi may already be set up to use Wifi, and configure your WiFi (probably again) from the wireless configuration menu option.)
编辑:(Edit:) sudo nano /etc/sysctl.conf
和取消注释(删除"(and uncomment (remove the ‘) #
‘)行(') the line) #net.ipv4.ip_forward=1
运行以下命令:(Run these commands:)
sudo iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
sudo iptables -A FORWARD -i wlan0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o wlan0 -j ACCEPT
sudo sh -c "iptables-save > /etc/iptables.ipv4.nat"
上面的命令(我能弄清楚的,应该是显而易见的)(The above commands (those that I can figure out and should be obvious) forward) wlan0
至(to) eth0
和(, and) eth0
至(to) wlan0
.然后保存配置文件,并使用以下命令在rPi引导时恢复:(. The configuration file is then saved and with the following command, restored when the rPi boots:)
编辑(Edit) sudo nano /etc/rc.local
并在上方(and just above the) exit 0
,添加行(, add the line) iptables-restore < /etc/iptables.ipv4.nat
.(.)
创造(Create)**/etc/network/interfaces.d/eth0(/etc/network/interfaces.d/eth0)**内容:(with the contents:)
auto eth0
allow-hotplug eth0
iface eth0 inet static
address 10.1.1.1
netmask 255.255.255.0
gateway 10.1.1.1
创造(Create)**/etc/dnsmasq.d/bridge.conf(/etc/dnsmasq.d/bridge.conf)**内容:(with the contents:)
interface=eth0
bind-interfaces
server=8.8.8.8
domain-needed
bogus-priv
dhcp-range=10.1.1.2,10.1.1.254,12h
重启.试用以下命令:(Reboot. Try out these commands:)
ifconfig
您应该看到(您的无线IP很可能会有所不同):(You should see (your wireless IP will most likely be different):)
eth0: flags=4163<up,broadcast,running,multicast> mtu 1500
inet 10.1.1.1 netmask 255.255.255.0 broadcast 10.1.1.255
...
wlan0: flags=4163<up,broadcast,running,multicast> mtu 1500
inet 192.168.0.15 netmask 255.255.255.0 broadcast 192.168.0.255
</up,broadcast,running,multicast></up,broadcast,running,multicast>
同时执行:(Also execute:)
sudo iptables -L
您应该看到:(You should see:)
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
ACCEPT all -- anywhere anywhere
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
如果不是,请查看上述步骤和文章链接.如果一切正常,则可以将设备连接到以太网集线器.(If not, review the steps above and the article links. If all looks good, you can connect a device to the ethernet hub.)
速度测试(Speed Test)
笔记本电脑Wifi:(Laptop Wifi:)
笔记本电脑连接到rPi Wifi-以太网桥:(Laptop connecting to rPi Wifi-Ethernet bridge:)
奇怪的是,当我在前一天晚上进行测试时,rPi Wifi-以太网桥速度更快.去搞清楚.(The odd thing about this is when I ran the test the previous evening, the rPi Wifi-Ethernet bridge was faster. Go figure.)
对于每个rPI(For Each rPI)
应该为每个rPi执行这些步骤,因为它比连接四个显示器,键盘和鼠标或一直来回移动电缆要容易得多.(These steps should be performed for each rPi as it makes working to them much easier than hooking up four monitors, keyboards, and mice, or moving cables back and forth all the time.)
启用SSH(Enable SSH)
用(Use) raspi-config
为每个rPI启用SSH:(to enable SSH for each rPI:)
sudo raspi-config
出现一个简单的UI:(which brings up a simple UI:) 导航到项目5"(Navigate to item 5 “)界面选项(Interface Options)"(") 选择 “(Select “)P2 SSH-使用SSH启用/禁用对Pi的远程命令行访问(P2 SSH - Enable/Disable remote command line access to your Pi using SSH)"(") 选择 “(Select “)是(Yes)” 提示时 “(” when prompted “)您要启用SSH服务器吗?(Would you like the SSH server to be enabled?)"(") 选择 “(Select “)好(OK)"(") 选择 “(Select “)完(Finish)“退出配置应用.(” to exit the config app.) 阅读有关raspi-config应用程序的更多信息(Read more about the raspi-config app) 这里(here) .(.)
安装.NET Core 2.2(Install .NET Core 2.2)
我将使用.NET Core和C#进行开发,因此接下来将其安装在所有四个rPI上:(I’ll be doing development with .NET Core and C#, so let’s install this next on all four rPI’s:)
wget <a href="https://download.visualstudio.microsoft.com/download/pr/
36bff52b-2cdd-4011-8e92-d00f7537704f/9885ba267b1ef29a1401adc387d9a016/
dotnet-sdk-2.2.101-linux-arm.tar.gz">https://download.visualstudio.microsoft.com/
download/pr/36bff52b-2cdd-4011-8e92-d00f7537704f/9885ba267b1ef29a1401adc387d9a016/
dotnet-sdk-2.2.101-linux-arm.tar.gz</a>
sudo mkdir -p /bin/dotnet && sudo tar zxf dotnet-sdk-2.2.101-linux-arm.tar.gz -C /bin/dotnet
export DOTNET_ROOT=/bin/dotnet
export PATH=$PATH:/bin/dotnet
sudo ln -s /bin/dotnet/dotnet /usr/local/bin
这个:(This:)
- 在以下位置安装dotnet(Installs dotnet at)/bin/dotnet(/bin/dotnet)
- 设置路径(sets up paths)
- 创建一个名为"的符号链接(快捷方式)(creates a symlink (shortcut) called “)
dotnet
“(")
设置其他3个rPI(Setup of the Other 3 rPI’s)
现在,我们可以使用wifi-以太网链接来设置其他rPI,而无需在它们上启用Wifi!(We can now use the wifi-ethernet link to set up the other rPI’s without enabling Wifi on them!)
静态IP(Static IP)
我希望我的rPI具有静态IP.最高的是10.1.1.1,因此逻辑上接下来的三个应该是.2到.4.这很容易通过编辑来完成(I’d like my rPI’s to have static IPs. The top one is 10.1.1.1, so it seems logical that the next three should be .2 through .4. This is easily done by editing)**/etc/dhcpcd.conf(/etc/dhcpcd.conf)**并找到以下部分,取消注释配置并相应地设置IPv4地址:(and finding the following section, uncommenting the configuration and setting the IPv4 addresses accordingly:)
# Example static IP configuration:
interface eth0
static ip_address=10.1.1.2/24
static ip6_address=fd51:42f8:caae:d92e::ff/64
static routers=10.1.1.1
static domain_name_servers=10.1.1.1 8.8.8.8 fd51:42f8:caae:d92e::1
重新启动,运行(Reboot, run) ifconfig
,然后验证静态IP地址:(, and verify the static IP address:)
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.1.1.2 netmask 255.255.255.0 broadcast 10.1.1.255
在WiFi Bridge rPi上安装(Installation on the WiFi Bridge rPi)
我已经详细写过的以下文章(The following pieces I already wrote about in more detail) 这里(here) ,因此这只是一组快速的"执行此操作"步骤.在设置为WiFi-Ethernet桥接器的任何rPI(在我的情况下,排名第一)上执行这些步骤.(, so this is just a quick “do this” set of steps. These steps are performed on the whatever rPI (in my case, the top one) is set up as the WiFi-Ethernet bridge.)
安装PuTTY(Install PuTTY)
在10.1.1.1上安装PuTTY,这样我们就可以与.1,.2,.3和.4上的其他rPI进行交流(是的,即使在.3下也可以对.1进行此操作) rPI.(Install PuTTY on 10.1.1.1, so we can talk with the other rPI’s on .1, .2, .3, and .4 (yeah, do this for .1 as well, even though this is under the section Setup the other 3 rPI’s.)
sudo apt-get install -y putty
安装nginx(Install nginx)
我将在.1上安装nginx,目的是将公共WiFi地址端口路由到负责服务该网站的特定rPI(每个rPI一个网站).(I’m going to install nginx on .1 with the intention that it will route the public WiFi address ports to specific rPI’s that are responsible for serving the web site – One website per rPI.) 安装nginx:(Install nginx:)
sudo apt-get install nginx
在启动时自动启动Nginx:(Auto-start nginx at boot:)
cd /etc/init.d
sudo update-rc.d nginx defaults
重新启动并打开rPI桌面上的Chromium浏览器,或从通过以太网连接到集线器的笔记本电脑中打开Chromium浏览器,然后导航到(Reboot and open the Chromium browser on the rPI desktop, or from your laptop connected via Ethernet to the hub, and navigate to) http://10.1.1.1(http://10.1.1.1) .(.)
路由器端口转发和Nginx设置(Router Port Forwarding and nginx Setup)
接下来,我们想将Wifi地址转发到每个以太网地址.我将像这样配置路由器:(Next, we want to port forward the Wifi address to each of the Ethernet addresses. I’m going to configure my router like this:)
3001-3004是入站端口,8081-8084是我们希望nginx拦截并路由到10.1.1.1-4的端口.这实际上只是为了测试.在"现实世界"中,我将设置一个或多个域名,路由器将使用授权的SSL证书将端口80(HTTP)和端口443(HTTPS)路由到WiFi以太网桥rPi. SNI将域路由到适当的rPI. nginx还可以将特定的URL路径路由到不同的rPI,因此可以创建一种设置,其中由不同的rPI处理不同的页面,但这超出了"概念验证"文章的范围.(3001-3004 are the inbound ports, 8081-8084 are the ports we want nginx to intercept and route to 10.1.1.1-4. This is really just for testing. In “the real world”, I would have set up one or more domain names and the router would route port 80 (HTTP) and port 443 (HTTPS) to the rPi that is the WiFi-Ethernet bridge, using an authorized SSL certificate and SNI to route the domain(s) to the appropriate rPI. nginx can also route specific URL paths to different rPI’s, so one could create a setup where different pages are handled by different rPI’s, but that’s beyond the scope of this “proof of concept” article.)
配置nginx(Configuring nginx)
根据上述路由器配置,每个公开给公众的端口都将路由到特定的rPI.这是添加到Nginx的路由声明(Given the router configuration above, each port exposed to the public is routed to a specific rPI. This is the route declaration that gets added to the nginx)**/etc/nginx/sites-available/default(/etc/nginx/sites-available/default)**文件:(file:)
server {
listen 8081;
location / {
proxy_pass http://10.1.1.1:8080;
}
}
server {
listen 8082;
location / {
proxy_pass http://10.1.1.2:8080;
}
}
server {
listen 8083;
location / {
proxy_pass http://10.1.1.3:8080;
}
}
server {
listen 8084;
location / {
proxy_pass http://10.1.1.4:8080;
}
}
用以下命令重新加载nginx:(Reload nginx with:)
sudo /etc/init.d/nginx reload
使用dotnet-serve进行测试(Test using dotnet-serve)
通过安装进行测试(Test this by installing) 网络服务(dotnet-serve) 在其中一个rPI上(我选择了4个(on one of the rPI’s (I chose the 4)日(th)一):(one):)
dotnet tool install --global dotnet-serve
然后运行:(Then run:)
export PATH="$PATH:/home/pi/.dotnet/tools"
export DOTNET_ROOT=/bin/dotnet
dotnet-serve -a 10.1.1.[rPI IP address]
导出对于找到dotnet-serv和对于dotnet-serv都需要找到依赖库是必需的.(The exports are necessary to find dotnet-serve and for dotnet-serve to find dependant libraries.) 例如4(For example, the 4)日(th)rPI在我的堆栈中,最后的命令是:(rPI in my stack, the final command is:)
dotnet-serve -a 10.1.1.4
出于某种原因,当我尝试指定端口80时,访问被拒绝,这就是为什么nginx在上面使用端口8080配置的原因.(For some reason, I get an access denied when I try to specify port 80, which is why nginx was configured above with port 8080.) 查找您的公共IP(Find your public IP) 并输入:(and type in:)
http://[your public ip]:3004
您应该回来:(You should get back:)
和dotnet-serve应该显示:(and dotnet-serve should be displaying:)
您可以浏览文件夹并下载MagPi PDF!(You can navigate the folders and download the MagPi PDF!)
使用松弛广播命令(Using Slack to Broadcast Commands)
在我的文章中(In my article,) 与您的rPi闲聊(Slack Chatting with your rPi) ,我使用Slack与单个rPi进行通信.我们可以使用Slack向堆栈中的所有rPi发出命令.这对于执行诸如关闭或重新启动所有rPi的操作非常有用!(, I used Slack to communicate to a single rPi. We can use Slack to issue commands to all the rPi’s in the stack. This is really useful for doing things like shutting down or rebooting all the rPi’s!)
WinSCP之后,(Once you’ve WinSCPs, the)**slackbot \ bin \ Debug \ netcoreapp2.2 \ linux-arm \ publish(slackbot\bin\Debug\netcoreapp2.2\linux-arm\publish)**文件夹内容移至每个rPi,更改(folder contents over to each rPi, change the) slackBot
文件到可执行文件(此操作只需执行一次)并运行:(file to an executable (this only has to be done once) and run it:)
chmod +755 ./slackBot
./slackBot
对每个rPi执行此操作.现在,在Slack频道上ping rpi:(Do this for each rPi. Now, ping the rpi on your Slack channel:)
他们四个都回应了!(All four of them responded!) 让我们看一下每个rPi的内存利用率:(Let’s look at the memory utilization of each rPi:)
当然,我们想知道哪个rPi正在报告,因为它们不一定是按顺序排列的.每当rPi响应时,我们可以使用在C#slackBot应用程序中执行的bash脚本来报告eth0地址,以报告IP地址:(Of course, we’d like to know which rPi is reporting, as they may not necessarily be in order. We can report the IP address whenever the rPi responds by using a bash script executed in the C# slackBot application to get the eth0 address:)
static void GetIPAddress()
{
ipAddress = "ifconfig eth0 | grep \"inet \"".Bash().Trim().
RightOf("inet").LeftOf("netmask").Trim();
Console.WriteLine($"IP: {ipAddress}");
}
然后,我们可以将该地址添加到rPi通过Slack通道发送的所有内容之前:(We can then prepend this address to everything sent over the Slack channel by the rPi:)
...
if (router.TryGetValue(cmd, out Func<string, List<string>, string> fnc))
{
ret = ipAddress + ": " + fnc(data, options);
}
else
{
// Try as bash command.
string cmdline = (cmd + " " + data).Trim();
ret = $"```\r\n{ipAddress}\r\n{cmdline.Bash()}```";
}
...
结果很好:(The results are nice:)
或者,对于bash命令,这是带有rPi的IP地址的示例输出:(or, for bash commands, here’s an example output with the rPi’s IP address:)
当然,与特定的rPi对话也很好.为此,我们将rPi IP地址的最后一位添加为选项(使用”(Of course, it would also be nice to talk to a specific rPi. We’ll do this by adding the last digit of the rPi’s IP address as an option (using the “) --
“语法)仅与其中一个对话.在消息接收处理程序中,我们检查是否存在(” syntax) to talk to just one of them. In the message receive handler, we check for a) --[ddd]
哪里(where) [ddd]
是IP地址最后一部分中的数字:(is the digits in the last part of the IP address:)
...
while (cmd.StartsWith("--"))
{
var opt = cmd.LeftOf(" ");
// Check if a specific address [n] in our IP x.y.z.n is specified.
// If that's not our address, just exit now.
if (opt.Length > 2 && char.IsDigit(opt[2]))
{
if (opt.Substring(2) != ip4thDigits)
{
return;
}
}
options.Add(opt);
cmd = message.text.RightOf(opt).Trim().LeftOf(" ");
}
请注意,当我们使用(Note the difference now when we use the) --[ddd]
选项:(option:)
结论(Conclusion)
这太酷了!一切都在做:(This is very cool! Everything is doing its thing:)
-
路由器正在路由(The router is routing)
-
WiFi-以太网桥正在桥接(The WiFi-ethernet bridge is bridging)
-
nginx是反向代理(nginx is reverse proxy’ing)
-
服务器正在服务!(the server is serving!) 我们还修改了我的(We also modified my) 闲聊(Slack Chat) 应用程序,以便我们可以:(application so that we can:)
-
向所有rPi广播命令(Broadcast commands to all rPi’s)
-
将命令发送到各个rPi(Send commands to individual rPi’s) 尽管在通过SNI设置域名,SSL证书和ngnix方面还有很多工作要做,但本文的目的是您迈出第一步来建立rPI堆栈,从此我们现在可以为页面提供服务,提供"计算"功能,播放分布式数据等.(While there’s a lot more to get done in terms of setting up domain names, SSL certs, and ngnix with SNI, the purpose of this article is how you take the first step in setting up an rPI stack, from which we can now serve pages, provide “compute” capability, play around with distributed data, etc.) 该休息一下了.(Time to take a break.)
有关安装.NET Core的注意事项(Notes on Installing .NET Core)
这些说明是针对.NET Core 2.0的,我将其放在此处是因为它们比”(These notes are for .NET Core 2.0 and I put them here because they are less obtuse (I suppose) than that “) wget
“命令,并且在.NET Core 3.0逐渐成熟时可能很有用.(” command, and may be useful for when .NET Core 3.0 comes of age.)
从:(From:) https://blogs.msdn.microsoft.com/david/2017/07/20/setting_up_raspian_and_dotnet_core_2_0_on_a_raspberry_pi/(https://blogs.msdn.microsoft.com/david/2017/07/20/setting_up_raspian_and_dotnet_core_2_0_on_a_raspberry_pi/)
- 运行sudo apt-get install curl libunwind8 gettext.这将使用apt-get程序包管理器安装三个先决条件程序包.(Run sudo apt-get install curl libunwind8 gettext. This will use the apt-get package manager to install three prerequiste packages.)
- 运行curl -sSL -o dotnet.tar.gz https://dotnetcli.blob.core.windows.net/dotnet/Runtime/release/2.0.0/dotnet-runtime-latest-linux-arm.tar.gz进行下载最新的ARM32 .NET Core运行时.这在"每日构建"页面上称为armhf.(Run curl -sSL -o dotnet.tar.gz https://dotnetcli.blob.core.windows.net/dotnet/Runtime/release/2.0.0/dotnet-runtime-latest-linux-arm.tar.gz to download the latest .NET Core Runtime for ARM32. This is refereed to as armhf on the Daily Builds page.)
- 运行sudo mkdir -p/opt/dotnet && sudo tar zxf dotnet.tar.gz -C/opt/dotnet创建目标文件夹并将下载的软件包解压缩到其中.(Run sudo mkdir -p /opt/dotnet && sudo tar zxf dotnet.tar.gz -C /opt/dotnet to create a destination folder and extract the downloaded package into it.)
- 运行sudo ln -s/opt/dotnet/dotnet/usr/local/bin
来设置符号链接... Windows亲朋好友对dotnet可执行文件的快捷方式.(*Run sudo ln -s /opt/dotnet/dotnet /usr/local/bin
to set up a symbolic link…a shortcut to you Windows folks 😉 to the dotnet executable.*) - 通过键入来测试安装(Test the installation by typing)
dotnet --help
.(.)
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
C# Raspberry .NET-Core .NET Dev 新闻 翻译