課題需要研究分佈式計算,爲此我學習在 Linux 集羣上運行 MPI 程序。爲了先熟悉一下過程,我在 VirtualBox 搭建的 4 臺 CentOS 7 虛擬機上構建了一個集羣。
這裏涉及的知識有:
- 虛擬機靜態 ip 分配和網絡互聯的設置
- SSH 免密登陸
- NFS 文件共享系統
- MPICH 的安裝,和在集羣上運行
文章目錄
1 虛擬機分區
master 採用 40 GB 的空間,按如下分配:
- BIOS Boot:2MB
- /boot:1GB
- /:10 GB
- /var:5 GB
- /tmp:3 GB
- Swap:2 GB ( 因爲我每部 Linux 虛擬機上面都有 1GB 的內存 )
- /mpi_cloud:19 GB(僅僅 master 虛擬機有這個分區)
2 虛擬機網絡設置
首先要設置宿主機和虛擬機的靜態 ip,並且要實現 3 個方向能夠 ping
成功:
1 宿主機 ping
虛擬機
2 虛擬機1 ping
虛擬機 2
3 虛擬機 ping
因特網
VirtualBox 的網絡設置的特點(來自 VirtualBox 的幫助文檔):
根據我們要實現的目標我們可以使用 Bridged 方式設置一張網卡,或者使用 Host-only 和 NAT 方式設置兩張網卡。
這裏我採用第二種。
設置靜態 ip
主機名和靜態 ip:
- 宿主機:192.168.0.1
- master.cluster:192.168.0.2
- node1.cluster:192.168.0.3
- node2.cluster:192.168.0.4
- node3.cluster:192.168.0.5
① 宿主機
爲了設置靜態 ip,操作 VirtualBox 管理器:管理 -> 主機網絡管理器
默認的 Adapter 不知道爲什麼無法修改成自動配置網卡,因此我就創建了一個新的 Adapter #2,不啓用 DHCP 服務器,設置手動配置網卡,IPv4 地址和掩碼使用了默認值。設置完成之後,在 Window 中打開 cmd:
C:\WINDOWS\system32>ipconfig
...
以太網適配器 VirtualBox Host-Only Network #2:
連接特定的 DNS 後綴 . . . . . . . :
本地鏈接 IPv6 地址. . . . . . . . : fe80::70dc:fbfc:8eb2:d37d%62
IPv4 地址 . . . . . . . . . . . . : 192.168.1.1
子網掩碼 . . . . . . . . . . . . : 255.255.255.0
默認網關. . . . . . . . . . . . . :
設置成功,宿主機的靜態 ip 爲 192.168.1.1。
② 虛擬機
點擊虛擬機:設置 -> 網絡
添加網卡 1 爲 Host-Only,採用剛剛添加的 Adapter #2。
打開虛擬機後,設置虛擬機的網絡屬性:
[root@p1 mindle]# nmcli connection show
NAME UUID TYPE DEVICE
enp0s3 86605a09-7b00-44a0-9107-573c20084c7b ethernet enp0s3
[root@p1 mindle]# nmcli connection modify enp0s3 ipv4.method manual ipv4.addresses 192.168.1.2/24
[root@p1 mindle]# nmcli connection up enp0s3
通過 nmcli 命令發現網卡的名稱爲 enp03,進一步修改了網卡的靜態地址爲 192.168.1.2。
到這裏,宿主機就可以用 ping 上虛擬機,虛擬機之間也可以 ping 通。下一步解決虛擬機連上互聯網。
NAT
這一步很簡單,再增加一張 NAT 的網卡就可以了,虛擬機也不需要設置。
這下虛擬機就可以訪問互聯網了。
3 SSH 免密連接
關於 SSH 的設置建議參考鳥哥的官網,寫得非常詳細,圖文並茂,不習慣繁體字的朋友可以使用谷歌翻譯插件將頁面翻譯成中文簡體。
爲方便登陸時知道在哪一個主機上,我修改了主機的 hostname
[mindle@localhost ~]$ hostname node1.cluster
[mindle@localhost ~]$ sudo /etc/hostname
node1.cluster
這樣登陸成功後顯示的就是:
[mindle@node1 ~]$
另外爲了方便,我修改了虛擬機的 hosts 文件,給靜態 ip 地址取了別名,一臺 VM 爲 master,另一臺 VM 爲 p1:
[mindle@p1 ~]$ sudo vim /etc/hosts
192.168.1.2 master
192.168.1.3 node1
192.168.1.4 node2
192.168.1.5 node3
我們需要實現,master 免密登陸 node1、node2、node3,且 node1、node2、node3 免密登陸 master。這樣來來回回得設置 6 趟呢,咱們以 node1 免密 ssh 登陸 master 爲例子:
1.node1 生成 RSA 密鑰系統,並將公鑰通過 scp 發送給 master。
# 生成 RSA 密鑰系統
[mindle@node1 ~]$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/mindle/.ssh/id_rsa): # Enter 鍵,使用默認值
Created directory '/home/mindle/.ssh'.
Enter passphrase (empty for no passphrase): # Enter 鍵,使用空密碼
Enter same passphrase again: # Enter 鍵,使用空密碼
Your identification has been saved in /home/mindle/.ssh/id_rsa.
Your public key has been saved in /home/mindle/.ssh/id_rsa.pub.
# 將公鑰通過 scp 發送給 master
[mindle@node1 ~]$ scp .ssh/id_rsa.pub master:/home/mindle/
id_rsa.pub 100% 402 536.3KB/s 00:00
2.master 將 node1 的公鑰添加進去自己的 ~/.ssh/authorized_keys
文件中
[mindle@master ~]$ cat id_rsa.pub >> .ssh/authorized_keys
[mindle@master ~]$ rm id_rsa.pub
# 一定保證 authorized_keys 的權限爲 644
[mindle@master ~]$ chmod 644 .ssh/authorized_keys
[mindle@master ~]$ ll .ssh/authorized_keys
-rw-r--r--. 1 mindle mindle 1206 Nov 26 19:02 .ssh/authorized_keys
3.從 node1 上面再次用 ssh 連接 master,已經不需要密碼了
4 創建 NFS(Network FileSystem)
創建 NFS 系統也建議參考鳥哥的官網。
NFS 服務器和客戶端需要有兩個軟件,分別是 RPC 主程序 rpcbind
和 NFS 主程序 nfs-utils
,如果沒有的話需要先安裝好哦。
① 服務端
master 將自己的 /mpi_cloud
文件夾共享出來。NFS 服務器的假設實在很簡單,只要編輯好主要設置文件 /etc/exports 之後,先啓動 rpcbind
,再啓動 nfs
,你的 NFS 就成功了。
# 1.編輯主要設置文件
[mindle@master ~]$ sudo vim /etc/exports
/mpi_cloud 192.168.1.0/24(rw,async,no_root_squash)
#語法爲:[分享目錄] [第一部主機(權限)] [可用主機名] [可用萬用字元]
# 2.啓動 rpcbind 和 nfs 並設爲開機自啓動
[mindle@master ~]$ sudo systemctl start rpcbind
[mindle@master ~]$ sudo systemctl start nfs
[mindle@master ~]$ sudo systemctl enable rpcbind
[mindle@master ~]$ sudo systemctl enable nfs
# 如果你想要增加 NFS 服務器資料的一致性功能時,可以增加一個服務,
# 那就是 nfslock 咯!
[mindle@master ~]$ sudo systemctl start nfslock
[mindle@master ~]$ sudo systemctl enable nfslock
② 客戶端
node 虛擬機掛載 master 共享的文件夾。
# 1.啓動必需的兩個服務。
[mindle@master ~]$ sudo systemctl start rpcbind
[mindle@master ~]$ sudo systemctl start nfslock
# 2.掛載前查詢 master 共享的文件夾有哪些:
[mindle@node1 ~]$ showmount -e master
/mpi_cloud192.168.1.0/24
# 3.建立掛載點,正式掛載
[mindle@node1 mindle]$ mkdir /mpi_cloud
[mindle@node1 mindle]$ mount -t nfs master:/mpi_cloud /mpi_cloud
# 掛載的語法,『-t nfs』 指定文件系統類型
# IP:/dir 則是指定某一部主機的某個提供的目錄!另外,如果出現如下錯誤:
mount: master:/mpi_cloud failed, reason given by server: No such file
or directory
# 這代表你在 mster上面並沒有建立 /disk1 啦!自己在 mster 端建立他吧!
# 4.看看掛在後的情況,可以使用 df 或 mount 啦!
[mindle@node1 mindle]$ df -h /mpi_cloud/
文件系統 容量 已用 可用 已用% 掛載點
master:/mpi_cloud 19G 4.9G 14G 26% /mpi_cloud
那麼如何將掛在的 NFS 目錄卸載呢?就是用 umount 啊!
[mindle@node1 mindle]$ sudo unmount /mpi_cloud
5 在虛擬機上安裝 MPICH
採用 yum 來安裝 MPICH 確實好簡單:
1.列出支持的 MPICH 版本
[mindle@node1 ~]$ yum list mpich*
可安裝的軟件包
mpich-3.0.i686 3.0.4-10.el7 base
mpich-3.0.x86_64 3.0.4-10.el7 base
mpich-3.0-autoload.x86_64 3.0.4-10.el7 base
mpich-3.0-devel.i686 3.0.4-10.el7 base
mpich-3.0-devel.x86_64 3.0.4-10.el7 base
mpich-3.0-doc.noarch 3.0.4-10.el7 base
mpich-3.2.i686 3.2-2.el7 base
mpich-3.2.x86_64 3.2-2.el7 base
mpich-3.2-autoload.x86_64 3.2-2.el7 base
mpich-3.2-devel.i686 3.2-2.el7 base
mpich-3.2-devel.x86_64 3.2-2.el7 base
mpich-3.2-doc.noarch 3.2-2.el7 base
2.安裝最新版
[mindle@node1 ~]$ sudo yum install mpich-3.2*
3.安裝完成後,重載系統的環境變量,使得 mpicc
mpirun
mpiexec
命令馬上生效
[mindle@node1 ~]$ sudo source /etc/profile
4.測試安裝成功
[mindle@node1 ~]$ mpicc
Error: Command line argument is needed!
我們在 master 的共享文件夾 /mpi_cloud
中新建測試程序 /mpi_cloud/hello.c
:
#include <mpi.h>
#include <stdio.h>
#include <math.h>
int main(int argc, char *argv[])
{
int myid, numprocs;
int namelen;
char processor_name[MPI_MAX_PROCESSOR_NAME];
MPI_Init(&argc,&argv);/* 初始化並行環境 */
MPI_Comm_rank(MPI_COMM_WORLD,&myid);/* 當前進程的ID號 */
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);/* 進程的總數 */
MPI_Get_processor_name(processor_name,&namelen);/* 當前處理器的名稱 */
fprintf(stderr,"Hello World! Process %d of %d on %s\n",
myid, numprocs, processor_name);
MPI_Finalize();/* 結束並行環境 */
return 0;
}
編譯程序,並單機測試:
# 編譯程序
[mindle@master mpi_cloud ]$ mpicc hello.c
[mindle@master mpi_cloud ]$ ll
-rwxrwxr-x. 1 mindle mindle 12688 Nov 26 16:49 a.out
-rw-r--r--. 1 mindle mindle 624 Nov 26 16:40 hello.c
# 單機測試
[mindle@master mpi_cloud ]$ mpirun -n 2 ./a.out
Hello World! Process 0 of 2 on master.cluster
Hello World! Process 1 of 2 on master.cluster
在集羣中測試:
前提:
- 所有虛擬機都已經安裝 MPICH
- 所有 node 和 master 可以 ssh 無密連接
# 方式一:使用 --host 指定 IP
[mindle@master mpi_cloud]$ mpirun -n 2 --hosts master,node1 ./a.out
Hello World! Process 0 of 2 on master.cluster
Hello World! Process 1 of 2 on node1.cluster
# 方式二:使用 -f 指定保存集羣 IP 的文件
[mindle@master mpi_cloud]$ vim mpi_file
master
node1
node2
node3
[mindle@master mpi_cloud]$ mpirun -n 4 -f mpi_file /mpi_cloud/a.out
Hello World! Process 0 of 4 on master.cluster
Hello World! Process 1 of 4 on node1.cluster
Hello World! Process 2 of 4 on node2.cluster
Hello World! Process 3 of 4 on node3.cluster