Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

LinuxインスタンスでNFSを自動マウント

By Sayle MatthewsJul 20, 20208 min read

このページはEnglishDeutschEspañolFrançaisItalianoPortuguêsでもご覧いただけます。

1 fl0wtntavgxuf3yqbi5owg

数週間前、自宅ラボの多数のVMをKubernetesに移行する際、当時はかなり特殊だと思っていたユースケースに直面しました。それが、LinuxマシンやDockerコンテナにNFSボリュームを自動マウントするというものです。

目的は、InfluxDB・MySQL・Grafanaのバックエンドストレージを、稼働マシンのローカルファイルシステムからNASへ移すことでした。NFSはシンプルかつ対応デバイスが豊富なので、自宅ネットワークでも複数台でファイルを共有する用途で頻繁に使っています。

自宅ラボでこの構成を組み終えてみると、世の中でNFSが使われている範囲を考えれば、これは決して特殊なユースケースではないと気づきました。クラウド環境からオンプレミスのNFS共有をマウントしてデータを取り込む、プロセスにNFS共有への読み書きを許可する、ユーザーのホームディレクトリをNFSからマウントする──ほかにも数え切れないほどの活用シーンがあります。

自動マウントを実現するうえでの落とし穴と突破口

最初は、自分が一番慣れているfstabを使う方法から試しました。ここ数十年、折に触れて使ってきた手段です。ところがすぐに、データベースデーモンが認識できる速さでNFSをマウントできず、深刻な不具合を引き起こすことがわかりました。

そこで見つけたのが、autofsというLinuxパッケージでした。動かせるようになるまでには相当な試行錯誤が必要でした。ネット上のガイドの多くは情報が古かったり、肝心なポイントが抜け落ちていたりしたためです。本ガイドは、皆さんが半日を溶かさずに済むよう、必要な手順だけを端的にまとめました。この業界に身を置く私たちにとって、時間ほど足りないものはありませんから。

autofsの正体は、必要なときにバックグラウンドで共有を自動的にマウント・アンマウントするデーモンです。fstabと違って要求ベースで動くので、デーモンの起動順序を気にせずブート時にも処理できます。


前提条件

話を簡潔にするため、本記事ではNASやLinuxマシン上にNFSサーバーがすでに構築済みであるか、Google CloudのFilestoreのようなサービスをNAS代わりに使っていることを前提とします。

追加したい共有ごとに、NFS共有のフルパスを必ず控えておいてください。想定とは異なる形になっていることもあるので、必ず確認しましょう。たとえばSynology NASでは、/volume1/share_pathのようにボリューム名が頭に付きます。

また、コマンドはDebian系ディストリビューション(Debian、Ubuntu、Kaliなど)を前提に記載します。各セクションにはRed Hat系向けのコマンドも併記するので、RHELやCentOSをお使いの方も読み替える必要はありません。

本ガイドではNFSのセキュリティ運用については扱いません。これは非常に大きなテーマで、踏み込めばガイドの分量が倍になりかねないため、あえて割愛します。もちろん極めて重要な要素であることは間違いないので、本記事の構成が一通り完成したら、組織に最適な形で組み込めるよう別途学習することをおすすめします。さらに詳しく知りたい方は、Red Hatが基本を解説した良記事をこちらから読み始めるとよいでしょう。


手順

  1. お使いのディストリビューションに合わせて、以下のコマンドでautofsパッケージをインストールします。

    Ubuntu: `sudo apt -y install nfs-common autofs

    Red Hat: sudo yum -y install nfs-common autofs`

  2. お好みのエディタで/etc/auto.masterを開きます。

  3. ファイル末尾までスクロールし、追加したいマウントごとに以下のような行を書き加えます。auto.shareshareの部分は、共有用に好きな名前へ置き換えてください:

    `/- /etc/auto.share -nosuid,noowners

    `(読みやすくしたい場合はスペースを増やしても構いません。Mediumでは番号付きリスト内のコードブロックで連続スペースが省略されるため、ここではこの形で記載しています。)

  4. 続いて、前の手順で参照した各ファイルを作成します。いずれも/etc配下に置き、ファイル名はauto.[share_name]の形式にします。先ほど追加したauto.shareの各行に対応するファイルを、お好みのテキストエディタで開いて作成してください。ファイル内には、共有名(個人的には/mnt配下にまとめるのが好みですが、適宜変更可)、サーバー名、共有パスを置き換えて、以下の行を記述します:

    `/mnt/[share_name] -fstyle=nfs,user,nolock,nosuid,rw [server_name]:[share_path]

    `(ここでも読みやすさのためにスペースを増やしてかまいません。また、読み書きではなく読み取り専用にしたい場合は、上記のrwをroに変更してください。)

  5. ここまで終えたら、以下のコマンドでautofsサービスを再起動します。

    Ubuntu: sudo service autofs restart

    Red Hat: sudo systemctl restart autofs

  6. 次に、サービスが正しく起動したか、構文エラーやネットワークエラーなどが起動時に発生していないかを確認します。以下のコマンドでステータスを確認してください:

    Ubuntu: sudo service autofs status

    Red Hat: sudo systemctl status autofs

  7. 正常であれば、出力にステータスがrunningと表示されているはずです。問題があれば、ログの末尾数行が表示され、デバッグの手がかりになります。基本的なデバッグ方法については、記事末尾のセクションでも解説しています。

  8. ここまで来たら、上記のファイルに記載したディレクトリにcdするだけで共有にアクセスできます。これらのディレクトリを事前に作成しておく必要はありません。autofsデーモンが自動で作成してくれます。

  9. 最終確認として、mountコマンドを実行するとインスタンス上の全マウントが一覧表示されます。autofsで作成された分だけを抜き出すには、mount | grep autofsを実行するのが手軽です。

  10. これ以降、マウントは自動で読み込まれ、必要に応じて再アタッチされます。

  11. この段階で、NFSのセキュリティについて学び、マウントを保護したうえで、用途に最適なセキュリティ手法を導入することを強くおすすめします。


よくある問題のデバッグ

この仕組みを学ぶ過程でいくつか引っかかった点があったので、その内容と切り分け方法を紹介します。

最初にぶつかったのは、デーモンがNFS接続に関して大量のエラーを吐く問題でした。原因は、Synologyが共有名の前にボリューム番号を付けることを当時知らなかったことでした。切り分けには、ホームディレクトリ内のフォルダにNFS共有を手動でマウントしてみる方法を取りました。コマンドはmkdir tmp_mnt && sudo mount -v -r -o user,nolock,nosuid [server_name]:[share_path] tmp_mntで、ローカルディレクトリに共有をマウントします。成功するか、エラーであれば原因が表示されます。アンマウントにはsudo umount tmp_mntを実行します。

もう一つ遭遇したのは、サーバーにホスト名でアクセスできないという問題でした。原因は内部DNSの不具合で、ホスト名が解決できていませんでした。IPアドレスでは共有にアクセスできることを確認したうえで、nslookup hostnameを実行し、IPアドレスからホスト名への変換ができていないことを突き止めて切り分けました。なお、このコマンドを使うには、bind-utils(Red Hatの場合sudo yum -y install bind-utils)またはdnsutils(Debianの場合sudo apt install -y dnsutils)パッケージのインストールが必要なことがあります。

最後の問題はKubernetes固有のものでした。クラスター内のどのPodからも、NFS共有を含むクラスター外の外部サービスにアクセスできなかったのです。原因は、クラスターが外部にある内部DNSサーバーを認識しておらず、DNSでホスト名を解決できなかったことでした。背景の理論は本ガイドの範囲を大きく超えるので、ここでは解決策と詳細を読める参考リンクだけを示します。

  1. 以下のコマンドでCoreDNSのconfigmapを編集します:kubectl edit configmap coredns -n kube-system
  2. テキストエディタが開き、CoreDNSのyamlファイルが表示されます。その中にCorefileというセクションがあり、.:53で始まるyamlブロックがあります。
  3. 内部ドメインを確認します。これは内部DNSサーバーの設定によって決まりますが、内部DNSサーバーがない場合はlocalを指定してください。
  4. DNSサーバーのIPアドレスを確認します。ない場合は、ほとんどの場合ルーターのIPアドレスになります。
  5. 以下のコードブロックを自分の情報に置き換えたうえで、その下に新しい行として追加します(タブではなくスペースを使うことを必ず確認してください)。保存してエディタを閉じます:

[domain_name]:53 { errors cache 30 forward . [dns_server] }

この方法が機能する理由の詳細はこちらをご覧ください。