1

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

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

Dockerfile 的最后一个命令是 USER 26,其中 26 是 postgres 用户的 id。入口点脚本可以以 postgres 用户或sudo user.

一切都在 Docker 中运行良好。

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

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

谢谢!

最好的问候, rimetnac

4

3 回答 3

2

你有两个选择。

首选是修复您的映像,以便它可以以任何用户身份运行。为此,请勿使用现有postgres用户。创建一个新用户,该用户拥有 group root。然后确保 PostgreSQL 需要写入的所有目录/文件都归该用户所有,但也具有组root和组可写。当容器随后启动时,它将作为分配的用户 ID 运行,而不是在 中/etc/passwd,因此仍将回退到使用组root。因为目录/文件对 group 是可写的root,所以一切仍然有效。有关更多信息,请参阅:

具体来说,“支持任意用户 ID”部分。

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

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

oc create serviceaccount runasnonroot

接下来授予该服务帐户作为其选择的非 root 用户 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。

于 2018-04-07T01:56:31.337 回答
2

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

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

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

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

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

    1. 使用一个名为 nss_wrapper 的包,“它拦截任何查找用户详细信息并返回有效条目的调用。”

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

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


最好的解决方案是构建 docker 镜像以作为用户运行 OpenShift Origin 将运行镜像。我用它构建了这个教学图像

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

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

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

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

  1. 切换到非root用户。

这是必需的,因为 initdb 可执行文件必须“以拥有服务器进程的用户身份执行,因为服务器需要有权访问 initdb 创建的文件和目录”(PostgreSQL 文档),并且因为 PostgreSQL 服务器将启动到设置在 OpenShift Origin 上运行服务器所需的组件(例如角色和数据库)。

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

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

于 2018-06-15T20:43:32.207 回答
1

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

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

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

谢谢大家的贡献。

于 2018-06-20T08:11:27.250 回答