Red Hatの森若です。 今日はRHEL上でコンテナを使うときにちょっと不思議なアレについておはなしします。
Red Hat Universal Base Image
1年とすこし前、Red Hat Universal Base Images (以下UBI) というコンテナイメージが公開されました。 これはRHEL 7および RHEL 8の基本的なコンテナイメージと、さらにRHELの約1/3のrpmパッケージをEULA契約のみで無償で入手でき、さらに自由に利用・再配布できるというものです。
単に入手再配布が簡単というだけでなく、これをベースにアプリケーションのコンテナイメージを作成すると、Red Hatのコンテナ環境上(RHELまたはOpenShift)であればUBI部分もRed Hatからのサポート対象になります。 この仕組みが登場したことで「通常の契約ではRHELは再配布できない」という制約を部分的にゆるめ、OSSプロジェクトを含むISVがRHEL対応ソフトウェアのコンテナイメージを作成しやすくなりました。
UBIについて詳しくは、以下のページをごらんください。 developers.redhat.com
Red Hatのテクノロジーパートナーによる認定コンテナイメージについては、2020年2月にさらに制約をゆるめるアナウンスが行われ、kernel以外の全てのrpmパッケージを配布できるようになっています。こちらについては以下の記事をごらんください。 developers.redhat.com
RHELのベースイメージとしてのUBI
さて、UBI自体はRHELを契約していなくても利用できますが、UBIはRHELのベースイメージを兼任しています。ついさっきUBIで「RHELの約1/3のrpmパッケージ」が利用できると書いていたのに、UBIに含まれないRHEL一般のrpmパッケージはどうやって使うのでしょうか?
実は、RHEL上でUBIを利用すると 自動的に RHELのリポジトリを利用できるようになります。今回はその仕組みをちょっと見てみましょう。
RHELのサブスクリプション情報はどこにある?
RHELのユーザであれば、多くの方が subscription-manager を利用してシステムを登録し、システムとサブスクリプションとを対応づけたことがあるかと思います。この作業をすることで、 yumコマンドによるパッケージの導入などが利用できるようになります。(パブリッククラウド上のものに一部例外があります。)
普段あまり意識することはありませんが、これらのコマンドの裏側では複数の証明書を利用して個別のシステムを識別し、製品の種類や、いつからいつまで利用可能かなどを管理しています。
$ ls -l /etc/pki/product-default/ # 製品の種類 total 4 -rw-r--r--. 1 root root 2171 Mar 31 20:15 479.pem $ ls -l /etc/pki/entitlement/ # サブスクリプションの情報 total 144 -rw-r--r--. 1 root root 3247 Jun 8 15:24 5747300626421762999-key.pem -rw-r--r--. 1 root root 141049 Jun 8 15:24 5747300626421762999.pem $ ls -l /etc/pki/consumer/ # システムの識別情報 total 8 -rw-r-----. 1 root root 2228 Mar 9 17:35 cert.pem -rw-r-----. 1 root root 3247 Mar 9 17:35 key.pem
UBIへホストRHELのサブスクリプション情報を共有する
コンテナ内からRHELのリポジトリを利用できるよう、コンテナ実行時にホスト側のサブスクリプション情報を自動的にコンテナ内の(揮発する)ディレクトリへコピーしています。
具体的には、containers-common パッケージで提供される /usr/share/containers/mounts.conf が起点となります。このファイルにはホストの特定ディレクトリからコンテナの特定ディレクトリにファイルをコピーする設定を記述します。(ファイル名がまぎらわしいのですがbind mountではなく再帰的なコピーが行われます。)
$ cat /usr/share/containers/mounts.conf /usr/share/rhel/secrets:/run/secrets
ホストの/usr/share/rhel/secrets には、あらかじめサブスクリプション情報が含まれるディレクトリへのシンボリックリンクが作成されています。
$ ls -l /usr/share/rhel/secrets total 0 lrwxrwxrwx. 1 root root 20 Apr 21 03:17 etc-pki-entitlement -> /etc/pki/entitlement lrwxrwxrwx. 1 root root 28 Apr 21 03:17 redhat.repo -> /etc/yum.repos.d/redhat.repo lrwxrwxrwx. 1 root root 9 Apr 21 03:17 rhsm -> /etc/rhsm
コンテナ内のyumでは、これらの情報を参照することでRHELのリポジトリを使うことができます。
UBIでRHELリポジトリを利用する
サブスクリプションを登録したRHEL上で podman run -it bash ubi8
のようにして起動したコンテナの中で、利用できるリポジトリを確認してみましょう。RHELのリポジトリが利用できることがわかります。
# yum repolist Updating Subscription Management repositories. Unable to read consumer identity Subscription Manager is operating in container mode. repo id repo name rhel-8-for-x86_64-appstream-rpms Red Hat Enterprise Linux 8 for x86_64 - AppStream (RPMs) rhel-8-for-x86_64-baseos-rpms Red Hat Enterprise Linux 8 for x86_64 - BaseOS (RPMs) ubi-8-appstream Red Hat Universal Base Image 8 (RPMs) - AppStream ubi-8-baseos Red Hat Universal Base Image 8 (RPMs) - BaseOS ubi-8-codeready-builder Red Hat Universal Base Image 8 (RPMs) - CodeReady Builder
コンテナイメージの中に製品証明書が含まれていて適切なリポジトリが選択されるので、ホストのRHELとコンテナUBIのバージョンが異なっていても問題なく利用できます。
ためしてみよう
Red Hat Enterprise Linux 8を試せるラボを公開しています。以下リンクのラボではRHEL8のコンテナの基本的な利用をためせるほか、シナリオの中にないコマンドも自由に入力できます。以下のようなコマンドを試すとこの記事の理解が深まるかと思います。
ホスト側で # podman pull ubi8 # podman run -it ubi8 bash コンテナ内で # yum repolist # yum list coreutils # yum list postgresql # ls /run/secrets/