はじめに
DockerからPodmanへの置き換えの流れがある。
Docker for MacではMac上から透過的にDockerを操作できたり、docker-composeなどで便利な操作ができたのだが、podmanだと現状どうなのか。
当記事ではその辺りをまとめてみる。
環境情報
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.15.6
BuildVersion: 19G2021
$ VBoxManage -v
6.0.8r130520
$ vagrant -v
Vagrant 2.2.9
Setup
やることは以下の2つ。
- Podman環境のVMのSetup
- Mac側でのpodman-remoteのSetup
Podman環境のVMのSetup
VMの構築はboot2podmanとかpodman-machineとかpodman専用のものがあるが、使い慣れたVagrantで作ろうと思う。
まずVagrantfileを用意する。
private networkの固定IPを割り振っておくことがポイント
Vagrant.configure("2") do |config|
config.vm.box = "fedora/32-cloud-base"
config.vm.provider "virtualbox" do |vb|
vb.memory = "2048"
end
config.vm.network :private_network, ip: "192.168.33.11"
end
そして起動してlogin
$ vagrant up
...
$ vagrant ssh
[vagrant@localhost ~]$
vagrant login後はpodmanの設定をしておく。
[vagrant@localhost ~]$ sudo dnf -y install podman
[vagrant@localhost ~]$ systemctl --user enable podman.socket
Created symlink /home/vagrant/.config/systemd/user/sockets.target.wants/podman.socket → /usr/lib/systemd/user/podman.socket.
[vagrant@localhost ~]$ sudo loginctl enable-linger $USER
[vagrant@localhost ~]$ systemctl --user status podman.socket
● podman.socket - Podman API Socket
Loaded: loaded (/usr/lib/systemd/user/podman.socket; enabled; vendor preset: disabled)
Active: inactive (dead)
Triggers: ● podman.service
Docs: man:podman-system-service(1)
Listen: /run/user/1000/podman/podman.sock (Stream)
[vagrant@localhost ~]$ systemctl --user start podman.socket
[vagrant@localhost ~]$ systemctl --user status podman.socket
● podman.socket - Podman API Socket
Loaded: loaded (/usr/lib/systemd/user/podman.socket; enabled; vendor preset: disabled)
Active: active (listening) since Fri 2020-09-11 06:29:56 UTC; 3s ago
Triggers: ● podman.service
Docs: man:podman-system-service(1)
Listen: /run/user/1000/podman/podman.sock (Stream)
CGroup: /user.slice/user-1000.slice/user@1000.service/podman.socket
Sep 11 06:29:56 localhost.localdomain systemd[2509]: Listening on Podman API Socket.
[vagrant@localhost ~]$ podman --remote info
host:
arch: amd64
buildahVersion: 1.15.1
cgroupVersion: v2
...
以上で完了。
Mac側でpodman remoteのsetup
$ brew install podman
$ podman --version
podman version 2.0.6
$ podman system connection add vagrant --identity $HOME/podman_env/.vagrant/machines/default/virtualbox/private_key ssh://vagrant@192.168.33.11/run/user/1000/podman/podman.sock
$ podman system connection list
Name Identity URI
vagrant* /Users/seijitada/podman_env/.vagrant/machines/default/virtualbox/private_key ssh://vagrant@192.168.33.11:22/run/user/1000/podman/podman.sock
$ podman info
host:
arch: amd64
buildahVersion: 1.15.1
cgroupVersion: v2
...
以上で完了。
Operation
dockerでよく使っていたのは以下の操作でこれらをpodmanでもいい感じで行いたい。
- docker-compose likeな操作
- Container間の通信
- Volumeの使用
- Imageのbuild
- Container外部から通信
docker compose likeな操作
podmanでもpodman-composeというdocker-compose likeな非公式ツールがあるが、
podmanに内蔵されているKubernetes yamlを読み込む機能が良さげなのでこれを使う。
Kubernetes yamlは慣れた人なら一から作れそうだが、ここではpodmanから自動生成してみる。
$ podman pod create -n pod01
06267e4e35e53ff1c7cf843fd74c617601870a7b82e5eb2404053fdc2f54f1ce
$ podman run --pod pod01 -d --name postgres -e POSTGRES_PASSWORD=password postgres:13
f54a6902a3e0d7b62ec3a1b4c92f637b14c2ea6dd8fbd8856804e9692b870f50
$ podman pod ls
POD ID NAME STATUS CREATED # OF CONTAINERS INFRA ID
06267e4e35e5 pod01 Running About a minute ago 2 2a9e30d39f67
$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2a9e30d39f67 k8s.gcr.io/pause:3.2 About a minute ago Up 21 seconds ago 06267e4e35e5-infra
f54a6902a3e0 docker.io/library/postgres:13 postgres 21 seconds ago Up 20 seconds ago postgres
$ podman generate kube pod01 > pod01.yaml
$ cat pod01.yaml
# 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-2.0.6
apiVersion: v1
kind: Pod
こんな感じでpodman generate kubeコマンドで今動いているpodやcontainerからKubernetes yamlを生成することができる。
続いて生成したKubenetes yamlを読み込ませてみる。
$ podman pod rm pod01 -f
06267e4e35e53ff1c7cf843fd74c617601870a7b82e5eb2404053fdc2f54f1ce
$ podman pod ls
POD ID NAME STATUS CREATED # OF CONTAINERS INFRA ID
$ podman play kube pod01.yaml
Pod:
4203ed53e966d6c0f8c2ae8008efe9fb9cc42fb73d9a1b06831de664cdfa5843
Container:
f62bf71b3f8ea19b0c2084bf21cd2d7dbfa9f18097d14c213a49fb9c562d3b6e
$ podman pod ls
POD ID NAME STATUS CREATED # OF CONTAINERS INFRA ID
4203ed53e966 pod01 Running 11 seconds ago 2 4058387dce44
$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4058387dce44 k8s.gcr.io/pause:3.2 22 seconds ago Up 21 seconds ago 4203ed53e966-infra
$ podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4058387dce44 k8s.gcr.io/pause:3.2 27 seconds ago Up 26 seconds ago 4203ed53e966-infra
f62bf71b3f8e docker.io/library/postgres:13 postgres 27 seconds ago Exited (1) 26 seconds ago pod01-postgres
podman play kubeコマンドでKubernetes yamlを使うことができるのだが、何やらpostgresが正しく動いていない。
logを見てみるとなにやらpostgresをrootであげようとしているようだ。
$ podman logs pod01-postgres
"root" execution of the PostgreSQL server is not permitted.
The server must be started under an unprivileged user ID to prevent
possible system security compromise. See the documentation for
more information on how to properly start the server.
調べてみると、どうやらKubernetes yamlではImageのEntrypointをspec.containers.commandの指定で上書きする仕様のようだが、
podman kube generateで生成されたKubernetes yamlではこれが指定されてしまっている模様。
したがってここを修正すればok
$ cp pod01.yaml pod01.yaml.bk
# vim pod01.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: "2020-09-11T06:56:41Z"
labels:
app: pod01
name: pod01
spec:
containers:
- command: <---- ここが不要
- postgres <---- ここが不要
env:
$ diff pod01.yaml.bk pod01.yaml
16,18c16
< - command:
< - postgres
< env:
---
> - env:
$ podman pod rm pod01 -f
4203ed53e966d6c0f8c2ae8008efe9fb9cc42fb73d9a1b06831de664cdfa5843
$ podman play kube pod01.yaml
Pod:
3cd402c2bc67b07fc31f845de84169ba574d8171c263c6a74aeec816fbf0e234
Container:
f6278b9af26d956185618b5424792f240d814cca3ed34d02ca0df63cc2c73fcb
$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
12f881ec8125 k8s.gcr.io/pause:3.2 11 seconds ago Up 10 seconds ago 3cd402c2bc67-infra
f6278b9af26d docker.io/library/postgres:13 docker-entrypoint... 10 seconds ago Up 10 seconds ago pod01-postgres
これでpodman play kubeでkubernetes yamlから起動できることが確認できた。
Container間の通信
Container間の通信はdocker-composeの場合はnetworkを作成して、container名でのアクセスをできるようにしてくれていた。
podmanの場合はpod(ipc,net,utsの共有)なので、localhostでの通信やinter-process communicationが可能。
Volumeの使用
docker-composeではbind mountとvolume mountが可能であったが、podman playでは今のところはhostPath(bind mount)のみのサポートのようだ。
hostPathを使用する上では事前にvm側でのpathの作成が必要になることと、SELinuxの関連の指定に注意が必要となる。
[vagrant@localhost ~]$ mkdir -p /tmp/pg_data
$ cat pod01.yaml
...
spec:
containers:
...
securityContext:
allowPrivilegeEscalation: true
capabilities: {}
privileged: false
readOnlyRootFilesystem: false
seLinuxOptions:
type: spc_t <---- SELinuxでホストアクセスの特権が付与される。
workingDir: /
volumeMounts:
- mountPath: /var/lib/postgresql/data
name: pg_data
volumes:
- name: pg_data
hostPath:
path: "/tmp/pg_data"
Imageのbuild
buildに関してはdocker-composeのようにはできないので、podmanコマンドから行う。
$ podman build -t node_app:latest -f Dockerfile ./
Container外部から通信
Kubernetes yaml的にはspec.containers.portsの追加で可能。
PCからはVagrantで設定した固定IP宛でアクセスできる。
ports:
- containerPort: 5432
hostPort: 5432
protocol: TCP
まとめ
Docker互換とはいかないものの、今の段階でも実用上困らないくらいには使うことはできそうだ。
今後のさらなる拡張に期待。