如何记录由 podman 运行的官方 nginx docker 镜像

如何记录由 podman 运行的官方 nginx docker 镜像

我使用以下命令在 root 下的 podman 中启动了官方 nginx 映像:

sudo podman run --name nginx \
 ... \
 -v /var/log/nginx:/var/log/nginx \
 docker.io/library/nginx:latest

日志记录工作正常,但是当尝试使用从互联网获取的所有配置在主机上进行 logrotate 时,它​​会失败,例如:

/var/log/nginx/*.log {
 hourly
 missingok
 rotate 24
 compress
 delaycompress
 notifempty
 su root root
 create 0644
 sharedscripts
 postrotate
    podman exec nginx /bin/bash reset_log.sh
 endscript
}

reset_log.sh 脚本包含启动新日志的众所周知的命令,如果登录到容器并手动运行,它会按预期工作:

 kill -USR1 `cat /var/run/nginx.pid`

但所有这些东西并没有按预期一起工作,日志记录继续记录到 access.log.1 文件或根本不记录日志。尝试了没有“su root root”、没有“create ..”的变体 - 没有成功。

更新:似乎存在权限问题,需要更多调查。手动强制命令 logrotate -f -v /etc/logrotate.conf 按预期工作。主机上未安装 selinux 或 apparmor (arch linux)

systemd[1]: Starting Rotate log files...
conmon[4388]: conmon 32834b35446220b4e6d4 <nwarn>: runtime stderr: setns `mnt`: Operation not permitted
                                fail startup
conmon[4388]: conmon 32834b35446220b4e6d4 <error>: Failed to create container: exit status 1
logrotate[4377]: Error: crun: setns `mnt`: Operation not permitted: OCI permission denied
logrotate[4374]: error: error running shared postrotate script for '/var/log/nginx/*.log '
systemd[1]: logrotate.service: Main process exited, code=exited, status=1/FAILURE
systemd[1]: logrotate.service: Failed with result 'exit-code'.
systemd[1]: Failed to start Rotate log files.

答案1

最简单的解决方案可能是将您的使用替换podman exec nginx ...podman kill

/var/log/nginx/*.log {
 hourly
 missingok
 rotate 24
 compress
 delaycompress
 notifempty
 su root root
 create 0644
 sharedscripts
 postrotate
    podman kill --signal USR1 nginx
 endscript
}

这是有效的,因为podman kill将指定的信号发送到容器中的 PID 1,我们知道该容器是 nginx。我们不需要/var/run/nginx.pid,也根本不需要进入容器,这样就避免了导致“OCI Permission Denied”错误的问题。


根本问题是该logrotate服务在启用各种保护的情况下运行;看看/lib/systemd/system/logrotate.service(Rocky 9),我们看到:

[Service]
Type=oneshot
ExecStart=/usr/sbin/logrotate /etc/logrotate.conf

# performance options
Nice=19
IOSchedulingClass=best-effort
IOSchedulingPriority=7

# hardening options
#  details: https://www.freedesktop.org/software/systemd/man/systemd.exec.html
#  no ProtectHome for userdir logs
#  no PrivateNetwork for mail deliviery
#  no NoNewPrivileges for third party rotate scripts
#  no RestrictSUIDSGID for creating setgid directories
LockPersonality=true
MemoryDenyWriteExecute=true
PrivateDevices=true
PrivateTmp=true
ProtectClock=true
ProtectControlGroups=true
ProtectHostname=true
ProtectKernelLogs=true
ProtectKernelModules=true
ProtectKernelTunables=true
ProtectSystem=full
RestrictNamespaces=true
RestrictRealtime=true

关键限制是RestrictNamespaces=true选项;从文档:

限制本单元进程访问 Linux 命名空间功能...如果为 true,则禁止访问任何类型的命名空间。

除此之外,这会阻止访问备用安装命名空间,因此podman exec无法工作。您可以使用 systemd 覆盖单元消除限制,但使用podman kill更干净,因为它需要的更改更少。

相关内容