Fedora で作る PC クラスター part3

# 概要
1台ごとに計算ソフトをインストールし、環境構築を行という面倒を解消するために、Fedora 40 server edition で PC クラスターを作成した際のログ。
使用するソフトは、Gaussian16、Gromacs、Amber、AlphaFold3、CREST、NCI Plot
セットアップの流れは、以下

1. HDD のマウント
1. ネットワーク設定
1. Ansible の設定
1. NFS の設定
1. LDAP の設定
1. SSSD の設定
1. SLURM のインストール
1. Apptainer (Sigularity) を導入し、コンテナを共有ディレクトリに配置
1. ユーザー管理
1. テストジョブ
1. バックサーバーの設定

Part 3 では、Singularity の設定からバックサーバーの設定までを行う。

# 検証環境

![PC_cluster.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4035613/3d545b85-b143-42c1-aa25-1a3a1e7b5c6c.png)

ヘッドノートは、各計算機からのデータの I/O と Slurm の制御を行うため、コア数の多い CPU が好ましい。バックアップノードは負荷が低いため、性能の低い CPU で十分。

・ヘッドノード（1台）
AMD Ryzen Threadripper 3990x (64core/128thread)
RAM 128GB
M.2 SSD 4TB + HDD 18TB x 2 (RAID 0)

・バックアップノード（1台）
Intel core i7-7700 (4core/8thread)
RAM 128GB
SSD 1TB + HDD 18TB x 2 (RAID 0)
Fedora 40 server edition

・計算ノード（7台）
AMD Ryzen 9 9950x or 7950x (16core/32thread)
RAM 96GB
M.2 SSD 2TB
GPU: RTX A4000 or A6000 or RX 4080 super
Fedora 40 server edition

・スイッチ
NETGEAR 卓上型コンパクト アンマネージスイッチングハブ GS316 ギガビット 16ポート 


# Apptainer (Sigularity) の導入
以前は、Singularity という名前で呼ばれていたが、現在は Apptainer という名前で管理されている。
PC クラスターのノード数が多く、計算機の入れ替えも多い場合は、Apptainer で設定を行うと手間を省くことができる。計算ノード数が少ない場合や、計算の実行速度にこだわりがある場合は、Ansible で各計算ノードにソフトウェアをインストールしてしまった方が簡便。

1. nvidia-driver や cuda は、各ノードでの設定が必要。Ansible を利用すると設定が簡単
1. AlphaFold3 は、アクセス頻度の高い public_databases は各計算ノードに配置し、その他の部分を apptainer を利用する
1. Apptainer の .sif イメージは NFS 上に置く（/mnt/data/containers）


### 設定方法
必要なファイルをインストールする
```shell
sudo dnf install -y git wget squashfs-tools libseccomp-devel \
    glibc-devel golang cryptsetup
```

Ansible で一括設定する。
~/cluster-setup/playbooks/apptainer.yml を作成。
```shell
# playbooks/apptainer.yml

- name: Install and configure Apptainer
  hosts: compute
  become: yes
  tasks:

    - name: Install dependencies
      package:
        name:
          - gcc
          - libseccomp-devel
          - make
          - squashfs-tools
          - cryptsetup
          - wget
          - git
          - golang
        state: present

    - name: Clone Apptainer source (stable release)
      git:
        repo: https://github.com/apptainer/apptainer.git
        dest: /usr/local/src/apptainer
        version: v1.2.5  # 最新安定版に合わせて変更可能
        force: yes

    - name: Build and install Apptainer
      shell: |
        cd /usr/local/src/apptainer
        ./mconfig --prefix=/usr/local
        make -C builddir
        make -C builddir install
      args:
        creates: /usr/local/bin/apptainer

    - name: Ensure apptainer is in PATH
      lineinfile:
        path: /etc/profile.d/apptainer.sh
        line: 'export PATH=/usr/local/bin:$PATH'
        create: yes
        mode: '0755'
```

以下のコマンドで実行する。
5 分ほど時間がかかる。
```shell
cd ~/cluster-setup/
ansible-playbook playbooks/apptainer.yml --ask-become-pass
```

## Apptainer を用いた Amber24 のインストール方法

Fedora40 で Amber24 をビルドする際、gcc や cuda のバージョンなどでエラーが起きることが多い。そのため、Amber24 は Apptainer で利用する。

```shell
# cuda12.4 のインストール
sudo dnf config-manager --add-repo https://developer.download.nvidia.com/compute/cuda/repos/fedora39/x86_64/cuda-fedora39.repo
sudo dnf -y install cuda-toolkit-12-4

# ファイルダウンロード
cd /opt
tar jxvf AmberTools24.tar.bz2
tar jxvf Amber24.tar.bz2
```

ここで、apptainer の定義ファイル /opt/amber24-ubuntu22.04.def を作成する。
`vi amber24-ubuntu22.04.def` で以下の内容を書き込む。

```shell
Bootstrap: docker
From: ubuntu:22.04

%environment
    export DEBIAN_FRONTEND=noninteractive
    export PATH=/usr/local/cuda-12.4/bin:$PATH
    export LD_LIBRARY_PATH=/usr/local/cuda-12.4/lib64:$LD_LIBRARY_PATH
    export CUDA_HOME=/usr/local/cuda-12.4
    export AMBERHOME=/opt/amber24
    export PATH=$AMBERHOME/bin:$PATH
    export LANG=en_US.UTF-8
    export LC_ALL=en_US.UTF-8
    
%post
    # リポジトリの設定（universe を明示的に追加）
    apt-get update -y
    apt-get install -y software-properties-common
    echo "deb http://archive.ubuntu.com/ubuntu/ jammy main restricted universe multiverse" > /etc/apt/sources.list
    echo "deb http://archive.ubuntu.com/ubuntu/ jammy-updates main restricted universe multiverse" >> /etc/apt/sources.list
    echo "deb http://archive.ubuntu.com/ubuntu/ jammy-security main restricted universe multiverse" >> /etc/apt/sources.list
    apt-get update -y && apt-get upgrade -y
    apt-get clean && rm -rf /var/lib/apt/lists/*
    apt-get update -y

    # 必要なパッケージのインストール（python-is-python3 を追加）
    apt-get install -y \
        tcsh make cmake gcc g++ gfortran flex bison patch bc \
        xorg-dev libbz2-dev wget libopenmpi-dev openmpi-bin \
        libnetcdf-dev libnetcdff-dev libhdf5-dev zlib1g-dev \
        libfftw3-dev libblas-dev liblapack-dev python3 python3-dev python3-pip \
	python-is-python3 \
	libncursesw5-dev libssl-dev build-essential checkinstall\
	libsqlite3-dev libgdbm-dev libc6-dev libffi-dev zlib1g-dev \
        && apt-get clean

    # CUDA 12.4 のインストール
    wget https://developer.download.nvidia.com/compute/cuda/12.4.0/local_installers/cuda_12.4.0_550.54.14_linux.run
    sh cuda_12.4.0_550.54.14_linux.run --silent --toolkit --no-drm --no-man-page
    rm cuda_12.4.0_550.54.14_linux.run

    # Miniconda のインストール
    wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
    bash Miniconda3-latest-Linux-x86_64.sh -b -p /opt/miniconda
    rm Miniconda3-latest-Linux-x86_64.sh
    /opt/miniconda/bin/conda init

    # Conda パッケージのインストール
    export PATH=/opt/miniconda/bin:$PATH
    conda config --set always_yes true
    conda install numpy scipy matplotlib

%labels
    Author YourName
    Version v1.0
    Description Amber24 build environment based on Ubuntu 22.04

%runscript
    echo "Amber24 build container based on Ubuntu 22.04"
    exec /bin/bash

%help
    This is an Apptainer container for building Amber24 on Ubuntu 22.04.
    Example: apptainer shell --nv --bind /opt/amber24_src:/opt/amber24_src,/opt/amber24:/opt/amber24 /opt/amber24-ubuntu22.04.sif

```

```shell
# apptainer のイメージをビルド
cd /opt
sudo apptainer build amber24-ubuntu22.04.sif /opt/amber24-ubuntu22.04.def

apptainer shell --nv \
    --bind /opt/amber24_src:/opt/amber24_src,/opt/amber24:/opt/amber24 \
    /opt/amber24-ubuntu22.04.sif

# 以下、apptainer 内での作業
cd /opt/amber24_src
./update_amber --update

cd /opt/amber24_src/build
AMBER_PREFIX=/opt
cmake $AMBER_PREFIX/amber24_src \
    -DCMAKE_INSTALL_PREFIX=/opt/amber24 \
    -DCOMPILER=GNU \
    -DMPI=TRUE \
    -DOPENMP=TRUE \
    -DCUDA=TRUE \
    -DBUILD_GUI=FALSE \
    -DBUILD_QUICK=TRUE \
    -DINSTALL_TESTS=TRUE \
    -DNCCL=FALSE \
    -DDOWNLOAD_MINICONDA=TRUE \
    -DMPI_C_COMPILER=/usr/bin/mpicc \
    -DMPI_CXX_COMPILER=/usr/bin/mpicxx \
    -DMPI_Fortran_COMPILER=/usr/bin/mpif90 \
    -DCUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda-12.4 \
    -DNETCDF_INCLUDE_DIR=/usr/include \
    -DNETCDF_LIBRARIES=/usr/lib/x86_64-linux-gnu/libnetcdf.so \
    -DNETCDF_FORTRAN_LIBRARIES=/usr/lib/x86_64-linux-gnu/libnetcdff.so \
    -DHDF5_LIBRARIES=/usr/lib/x86_64-linux-gnu/libhdf5.so \
    -DHDF5_HL_LIBRARIES=/usr/lib/x86_64-linux-gnu/libhdf5_hl.so \
    -DUSE_BUNDLED_NETCDF=OFF \
    -DCMAKE_C_COMPILER=/usr/bin/gcc \
    -DCMAKE_CXX_COMPILER=/usr/bin/g++ \
    -DCMAKE_Fortran_COMPILER=/usr/bin/gfortran \
    -DCMAKE_CXX_FLAGS="-std=c++11" \
    -DCUDA_HOST_COMPILER=/usr/bin/g++ \
    -DCUDA_NVCC_FLAGS="-arch=sm_80;-std=c++11" \
    2>&1 | tee cmake.log

make -j32 install


```



# Apptainer (Sigularity) を導入しない場合
## Gaussian16
Gaussian16 では、スクラッチファイルの読み書きが非常に多く、この部分が律速となってしまうことがある。そのため、Gaussian16 を NFS 上に配置することはお勧めしない。
Gaussian16 自体は数 GB しかないため、各計算ノードのローカル SSD に配置した方が良い。そして、別の M.2 SSD をマウントしてスクラッチディレクトリとして利用するのが良い。もし可能であれば、スクラッチ用の M.2 SSD を RAID 0 で構成するとさらに高速になる。スクラッチディレクトリは、一時ファイルの保管場所なので、RAID 0 で運用して問題ない。
Gaussian16 のスクラッチディレクトリは、システムをインストールしている SSD とは分けた方が良い。SSD には書き込み上限回数があるため、定期的にスクラッチディレクトリの M.2 SSD のみ交換した方が良い。
ちなみに、NFS 上にスクラッチディレクトリを配置しておくと、ローカル M.2 SSD の場合と比べて書き込み速度が 10分の1程度にまで低下する。
ちなみに、chk ファイルは、書き込み頻度が他のスクラッチファイルに比べて少ないため、NFS 上に配置してもそれほど速度には影響しない。

# ユーザー管理




# テストジョブ
ここでは、Gaussian16、AlphaFold3 などのソフトウェアを slurm 経由で実行する際の slurm スクリプトを示す。

## g16 の slurm スクリプト

g16 の計算結果のファイルは、NSF 上に置くが、計算で生じるスクラッチファイルは各計算ノードのローカルディレクトリ（/scratch)に保存する。
slurm の実行ファイルに以下のように記述して設定を読み込ませる。
```shell
#!/bin/bash
#SBATCH --job-name="ultra_high_end_job"
#SBATCH --partition=normal
#SBATCH --cpus-per-task=16
#SBATCH --mem=16gb

echo "Running on node: $(hostname)"

alias ulimit=':'
export g16root=/opt
. $g16root/g16/bsd/g16.profile
export GAUSS_SCRDIR=/scratch
unalias ulimit

g16 ultra_high_end_job.com
```


## AlphaFold3 の slurm スクリプト

slurm の実行ファイルに以下のように記述して設定を読み込ませる。
```shell
#!/bin/bashutput_dir="${OUTPUT_DIR}" \
#SBATCH --job-name="super ultra hyper job"
#SBATCH --partition=normal
#SBATCH --gres=gpu:1
#SBATCH --exclusive

echo "Running on node: $(hostname)"

ALPHAFOLD3DIR="/opt/alphafold3/3.0.0"
HMMER3_BINDIR="/opt/hmmer/bin"
DB_DIR="/opt/alphafold3/3.0.0/public_databases"
MODEL_DIR="/opt/alphafold3/3.0.0/models"

export CUDA_VISIBLE_DEVICES=0
export XLA_FLAGS="--xla_gpu_cuda_data_dir=/usr/lib/cuda"
export TF_XLA_FLAGS="--tf_xla_cpu_global_jit"
source "${ALPHAFOLD3DIR}/.venv/bin/activate"
export XLA_PYTHON_CLIENT_MEM_FRACTION=0.8

WORK_DIR=$(pwd)
JSON_FILE="aatps11_Q.json"
BASE_NAME=$(basename "$JSON_FILE" .json)
OUTPUT_DIR="${WORK_DIR}/output/${BASE_NAME}"
LOG_FILE="af3_run.log"

mkdir -p "${OUTPUT_DIR}"

source ${ALPHAFOLD3DIR}/.venv/bin/activate

python3 ${ALPHAFOLD3DIR}/run_alphafold.py \
        --jackhmmer_binary_path="${HMMER3_BINDIR}/jackhmmer" \
        --nhmmer_binary_path="${HMMER3_BINDIR}/nhmmer" \
        --hmmalign_binary_path="${HMMER3_BINDIR}/hmmalign" \
        --hmmsearch_binary_path="${HMMER3_BINDIR}/hmmsearch" \
        --hmmbuild_binary_path="${HMMER3_BINDIR}/hmmbuild" \
        --db_dir="${DB_DIR}" \
        --model_dir="${MODEL_DIR}" \
        --json_path="${JSON_FILE}" \
        --output_dir="${OUTPUT_DIR}" \
        --buckets="256,512,768,1024,1280,1536,2048,2560,3072,3584,4096,4608,5120"
```

# バックサーバーの設定
ヘッドノードからバックアップに向けて rsync でデータを定期的に転送する。rsync で --link-dest オプションを使用すると、差分のみコピーされる。

以下のスクリプトをヘッドノードの `/opt/script/rsync_daily_backup.sh` に作成する。
```shell
#!/bin/bash

# バックアップ対象と保存先
SRC="/mnt/data/home/"
DEST_BASE="/mnt/backup/daily"
USER="odyssey"
HOST="horowitz"

# 日付（例: 20250424）
TODAY=$(date +%Y%m%d)
YESTERDAY=$(date -d "yesterday" +%Y%m%d)

# バックアップ先ディレクトリ
DEST_DIR="${DEST_BASE}/${TODAY}"
LINK_DEST_DIR="${DEST_BASE}/${YESTERDAY}"

# SSH経由でバックアップサーバーにディレクトリ作成
ssh ${USER}@${HOST} "mkdir -p ${DEST_DIR}"

# rsync 実行（--link-dest を使って前日のハードリンクを活用）
rsync -a -v \
    --link-dest="${LINK_DEST_DIR}" \
    "${SRC}" \
    "${USER}@${HOST}:${DEST_DIR}/"

# ログ出力（任意）
echo "[INFO] Backup completed: ${TODAY}" >> /var/log/rsync_daily_backup.log

```

続いて、以下のように cron を設定する。
```shell
crontab -e
```
```shell
0 3 * * * /opt/scripts/rsync_daily_backup.sh
```

実行権限を与える。
```shell
chmod +x /opt/scripts/rsync_daily_backup.sh
```