摆脱Docker-compose的限制,实现从Podman-compose到Pod化的过程

首先在咨询使用Podman来代替有偿Docker小型容器环境的同时,我也顺便尝试了一些东西,下面是总结:

从RHEL8开始,Docker已经被弃用,建议使用Podman!但是如果要求能否在Podman中进行运维,我有点不太确定。特别是已经使用了docker-compose的部署,如何能在Podman中运行呢?我现在才开始想起来…

考虑到Podman是否已经支持M1芯片等因素,我在自己的环境中实际尝试了将docker-compose转换为’play kube’来执行Pod的过程。

索引

    1. 准备

 

    1. 执行 podman-compose

 

    1. Pod化和执行

 

    1. 总结

 

    参考资料

准备好首先,我们将收集所需的东西。首先搜索适用于docker-compose的适当yml文件。此处我借用了最初参考的红帽博客上的wordpress文件。

version: '3.1'

services:

  wordpress:
    image: wordpress
    restart: always
    ports:
      - 8080:80
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: exampleuser
      WORDPRESS_DB_PASSWORD: examplepass
      WORDPRESS_DB_NAME: exampledb
    volumes:
      - wordpress:/var/www/html

  db:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_DATABASE: exampledb
      MYSQL_USER: exampleuser
      MYSQL_PASSWORD: examplepass
      MYSQL_RANDOM_ROOT_PASSWORD: '1'
    volumes:
      - db:/var/lib/mysql

volumes:
  wordpress:
  db:

下面是对上述内容的汉语本地化释义:

接下来是安装Podman。据说在3.x版本中,M1芯片无法运行podman机器,或者需要额外进行设置,但从4.x版本开始,它针对Mac/Win(WSL)进行了改进。实际上,并没有遇到任何问题,安装完成了。

% brew install podman
% podman -v
podman version 4.1.1

接下来,我们将使用Podman机器在macOS上准备一个Linux环境。

% podman machine init

顺利完成。似乎Fedora会更新到36版。

%  ls -lh ~/.local/share/containers/podman/machine/qemu 
total 8197592
-rw-r--r--  1 toomori  staff   604M  8  4 14:35 fedora-coreos-36.20220723.2.2-qemu.aarch64.qcow2.xz
-rw-------  1 toomori  staff   3.2G  8  9 23:31 podman-machine-default_fedora-coreos-36.20220723.2.2-qemu.aarch64.qcow2
-rw-r--r--  1 toomori  staff    64M  8  4 14:58 podman-machine-default_ovmf_vars.fd

最后启动Podman机器,准备工作完成。

% podman machine start
・・・
Machine "podman-machine-default" started successfully

现在已经可以运行Podman了。
(*如果无法使用podman命令,请在zsh中通过export添加PATH,但本次省略)

podman-compose执行
现在准备好了,但首先要考虑怎么做,这里我参考了这个。原来从Podman 3.x开始也可以运行docker-compose嘛..。但我想要做的是摆脱docker-compose,希望用Podman来控制docker-compose的定义。所以我找到了podman-compose。

我们立即把这个也加进去吧。这次是pip。虽然有点担心是第三方制作的,但还是算了吧。

pip3 install podman-compose

这里的安装没有问题。在感激前辈们的同时执行。

podman-compose -f docker-compose.yml up -d 

会显示一个类似的日志,表明将docker-compose.yml中列出的每个服务转换为podman run并执行。

...
Trying to pull docker.io/library/mysql:5.7...
Error: choosing an image from manifest list docker://mysql:5.7: no image found in manifest list for architecture arm64, variant "v8", OS linux
exit code: 125
podman start wordpress_db_1
Error: no container with name or ID "wordpress_db_1" found: no such container
exit code: 125

有点问题出现了。好像MySQL还不支持ARM。似乎是M1的问题,但我已经收到了v8和一些提示,所以我会更改一下。虽然没办法,但是切换到M1后仍然感到有些不方便。希望多架构支持能变得更加顺畅一些。

  db:
    image: arm64v8/mysql

重新修改并重新执行。 这次好像成功了,所以我们要确认一下容器。

% podman ps -a
CONTAINER ID  IMAGE                               COMMAND               CREATED     STATUS         PORTS                 NAMES
c431db05b0cb  docker.io/library/wordpress:latest  apache2-foregroun...  3 days ago  Up 3 days ago  0.0.0.0:8080->80/tcp  wordpress_wordpress_1
f24872732c1f  docker.io/arm64v8/mysql:latest      mysqld                3 days ago  Up 3 days ago                        wordpress_db_1
% podman pod ps                             
POD ID      NAME        STATUS      CREATED     INFRA ID    # OF CONTAINERS
image.png

将Pod转化并执行使用Podman的优点之一是可以支持Kubernetes,并且可以生成用于Kubernetes的yaml文件。我们希望考虑将来迁移到Kubernetes,所以这次的目标是利用这个功能来生成yaml文件。

这个功能是针对正在使用Podman运行的Pod(或容器)生成的,所以我们认为,如果在之前使用podman-compose时,两个容器都在同一个Pod中,那么通信关系也应该可以顺利地转化为Pod!但实际上,它们是作为独立的容器运行的(不知道它是如何找到数据库的…)。

我在这里考虑了一些可能可行的方法。

    1. 事前に创建Pod,并使用podman-compose指定Pod。

 

    1. 将它们分别生成为不同的Pod,并使用Podman网络进行连接。

 

    将它们分别生成为不同的Pod,并手动合并YAML文件。

根据结论,第三种方法最简单。

请使用母语中文转述以下内容,只需提供一种选项:案1

在podman-run-args参数中使用–pod来指定pod并尝试。

% podman pod create --name wp-pod 
56977b21b4ce8062bbbc3eac4c013feb39d98bb10d4ed9f61fc50a93d44a9ee0
% podman pod ps
POD ID        NAME        STATUS      CREATED     INFRA ID      # OF CONTAINERS
56977b21b4ce  wp-pod      Created     3 days ago  7b8bf8e908ee  1
% podman-compose -f docker-compose.yml up -d --podman-run-args="--pod='wp-pod'"
 ...
podman-compose: error: unrecognized arguments: --podman-run-args=--pod='wp-pod'

如果选项出了问题或者没能成功执行,请告诉我该如何解决。

2号案这是一个有用的参考。据说,通过安装插件并指定Pod,您可以在Podman上实现Pod之间的通信。但是,这个过程稍微繁琐,如果要做到这一点,最好将其移到Kubernetes上执行。由于我想尽量保持与原始行为的相似性,所以这次我选择了pass。

第三个案例
首先,案例3将创建WordPress和MySQL的Pod,并手动合并它们。
首先,我们将生成各自的容器,并将其合并到用于Pod的yaml文件中。

% podman generate kube wordpress_wordpress_1 > kubernetes-wp.yml
# Save the output of this file and use kubectl create -f to import
# it into Kubernetes.
#
# Created with podman-4.1.1

# NOTE: If you generated this yaml from an unprivileged and rootless podman container on an SELinux
# enabled system, check the podman generate kube man page for steps to follow to ensure that your pod/container
# has the right permissions to access the volumes added.
---
apiVersion: v1
kind: Pod
metadata:
  annotations:
    io.kubernetes.cri-o.TTY/wordpresswordpress1: "false"
    io.podman.annotations.autoremove/wordpresswordpress1: "FALSE"
    io.podman.annotations.init/wordpresswordpress1: "FALSE"
    io.podman.annotations.privileged/wordpresswordpress1: "FALSE"
    io.podman.annotations.publish-all/wordpresswordpress1: "FALSE"
  creationTimestamp: "2022-08-05T13:46:41Z"
  labels:
    app: wordpresswordpress1-pod
  name: wordpresswordpress1-pod
spec:
  containers:
  - args:
    - apache2-foreground
    env:
    - name: WORDPRESS_DB_USER
      value: exampleuser
    - name: WORDPRESS_DB_PASSWORD
      value: examplepass
    - name: WORDPRESS_DB_NAME
      value: exampledb
    - name: WORDPRESS_DB_HOST
      value: wordpressdb1-pod
    image: docker.io/library/wordpress:latest
    name: wordpresswordpress1
    ports:
    - containerPort: 80
      hostPort: 8081
    securityContext:
      capabilities:
        drop:
        - CAP_MKNOD
        - CAP_NET_RAW
        - CAP_AUDIT_WRITE
    volumeMounts:
    - mountPath: /var/www/html
      name: wordpress_wordpress-pvc
  volumes:
  - name: wordpress_wordpress-pvc
    persistentVolumeClaim:
      claimName: wordpress_wordpress
% podman generate kube wordpress_db_1 > kubernetes-mysql.yml
# Created with podman-4.1.1

# NOTE: If you generated this yaml from an unprivileged and rootless podman container on an SELinux
# enabled system, check the podman generate kube man page for steps to follow to ensure that your pod/container
# has the right permissions to access the volumes added.
---
apiVersion: v1
kind: Pod
metadata:
  annotations:
    io.kubernetes.cri-o.TTY/wordpressdb1: "false"
    io.podman.annotations.autoremove/wordpressdb1: "FALSE"
    io.podman.annotations.init/wordpressdb1: "FALSE"
    io.podman.annotations.privileged/wordpressdb1: "FALSE"
    io.podman.annotations.publish-all/wordpressdb1: "FALSE"
  creationTimestamp: "2022-08-05T09:32:54Z"
  labels:
    app: wordpressdb1-pod
  name: wordpressdb1-pod
spec:
  containers:
  - args:
    - mysqld
    env:
    - name: MYSQL_PASSWORD
      value: examplepass
    - name: MYSQL_RANDOM_ROOT_PASSWORD
      value: "1"
    - name: MYSQL_USER
      value: exampleuser
    - name: MYSQL_DATABASE
      value: exampledb
    image: docker.io/arm64v8/mysql:latest
    name: wordpressdb1
    securityContext:
      capabilities:
        drop:
        - CAP_MKNOD
        - CAP_NET_RAW
        - CAP_AUDIT_WRITE
    volumeMounts:
    - mountPath: /var/lib/mysql
      name: wordpress_db-pvc
  volumes:
  - name: wordpress_db-pvc
    persistentVolumeClaim:
      claimName: wordpress_db

请使用podman play kube命令逐个验证每个YAML文件是否能够独立运行。
如果运行正常,然后将它们合并如下。

# Save the output of this file and use kubectl create -f to import
# it into Kubernetes.
#
# Created with podman-4.1.1

# NOTE: If you generated this yaml from an unprivileged and rootless podman container on an SELinux
# enabled system, check the podman generate kube man page for steps to follow to ensure that your pod/container
# has the right permissions to access the volumes added.
---
apiVersion: v1
kind: Pod
metadata:
  annotations:
    io.kubernetes.cri-o.TTY/wordpresswordpress1: "false"
    io.podman.annotations.autoremove/wordpresswordpress1: "FALSE"
    io.podman.annotations.init/wordpresswordpress1: "FALSE"
    io.podman.annotations.privileged/wordpresswordpress1: "FALSE"
    io.podman.annotations.publish-all/wordpresswordpress1: "FALSE"
  creationTimestamp: "2022-08-05T13:46:41Z"
  labels:
    app: wordpresswordpress1-pod
  name: wordpresswordpress1-pod
spec:
  containers:
  - args:
    - apache2-foreground
    env:
    - name: WORDPRESS_DB_USER
      value: exampleuser
    - name: WORDPRESS_DB_PASSWORD
      value: examplepass
    - name: WORDPRESS_DB_NAME
      value: exampledb
    - name: WORDPRESS_DB_HOST
      value: 127.0.0.1
    image: docker.io/library/wordpress:latest
    name: wordpresswordpress1
    ports:
    - containerPort: 80
      hostPort: 8081
    securityContext:
      capabilities:
        drop:
        - CAP_MKNOD
        - CAP_NET_RAW
        - CAP_AUDIT_WRITE
    volumeMounts:
    - mountPath: /var/www/html
      name: wordpress_wordpress-pvc
  - args:
    - mysqld
    env:
    - name: MYSQL_PASSWORD
      value: examplepass
    - name: MYSQL_RANDOM_ROOT_PASSWORD
      value: "1"
    - name: MYSQL_USER
      value: exampleuser
    - name: MYSQL_DATABASE
    -      value: exampledb
    image: docker.io/arm64v8/mysql:latest
    name: wordpressdb1
    securityContext:
      capabilities:
        drop:
        - CAP_MKNOD
        - CAP_NET_RAW
        - CAP_AUDIT_WRITE
    volumeMounts:
    - mountPath: /var/lib/mysql
      name: wordpress_db-pvc
  volumes:
  - name: wordpress_wordpress-pvc
    persistentVolumeClaim:
      claimName: wordpress_wordpress
  - name: wordpress_db-pvc
    persistentVolumeClaim:
      claimName: wordpress_db

我只改变了WORDPRESS_DB_HOST的值。将其修改为指向127.0.0.1。
(*为了方便起见,我将8080改为了8081。)
其他只需对行进行重新排序即可。

    - name: WORDPRESS_DB_HOST
      value: 127.0.0.1

由于Pod化已经完成,所以使用podman play kube来执行。

% podman play kube kubernetes-hybrid.yml

确认动作

% podman pod ps
POD ID        NAME                     STATUS      CREATED     INFRA ID      # OF CONTAINERS
f6ee088f1f1f  wordpresswordpress1-pod  Running     3 days ago  6ff1c5d2686a  3
% podman ps -a
CONTAINER ID  IMAGE                                    COMMAND               CREATED     STATUS         PORTS                 NAMES
6ff1c5d2686a  localhost/podman-pause:4.1.1-1655914710                        3 days ago  Up 3 days ago  0.0.0.0:8081->80/tcp  f6ee088f1f1f-infra
72e336da5e7b  docker.io/library/wordpress:latest       apache2-foregroun...  3 days ago  Up 3 days ago  0.0.0.0:8081->80/tcp  wordpresswordpress1-pod-wordpresswordpress1
1d36ae3682ed  docker.io/arm64v8/mysql:latest           mysqld                3 days ago  Up 3 days ago  0.0.0.0:8081->80/tcp  wordpresswordpress1-pod-wordpressdb1

我有一个Pod,里面有三个容器。infra是否会自动进入呢?PORTS也有点可疑…我会尝试通过Web访问。在浏览器中输入http://localhost:8081进行访问。

image.png
顺利显示并成功进行了与数据库的通信。

概述如果是关于使用相对简单操作的层次的话,使用Podman也可以完成同样的事情。如果考虑迁移到Kubernetes,使用podman-compose进行转换可能会使迁移到Kubernetes/Openshift更加容易,我认为。

使用podman-compose,从docker-compose迁移到Podman很简单。
在使用podman-compose创建多容器Pod时,需要进行部分编辑。
虽然podman可以管理Pod,但如果情况过于复杂,还是建议使用kubernetes进行管理。

如果我能巧妙地利用podman-compose的选项,可能还能做更多不同的事情,所以我想再次尝试一下。

文献引用

    • 赤帽エンジニアブログ Podman v3 で docker-composeを実行する

 

    • 豆蔵デベロッパーサイト macOS 上で Podman を動かす

 

    • Podman で Compose したかったらどうするの?

 

    ZU-MIN.COM podman のコンテナ名で通信する

bannerAds