podman

使用 Podman 对容器镜像进行签名和分发

对容器映像进行签名源于仅信任专用映像提供程序的动机,以缓解中间人 (MITM) 攻击或对容器注册表的攻击。对图像进行签名的一种方法是使用 GNU 隐私卫士 (GPG) 密钥。此技术通常与任何符合 OCI 的容器注册表(如 Quay.io)兼容。值得一提的是,OpenShift 集成容器注册表开箱即用地支持这种签名机制,这使得单独的签名存储变得不必要。

从技术角度来看,我们可以在将映像推送到远程注册表之前利用 Podman 对映像进行签名。之后,所有运行Podman的系统都必须配置为从远程服务器检索签名,远程服务器可以是任何简单的Web服务器。这意味着在映像拉取操作期间,每个未签名的映像都将被拒绝。但是这是如何工作的呢?

首先,我们必须创建一个GPG密钥对或选择一个本地可用的密钥对。要生成新的GPG密钥,只需运行并按照交互式对话框进行操作即可。现在我们应该能够验证密钥是否在本地存在:gpg --full-gen-key
Podman 对容器镜像进行签名和分发官方写法

Podman 远程客户端

Podman 远程客户端官方写法

配置 podman 服务

hehe是服务端的用户,并且能进行 sudo 操作。服务端 的主机名是 node-1。

$ ssh hehe@localhost
$ systemctl --user enable podman.socket
Created symlink /home/hehe/.config/systemd/user/sockets.target.wants/podman.socket → /usr/lib/systemd/user/podman.socket.
$ systemctl --user start podman.socket
$ sudo loginctl enable-linger hehe
[sudo] hehe 的密码:

客户端 远程访问 podman
直接访问远程 podman
可以用 --url 参数访问节点 1 的远程 podman 服务。
$ NODE_1_IP=<YOUR-IP>

$ podman-remote --url ssh://hehe@${NODE_1_IP}/run/user/1000/podman/podman.sock info | grep hostname
Login password:
  hostname: node-1

使用 Connection 访问

可以创建 connection 记录远程访问方式。

$ podman system connection add remote-1 ssh://hehe@${NODE_1_IP}/run/user/1000/podman/podman.sock
$ podman system connection list
Name        URI                                                             Identity    Default
remote-1    ssh://hehe@192.168.40.99:22/run/user/1000/podman/podman.sock              true

使用 --connection 访问服务端 的podman 服务。如果是 Default 的 connection,可以不用写。由于以上的 connection 没有配置 Identity,因此远程访问还需要提供服务端 的 hehe 密码。

$ podman-remote info | grep hostname
Login password:
  hostname: node-1
 
$ podman-remote --connection remote-1 info | grep hostname
Login password:
  hostname: node-1

另外还可在客户端 上用 podman --remote 也会使用远程方式访问。

$ podman --remote --url ssh://hehe@${NODE_1_IP}/run/user/1000/podman/podman.sock info | grep hostname
Login password:
  hostname: node-1

使用 Connection 免密访问
执行命令生成公钥私钥对,所有都回车即可。

$ ssh-keygen -t tr25508

将公钥文件的内容复制到服务端目标用户下的 ~/.ssh/authorized_keys 文件里。执行完命令可自行确认。

$ sh-copy-id -i .ssh/id_ed25519.pub hehe@${NODE_1_IP}
dawnsky@192.168.40.99's password:
 
Number of key(s) added: 1
 
Now try logging into the machine, with:   "ssh 'hehe@192.168.40.99'"
and check to make sure that only the key(s) you wanted were added.

执行命令创建一个新的 connection 配置,其中配置有访问证书。

$ podman system connection add --identity .ssh/id_tr25508remote-no-password ssh://hehe@192.168.4.99/run/user/1000/podman/podman.sock
$ podman system connection list
Name                URI                                                             Identity         Default
remote-1            ssh://dawnsky@192.168.40.99:22/run/user/1000/podman/podman.sock                   true
remote-no-password  ssh://hehe@192.168.40.99:22/run/user/1000/podman/podman.sock
$ podman-remote --connection remote-no-password info | grep hostname
  hostname: node-2

podman网络

podman网络官方

rootfull和rootless容器网络之间的差异

podman容器联网的指导因素之一将是容器是否由root用户运行。这是因为非特权用户无法在主机上创建网络接口。因此,对于rootfull容器,默认网络模式是使用容器网络接口(CNI)插件,特别是桥接插件。对于rootless,默认的网络模式是slir4netns。由于权限有限,slirnetns缺少CNI组网的一些功能;例如,slirp4netns无法为容器提供可路由的IP地址。cni是容器网络接口

防火墙

防火墙的作用不会影响网络的设置和配置,但会影响这些网络上的流量。最明显的是容器主机的入站网络流量,这些流量通常通过端口映射传递到容器上。根据防火墙的实现,我们观察到防火墙端口由于运行带有端口映射的容器(例如)而自动打开。如果容器流量似乎无法正常工作,请检查防火墙并允许容器正在使用的端口号上的流量。一个常见的问题是重新加载防火墙会删除cni iptables规则,从而导致rootful容器的网络连接丢失。podman v3提供了podman network reload命令来恢复它而无需重新启动容器。

基本网络设置

大多数使用 Podman 运行的容器和 Pod 都遵循几个简单的场景。默认情况下,rootfull Podman 将创建一个桥接网络。这是 Podman 最直接和首选的网络设置。桥接网络在内部桥接网络上为容器创建一个接口,然后通过网络地址转换(NAT)连接到互联网。我们还看到用户也希望macvlan 用于联网。这macvlan插件将整个网络接口从主机转发到容器中,允许它访问主机所连接的网络。最后,无根容器的默认网络配置是 slirp4netns。slirp4netns 网络模式功能有限,但可以在没有 root 权限的用户上运行。它创建了一个从主机到容器的隧道来转发流量。

容器间通信示例

[root@localhost ~]# podman run -it --name test docker.io/library/busybox:latest /bin/sh  // 启动一个test容器
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0@if4: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 52:88:dc:58:af:08 brd ff:ff:ff:ff:ff:ff
    inet 10.88.0.2/16 brd 10.88.255.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::5088:dcff:fe58:af08/64 scope link 
       valid_lft forever preferred_lft forever

再启动一个test1的容器

[root@localhost ~]# podman run -it --name test1 docker.io/library/busybox:latest /bin/sh

/ # ping -c2 10.88.0.2
PING 10.88.0.2 (10.88.0.2): 56 data bytes
64 bytes from 10.88.0.2: seq=0 ttl=64 time=0.087 ms
64 bytes from 10.88.0.2: seq=1 ttl=64 time=0.080 ms

--- 10.88.0.2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.080/0.083/0.087 ms

每当启动一个容器就会在宿主机上启动一个veth类型的网卡,当容器停止运行就会关闭

[root@localhost ~]# ifconfig
3: cni-podman0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether ca:18:8f:f7:90:cc brd ff:ff:ff:ff:ff:ff
    inet 10.88.0.1/16 brd 10.88.255.255 scope global cni-podman0
       valid_lft forever preferred_lft forever
    inet6 fe80::c818:8fff:fef7:90cc/64 scope link 
       valid_lft forever preferred_lft forever
4: veth068c0b11@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master cni-podman0 state UP group default 
    link/ether 6a:b9:83:ce:04:eb brd ff:ff:ff:ff:ff:ff link-netns cni-9fe9f57d-2a01-c3fe-4dfa-a0d2213ff9a1
    inet6 fe80::68b9:83ff:fece:4eb/64 scope link 
       valid_lft forever preferred_lft forever
5: vethb5141e5a@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master cni-podman0 state UP group default 
    link/ether 7e:d1:e5:fe:28:15 brd ff:ff:ff:ff:ff:ff link-netns cni-4d8b67ae-52cd-b9c9-3f58-d56ccd1d70c7
    inet6 fe80::7cd1:e5ff:fefe:2815/64 scope link 
       valid_lft forever preferred_lft forever

查看防火墙规则

[root@localhost ~]# iptables -t nat -nvL
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

运行容器测试

[root@localhost ~]# podman run -d -p 80:80 --name web --rm docker.io/library/httpd
[root@localhost ~]# iptables -t nat -nvL
Chain CNI-HOSTPORT-DNAT (2 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 CNI-DN-221138b7a7c984de5db72  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            /* dnat name: "podman" id: "2a378d287e05363c44bcd4bddbf62bcdaa59dbf58b52dfe413c66051e94af9d8" */ multiport dports 80

[root@localhost ~]# podman inspect -l | grep -i address  //查看容器的IP地址
            "IPAddress": "10.88.0.6",
            "GlobalIPv6Address": "",
            "MacAddress": "32:5f:7b:f4:53:ad",
            "LinkLocalIPv6Address": "",
                    "IPAddress": "10.88.0.6",
                    "GlobalIPv6Address": "",
                    "MacAddress": "32:5f:7b:f4:53:ad",
[root@localhost ~]# curl 10.88.0.6  //访问测试
<html><body><h1>It works!</h1></body></html>

使用重启容器恢复防火墙规则

[root@localhost ~]# iptables -t nat -F  //清空防火墙规则
[root@localhost ~]# iptables -t nat -nvL  // 没有80了
[root@localhost ~]# iptables -t nat -nvL
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain CNI-HOSTPORT-SETMARK (0 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain CNI-HOSTPORT-MASQ (0 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain CNI-HOSTPORT-DNAT (0 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain CNI-221138b7a7c984de5db72695 (0 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain CNI-DN-221138b7a7c984de5db72 (0 references)
 pkts bytes target     prot opt in     out     source               destination

重启容器

[root@localhost ~]# podman restart -l
73d028b2e5469bc836c0aa613b0ccf852a42098c64a70128516537f74906e348

[root@localhost ~]# iptables -t nat -nvL
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 CNI-HOSTPORT-DNAT  all  --  *      *       0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    1    76 CNI-HOSTPORT-MASQ  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* CNI portfwd requiring masquerade */
    0     0 CNI-22189af7f3e87acc96dda61c  all  --  *      *       10.88.0.10           0.0.0.0/0            /* name: "podman" id: "73d028b2e5469bc836c0aa613b0ccf852a42098c64a70128516537f74906e348" */

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 CNI-HOSTPORT-DNAT  all  --  *      *       0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain CNI-HOSTPORT-SETMARK (2 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* CNI portfwd masquerade mark */ MARK or 0x2000

Chain CNI-HOSTPORT-MASQ (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 MASQUERADE  all  --  *      *       0.0.0.0/0            0.0.0.0/0            mark match 0x2000/0x2000

Chain CNI-HOSTPORT-DNAT (2 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 CNI-DN-22189af7f3e87acc96dda  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            /* dnat name: "podman" id: "73d028b2e5469bc836c0aa613b0ccf852a42098c64a70128516537f74906e348" */ multiport dports 80

容器的开机自启

[root@localhost ~]# podman create --name nginx nginx:latest 
dc579013274433766bf6cbf29adb9d02ffc8518f37365e6bb4b350f7b68af954

[root@localhost ~]# systemctl start container-nginx.service // 启动服务并查看状态
[root@localhost ~]# systemctl status container-nginx.service 
[root@localhost ~]# systemctl enable --now container-nginx.service   //设置开机自启

普通用户设置容器的开机自启
首先需要使用ssh的方式连接到普通用户而不能使用sudo或者su命令

[root@localhost ~]# ssh haha@192.168.40.99

// 创建此目录用来存放unit文件
[haha@localhost ~]$ mkdir -p ~/.config/systemduser/user/

// 配置redhat quay registry的证书可信
[root@localhost ~]# scp -rp root@localhost:/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem /etc/pki/tls/certs/ca-bundle.crt

[haha@localhost user]$ mkdir  hehe

[haha@localhost ~]$ podman run -d --name web -v /home/user/hehe/:/var/hehe:Z nginx

[haha@localhost ~]$ podman generate systemd --name web --files  //生成service文件
[haha@localhost ~]$ systemctl --user daemon-reload  //重新加载使其生效
[haha@localhost ~]$ systemctl --user enable container-web.service --now  //设置开机自启
[haha@localhost ~]$ systemctl --user status container-web.service 

本文Podman 远程客户端参考链接:https://blog.csdn.net/weixin_43902588/article/details/124796454
本文podman网络参考链接:https://blog.csdn.net/qq_60387497/article/details/121940197

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值