我使用以下命令在 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
更干净,因为它需要的更改更少。