Openshift 中的 PostgreSQL 不会执行入口点并且无法启动数据库

PostgreSQL in Openshift won't execute the entrypoint and can not start the database

我们有一个只读的 Postgresql 数据库,它应该 运行 在 Openshift 集群中。 我们使用 RHEL 作为底层操作系统。 我们的 Docker 文件将安装 postgres 软件,创建数据库实例,将数据加载到其中,然后关闭数据库并保存图像。 我们仅使用 bash 和 sql 脚本并使用 flyway 部署数据库。

启动容器时,入口点脚本将简单地使用 "pg_ctl" 命令启动数据库实例,然后执行无限循环以保持容器 运行ning。

Docker文件的最后一个命令是 USER 26,其中 26 是 postgres 用户的 ID。入口点脚本可以作为 postgres 用户或由 sudo user.

启动

Docker一切正常。

在 Openshift 中,容器由属于 root 组的不同用户启动,但不是 root 用户或用户 26。实际上 Openshift 忽略了 Docker 文件中的 USER 26 子句。 启动容器的用户(我们称它为 containeruser)无论如何都没有启动 postgres 实例的权限,因此当 运行 进入入口点时,它将获得对 postgresql 数据文件夹的拒绝权限。 我尝试了不同的选项,将 containeruser 用户添加到 wheel 组并修改 sudoers 文件以允许它使用 sudo 并以 postgres 用户身份启动入口点但没有成功。 所以我准备好了我的数据库映像,但无法在 Openshift 中启动它。 在 openshift 配置方面,我们不允许进行更改,例如允许使用 sudo,或以 root 或 postgres 用户身份启动容器。

对这个问题有什么想法或帮助吗? 我不是 Openshift 专家。

谢谢!

此致, 雷美萘

你有两个选择。

首选是修复您的图像,以便它可以 运行 作为任何用户。为此,请勿使用现有的 postgres 用户。创建一个新用户,该用户拥有组 root。然后确保 PostgreSQL 需要写入的所有 directories/files 都属于该用户,但也有组 root 并且可以由组写入。当容器随后启动时,它将 运行 作为分配的用户 ID,而不是 /etc/passwd,因此将回退到仍然使用组 root。因为 directories/file 可写到组 root,所以一切仍然有效。有关详细信息,请参阅:

具体来说,第 'Support Arbitrary User IDs'.

部分

如果您拥有集群的管理员控制权,并且您的安全团队不反对您覆盖默认安全模型,则第二个选项是允许您的图像 运行 作为它想要的用户 ID到.

首先创建一个新的服务帐户:

oc create serviceaccount runasnonroot

接下来授予该服务帐户 运行 作为其选择的非根用户 ID 的能力。

oc adm policy add-scc-to-user nonroot -z runasnonroot --as system:admin

然后修补部署配置以使用该服务帐户。

oc patch dc/mydatabase --patch '{"spec":{"template":{"spec":{"serviceAccountName": "runasnonroot"}}}}'

请注意,这仍然需要您在图像中使用 USER 和整数用户 ID,而不是 postgres。否则它无法验证它将 运行 作为非 root 用户。那是因为如果您使用用户名而不是用户 ID,您可能会恶意地将其映射到 root。

我花了好几天时间来解决这个问题并找到了一个很好的解决方案。

OpenShift Origin 运行是它创建的用户图像,如 this OpenShift 博客 post 中所述。这会阻止程序访问所需的文件和目录。为了在 OpenShift Origin 上成功 运行 一个程序,博客 post 提供了两个解决方案,但是,第一个不适用于 PostgreSQL,第二个有两个缺点(在注释中解释):

  1. 授予组对主程序使用的目录的写入权限。

这不会解决问题,因为尽管任何程序都可以访问 PostgreSQL 文件,但它们必须由 PostgreSQL 进程的所有者拥有。

  1. 确保当操作系统库用于查找系统用户时,返回一个作为用户 OpenShift Origin 运行s 图像的 ID。以下是执行此操作的两种方法:

    1. 使用名为 nss_wrapper、"which intercepts any calls which look up details of a user and returns a valid entry."

    2. 的包
    3. 使 UNIX 密码数据库文件 (/etc/passwd) 在映像构建中具有全局写入权限,以便可以在 S2I 运行 脚本中将 OpenShift 用户添加到其中.

每个选项都有缺点:1. 安装额外的软件包和 2. 使用户帐户不安全。


最好的解决方案是将 docker 图像构建为 运行 as 用户 OpenShift Origin 将 运行 图像作为。我用它构建了 this instructional image

另外一个需要注意的问题是,由于PostgreSQL进程的所有者必须是PostgreSQL访问的文件和目录的所有者,因此在执行过程中必须设置PostgreSQL(即initdb、角色、数据库等)图像构建。这是因为文件所有权只能在映像构建期间更改,并且文件的所有权必须在设置 PostgreSQL 后更改,原因在下面的 #2 中解释。

以下是在映像构建中设置 PostgreSQL 的完整步骤和注释:

  1. 手动创建 PostgreSQL 数据目录并将其所有权更改为非根用户,该用户将用于初始化 PostgreSQL 并设置 运行 OpenShift 服务器所需的组件(例如角色和数据库)来源.

这是必需的,因为 "initdb" 可执行文件必须由 root 以外的用户执行,并且需要访问数据目录。此外,此用户不能是 OpenShift Origin 将 运行 图像视为系统中的用户。

  1. 切换到非根用户。

这是必需的,因为必须执行 initdb 可执行文件 "as the user that will own the server process, because the server needs to have access to the files and directories that initdb creates"(PostgreSQL 文档)并且因为 PostgreSQL 服务器将启动以设置 运行 OpenShift Origin 上的服务器。

  1. 运行 "initdb" 可执行文件。
  2. 启动 PostgreSQL 服务器,设置所需的组件(角色、数据库等)并停止 PostgreSQL 服务器。
  3. 切换回根用户。
  4. 将 PostgreSQL 文件和目录的所有权更改为用户 OpenShift Origin 将 运行 图像作为。

编辑 (06/20/18):我发现在构建映像后有一个设置 PostgreSQL 的解决方案。用户 OpenShift Origin 将 运行 可以在构建开始时添加到系统的图像。这将允许在映像构建后设置 PostgreSQL 并更改其文件和目录的所有权。

收集所有贡献者的评论后,我可以按如下方式回答我的问题:

  1. 选项 1 在镜像构建期间创建 postgres 数据库时,您必须配置 openshift 策略以允许以在镜像构建期间创建数据库的用户身份启动容器。当数据库必须填充数据并且此操作需要很长时间使其不适合容器启动时,请使用此选项。入口点只会启动已经准备好的数据库。
  2. 选项 2 使用入口点脚本启动容器时创建数据库。当数据库创建速度快到可以在容器启动时完成时使用此选项。

  3. 选项 3 请参阅 Adrian 的最后一条评论,它似乎回答了所有问题,但我没有时间测试它。

感谢大家的贡献。