Red Hatでソリューションアーキテクトをしている小島です。
本記事は赤帽エンジニアAdvent Calendar 2018の14日目です。
RHEL 8/Fedora 28ではModularityという概念が導入され、アプリケーションのライフサイクルを設定するための新しい仕組みが追加されました。本記事ではModularityの概要や利用方法について紹介していきます。
Modularityとは
Modularityは、RHELやFedoraといったOSからアプリケーションのライフサイクルをある程度独立させるための仕組みです。Modularityを利用しているイメージは下図のようになります。
この図では「Fedora AppStream」という名前のリポジトリが、nodejs, calc unstable, django
と名付けられたModuleを提供しています。Moduleは小さなRPMリポジトリであり、それぞれの名前に関連したRPMパッケージ郡から構成されています。また、nodejs-{6,8,10}
やunstable
といったバージョンに関する情報によってModuleを分けることができます。これをStreamと定義していて、StreamごとにFedora 28やFedora 29といった異なるリリースのOSで利用できるようなAPI/ABIの互換性を担保するようにModuleが作られます(作られるべきとしています)。
一方、「Base」という名前のリポジトリは、OSのリリースに紐付いたRPMパッケージを提供します。「Base」リポジトリの利用は従来と変わる所はありません。こうした仕組みにより、アプリケーションをある程度OSと独立して利用できるようになります。例えば、Fedoraのように半年ごとにリリースされるOS上では、リリース間隔より長いサポート期間を持つ古めのアプリケーションを利用し、RHELのように長期間のサポートを提供するOSの上では、独自に定義されたサポート期間のもとに新しめのアプリケーションを利用できるようになります。
RHEL 8のリポジトリ
Fedora 28をベースとして開発されたRHEL 8もModularityという概念を取り入れています。RHEL 8の主なリポジトリは、「BaseOS」と「AppStream」の2つです。「BaseOS」がRHEL7までのベースリポジトリに該当します。「AppStream」ではいくつかのアプリケーションをModuleとして提供している他に、従来のRHELのSoftware CollectionsやExtrasリポジトリで提供していたアプリケーションもいくつか提供しています。これらのリポジトリが提供するModuleやパッケージ名の一覧は、下記を参照してください。
Software Collectionsとの違い
Software Collectionsも同様に、利用者はOS標準のアプリケーションとは異なるバージョンのアプリケーションを利用できます。ただし、Software Collectionsのアプリケーションは、OS標準のアプリケーションとは別に、専用のPATHにインストールするようになっています。そのため、異なるバージョンのアプリケーションを1つのシステムにインストールできます。
Modularityの場合はSoftware Collectionsと異なり、基本的には複数のバージョンのアプリケーションをインストールできないようになっています。アプリケーションの並列な導入という点ではSoftware Collectionsが上ですが、Software Collectionsの特徴に起因した特別な変更*1をしなくていいといった利点も産まれます。Modularityを利用していて、1つのシステムに複数のバージョンのアプリケーションを導入したい場合はコンテナ環境の利用を推奨します。
なお、現時点では、Fedora ProjectによるSoftware Collectionsのサポートは提供されていません。そのため、Red Hat系のLinuxディストリビューションを今後利用していく場合、Software CollectionsだけでなくModularityにも慣れていくことを推奨します。
Moduleの利用方法
RHEL 8を例にします。最初にRed Hat Developer Programを利用してRHEL 8のインストールイメージを取得し、RHEL 8をローカルマシンにインストールします。インストール後は、RHEL 8上で次のコマンドを実行してRed Hatのカスタマーポータルへにシステムを登録し、必要なリポジトリの利用を有効化します。
# subscription-manager register --username <username> --password <password> --auto-attach # subscription-manager repos --disable="*" # subscription-manager repos --enable=rhel-8-for-x86_64-baseos-beta-rpms --enable=rhel-8-for-x86_64-appstream-beta-rpms
これでModuleの利用準備が整いました。どのModuleが利用できるかはdnf module list [module_name]
*2で確認できます。
# dnf module list postgresql Red Hat Enterprise Linux 8 for x86_64 - AppStream Beta (RPMs) Name Stream Profiles Summary postgresql 10 [d] client, default [d] postgresql module postgresql 9.6 client, default [d] postgresql module Hint: [d]efault, [e]nabled, [x]disabled, [i]nstalled
この例では「AppStream」リポジトリで提供しているPostgreSQLのModule一覧を表示しています。ProfileはPostgreSQLのModuleに関するRPMパッケージ郡に付けられた名前であり、client
とdefault
の2つがあることを意味しています。client
とdefault
がどのRPMパッケージを含んでいるかについては、DNFリポジトリのメタデータ(repodata
ディレクトリにあるxxx-modules.yaml.gz
)で、次のように記載されています。
profiles: client: rpms: - postgresql default: rpms: - postgresql-server
また、[d]efault, [e]nabled, [x]disabled, [i]nstalled
との表示がありますが、それぞれ次の意味を持ちます。
[d]efault
:
Moduleをインストールする時に利用されるStreamとProfileのデフォルト値。これらはDNFリポジトリのメタデータで定義しています。
[e]nabled
:
ModuleのStreamにあるRPMパッケージ郡が、dnfでインストールできる(RPMパッケージの依存関係を確認できる)ようになっている状態です。
[x]disabled
:
ModuleのStreamにあるRPMパッケージ郡が、dnfでインストールできない(RPMパッケージの依存関係を確認できない)ようになっている状態です。
[i]nstalled
:
Moduleがインストールされた場合に表示されます。例えばclient
Profileをインストールすると、Profileの箇所にclient [i]
と表示されるようになります。
Streamのenabled
とdisabled
は、Fedoraのメジャーリリースのアップグレード(28 -> 29など)などの需要に基づいて産まれたものです。アップグレードの際に、今まで使えていたStreamが廃止されて新しいStreamを利用しなくてはいけない場合、またはその逆で、RPMパッケージの競合状態を防ぐために特定のStreamにあるRPMパッケージ郡を利用しないようにする場合に使われます。なお、enabled
とdisabled
はあくまでもDNFリポジトリでの依存関係の確認の可否に関わるものであり、システムの既存のRPMパッケージに影響を及ぼすものではありません。
では、PostgreSQLのModuleをインストールしてみましょう。dnf module install <module_spec>
でModuleをインストールできます。<module_spec>
では、module:stream/profile
を指定しますが、StreamとProfileは省略できます。その場合は[d]efault
で指定されている値が利用されます。この時Streamがdisabled
状態であれば、自動的にenabled
状態に変更されます。
# dnf -y module install postgresql:10/client Dependencies resolved. ============================================================================================================================================================================ Package Arch Version Repository Size ============================================================================================================================================================================ Installing group/module packages: postgresql x86_64 10.5-1.el8+1546+27ad5f8e rhel-8-for-x86_64-appstream-beta-rpms 1.5 M Installing dependencies: libpq x86_64 10.5-1.el8 rhel-8-for-x86_64-appstream-beta-rpms 188 k Enabling module streams: postgresql 10 Transaction Summary ============================================================================================================================================================================ Install 2 Packages Total download size: 1.7 M Installed size: 6.2 M Downloading Packages: (1/2): libpq-10.5-1.el8.x86_64.rpm 154 kB/s | 188 kB 00:01 (2/2): postgresql-10.5-1.el8+1546+27ad5f8e.x86_64.rpm 1.1 MB/s | 1.5 MB 00:01 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Total 1.3 MB/s | 1.7 MB 00:01 ...<snip>... Installed: postgresql-10.5-1.el8+1546+27ad5f8e.x86_64 libpq-10.5-1.el8.x86_64 Complete!
この後、インストールされたPostgreSQL Moduleの状態を確認してみます。
# dnf module list postgresql Red Hat Enterprise Linux 8 for x86_64 - AppStream Beta (RPMs) Name Stream Profiles Summary postgresql 10 [d][e] client [i], default [d] postgresql module postgresql 9.6 client, default [d] postgresql module Hint: [d]efault, [e]nabled, [x]disabled, [i]nstalled
PostgreSQL Moduleの10
Streamがenabled
状態になっていて、client
Profileがインストールされた状態になっていることを確認できます。ちなみに、この状態でPostgreSQL Moduleの9.6
Streamをインストールする場合、9.6
Streamへのダウングレードと切り替えを自動的に実行してくれます。
# dnf -y module install postgresql:9.6/client Dependencies resolved. ============================================================================================================================================================================ Package Arch Version Repository Size ============================================================================================================================================================================ Downgrading: postgresql x86_64 9.6.10-1.el8+1547+210b7007 rhel-8-for-x86_64-appstream-beta-rpms 1.4 M Switching module streams: postgresql 10 -> 9.6 Transaction Summary ============================================================================================================================================================================ Downgrade 1 Package Total download size: 1.4 M Downloading Packages: postgresql-9.6.10-1.el8+1547+210b7007.x86_64.rpm 433 kB/s | 1.4 MB 00:03 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Total 432 kB/s | 1.4 MB 00:03 ...<snip>... Downgraded: postgresql-9.6.10-1.el8+1547+210b7007.x86_64 Complete!
不要になったModuleを削除する場合は、dnf module remove <module_spec>
を実行します。Moduleを削除するときも、DNFリポジトリのメタデータを参照して削除対象のModuleを決定します。なお、Module削除の場合は、自動的にStreamがdisabled
状態に変更されることはありません。
# dnf -y module remove postgresql:9.6/client Dependencies resolved. ============================================================================================================================================================================ Package Arch Version Repository Size ============================================================================================================================================================================ Removing: postgresql x86_64 9.6.10-1.el8+1547+210b7007 @rhel-8-for-x86_64-appstream-beta-rpms 5.1 M Removing unused dependencies: libpq x86_64 10.5-1.el8 @rhel-8-for-x86_64-appstream-beta-rpms 702 k Removing module profiles: postgresql/client Transaction Summary ============================================================================================================================================================================ Remove 2 Packages Freed space: 5.8 M ...<snip>... Removed: postgresql-9.6.10-1.el8+1547+210b7007.x86_64 libpq-10.5-1.el8.x86_64 Complete! # dnf module list postgresql Red Hat Enterprise Linux 8 for x86_64 - AppStream Beta (RPMs) Name Stream Profiles Summary postgresql 10 [d] client, default [d] postgresql module postgresql 9.6 [e] client, default [d] postgresql module Hint: [d]efault, [e]nabled, [x]disabled, [i]nstalled
Moduleの配信方法
RHEL 8のデフォルトに目当てのModuleが無い場合、既存のRPMパッケージを指定してModule用のリポジトリを作ることができます。その際は、指定したRPMパッケージをModuleとして配信するためのメタデータを、RPMリポジトリ内に作成・追加する必要があります。この手順をzsh
RPMパッケージを例にして見ていきましょう。
最初にzsh
パッケージを適当なディレクトリに保存します。zsh
パッケージはRHEL 8のインストールイメージから取得してもいいですし、次の例のようにdnf download
でRed Hatのカスタマーポータルのリポジトリからダウンロードすることもできます。
# mkdir /tmp/moduledir; cd /tmp/moduledir/ # dnf download zsh
次にzsh
Module用のメタデータをYAML形式のファイルで作成します。これはmodulemdファイルと定義されています。簡単なメタデータのサンプルが下記になります。最初のdocument: modulemd
とversion: 2
の2行で、modulemdファイルであることを宣言します。そしてModule名、Stream名、アーキテクチャ名、実行時の要件(下記の例ではRHEL 8を指定)、Profileの名前(最低限default
という名前のProfileが1つ必要)、default
Profileに紐付けるRPMパッケージの名前zsh
を記載して保存します。
# cat <<EOF > /tmp/moduledir/zsh-modules.yaml --- document: modulemd version: 2 data: name: zsh # <- Module name stream: latest # <- Stream name arch: x86_64 summary: zsh package dependencies: - requires: platform: [el8] # <- Run on RHEL 8 profiles: default: # <- Profile default name description: zsh package rpms: - zsh # <- Binary RPM package name EOF
こうして作成したzsh-modules.yaml
をRPMリポジトリのメタデータに追加します。まずはローカルにRPMリポジトリを作るためにcreaterepo_c <path_of_repository>
を実行し、zsh
RPMパッケージを保存したディレクトリ内にメタデータ一式(repodata
ディレクトリ)を作成します。続いて、/tmp/moduledir/repodata/
内にあるメタデータに先程作成したzsh-modules.yaml
を追加するために、modifyrepo_c --mdtype=modules <modulemd_file> <repodata_path_of_directory>
を実行します。これによってrepodata
ディレクトリ内に、xxx-zsh-modules.yaml.gz
という名前のgzファイルが自動的に作成されます。最後に作成したローカルリポジトリを利用するための設定ファイルを作成します。リポジトリを利用するための設定ファイルの保存場所はYUMと同様に、/etc/yum.repos.d/
となります。
# dnf -y install createrepo_c # createrepo_c /tmp/moduledir # modifyrepo_c --mdtype=modules zsh-modules.yaml /tmp/moduledir/repodata/ # ls /tmp/moduledir/repodata/ xxx-zsh-modules.yaml.gz ...<snip>... # cat <<EOF > /etc/yum.repos.d/local.repo [local] name=local-repo baseurl=file:///tmp/moduledir/ gpgcheck=0 enabled=1 EOF
これでローカルリポジトリにあるModuleを利用するための準備が完了しました。あとは先程紹介したのと同様の手順で、Moduleの一覧出力やインストールなどができるようになります。
# dnf module list zsh local-repo Name Stream Profiles Summary zsh latest default zsh package Hint: [d]efault, [e]nabled, [x]disabled, [i]nstalled # dnf -y module install zsh:latest/default Dependencies resolved. ============================================================================================================================================================================ Package Arch Version Repository Size ============================================================================================================================================================================ Installing group/module packages: zsh x86_64 5.5.1-4.el8 local 2.9 M Installing module profiles: zsh/default Enabling module streams: zsh latest Transaction Summary ============================================================================================================================================================================ Install 1 Package Total size: 2.9 M ...<snip>... Installed: zsh-5.5.1-4.el8.x86_64 Complete! # dnf module list zsh local-repo Name Stream Profiles Summary zsh latest [e] default [i] zsh package ...<snip>...
ちなみに、Streamのデフォルト値を指定したい場合、先程作成したzsh-modules.yaml
に下記の行を追加して、DNFリポジトリのメタデータを修正します。document: modulemd-defaults
を追加してzsh
Moduleのlatest
Streamを指定することで、latest
Streamがデフォルト値として使われるようになります。メタデータ修正後、modifyrepo_c
でModuleに関する既存のメタデータの削除と、新規メタデータの追加を行います。
# cat <<EOF >> /tmp/moduledir/zsh-modules.yaml ... --- document: modulemd-defaults version: 1 data: module: zsh stream: latest profiles: latest: [default] EOF # modifyrepo_c --remove=modules /tmp/moduledir/repodata/ # modifyrepo_c --mdtype=modules zsh-modules /tmp/moduledir/repodata/
そして、DNFリポジトリのキャッシュを削除してzsh
Moduleの情報を見てみると、デフォルト値が指定されていることが分かります。これでModuleの利用者が特にStream/Profileの値を指定しなくても、zsh
ModuleのデフォルトのStream/Profileをインストール・削除できるようになります。
# dnf clean all # dnf module list zsh local-repo Name Stream Profiles Summary zsh latest [d] default [d] zsh package ...<snip>...
ここで取り上げた例以外にも、modulemdファイルには様々な設定項目があります。これらの詳細を知りたい場合は、次のドキュメントも参考にしてください。