ytooyamaのブログ

サーバ構築とか、仕事で発見したこととか、趣味のこととかを書いています。

Fedora 33でPodman 2.1を触ってみる

はじめに

Fedora 33をダウンロードしたので、Podmanでも触ってみることにした。 yum install podman でインストールされたのは 2.1.1だった。

[root@fedora33 ~]# cat /etc/fedora-release 
Fedora release 33 (Thirty Three)
[root@fedora33 ~]# uname -a
Linux fedora33.localdomain 5.9.10-200.fc33.x86_64 #1 SMP Mon Nov 23 18:12:50 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
[root@fedora33 ~]# podman --version
podman version 2.1.1

podman runのオプションに --read-only というオプションを見つけた。 --read-onlyはコンテナのルートファイルシステムを読み取り専用にするオプションだそうだ。

[root@fedora33 ~]# podman run --read-only -itd fedora:33 
[root@fedora33 ~]# podman ps
CONTAINER ID  IMAGE                                     COMMAND    CREATED        STATUS            PORTS   NAMES
027a45af287b  registry.fedoraproject.org/fedora:latest  /bin/bash  5 seconds ago  Up 5 seconds ago          charming_murdock
[root@fedora33 ~]# podman exec -it charming_murdock bash
[root@027a45af287b /]# pwd
/
[root@027a45af287b /]# touch hoge
touch: cannot touch 'hoge': Read-only file system
[root@027a45af287b /]# cd /root/
[root@027a45af287b ~]# touch hoge
touch: cannot touch 'hoge': Read-only file system
[root@027a45af287b ~]# 

確かに書き込みができない。ただこのオプションを使う場合、アプリケーションコンテナーイメージが対応している必要がある模様。 centos:8 というイメージと、fedora:33 というイメージは問題なく利用できたが、 nginx:alpine などは使うことができなかった。

今回はFedora 33を使ったのでControl Group v2が標準になっている。 Fedoraはバージョン32でControl Group v2をデフォルトにしたので、Control Group v2に対応していない(20.10以前のバージョンの)Dockerや低レイヤーランタイムである(v1.0.0-rc93以前の)runCはControl Group v2では動かないらしい(当時はFedora 33ではいずれも該当していたため動かなかった)。

Fedora 33でインストールできるPodmanの設定をみたがデフォルト設定はrunCになっていた。おそらくPodman側がインストールされている低レイヤーランタイムでcgorupのバージョンを判定して適切な方を使っているんだろう。

[root@fedora33 ~]# podman --runtime /usr/bin/runc run --rm fedora:33 echo it works
ERRO[0000] oci runtime "runc" does not support CGroups V2: use system migrate to mitigate 
Error: this version of runc doesn't work on cgroups v2: OCI runtime error

[root@fedora33 ~]# podman --runtime /usr/bin/crun run --rm fedora:33 echo it works
it works

[2/9/2021 追記] Docker 20.10以降はControl Group v2をサポートしている。

Fedora32 31以降でFedoraパッケージの(20.10以前の)moby-engineと(v1.0.0-rc93以前の)runCを使うには、カーネルオプションでControl Group v1を使うように設定すれば使える(同様にPodmanでrunCを使いたい場合も)。DockerがControl Group v2をサポートするのはDocker 20.10くらいを予定しているらしい。 -> Docker 20.10でサポートされた。

fedoramagazine.org

[4/5/2021 追記] runCがrunc-1.0.0-375.dev.git12644e6.fc33.x86_64に更新されたため、Control Group v2で実行していても動作するようになった。ただし、Fedora 33のmoby-engineは更新されておらず、Fedoraのmoby-engineパッケージを使う場合はv1での利用が必要である。月末にリリース予定のFedora 34ではDcoker 20.10ベースのmoby-engineパッケージが提供される予定。

[root@localhost ~]# podman --version
podman version 3.0.1
[root@localhost ~]# podman --runtime /usr/bin/runc run --rm --memory 4M fedora echo it works
it works
[root@localhost ~]# podman --runtime /usr/bin/crun run --rm --memory 4M fedora echo it works
it works

runCとcrun

runCはいろいろなコンテナーランタイムのベースとして動いている。そのため低レイヤーランタイムなどと呼ばれるらしい。 runCはOCI仕様に基づいて、コンテナ生成・実行などを行うコンテナランタイムである。

runCはGo言語で書かれているが、crunはC言語で書き直された。crunもOCI Container Runtime仕様に準拠しているランタイムである。 高速に動き、メモリフットプリントが少ないランタイムだそうだ。ソースは公開されているため、多くのLinuxで利用できる。 ただし、runCはControl Group v2に現状は対応していないので、Fedora 33を使うと自動的にcrunを使うことになる。crunは --pids-limit 1 を指定してPIDに制限を加えても動くらしい。驚異的である。

crun開発の経緯は以下に書かれていた。

www.redhat.com

ユーザー的な立場としては、同じように動くならより軽量かつセキュアであればrunCだろうとcrunだろうと意識することはないと思う。

Podmanの設定

Podmanの設定は /usr/share/containers/containers.conf にデフォルトのファイルがあるので、 /etc/containers/containers.conf とかにコピーしておけば良いらしい。コンテナーイメージレジストリーの設定は /etc/containers/registries.conf にある。デフォルトでは次のような設定がされているため、FedoraやCentOSのイメージは各プロジェクトが用意するイメージが使われる。Docker HubのイメージPull制限対策がされており、安心だ。

unqualified-search-registries = ['registry.fedoraproject.org', 'registry.access.redhat.com', 'registry.centos.org', 'docker.io']

play kube モード

Dockerにはdocker-composeという、YAMLにデプロイする内容を書いてコンテナーアプリケーションを配備する方法がある。Podmanにもサードパーティのpodman-composeというのもあるが、公式のものではない。

その一方、Podmanは名前が示すようにPodを作ることができる。そして、 play kube モードを使うと、KubernetesのYAMLファイルを使ってPodを作ることが可能である。というわけで、まずは次のようなYAMLファイルを作って試してみることにした。

apiVersion: v1
kind: Pod
metadata:
  name: hello-busybox
spec:
  containers:
    - name: busybox
      image: busybox
      tty: true

実行するとあっという間にPodが作成される。

[root@fedora33 ~]# podman play kube bustbox-pod.yaml
Pod:
a996a20fb08d4adb657167b77919ec08d58c876f5a2d04e45113c62a3dfeef3c
Container:
daefbabc874527a2acb95440ac83d565dddc527cfdf8da76263be5ff670734fb

作成されたPodは podman pod コマンドを使って停止、再開、再起動、削除などの操作を行う。

[root@fedora33 ~]# podman pod ls
POD ID        NAME           STATUS   CREATED         # OF CONTAINERS  INFRA ID
a996a20fb08d  hello-busybox  Running  45 seconds ago  2                aac8f79420cc

作成したPodのシェルには podman container exec (もしくは podman exec ) コマンドを使って入る。

[root@fedora33 ~]# podman container ls
CONTAINER ID  IMAGE                 COMMAND  CREATED        STATUS            PORTS   NAMES
784d18aa0dc7  k8s.gcr.io/pause:3.2           7 seconds ago  Up 7 seconds ago          0c87158becab-infra
8e3136f61680  busybox               sh       7 seconds ago  Up 7 seconds ago          hello-busybox-busybox
[root@fedora33 ~]# podman container exec -it hello-busybox-busybox sh
/ # 

Podを削除するときは podman pod stop した後 podman pod rm で削除出来る。 kubectl delete -f pod.yaml のようにはできないのでちょっとだけここら辺は違うので覚える必要がある。

では、もう少し複雑なYAMLを用意してみる。これはNGINXのコンテナーイメージを使ってPodを作る例である。 Kubernetesの場合、アプリケーションを外部公開する場合はサービスというものを使うが、PodmanのPlay kubeではhostPortでアクセスを許可するポートを指定している。

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
spec:
  containers:
    - name: nginx-container
      image: nginx
      ports:
      - containerPort: 80
        hostPort: 8080

これを使ってPodを作ってみる。 「http://ipaddress-or-fqdn:8080」をブラウザーやcurlコマンドを使うとNGINXのデフォルトページが表示されるはずである。

[root@fedora33 ~]# podman play kube nginx-pod.yaml
[root@fedora33 ~]# curl http://172.16.131.4:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

ちなみに、Deployment YAMLファイルでもplay kubeでPodを作ることはできるようだった。ただし、基本的にはPodと一緒だが、残念ながらreplicasは思ったようには動かない。それをやりたければCRI-Oをランタイムとして、Kubernetesを使うか、k3sやmicrok8sといったものを利用するべきだろう。

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginxapp1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginxapp1
  template:
    metadata:
      labels:
        app: nginxapp1
    spec:
      containers:
      - name: nginxapp1
        image: nginx:alpine
        ports:
        - containerPort: 80
          hostPort: 8080

というわけで、今回はFedora 33で割と新しいPodman 2.1.1を使ってみた。

play kubeモードも割と使えるらしいのと、セキュアなコンテナー環境を目指すと「Linux capabilities」、「SELinux」、いろいろなランタイムのサポートは切っても切り離せないので、Podmanが高機能かつ色々便利になっているのが知られてよかった。

ちょっと早いけど、冬休みの宿題のその1は完了である。

追記

他のOSで試すには Podman Installation Instructionsを参照。 RHEL 8.3では Podman 2.0系のパッケージが利用可能だそうです。また、Ubuntu 20.10より、標準パッケージにPodmanが追加されています。

このブログサイトはJavaScriptを使っていますが、読み込んでいるJavaScriptは全てはてなが提供しているものであり、筆者が設置しているものではありません。