podman容器化介绍和部署
1.背景
本文主要对下一代容器技术podman的简单介绍和体验操作部署流程。
目前在部署过程中存在如下痛点:
1、需要安装多种依赖环境,有时候部署时会出现缺少依赖库的情况,或者缺少一些调试命令,比如ifconfig、ping、lsof、netcat、telnet、scp等
2、部署的目标机器完全离线,没有网络。
3、部署的目标机器操作系统未定,各省内的宿主机操作系统可能是centos7、centos8、redhat、bclinux、uos、openeuler等。
4、有时候需要对当前版本做备份或者迁移,需要对应用程序备份、配置进行备份、数据库备份、各类中间件的数据备份、minio数据备份等等。由于需要备份的事项太多,可采用备份虚拟机方式如导出ova、复制虚拟机文件夹方式(但是这种需要停机后再导出,同时需要具备虚拟机管理权限,而且备份一次容量占用太大,约40~100G左右),如果不具备上述条件,则需要手动逐项备份。
5、不容易分配ip,一般来说都是一个虚拟机中启动多个docker容器,各个容器共用同一个ip,比如启动了多个mysql数据库,那么则需要进行端口映射 3306、3307等。
6、docker编排,比如一整套完整的环境需要包括java程序、数据库、redis、中间件等、如果想要快速部署,那么可采用docker-compose方式进行编排,相当于用docker来进行服务管理,整体上问题不大,不过有几点不方便之处,比如绑定了docker方式,习惯了此种部署模式,如果碰到省内禁用docker就不方便了,另外就是排查问题时需要切换容器看日志,有时候还需要对容器的环境变量做对应的配置。
所以总体需求是希望一个轻量级的虚拟机(使用起来同虚拟机),比起虚拟机来说虽然隔离性很好,但是存在要求权限高、文件占用大、启动慢、性能较低的缺点,对于docker容器来说虽然没有虚拟机的缺点,但是因为docker容器的设计原则是单进程可控(pid=1)的应用,也使得对容器的用法和虚拟机(目标环境)有区别,比如无法使用systemd进行服务管理、运行多个服务(java进程、数据库、中间件等)。
2. 容器技术差异摘要
3.容器化部署
采用podman in podman方式制作容器
网络采用macvlan方式
要求:宿主机的网卡支持混杂模式
宿主机可采用ubuntu 22.04
宿主机podman版本3.4.4
3.1.配置podman网络
3.1.1.开启混杂模式(详解见4.4)
ifconfig ens33 promisc
3.1.2.创建 podman 的虚拟网络,本人局域网的网段为192.168.28.0/24,网关为路由器的192.168.28.1
podman network create -d macvlan --subnet=192.168.0.2/16 --gateway=192.168.0.1 -o parent=eth0 podman-bridge
3.1.3.解决配置文件版本不支持的警告
sed -i 's/1\.0\.0/0.4.0/g' /etc/cni/net.d/podman-bridge.conflist
3.1.4.创建 podman 容器,通过network参数指定前面创建的虚拟网络,ip参数指定容器的ip地址。下面是个例子,具体命令可以自行替换.
podman run -d --name podman-container --network=podman-bridge --ip=192.168.0.220 --privileged=true 238590ad490e
3.2.制作podman基础镜像
#关闭防火墙
ufw disable
systemctl disable ufw
#拉取基础镜像
podman run -itd --name ubuntu docker.io/ubuntu:24.04 /bin/bash
#进入镜像
podman exec -it ubuntu bash
#安装systemd及init
apt update
apt -y install systemd init
exit
#制作支持systemd的ubuntu镜像
podman commit ubuntu ubuntu_2404_systemd
#以支持systemd的ubuntu镜像为基础
podman run -itd --name u1 localhost/ubuntu_2404_systemd /usr/sbin/init
#进入支持systemd的ubuntu镜像,此时操作类似于在虚拟机的操作
podman exec -it u1 bash
#安装调试工具,podman
apt -y install vim net-tools inetutils-ping netcat-traditional traceroute podman cron tree
#启动crontab
systemctl enable cron
systemctl restart cron
#安装字体
apt-get -y install libfreetype6 fontconfig
#提高systemd对线程的限制
echo "DefaultTasksMax=65535" >> /etc/systemd/system.conf
systemctl daemon-reload
podman容器内,配置国内源
vim /etc/containers/registries.conf
unqualified-search-registries = ["docker.io"]
[[registry]]
prefix = "docker.io"
location = "docker.m.daocloud.iom"
insecure = true
[[registry.mirror]]
location = "docker.imgdb.de"
insecure = true
[[registry.mirror]]
location = "docker-0.unsee.tech"
insecure = true
[[registry.mirror]]
location = "docker.hlmirror.com"
insecure = true
[[registry.mirror]]
location = "cjie.eu.org"
insecure = true
3.2.1.配置sshd
apt -y install openssh-server
#接下来设置root密码,当前应以root方式登录
passwd
xxxx
#配置SSHD
vim /etc/ssh/sshd_config
#输入以下配置
AcceptEnv LANG LC_*
AllowAgentForwarding yes
AllowTcpForwarding yes
Include /etc/ssh/sshd_config.d/*.conf
KbdInteractiveAuthentication no
PermitRootLogin yes
PermitRootLogin yes
PrintMotd no
Subsystem sftp /usr/lib/openssh/sftp-server
UsePAM yes
X11DisplayOffset 10
X11Forwarding yes
X11UseLocalhost yes
#重启ssh服务
rm -rf /var/run/sshd/
systemctl restart ssh
3.2.4部署nginx用于测试
-
不适用于podman方式安装 nginx容器,只适用于容器内源码安装nginx,容器访问不通,原因不明。
-
podman容器内pull容器相对于宿主机来说,特别慢,反而apt install跟宿主机速度差不多。
apt -y install nginx
systemctl enable nginx
systemctl restart nginx
3.2.2.提交镜像
exit
podman commit u1 ubuntu_2404_systemd_podman
3.2.3.进入podman镜像并分配独立ip
podman run -itd --name u204 --network=podman-bridge --ip=192.168.0.220 --ulimit nofile=1024000:1024000 --privileged=true localhost/ubuntu_2404_systemd_podman /usr/sbin/init
podman exec -it u204 bash
podman inspect <容器ID或名称> | grep IPAddress
sudo iptables -t nat -L -n -v
#此时进入的容器已经为轻量级的虚拟机,具有独立ip,可ssh登录,可以podman方式安装其它中间件,具备systemd管理服务的能力。
ip路由转发测试云服务器公网ip,尝试通过公网ip转发到混杂模式的容器内网ip:192.168.0.220,但测试未通过。
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.0.220:8000
sudo iptables -t nat -A POSTROUTING -p tcp -d 192.168.0.220 --dport 8000 -j MASQUERADE
3.2.4部署postgis数据库
podman run -itd --restart=always --name postgis17 -e POSTGRES_PASSWORD=Cmdi@1028 --network=host docker.io/postgis/postgis:17-3.5-alpine
3.2.5.部署redis
podman run -itd --restart=always --name redis62-6379 --network=host docker.io/redis:6.2 --requirepass ITwh@306
3.2.6 systemd管理java进程
如程序放置在/opt/app/executable目录下
配置systemd任务
vi /etc/systemd/system/console.service
[Unit]
Description=Console
After=network.target
[Service]
User=root
ExecStart=/opt/app/jdk-17.0.2/bin/java -Xms256m -Xmx2048m -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:45013 -Dfile.encoding=utf-8 -Djava.io.tmpdir=/opt/app/tmp -XX:-UseGCOverheadLimit -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=45113 -Dspring.profiles.active=prod -jar /opt/app/executable/xps-vue.jar --spring.config.location=/opt/app/config/console/application-prod.yml --logging.config=/opt/app/config/console/logback.xml >/dev/null 2>&1 &
SuccessExitStatus=143
Restart=on-failure
RestartSec=10
Environment=SPRING_PROFILES_ACTIVE=prod
[Install]
WantedBy=multi-user.target
然后重新加载服务并启动
systemctl daemon-reload
systemctl restart console
3.2.6 podman镜像快照或导出
以下操作在宿主机上执行
#提交镜像
podman commit u204 ubuntu_2404_systemd_podman:v1
#或者导出镜像
podman export u204 -o ubuntu_2404_systemd_podman_export.rar
一般一套完整的环境镜像含数据库数据约在3G~10G左右,约为虚拟机的1/10
3.2.7podman镜像拉取或导入
#拉取镜像
podman pull ubuntu_2404_systemd_podman:v1
#导入镜像
podman import u204_export.rar ubuntu_2404_systemd_podman:v1
#分配新的ip,启动新的镜像
podman run -itd --name u205 --network=podman-bridge --ip=192.168.28.205 --ulimit nofile=1024000:1024000 --privileged=true f5de215fc7bb /usr/sbin/init
#通过这种方式可以很方便的完成整套环境的备份、迁移与部署。
3.3.总结
此时podman容器u204已经分配了独立ip 192.168.28.204,并且提供ssh服务,可通过ssh登录192.168.28.204,进入之后同一般虚拟机并无差异,进入容器之后可通过systemctl进行服务管理,同时可以使用podman方式部署中间件,而且操作方式与部署到虚拟机上无任何差异,相同的技术经验可复用。
网络情况如下:
java进程
podman in podman容器
podman in podman 的文件系统
4. 混杂模式
网络接口的混杂模式
混杂模式(Promiscuous mode)
,简称 Promisc mode
,俗称监听模式
。
混杂模式
通常被网络管理员用来诊断网络问题,但也会被无认证的、想偷听网络通信的人利用。根据维基百科的定义,混杂模式是指一个网卡会把它接收的所有网络流量都交给CPU,而不是只把它想转交的部分交给CPU
。
在 IEEE 802
定的网络规范中,每个网络帧都有一个目的MAC地址
。在非混杂模式下,网卡只会接收目的MAC地址
是它自己的单播帧
,以及多播及广播帧
;在混杂模式下,网卡会接收经过它的所有帧!
使用ifconfig
或者netstat-i
命令查看一个网卡是否开启了混杂模式,当输出包含 PROMISC
时,表明该网络接口处于混杂模式
。
liruilonger@cloudshell:~$ ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.88.0.3 netmask 255.255.0.0 broadcast 10.88.255.255
ether d2:54:95:f4:14:99 txqueuelen 0 (Ethernet)
RX packets 21025 bytes 162169296 (154.6 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 14137 bytes 20181898 (19.2 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
liruilonger@cloudshell:~$
4.1 物理机中设置混杂模式
4.1.1 windows10 如何查看物理网卡的混杂模式
使用powershell运行
Get-NetAdapter | Select InterfaceDescription, PromiscuousMode
4.1.2 windows 10 网卡混杂模式
1、可以安装wireshark 然后开启
注册表:
计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class{4d36e972-e325-11ce-bfc1-08002be10318}\0001
0001为要修改的网卡, 前面是路径
新建 字符串 MonitorModeEnabled = 1 开启monitor模式
新建 字符串 PreserveVlanInfoInRxPacket = 1 抓取vlan信息
改完之后禁用/启用网卡
4.1.3 vmware workstation pro中开启混杂模式
当虚拟机启动之后可以看到,桥接的物理网卡也变成了混杂模式
4.1.4 exsi中的网络开启混杂模式
4.2 虚拟机中设置混杂模式
在Linux操作系统中设置网卡混杂模式时需要管理员权限。
注意,虚拟机中设置混杂模式,前提是物理机中的网卡开启了混杂模式,否则不起作用
参考: https://www.jianshu.com/p/2b8b6c738bf6
https://www.bjpowernode.com/docker/1677.html
https://www.jianshu.com/p/42d88c0c47db
4.2.1开启混杂模式
ifconfig ens160 promisc
或者
ip link set ens160 promisc on
4.2.2 查看混杂模式
ifconfig ens160
未开启时的状态
开启之后
4.2.3 取消混杂模式
ifconfig ens160 -promisc
4.3 MACVLAN
参考:https://zhuanlan.zhihu.com/p/553167787
https://post.smzdm.com/p/agq9mw53/
4.3.1 Macvlan网络的定义和工作原理
Macvlan是一种特殊类型的网络设备,它允许单个物理设备拥有多个MAC地址。这样做的结果是,你可以在物理网络接口上创建一个新的虚拟网络接口,这个接口有自己的MAC地址,IP地址,以及其他网络设置。
Macvlan工作的原理是通过在数据链路层插入虚拟网络接口,使得每个接口都有自己的MAC地址,从而可以独立的接收和发送数据包。这种设计使得Macvlan设备看起来就像一台独立的物理机器,连接在同一网络中。
通俗来说,就是创建了Macvlan网络之后,如果你的容器接入了该网络,那么它就像是一台电脑,有胳(网)膊(口)有腿(网线),接在了你的路由器上,这样就可以直接获取到和你其他设备同网段的IP地址,而不需要有docker0接口再进行一层NAT,分配到一个类似于172.17.0.3的地址。
4.3.2 Macvlan网络的优点和缺点
Macvlan网络有一些显著的优点。首先,由于Macvlan设备直接在数据链路层工作,它们可以提供接近物理网络的性能。其次,由于Macvlan设备有自己的MAC和IP地址,它们可以直接访问网络,无需通过宿主机进行路由或NAT转换。
然而,Macvlan网络也有一些限制。最重要的一点是,由于以太网的工作原理,Macvlan设备不能和宿主机直接通信。这是因为宿主机和Macvlan设备都在同一物理网络接口上,一个网络接口不能接收到自己发送的数据包。这意味着,如果你的应用需要和宿主机通信,你需要使用其他的解决方案,例如创建一个ipvlan设备或者另一个Macvlan网络使得宿主机和docker容器进行通信。
总的来说,Macvlan网络提供了一种强大而灵活的方式,可以让Docker容器直接访问物理网络。但是,你也需要了解其局限性,以确保它适合你的应用需求。在下一部分中,我们将深入讨论如何在Docker中创建和配置Macvlan网络,包括如何配置IPv6地址。
4.4 PODMAN容器使用MACVLAN
参考:https://blog.csdn.net/qq_45083975/article/details/126437324?spm=1001.2101.3001.6650.4&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7Ebaidujs_baidulandingword%7ECtr-4-126437324-blog-130736402.235%5Ev43%5Epc_blog_bottom_relevance_base5&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7Ebaidujs_baidulandingword%7ECtr-4-126437324-blog-130736402.235%5Ev43%5Epc_blog_bottom_relevance_base5&utm_relevant_index=9
4.4.1 创建 podman 的虚拟网络,本人局域网的网段为192.168.28.0/24,网关为路由器的192.168.28.1
podman network create -d macvlan --subnet=192.168.28.0/24 --gateway=192.168.28.1 -o parent=ens160 podman-bridge
4.4.2 解决配置文件版本不支持的警告
sed -i 's/1\.0\.0/0.4.0/g' /etc/cni/net.d/podman-bridge.conflist
4.4.3 创建 podman 容器,通过network参数指定前面创建的虚拟网络,ip参数指定容器的ip地址。下面是个例子,具体命令可以自行替换
podman run -d --name b9 --network=podman-bridge --ip=192.168.28.220 --privileged=true --volume /sys:/sys:ro localhost/my-new-image
podman run -d --name podman-container --network=podman-bridge --ip=192.168.28.220 --privileged=true localhost/ubuntu_systemd_podman
4.5 关于解决MACVLAN互通的问题
待验证:https://blog.csdn.net/lizy0327/article/details/113902744
4.5.1 MACVLAN
参考:https://zhuanlan.zhihu.com/p/553167787
https://post.smzdm.com/p/agq9mw53/
4.5.2 Macvlan网络的定义和工作原理
Macvlan是一种特殊类型的网络设备,它允许单个物理设备拥有多个MAC地址。这样做的结果是,你可以在物理网络接口上创建一个新的虚拟网络接口,这个接口有自己的MAC地址,IP地址,以及其他网络设置。
Macvlan工作的原理是通过在数据链路层插入虚拟网络接口,使得每个接口都有自己的MAC地址,从而可以独立的接收和发送数据包。这种设计使得Macvlan设备看起来就像一台独立的物理机器,连接在同一网络中。
通俗来说,就是创建了Macvlan网络之后,如果你的容器接入了该网络,那么它就像是一台电脑,有胳(网)膊(口)有腿(网线),接在了你的路由器上,这样就可以直接获取到和你其他设备同网段的IP地址,而不需要有docker0接口再进行一层NAT,分配到一个类似于172.17.0.3的地址。
4.5.3 Macvlan网络的优点和缺点
Macvlan网络有一些显著的优点。首先,由于Macvlan设备直接在数据链路层工作,它们可以提供接近物理网络的性能。其次,由于Macvlan设备有自己的MAC和IP地址,它们可以直接访问网络,无需通过宿主机进行路由或NAT转换。
然而,Macvlan网络也有一些限制。最重要的一点是,由于以太网的工作原理,Macvlan设备不能和宿主机直接通信。这是因为宿主机和Macvlan设备都在同一物理网络接口上,一个网络接口不能接收到自己发送的数据包。这意味着,如果你的应用需要和宿主机通信,你需要使用其他的解决方案,例如创建一个ipvlan设备或者另一个Macvlan网络使得宿主机和docker容器进行通信。
总的来说,Macvlan网络提供了一种强大而灵活的方式,可以让Docker容器直接访问物理网络。但是,你也需要了解其局限性,以确保它适合你的应用需求。在下一部分中,我们将深入讨论如何在Docker中创建和配置Macvlan网络,包括如何配置IPv6地址。