Red Hat Training

A Red Hat training course is available for RHEL 8

第13章 container-tools CLI の使用

13.1. podman

podman コマンド (Pod Manager の略) を使用すると、Kubernetes、Docker ランタイム、またはその他のコンテナーランタイムを使用せずに、コンテナーをスタンドアロンエンティティーとして実行できます。それは、docker コマンドの代わりに機能できるツールです。同じコマンドライン構文を実装しながら、さらにコンテナーの管理機能を追加します。podman 機能は次のとおりです。

  • docker インターフェースに基づいている - podman 構文は docker コマンドに似ているため、docker に精通している場合には、podman への移行が簡単です。
  • コンテナーおよびイメージの管理 - 以下を行うために、Docker 互換と OCI 互換の両方のコンテナーイメージを、podman とともに使用できます。

    • コンテナーの実行、停止、および再起動
    • コンテナーイメージの作成および管理(プッシュ、コミット、設定、ビルドなど)
  • Pod の管理 - 個々のコンテナーを実行する以外に、podman は、Pod にグループ化された一連のコンテナーを実行できます。Pod は、Kubernetes が管理するコンテナーの最小単位です。
  • ランタイムなしでの動作 - ランタイム環境は、コンテナーと連携するため、podman では使用されません。

以下は、知っておくべき Podman の実装機能です。

  • Podman、Buildah、および CRI-O のコンテナーエンジンはすべて、Docker の保存場所 (/var/lib/docker) をデフォルトで使用する代わりに、同じバックエンドストアディレクトリー /var/lib/containers を使用します。
  • Podman、Buildah、および CRI-O は、同じストレージディレクトリーを共有しているため、互いのコンテナーと対話することはできません。ただし、このツールはイメージを共有できます。また、この機能は、コンテナーを共有できます。
  • docker などの podman コマンドは、Dockerfile からコンテナーイメージを構築できます。
  • podman コマンドは、CRI-O サービスが利用できない場合に有益なトラブルシューティングツールです。
  • podman が対応していない dockerコマンドのオプションには、network、node、plugin (podman はプラグインをサポートしません)、rename (rm および create を使用して podman でコンテナーの名前を変更します)、secret、service、stack、swarm (podman は Docker Swarm をサポートしません) が含まれます。container および imageオプションは、podman で直接使用されるサブコマンドを実行するのに使用します。
  • プログラムで Podman と対話するには、ルートおよびルートレス環境の両方で動作する Podman v2.0 RESTful API を使用してください。詳細は、「コンテナーツール API の使用」 の章を参照してください。

13.1.1. podman コマンドの使用

docker コマンドを使用してコンテナーを操作するのに慣れている場合は、そのほとんどの機能とオプションが podman の機能とオプションに一致することが分かるでしょう。表 1 は、podman で使用できるコマンドの一覧です (podman -h を実行するとこの一覧を表示できます)。

表13.1 podman が対応するコマンド

podman コマンド

説明

podman コマンド

説明

attach

実行中のコンテナーに割り当てる

commit

変更したコンテナーから新規イメージを作成する

build

Dockerfile 命令を使用してイメージを構築する

create

コンテナーを作成するが、起動はしない

diff

コンテナーのファイルシステムの変更を検証する

exec

実行中のコンテナーでプロセスを実行する

export

コンテナーのファイルシステムの内容を tar アーカイブとしてエクスポートする

help, h

コマンド一覧、または特定のコマンドのヘルプを表示する

history

指定したイメージの履歴を表示する

images

ローカルストレージ内のイメージを一覧表示する

import

tarball をインポートして、ファイルシステムイメージを作成する

info

システム情報を表示する

inspect

コンテナーまたはイメージの設定を表示する

kill

1 つ以上の実行中のコンテナーに特定のシグナルを送信する

load

アーカイブからイメージを読み込む

login

コンテナーレジストリーにログインする

logout

コンテナレジストリーからログアウトする

logs

コンテナーのログを取得する

mount

作業中のコンテナーの root ファイルシステムをマウントする

pause

1 つ以上のコンテナー内の全プロセスを一時停止する

ps

コンテナーの一覧を表示する

port

コンテナーのポートマッピングまたは特定のマッピングを一覧表示する

pull

レジストリーからイメージを取得する

push

指定した宛先にイメージをプッシュする

restart

1 つ以上のコンテナーを再起動する

rm

ホストから 1 つ以上のコンテナーを削除する。実行している場合は、-f を追加する

rmi

ローカルストレージから 1 つ以上のイメージを削除する

run

新しいコンテナーでコマンドを実行する

save

イメージをアーカイブに保存する

search

イメージのレジストリーを検索する

start

1 つ以上のコンテナーを起動する

stats

1 つ以上のコンテナーの CPU、メモリー、ネットワーク I/O、ブロック I/O、および PID の割合を表示する

stop

1 つ以上のコンテナーを停止する

tag

ローカルイメージに名前を追加する

top

コンテナーの実行中のプロセスを表示する

umount, unmount

作業コンテナーのルートファイルシステムをアンマウントする

unpause

1 つ以上のコンテナーでプロセスの一時停止を解除する

version

podman のバージョン情報を表示する

wait

1 つ以上のコンテナーをブロックする

  

13.1.2. crun コンテナーランタイムの使用

crun は、C 言語で書かれた高速および低メモリーフットプリントの OCI Container Runtime で、crun バイナリーはrunc バイナリーと比べると最大 1/50 のサイズで、 2 倍の速さとなります。crun を使用して、コンテナーの実行時に最小限のプロセス数を設定することもできます。crun ランタイムは OCI フックもサポートしています。

crun の追加機能には、以下が含まれます。

  • ルートレスコンテナーのグループによるファイルの共有
  • OCI フックの標準出力および標準エラーの制御
  • cgroup v2 での古いバージョンの systemd の実行
  • 他のプログラムによって使用される C ライブラリー
  • 拡張性
  • 移植性

13.1.3. コンテナーランタイムとしての crun の一時使用

podman run コマンドに --runtime オプションを指定して使用して、コンテナーのランタイムを変更できます。

前提条件

  • Podman ツールがインストールされている。

    #  yum module install -y container-tools

手順

  1. registry.access.redhat.com/ubi8/ubi コンテナーイメージをプルします。

    $ podman pull registry.access.redhat.com/ubi8/ubi
  2. --runtime オプションを使用してコンテナーランタイムを変更します。

    $ podman run --name=myubi -dt --runtime=crun ubi8 bash
    e4654eb4df12ac031f1d0f2657dc4ae6ff8eb0085bf114623b66cc664072e69b
  3. 必要に応じて、すべてのイメージを一覧表示します。

    podman ps -a
    CONTAINER ID  IMAGE                                   COMMAND  CREATED        STATUS            PORTS   NAMES
    e4654eb4df12  registry.access.redhat.com/ubi8:latest  bash     4 seconds ago  Up 4 seconds ago          myubi

検証手順

  • OCI ランタイムが myubi コンテナーで crun に設定されていることを確認します。

    $ podman inspect myubi --format "{{.OCIRuntime}}"
    crun

13.1.4. コンテナーランタイムとしての crun の永続使用

コンテナーランタイムおよびそのオプションを containers.conf 設定ファイルで設定できます。

手順

  1. containers.conf ファイルで、ランタイムを runc から crun に変更します。

    # vim /etc/containers/containers.conf
    [engine]
    runtime = "crun"
  2. myubi という名前のコンテナーを実行します。

    # podman run --name=myubi -dt ubi8 bash

検証手順

  • OCI ランタイムが myubi コンテナーで crun に設定されていることを確認します。

    # podman inspect myubi --format "{{.OCIRuntime}}"
    crun

13.1.5. コンテナーの SELinux ポリシーの作成

コンテナーの SELinux ポリシーを生成するには、UDICA ツールを使用します。詳細は「udica の SELinux ポリシージェネレーターの概要」を参照してください。

13.1.6. MPI での Podman の使用

Podman を Open MPI (Message Passing Interface) と共に使用して、HPC (High Performance Computing) 環境でコンテナーを実行できます。

この例は、Open MPI から取得した ring.c プログラムを基にしています。この例では、全プロセスで値はリングのように渡されます。メッセージがランク 0 を渡すと必ず、値は 1 つ下がります。各プロセスが 0 メッセージを受信すると、次のプロセスに渡して終了します。0 を最初に渡すと、すべてのプロセスが 0 メッセージを取得し、通常通りに終了できます。

手順

  1. Open MPI をインストールします。

    $ sudo yum install openmpi
  2. 環境モジュールをアクティベートするには、以下を入力します。

    $ . /etc/profile.d/modules.sh
  3. mpi/openmpi-x86_64 モジュールを読み込みます。

    $ module load mpi/openmpi-x86_64

    必要に応じて、mpi/openmpi-x86_64 モジュールを自動的に読み込むには、以下の行を .bashrc ファイルに追加します。

    $ echo "module load mpi/openmpi-x86_64" >> .bashrc
  4. mpirunpodman を統合するには、以下の定義でコンテナーを作成します。

    $ cat Containerfile
    FROM registry.access.redhat.com/ubi8/ubi
    
    RUN yum -y install openmpi-devel wget && \
        yum clean all
    
    RUN wget https://raw.githubusercontent.com/open-mpi/ompi/master/test/simple/ring.c && \
        /usr/lib64/openmpi/bin/mpicc ring.c -o /home/ring && \
        rm -f ring.c
  5. コンテナーをビルドします。

    $ podman build --tag=mpi-ring .
  6. コンテナーを起動します。このコマンドは、CPU が 4 つあるシステムではコンテナーを 4 つ起動します。

    $ mpirun \
       --mca orte_tmpdir_base /tmp/podman-mpirun \
       podman run --env-host \
         -v /tmp/podman-mpirun:/tmp/podman-mpirun \
         --userns=keep-id \
         --net=host --pid=host --ipc=host \
         mpi-ring /home/ring
    Rank 2 has cleared MPI_Init
    Rank 2 has completed ring
    Rank 2 has completed MPI_Barrier
    Rank 3 has cleared MPI_Init
    Rank 3 has completed ring
    Rank 3 has completed MPI_Barrier
    Rank 1 has cleared MPI_Init
    Rank 1 has completed ring
    Rank 1 has completed MPI_Barrier
    Rank 0 has cleared MPI_Init
    Rank 0 has completed ring
    Rank 0 has completed MPI_Barrier

    これにより、mpirun は 4 つの Podman コンテナーを開始し、コンテナーごとに ring バイナリーのインスタンスを 1 台実行します。4 つプロセスはすべて、MPI 経由で相互に通信しています。

    以下の mpirun オプションは、コンテナーの起動に使用します。

    • --mca orte_tmpdir_base /tmp/podman-mpirun 行は、Open MPI に対し、/tmp ではなく、/tmp/podman-mpirun にその一時ファイルをすべて作成するように指示します。複数のノードを使用する場合には、別のノードではこのディレクトリーの名前は異なります。このような場合には、/tmp ディレクトリー全体をコンテナーにマウントする必要があり、操作がより複雑です。

    mpirun コマンドは、podman コマンドを起動するコマンドを指定します。以下の podman オプションは、コンテナーの起動に使用されます。

    • run コマンドはコンテナーを実行します。
    • --env-host オプションは、ホストからコンテナーにすべての環境変数をコピーします。
    • -v /tmp/podman-mpirun:/tmp/podman-mpirun は、Open MPI が一時ディレクトリーとファイルをコンテナーで利用できるように、Podman にディレクトリーのマウントを指示します。
    • --userns=keep-id 行を使用すると、コンテナー内外でのユーザー ID マッピングを保証します。
    • --net=host --pid=host --ipc=host 行では、同じネットワーク、PID、および IPC 名前空間が設定されます。
    • mpi-ring はコンテナーの名前です。
    • /home/ring は、コンテナー内の MPI プログラムです。

詳細は、Adwell Reber による 「Podman in HPC environments」 の記事を参照してください。

13.1.7. コンテナーチェックポイントの作成および復元

CRIU (Checkpoint/Restore In Userspace) は、実行中のコンテナーまたは個々のアプリケーションでチェックポイントを設定して、その状態をディスクに保存するソフトウェアです。保存したデータを使用して、再起動後に、チェックポイントの時点にコンテナーを復元できます。

13.1.7.1. ローカルでのコンテナーチェックポイントの作成および復元

以下の例は、要求ごとにインクリメントする整数を 1 つ返す Python ベースの Web サーバーをベースとしています。

手順

  1. Python ベースのサーバーを作成します。

    # cat counter.py
    #!/usr/bin/python3
    
    import http.server
    
    counter = 0
    
    class handler(http.server.BaseHTTPRequestHandler):
        def do_GET(s):
            global counter
               s.send_response(200)
               s.send_header('Content-type', 'text/html')
               s.end_headers()
               s.wfile.write(b'%d\n' % counter)
               counter += 1
    
    
    server = http.server.HTTPServer(('', 8088), handler)
    server.serve_forever()
  2. 以下の定義でコンテナーを作成します。

    # cat Containerfile
    FROM registry.access.redhat.com/ubi8/ubi
    
    COPY counter.py /home/counter.py
    
    RUN useradd -ms /bin/bash counter
    
    RUN yum -y install python3 && chmod 755 /home/counter.py
    
    USER counter
    ENTRYPOINT /home/counter.py

    コンテナーは Universal Base Image (UBI 8) をベースとしており、Python ベースのサーバーを使用します。

  3. コンテナーをビルドします。

    # podman build . --tag counter

    counter.py ファイルおよび Containerfile ファイルは、コンテナービルドプロセス (podman build) の入力情報です。ビルドされたイメージはローカルに保存され、counter でタグ付けされます。

  4. root でコンテナーを起動します。

    # podman run --name criu-test --detach counter
  5. 実行中のコンテナーの一覧を表示するには、次のコマンドを実行します。

    # podman ps
    CONTAINER ID  IMAGE  COMMAND  CREATED   STATUS  PORTS NAMES
    e4f82fd84d48  localhost/counter:latest  5 seconds ago  Up 4 seconds ago  criu-test
  6. コンテナーの IP アドレスを表示します。

    # podman inspect criu-test --format "{{.NetworkSettings.IPAddress}}"
    10.88.0.247
  7. 要求をコンテナーに送信します。

    # curl 10.88.0.247:8080
    0
    # curl 10.88.0.247:8080
    1
  8. コンテナーのチェックポイントを作成します。

    # podman container checkpoint criu-test
  9. システムを再起動します。
  10. コンテナーを復元します。

    # podman container restore --keep criu-test
  11. 要求をコンテナーに送信します。

    # curl 10.88.0.247:8080
    2
    # curl 10.88.0.247:8080
    3
    # curl 10.88.0.247:8080
    4

    結果は 0 で開始あれるのではなく、以前の値で継続されます。

これにより、再起動後に完全なコンテナーの状態を簡単に保存できます。

詳細は、Adrian Reber による「Adding checkpoint/restore support to Podman」 の記事を参照してください。

13.1.7.2. コンテナー復元を使用した起動時間の短縮

コンテナーマイグレーションを使用して、初期化に特定の時間を必要とするコンテナーの起動時間を短縮できます。チェックポイントを使用すると、同じホストまたは別のホストでコンテナーを複数回復元できます。この例は、「コンテナーチェックポイントのローカルでの作成および復元」セクションのコンテナーを基にしています。

手順

  1. コンテナーのチェックポイントを作成し、チェックポイントイメージを tar.gz ファイルにエクスポートします。

    # podman container checkpoint criu-test --export /tmp/chkpt.tar.gz
  2. tar.gz ファイルからコンテナーを復元します。

    # podman container restore --import /tmp/chkpt.tar.gz --name counter1
    # podman container restore --import /tmp/chkpt.tar.gz --name counter2
    # podman container restore --import /tmp/chkpt.tar.gz --name counter3

    --name (-n) オプションは、エクスポートしたチェックポイントを基に復元したコンテナーに新しい名前を指定します。

  3. 各コンテナーの ID と名前を表示します。

    # podman ps -a --format "{{.ID}} {{.Names}}"
    a8b2e50d463c counter3
    faabc5c27362 counter2
    2ce648af11e5 counter1
  4. 各コンテナーの IP アドレスを表示します。

    #️ podman inspect counter1 --format "{{.NetworkSettings.IPAddress}}"
    10.88.0.248
    
    #️ podman inspect counter2 --format "{{.NetworkSettings.IPAddress}}"
    10.88.0.249
    
    #️ podman inspect counter3 --format "{{.NetworkSettings.IPAddress}}"
    10.88.0.250
  5. 各コンテナーに要求を送信します。

    #️ curl 10.88.0.248:8080
    4
    #️ curl 10.88.0.249:8080
    4
    #️ curl 10.88.0.250:8080
    4

    同じチェックポイントから異なるコンテナーを使用して復元しているので、結果は、どの場合も 4 になる点に注意してください。

この方法では、最初にチェックポイントを作成したコンテナーのステートフルレプリカを迅速に起動できます。

詳細は、Adrian Reber による「Container migration with Podman on RHEL」を参照してください。

13.1.7.3. システム間のコンテナーの移行

この手順は、コンテナーで実行しているアプリケーションの状態を失うことなく、実行中のコンテナーを別のシステムに移行する方法を示しています。この例は、counter とタグ付けされた 「コンテナーのチェックポイントの作成および復元のコンテナー」セクションのコンテナーを基にしています。

前提条件

以下の手順は、コンテナーがレジストリーにプッシュされている場合には不要です。理由は、Podman がローカルでコンテナーを利用できない場合に自動的にコンテナーをレジストリーからダウンロードするためです。この例ではレジストリーを使用していません。以前に構築およびタグ付けされたコンテナーをローカルにエクスポートし (「コンテナーチェックポイントのローカルでの作成および復元」セクションを参照)、この移行先システムにコンテナーをインポートする必要があります。

  • 以前にビルドしたコンテナーをエクスポートします。

    # podman save --output counter.tar counter
  • エクスポートしたコンテナーイメージを移行先システム (other_host) にコピーします。

    # scp counter.tar other_host:
  • エクスポートしたコンテナーを移行先システムにインポートします。

    # ssh other_host podman load --input counter.tar

このコンテナーの移行先のシステムには、ローカルコンテナーストレージに保存されているのと同じコンテナーイメージがあります。

手順

  1. root でコンテナーを起動します。

    # podman run --name criu-test --detach counter
  2. コンテナーの IP アドレスを表示します。

    # podman inspect criu-test --format "{{.NetworkSettings.IPAddress}}"
    10.88.0.247
  3. 要求をコンテナーに送信します。

    # curl 10.88.0.247:8080
    0
    # curl 10.88.0.247:8080
    1
  4. コンテナーのチェックポイントを作成し、チェックポイントイメージを tar.gz ファイルにエクスポートします。

    # podman container checkpoint criu-test --export /tmp/chkpt.tar.gz
  5. チェックポイントアーカイブを移行先ホストにコピーします。

    # scp /tmp/chkpt.tar.gz other_host:/tmp/
  6. 移行先ホスト (other_host) のチェックポイントを復元します。

    # podman container restore --import /tmp/chkpt.tar.gz
  7. 宛先ホスト (other_host) のコンテナーに要求を送信します。

    # curl 10.88.0.247:8080
    2

これで、ステートフルコンテナーが、状態を失うことなく、別のシステムへ移行されました。

詳細は、Adrian Reber による「Container migration with Podman on RHEL」を参照してください。