OpenShiftのマニュアルには、dockerコマンドと共に podmanコマンド が利用できるとされている。OpenShift を触る様になるまで、Podmanの存在を知らなかったので、調べたことをメモとして残しておく。
Podman とは?
このpodmanという名前は、コンテナだけでなく、Kubernetesのポッドの形態でコンテナを起動できることを期待させてくれる。プロジェクトのウェブページから特徴を拾うと次の7つがある。そして、プロジェクトのページの前面には出ていないが、Podmanには、ポッドのマニフェストを生成したり、コンテナを起動する機能もある。Podmanロゴは、可愛いもの路線で、複数のコンテナが内部で動くポッドを実行できることを感じさてくれる。
Podman の特徴
(1) Docker互換のコマンドラインフロントエンドを提供
最も簡単にいうと、alias docker = podman
ということだ。つまり、docker コマンドの代わりに、podmanで代用できることを意味する。
(2) オープンソースプロジェクトであり、GitHub でコードが公開されている
このプロジェクトは Red Hat によって運営されており、Fedora、Red Hat Enterprise Linuxの最新リリースバージョン、および Ubuntuに対して、ビルドをテストしている。
- ホームページ https://podman.io/
- GitHub https://github.com/containers/libpod
podmanのバンドル状況について、調べたところ、2019年9月現在で、次の表の状況がわかった。問題なく動作するのは Fedora 30 だけで、RHEL8はバージョンが古くルートレスモードが実装されていないなどの問題があった。RHEL7/CentOS7 でも動作するとされているが、ルートレスで動作させることができなかった。
Distribution | Status | Podman version | Remarks |
---|---|---|---|
Fedora 30 | GA | 1.5.1 | sudo なしの rootlessモードで実行可能 |
RHEL 8.0 | GA | 1.0.5 | rootlessモード未実装 |
RHEL 7.6 | GA | 1.4.4 | sudo podman で実行 |
CentOS 7.6 | GA | 1.4.4 | 同上 |
Ubuntu 18.04 | GA | 1.5.1 | sudo なしの rootlessモードで実行可能 |
このことから、podman は Red Hat がオープンソース・プロジェクトとして、発展途上であると見なされ、dockerコマンドを置き換えるまでに熟成されるには、もう少し時間が必要と考えられる。
(3) OCIに準拠するコンテナイメージの開発、管理、および、コンテナとして実行
Docker Hubに登録されたコンテナを実行すること、podmanでビルドして、レジストリに登録したイメージを、dockerコマンドで実行することも可能であり、互換性に問題はないと見られる。
(4) デーモンレスのコンテナエンジン
podman は、Dockerデーモンの様な root で動作するデーモンを必要としない。つまり、podman コマンドだけで、デーモンの助けを必要とせずにコンテナを実行できる。
(5) コンテナはルートレスモードで実行可能
ルートレスのコンテナは、それらを起動したユーザーよりも多くの特権を持つことはない。もちろん、root権限で実行されるDockerデーモンでも、コンテナが起動したユーザー以上の権限を持つことが無い様に考慮されているが、もしも、悪意のあるプログラムに隔離が突破された場合のリスクは大きい。その点で、ルートレスは明白なため安心感がある。
次は、podman で実行した場合のコンテナホスト上のプロセスのリストで、この中でコンテナのプロセスは、PID 21710 とその子プロセスである。 これらのプロセスの USER は、rootではなく、vagrant という一般ユーザーになっている。
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
vagrant 21729 0.0 0.1 4336 2760 pts/0 S 13:21 0:00 /usr/bin/slirp4netns --api-socket /run/user/1000/libpod/tmp/35de2a668cad2
vagrant 21710 0.0 0.0 80348 2012 ? Ssl 13:21 0:00 /usr/libexec/podman/conmon --api-version 1 -c 35de2a668cad28fa366c233a641
vagrant 21721 0.0 0.1 11688 2624 ? Ss 13:21 0:00 \_ bash -c while true; do /usr/bin/nc -l -p 3306 < /srv/hello.txt; done
vagrant 21740 0.0 0.1 43988 3364 ? S 13:21 0:00 \_ /usr/bin/nc -l -p 3306
vagrant 21707 0.0 0.1 5756 3208 ? Ss 13:21 0:00 /usr/bin/fuse-overlayfs -o lowerdir=/home/vagrant/.local/share/containers
vagrant 21478 0.0 1.8 80508 37540 ? S 13:19 0:00 podman
対比のために、Docker で同じコンテナを実行した場合のコンテナホスト上のプロセスのリストである。コンテナは PID番号 5339 のプロセスとその子プロセスですが、USER は全て root になっている。
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 5339 0.0 1.8 880444 37108 ? Ssl 13:46 0:00 /usr/bin/containerd
root 7684 0.0 0.2 10744 4724 ? Sl 13:49 0:00 \_ containerd-shim -namespace moby -workdir /var/lib/containerd/io.conta
root 7707 0.2 0.1 11692 2560 ? Ss 13:49 0:00 \_ bash -c while true; do /usr/bin/nc -l -p 3306 < /srv/hello.txt; d
root 7757 0.0 0.1 43992 3452 ? S 13:49 0:00 \_ /usr/bin/nc -l -p 3306
root 5701 4.4 4.4 1114504 90648 ? Ssl 13:46 0:10 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
root 7678 0.0 0.1 305136 2964 ? Sl 13:49 0:00 \_ /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 3306 -co
Docker 19.03 から rootless のコンテナが実行できる様になったが、podman では、よりシンプルに、デーモンレス + ルートレス である。
(6) ほとんどのLinuxプラットフォームで利用できる
パッケージマネージャーでインストールするだけで、簡単に動くかは解らないが、Arch Linux & Manjaro Linux, Fedora, CentOS, Gentoo, MacOS, openSUSE のインストール手順が https://podman.io/getting-started/installation に公開されている。
(7) Kubernetes の Pod を扱える
前面に出されていないが、GitHub の Docs には、マニュアルが整備されていて、その中にはポッドに関するものが多数ある。
ポッド関連のサブコマンドのリストは、https://github.com/containers/libpod/blob/master/docs/podman-pod.1.md でみることができる。
Podmanの今後の計画(ロードマップ)
podmanは、バージョン 1.0 に到達しているものの、更なる開発を計画されている。
- Podman CLIが Varlinkバックエンドを使用して、MacおよびWindowsから、リモートPodmanインスタンスに接続を実装
- libpodをCRI-Oに統合して、既存のコンテナー管理バックエンドを置き換え
- podman podコマンドのさらなる機能追加
- ルートレスコンテナのさらなる改善
Podman の Pod 関連の機能を試してみる
Podman のドキュメントを見ると、Kubernetes の pod のマニフェスト生成機能、 podマニフェストからpodの起動機能がある。https://github.com/containers/libpod/tree/master/docs
これは、試してみたくなるので、好奇心のままに、少し遊んでみる。
まずは、普通にnginxのコンテナを起動する。このコンテナから Kubernetesのマニフェストを生成してみたい。
[vagrant@fedora30 ~]$ podman run -d -p 8080:80 nginx
Trying to pull docker.io/library/nginx...
Getting image source signatures
Copying blob b8f262c62ec6 done
Copying blob 22a7aa8442bf done
Copying blob a6639d774c21 done
Copying config ab56bba913 done
Writing manifest to image destination
Storing signatures
e65c774464616011c27d419eb15ef38a7f95b9807bf19e81de926a2bb48bf18c
[vagrant@fedora30 ~]$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e65c77446461 docker.io/library/nginx:latest nginx -g daemon o... 5 seconds ago Up 4 seconds ago 0.0.0.0:8080->80/tcp elated_taussig
[vagrant@fedora30 ~]$ curl http://localhost:8080/
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
podmanコマンド で コンテナからポッドのマニフェストを生成
実行中のコンテナの名前、または、CONTIAINER ID を指定して、YAML形式のマニフェストを生成できる。
vagrant@fedora30 ~]$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e65c77446461 docker.io/library/nginx:latest nginx -g daemon o... 6 minutes ago Up 6 minutes ago 0.0.0.0:8080->80/tcp elated_taussig
[vagrant@fedora30 ~]$ podman generate kube elated_taussig
# Generation of Kubernetes YAML is still under development!
#
# Save the output of this file and use kubectl create -f to import
# it into Kubernetes.
#
# Created with podman-1.5.1
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: "2019-09-14T18:00:49Z"
labels:
app: elatedtaussig
name: elatedtaussig
spec:
containers:
- command:
- nginx
- -g
- daemon off;
env:
- name: PATH
value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
- name: TERM
value: xterm
- name: HOSTNAME
- name: container
value: podman
- name: NGINX_VERSION
value: 1.17.3
- name: NJS_VERSION
value: 0.3.5
- name: PKG_RELEASE
value: 1~buster
image: docker.io/library/nginx:latest
name: elatedtaussig
ports:
- containerPort: 80
hostPort: 8080
protocol: TCP
resources: {}
securityContext:
allowPrivilegeEscalation: true
capabilities: {}
privileged: false
readOnlyRootFilesystem: false
workingDir: /
status: {}
Kubernetesマニフェストから、コンテナを実行
マニフェストを生成して、既存のコンテナを停止させる。
[vagrant@fedora30 ~]$ podman generate kube elated_taussig > pod.yaml
[vagrant@fedora30 ~]$ podman kill elated_taussig
e65c774464616011c27d419eb15ef38a7f95b9807bf19e81de926a2bb48bf18c
[vagrant@fedora30 ~]$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
生成されたマニフェストを指定して、コンテナを実行する
[vagrant@fedora30 ~]$ podman play kube pod.yaml
a container exists with the same name (elatedtaussig) as the pod in your YAML file; changing pod name to elatedtaussig_pod
Pod:
475a420c00e777182de6e294f83d68e48e646bc3c3b8912ebdcf8aa19f014ec7
Container:
adbb48def6a8ed85db124f54e5b7d249006f6b1bf57fe303b5b8fa444d882fde
以下の様に、コンテナとして起動していることを確認できる。
[vagrant@fedora30 ~]$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
adbb48def6a8 docker.io/library/nginx:latest nginx -g daemon o... 25 seconds ago Up 25 seconds ago 0.0.0.0:8080->80/tcp elatedtaussig
ポッドとして扱うコマンドも用意されている。
[vagrant@fedora30 ~]$ podman pod ps
POD ID NAME STATUS CREATED # OF CONTAINERS INFRA ID
475a420c00e7 elatedtaussig_pod Running 37 seconds ago 2 3659edba15a5
Podmanは サイドカーを実行できるか?
サイドカーを持つポッドのマニフェストを利用して、podman のロゴが象徴する複数のコンテナを一まとめにして動作させることができるか、確認してみる。
GitHubからサイドカーを持つポッドのマニフェストをクローンして、podman play kube filename
で実行してみる。
[vagrant@fedora30 ~]$ git clone https://github.com/takara9/codes_for_lessons
[vagrant@fedora30 ~]$ cd codes_for_lessons/step07/sidecar/
[vagrant@fedora30 sidecar]$ ls
Dockerfile contents-cloner webserver.yml
次は、マニフェストのリストである。二つのコンテナ間は、emptyDir というストレージで連携する。
## サイドカーポッドのサンプル
#
apiVersion: v1
kind: Pod
metadata:
name: webserver
spec:
containers: ## メイン コンテナ
- name: nginx
image: nginx
volumeMounts:
- mountPath: /usr/share/nginx/html
name: contents-vol
readOnly: true
- name: cloner ## サイドカー コンテナ
image: maho/c-cloner:0.1
env:
- name: CONTENTS_SOURCE_URL
value: "https://github.com/takara9/web-contents"
volumeMounts:
- mountPath: /data
name: contents-vol
volumes: ## 共有ボリューム
- name: contents-vol
emptyDir: {}
次は、podman play kube webserver.yml
で実行した結果である。
残念ながら、サイドカーの中のコンテナを連携させるための 共有ボリュームで エラーが発生した。まだ、これからという感じだ。
[vagrant@fedora30 sidecar]$ podman play kube webserver.yml
Error: HostPath is currently the only supported VolumeSource
おそらく、共有ボリュームを必要としないタイプのサイドカーであれば、問題なく動作するであろう。しかし、その様な例は稀だと思う。
感想
Podman は、dockerコマンドを置き換える目的で、開発されている ルートレス、デーモンレスのコンテナ開発と実行環境である。また、その名前が示す様に、Kubernetesのポッドを実行できることも目指している。Red Hat が立ち上げたオープンソースプロジェクトであり、コミッターのリストをみると、Red Hatの社員が牽引している。そのためか、RHELよりも、Fedoraで最新のバージョンが利用できる。 また、様々な Linux Distribution にも対応すると宣言して、業界でよく知られたメジャーな存在となることを目指していることが伺われる。
個人的には、Dockerはコンテナの世界を幅広く世の中に知らしめ、コンテナの流通の仕組みを作るなど、IT業界への多大な貢献があるにも関わらず、どうして、ここまで置き換え様とされるのか、少々不敏な印象を受ける。 Dockerが非常に価値があることの裏返しでもあると思う。
これからのpodman の動向は注視していきたい。
その他の参考資料
- Red HatがCRI-OとPodmanに投資している理由(英語), https://www.redhat.com/en/blog/why-red-hat-investing-cri-o-and-podman
- Podman and Buildah for Docker users, https://developers.redhat.com/blog/2019/02/21/podman-and-buildah-for-docker-users/