👨‍👩‍👧‍👦

Raspberry Pi 4クラスタ(5台)にNIS環境を構築してみる

2021/05/14に公開

はじめに

仕事でNIS(Network Information Service)を使っているサーバ群を管理することになり、勉強のために自宅のRaspberry Pi 4クラスタ(5台)にNIS環境を構築してみました。
実験用の環境でありセキュリティ関係はあまり気にしていないため、参考にする際はご注意ください。

NISとは?

「NIS」は「Network Information Service」の略で、複数のホスト間で設定情報(例えばユーザ情報)を共有するための仕組みです。

詳しくは、以下のサイトなどを参照ください。

共有する情報

NISでは色々な情報を共有することができますが、今回はユーザ情報、グループ情報のみに焦点を当てています。

環境

今回の実験は、以下の環境で実施しました。

外観は以下の通りです。実験環境なので、雑に積んでいます。

NISサーバの環境を以下に示します。450GBのSSDからブートしています。

pi@raspi4b8g-1:~ $ cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"

pi@raspi4b8g-1:~ $ uname -a
Linux raspi4b8g-1 5.10.17-v8+ #1403 SMP PREEMPT Mon Feb 22 11:37:54 GMT 2021 aarch64 GNU/Linux

pi@raspi4b8g-1:~ $ grep Model /proc/cpuinfo
Model		: Raspberry Pi 4 Model B Rev 1.4

pi@raspi4b8g-1:~ $ free
              total        used        free      shared  buff/cache   available
Mem:        8000844       70332     7565916       16844      364596     7798872
Swap:        102396           0      102396

pi@raspi4b8g-1:~ $ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/root       441G  1.4G  421G   1% /
devtmpfs        3.7G     0  3.7G   0% /dev
tmpfs           3.9G     0  3.9G   0% /dev/shm
tmpfs           3.9G  8.5M  3.9G   1% /run
tmpfs           5.0M  4.0K  5.0M   1% /run/lock
tmpfs           3.9G     0  3.9G   0% /sys/fs/cgroup
/dev/sda1       253M   31M  222M  13% /boot
tmpfs           782M     0  782M   0% /run/user/1000

NISクライアントの環境を以下に示します。64GBのmicroSDカードからブートしています。OSはNISサーバと同一です。

pi@raspi4b4g-1:~ $ grep Model /proc/cpuinfo
Model		: Raspberry Pi 4 Model B Rev 1.2

pi@raspi4b4g-1:~ $ free
              total        used        free      shared  buff/cache   available
Mem:        3886428       69816     3451380       16844      365232     3728344
Swap:        102396           0      102396

pi@raspi4b4g-1:~ $ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/root        57G  1.2G   53G   3% /
devtmpfs        1.8G     0  1.8G   0% /dev
tmpfs           1.9G     0  1.9G   0% /dev/shm
tmpfs           1.9G   17M  1.9G   1% /run
tmpfs           5.0M  4.0K  5.0M   1% /run/lock
tmpfs           1.9G     0  1.9G   0% /sys/fs/cgroup
/dev/mmcblk0p1  253M   32M  221M  13% /boot
tmpfs           380M     0  380M   0% /run/user/1000

ネットワーク構成

Raspberry Pi 5台はすべて2つのネットワークインターフェースを持ち、それぞれ別のネットワークに接続されています。

Internet --- Router ----+-- [wlan0] raspi4b8g-1 [eth0] --+
                        |                                |
                        +-- [wlan0] raspi4b4g-1 [eth0] --+
 Wi-Fi (192.168.1.0/24) |                                | 1Gbps Ethernet (192.168.2.0/24)
                        +-- [wlan0] raspi4b4g-2 [eth0] --+
                        |                                |
                        +-- [wlan0] raspi4b4g-3 [eth0] --+
                        |                                |
                        +-- [wlan0] raspi4b4g-4 [eth0] --+

1つ目は、家庭内ネットワークに接続するためのwlan0で、実体は無線LANです。192.168.1.0/24のネットワークに接続されており、IPアドレスはDHCPにて取得します。また、名前解決はmDNSにて行います。

2つ目は、Raspberry Pi同士を接続するためのeth0で、実体は有線LAN(1Gbps)です。192.168.2.0/24のネットワークに接続されており、IPアドレスは固定されています。名前解決は/etc/hostsにて行います。

wlan0はセットアップやメンテナンスのために使用し、eth0はRaspberry Pi同士の接続(NIS、NFSの通信)に使います。

具体例を以下に示します。(不要な部分は省略)

pi@raspi4b8g-1:~ $ ip address
...
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether dc:a6:32:f8:7c:aa brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.81/24 brd 192.168.2.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::6d6c:4ab6:84b:bc25/64 scope link
       valid_lft forever preferred_lft forever
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether dc:a6:32:f8:7c:ab brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.119/24 brd 192.168.1.255 scope global dynamic noprefixroute wlan0
       valid_lft 45949sec preferred_lft 35149sec
    inet6 fe80::219a:9f2e:c909:124c/64 scope link
       valid_lft forever preferred_lft forever
...

NFSのセットアップ

NISのセットアップに先立ち、NFSによる共有ディレクトリのエクスポート、マウントを設定しました。
NISでユーザ情報を共有した場合に、ホームディレクトリも共有できると便利なためです。

NISサーバでの設定

NISサーバに共有ディレクトリ/mnt/raspi4b8g-1を作成し、それをNFSでエクスポート(公開)します。実体はUSBで接続されているSSD上にあります。
ディレクトリ名にホスト名が入っているのは、実体がどのホストにあるか分かりやすくなり、かつすべてのホストから同一のパスでアクセスできるようにするためです。

以下の設定例は、Docker for MacからNFSのマウントを行う実験などの関係で、セキュリティガバガバの設定になっていますのでご注意ください。

主な作業の流れは以下の通りです。

  1. nfs-kernel-serverパッケージをインストールする。
  2. エクスポートする共有ディレクトリ/mnt/raspi4b8g-1を作成する。
  3. /etc/hostsファイルにて、他のRaspberry Piの名前解決を行えるようにする。(eth0側のIPアドレス)
  4. /etc/exportsファイルでNFSのエクスポートについて設定する。
  5. exportfs -raコマンドでNFSのエクスポート設定を反映する。
  6. exportfs -vコマンドでNFSのエクスポート設定を確認する。
pi@raspi4b8g-1:~ $ sudo apt install --yes nfs-kernel-server
pi@raspi4b8g-1:~ $ systemctl status nfs-kernel-server
● nfs-server.service - NFS server and services
   Loaded: loaded (/lib/systemd/system/nfs-server.service; enabled; vendor preset: enabled)
   Active: active (exited) since Sat 2021-05-01 00:39:08 JST; 25s ago
 Main PID: 13782 (code=exited, status=0/SUCCESS)
    Tasks: 0 (limit: 4915)
   CGroup: /system.slice/nfs-server.service

pi@raspi4b8g-1:~ $ sudo mkdir -p /mnt/raspi4b8g-1
pi@raspi4b8g-1:~ $ ls -la /mnt/raspi4b8g-1/
total 8
drwxr-xr-x 2 root root 4096 May  1 00:40 .
drwxr-xr-x 4 root root 4096 May  1 00:40 ..

pi@raspi4b8g-1:~ $ sudo vim /etc/hosts
pi@raspi4b8g-1:~ $ cat /etc/hosts
127.0.0.1	localhost
::1		localhost ip6-localhost ip6-loopback
ff02::1		ip6-allnodes
ff02::2		ip6-allrouters

192.168.2.81	raspi4b8g-1 raspi4b8g-1.eth0 raspi4b8g-1.raspi
192.168.2.41 	raspi4b4g-1 raspi4b4g-1.eth0
192.168.2.42 	raspi4b4g-2 raspi4b4g-2.eth0
192.168.2.43 	raspi4b4g-3 raspi4b4g-3.eth0
192.168.2.44 	raspi4b4g-4 raspi4b4g-4.eth0

pi@raspi4b8g-1:~ $ sudo vim /etc/exports
pi@raspi4b8g-1:~ $ cat /etc/exports
# /etc/exports: the access control list for filesystems which may be exported
#		to NFS clients.  See exports(5).
#
# Example for NFSv2 and NFSv3:
# /srv/homes       hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check)
#
# Example for NFSv4:
# /srv/nfs4        gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
# /srv/nfs4/homes  gss/krb5i(rw,sync,no_subtree_check)
#
/mnt/raspi4b8g-1  raspi4b4g-1.eth0(rw,sync,no_subtree_check,fsid=0,crossmnt,insecure,anonuid=1000,anongid=1000)
/mnt/raspi4b8g-1  raspi4b4g-2.eth0(rw,sync,no_subtree_check,fsid=0,crossmnt,insecure,anonuid=1000,anongid=1000)
/mnt/raspi4b8g-1  raspi4b4g-3.eth0(rw,sync,no_subtree_check,fsid=0,crossmnt,insecure,anonuid=1000,anongid=1000)
/mnt/raspi4b8g-1  raspi4b4g-4.eth0(rw,sync,no_subtree_check,fsid=0,crossmnt,insecure,anonuid=1000,anongid=1000)

pi@raspi4b8g-1:~ $ sudo exportfs -ra
pi@raspi4b8g-1:~ $ sudo exportfs -v
/mnt/raspi4b8g-1
		raspi4b4g-1(rw,wdelay,crossmnt,insecure,root_squash,no_subtree_check,fsid=0,anonuid=1000,anongid=1000,sec=sys,rw,insecure,root_squash,no_all_squash)
/mnt/raspi4b8g-1
		raspi4b4g-2(rw,wdelay,crossmnt,insecure,root_squash,no_subtree_check,fsid=0,anonuid=1000,anongid=1000,sec=sys,rw,insecure,root_squash,no_all_squash)
/mnt/raspi4b8g-1
		raspi4b4g-3(rw,wdelay,crossmnt,insecure,root_squash,no_subtree_check,fsid=0,anonuid=1000,anongid=1000,sec=sys,rw,insecure,root_squash,no_all_squash)
/mnt/raspi4b8g-1
		raspi4b4g-4(rw,wdelay,crossmnt,insecure,root_squash,no_subtree_check,fsid=0,anonuid=1000,anongid=1000,sec=sys,rw,insecure,root_squash,no_all_squash)

NISクライアントでの設定

続いて、NISクライアント側でNFSをマウントします。4台すべてで実施します。

主な作業の流れは以下の通りです。

  1. nfs-commonパッケージをインストールする。
  2. /etc/hostsファイルにて、他のRaspberry Piの名前解決を行えるようにする。(eth0側のIPアドレス)
  3. マウント先ディレクトリ/mnt/raspi4b8g-1を作成する。
  4. mountコマンドでマウントする。
  5. 問題無くマウントできれば、/etc/fstabファイルに設定を追加して、自動マウントを設定する。
pi@raspi4b4g-1:~ $ sudo apt install --yes nfs-common

pi@raspi4b4g-1:~ $ sudo vim /etc/hosts
pi@raspi4b4g-1:~ $ cat /etc/hosts
127.0.0.1	localhost
::1		localhost ip6-localhost ip6-loopback
ff02::1		ip6-allnodes
ff02::2		ip6-allrouters

192.168.2.81	raspi4b8g-1 raspi4b8g-1.eth0 raspi4b8g-1.raspi
192.168.2.41 	raspi4b4g-1 raspi4b4g-1.eth0
192.168.2.42 	raspi4b4g-2 raspi4b4g-2.eth0
192.168.2.43 	raspi4b4g-3 raspi4b4g-3.eth0
192.168.2.44 	raspi4b4g-4 raspi4b4g-4.eth0

pi@raspi4b4g-1:~ $ sudo mkdir /mnt/raspi4b8g-1
pi@raspi4b4g-1:~ $ sudo mount -t nfs raspi4b8g-1.eth0:/mnt/raspi4b8g-1 /mnt/raspi4b8g-1
pi@raspi4b4g-1:~ $ sudo umount /mnt/raspi4b8g-1

pi@raspi4b4g-1:~ $ sudo vim /etc/fstab
pi@raspi4b4g-1:~ $ cat /etc/fstab
proc            /proc           proc    defaults          0       0
PARTUUID=d4af8c7e-01  /boot           vfat    defaults          0       2
PARTUUID=d4af8c7e-02  /               ext4    defaults,noatime  0       1
# a swapfile is not a swap partition, no line here
#   use  dphys-swapfile swap[on|off]  for that
raspi4b8g-1.eth0:/mnt/raspi4b8g-1  /mnt/raspi4b8g-1  nfs  defaults,noatime,nofail  0  0

pi@raspi4b4g-1:~ $ sudo mount /mnt/raspi4b8g-1

NISのセットアップ

続いて、NISをセットアップしていきます。

NISサーバでの設定

NISサーバ(マスタ)を設定します。

主な作業の流れは以下の通りです。

  1. nisパッケージをインストールする。
  2. /etc/default/nisファイルでNISサーバ(マスタ)に設定する。
  3. nisサービスを再起動する。
  4. /usr/lib/yp/ypinit -mコマンドでデータベースを初期化する。
pi@raspi4b8g-1:~ $ sudo apt install --yes nis
# NIS domainに「raspi」を設定

pi@raspi4b8g-1:~ $ sudo cp /etc/default/nis /etc/default/nis.20210501
pi@raspi4b8g-1:~ $ sudo vim /etc/default/nis
pi@raspi4b8g-1:~ $ diff -u /etc/default/nis.20210501 /etc/default/nis
--- /etc/default/nis.20210501	2021-05-01 01:15:44.681200984 +0900
+++ /etc/default/nis	2021-05-01 01:17:22.799675423 +0900
@@ -3,7 +3,7 @@
 #

 # Are we a NIS server and if so what kind (values: false, slave, master)?
-NISSERVER=false
+NISSERVER=master

 # Are we a NIS client?
 NISCLIENT=true

pi@raspi4b8g-1:~ $ sudo systemctl restart nis
pi@raspi4b8g-1:~ $ systemctl status nis
● nis.service - LSB: Start NIS client and server daemons.
   Loaded: loaded (/etc/init.d/nis; generated)
   Active: active (running) since Sat 2021-05-01 01:27:03 JST; 44s ago
     Docs: man:systemd-sysv-generator(8)
  Process: 18689 ExecStart=/etc/init.d/nis start (code=exited, status=0/SUCCESS)
    Tasks: 6 (limit: 4915)
   CGroup: /system.slice/nis.service
           ├─18696 /usr/sbin/ypserv
           ├─18699 /usr/sbin/rpc.yppasswdd -D /etc -e chsh
           ├─18702 /usr/sbin/rpc.ypxfrd
           └─18711 /usr/sbin/ypbind -broadcast

pi@raspi4b8g-1:~ $ sudo /usr/lib/yp/ypinit -m

At this point, we have to construct a list of the hosts which will run NIS
servers.  raspi4b8g-1 is in the list of NIS server hosts.  Please continue to add
the names for the other hosts, one per line.  When you are done with the
list, type a <control D>.
	next host to add:  raspi4b8g-1
	next host to add:
The current list of NIS servers looks like this:

raspi4b8g-1

Is this correct?  [y/n: y]
We need a few minutes to build the databases...
Building /var/yp/raspi/ypservers...
Running /var/yp/Makefile...
make[1]: Entering directory '/var/yp/raspi'
Updating passwd.byname...
Updating passwd.byuid...
Updating group.byname...
Updating group.bygid...
Updating hosts.byname...
Updating hosts.byaddr...
Updating rpc.byname...
Updating rpc.bynumber...
Updating services.byname...
Updating services.byservicename...
Updating netid.byname...
Updating protocols.bynumber...
Updating protocols.byname...
Updating netgroup...
Updating netgroup.byhost...
Updating netgroup.byuser...
Updating shadow.byname...
make[1]: Leaving directory '/var/yp/raspi'

raspi4b8g-1 has been set up as a NIS master server.

Now you can run ypinit -s raspi4b8g-1 on all slave server.

NISクライアントでの設定

NISクライアントを設定します。4台すべてで実施します。

主な作業の流れは以下の通りです。

  1. nisパッケージをインストールする。
  2. /etc/yp.confファイルでNISサーバを指定する。
  3. /etc/nsswitch.confファイルでユーザ情報、グループ情報、ホスト情報についてNISを参照するように設定する。
  4. rpcbindnisサービスを再起動する。
pi@raspi4b4g-1:~ $ sudo apt install --yes nis
# 「NIS domain」に「raspi」を入力してOK

pi@raspi4b4g-1:~ $ sudo cp /etc/yp.conf /etc/yp.conf.20210501
pi@raspi4b4g-1:~ $ sudo vim /etc/yp.conf
pi@raspi4b4g-1:~ $ diff -u /etc/yp.conf.20210501 /etc/yp.conf
--- /etc/yp.conf.20210501	2021-05-01 01:37:17.919943863 +0900
+++ /etc/yp.conf	2021-05-01 01:39:19.041348761 +0900
@@ -11,3 +11,4 @@
 #		be resolved and ypbind won't ever bind to the server.

 # ypserver ypserver.network.com
+domain raspi server raspi4b8g-1.eth0

pi@raspi4b4g-1:~ $ sudo cp /etc/nsswitch.conf /etc/nsswitch.conf.20210501
pi@raspi4b4g-1:~ $ sudo vim /etc/nsswitch.conf
pi@raspi4b4g-1:~ $ diff -u /etc/nsswitch.conf.20210501 /etc/nsswitch.conf
--- /etc/nsswitch.conf.20210501	2021-05-01 01:40:36.315160335 +0900
+++ /etc/nsswitch.conf	2021-05-01 01:42:38.103492465 +0900
@@ -4,12 +4,12 @@
 # If you have the `glibc-doc-reference' and `info' packages installed, try:
 # `info libc "Name Service Switch"' for information about this file.

-passwd:         files
-group:          files
-shadow:         files
+passwd:         files nis
+group:          files nis
+shadow:         files nis
 gshadow:        files

-hosts:          files mdns4_minimal [NOTFOUND=return] dns
+hosts:          files mdns4_minimal [NOTFOUND=return] dns nis
 networks:       files

 protocols:      db files

pi@raspi4b4g-1:~ $ sudo systemctl restart rpcbind nis

※改めて見てみると、hostsの行でdnsより後ろにnisがあるのは検索順序的に望ましくないですね。今回はユーザ情報、グループ情報の共有がメインであり、ホスト情報は/etc/hostsで対応しているので上記のままとします。

ユーザの追加

では実際に、すべてのホストにログインできるユーザyuyaを追加してみます。ユーザの追加はNISサーバにて行います。

主な作業の流れは以下の通りです。

  1. NFSにエクスポートされている場所にホームディレクトリのベースディレクトリを作成する。(初回のみ)
  2. ユーザを追加する。その際、ホームディレクトリを明示的に指定する。
  3. NISデータベースを更新する。(/var/ypディレクトリでmakeコマンドを実行する)
pi@raspi4b8g-1:~ $ sudo mkdir /mnt/raspi4b8g-1/home
pi@raspi4b8g-1:~ $ sudo adduser --home /mnt/raspi4b8g-1/home/yuya yuya
pi@raspi4b8g-1:~ $ ls -l /mnt/raspi4b8g-1/home/
total 4
drwxr-xr-x 2 yuya yuya 4096 May  1 01:45 yuya

pi@raspi4b8g-1:~ $ grep yuya /etc/passwd
yuya:x:1001:1001:Yuya Kato,,,:/mnt/raspi4b8g-1/home/yuya:/bin/bash

pi@raspi4b8g-1:~ $ grep yuya /etc/group
yuya:x:1001:

pi@raspi4b8g-1:~ $ id yuya
uid=1001(yuya) gid=1001(yuya) groups=1001(yuya)

pi@raspi4b8g-1:~ $ cd /var/yp/
pi@raspi4b8g-1:/var/yp $ sudo make
make[1]: Entering directory '/var/yp/raspi'
Updating passwd.byname...
Updating passwd.byuid...
Updating netid.byname...
Updating shadow.byname...
make[1]: Leaving directory '/var/yp/raspi'

NISクライアントにてyuyaユーザでログインできることを確認します。もちろんSSH経由でもログインできました。

pi@raspi4b4g-1:~ $ su - yuya
Password:
yuya@raspi4b4g-1:~ $ id
uid=1001(yuya) gid=1001(yuya) groups=1001(yuya)

未解決問題

NISクライアントをリブートすると、nisサービスが起動に失敗してしまいます。
リブート後に手動でnisサービスを再起動すると起動に成功しますが、解決方法は見つかっていません。何か情報があれば教えて頂けると幸いです。

pi@raspi4b4g-1:~ $ systemctl status nis
● nis.service - LSB: Start NIS client and server daemons.
   Loaded: loaded (/etc/init.d/nis; generated)
   Active: active (exited) since Sun 2021-05-02 22:40:09 JST; 8min ago
     Docs: man:systemd-sysv-generator(8)
  Process: 578 ExecStart=/etc/init.d/nis start (code=exited, status=0/SUCCESS)

May 02 22:39:57 raspi4b4g-1 systemd[1]: Starting LSB: Start NIS client and server daemons....
May 02 22:39:58 raspi4b4g-1 nis[578]: Setting NIS domainname to: raspi.
May 02 22:39:58 raspi4b4g-1 ypbind[621]: Unable to register (YPBINDPROG, YPBINDVERS, udp).
May 02 22:40:09 raspi4b4g-1 nis[578]: Starting NIS services: ypbindbinding to YP server...........................................failed (backgrounded).
May 02 22:40:09 raspi4b4g-1 nis[578]: .
May 02 22:40:09 raspi4b4g-1 systemd[1]: Started LSB: Start NIS client and server daemons..

pi@raspi4b4g-1:~ $ sudo systemctl restart nis

最後に

駆け足ではありますが、NFSによるホームディレクトリの共有、NISによるユーザ情報、グループ情報の共有について紹介しました。
今後は、この実験環境を使ってNFS、NISの学習を進めたいと思います。

参考

Discussion