Docker容器中crond服务启动后无法执行

目录

问题现象

在 Docker 容器内安装 crontab 后,启动 crond 服务但任务无法执行。

环境:

  • CentOS 6.7
  • 内核:Linux 3.10.101-1.el6.elrepo.x86_64
yum install crontabs
/etc/init.d/crond start
crontab -l
# */1 * * * * echo "aaaaaaaaaaaaa" >> /tmp/test.log

等待几分钟,发现 /tmp/test.log 文件未出现,说明 crond 没有正常工作。

排查步骤

启用 rsyslog 查看日志

/etc/init.d/rsyslog start
tail /var/log/crond

可能看到错误:FAILED to open PAM security session (Cannot make / remove an entry for the specified session)

查看 /var/log/securepam_loginuid(crond:session): set_loginuid failed

根本原因

pam_loginuid.so 模块用来设置已通过认证的进程的 uid,以使程序通过审核(audit)。但在 Docker 容器内,由于内核能力机制的安全限制,容器被严格限制只允许使用内核的部分能力。容器无法获取这些特权进程信息,导致 crond 启动时的 set_loginuid 失败。

由于 PAM 配置中使用了 required 机制(所有条件均须满足),这导致 crond 执行失败。

解决方案

修改 /etc/pam.d/crond,将 pam_loginuid.sorequired 改为 sufficient

cat /etc/pam.d/crond
# account required pam_access.so
# account include password-auth
# #session required pam_loginuid.so  #注释此行
# session include password-auth
# auth include password-auth

或者直接注释掉该行:

# cat /etc/pam.d/crond
# #session required pam_loginuid.so #注释此行
# session sufficient pam_loginuid.so

重启 crond:

/etc/init.d/crond restart
tailf /tmp/test.log  # 此时应该能看到任务执行日志

补充说明

PAM 鉴证级别(四种取值):

  • required:该行以及所有模块的成功是用户通过鉴别的必要条件。任何错误都会继续执行所有模块,最后才返回错误。
  • requisite:同 required,但某个模块失败会立即返回错误。
  • sufficient:该模块验证成功是用户通过鉴别的充分条件。成功则立即返回成功,失败则当做 optional 对待。
  • optional:模块验证结果忽略,不影响最终结果。

在 Docker 容器中,使用 sufficient 而不是 required 可以让鉴证在 pam_loginuid 成功时直接通过,失败时进行其他尝试,从而绕过容器权限限制。

#docker #crontab