ruby、openssl、unicorn、systemd (Gcloud) 的行为非常奇怪

Posted

技术标签:

【中文标题】ruby、openssl、unicorn、systemd (Gcloud) 的行为非常奇怪【英文标题】:very strange behaviour with ruby, openssl, unicorn, systemd (Gcloud) 【发布时间】:2018-08-08 16:55:24 【问题描述】:

我们开始在日志中看到一些奇怪的错误,这些错误通常在 ruby​​ 未使用 OpenSSL 正确编译时出现。但它不一致...

我们收到如下错误:

RuntimeError: Unsupported digest algorithm (SHA256).(还有其他摘要,例如 sha1)。 example error trace Faraday::SSLError (SSL_CTX_new: (null))example error trace

我们在使用service unicorn startsystemctl start unicorn 启动独角兽时设法重现了它。但只有 一些 请求......不是全部。一些在后台使用 OpenSSL 的请求确实有效。其他人没有。

但是,当我们使用 /etc/init.d/unicorn start 启动 unicorn 时,一切正常。(澄清一下,systemd 启动相同的 /etc/init.d 脚本)

我们尝试调试 ENV 变量、用户权限、文件/目录所有权、重新编译 ruby​​、从头开始引导新服务器...似乎没有任何帮助。

如果这有帮助:

unicorn init.d script unicorn.rb

我们缺少什么?我们可以尝试什么我们没有想到的?

更新 1

output of some debug commands,例如OpenSSL、ruby 等 正在设置路径inside the init.d script 独角兽被executed via su into www-data user 当我们在/etc/systemd/system 中使用this unicorn.service 文件时也会出现同样的问题 我们在 Gcloud 上运行 Ubuntu 16.04 Ruby 没有通过apt 安装(明确删除,以防平台预先安装)并从头开始编译。我们目前正在运行 2.3.4 并尝试过 2.3.6。手动或使用ruby-build 编译。没有rbenv,也没有RVM。 我们通过 apt 安装 libssl-dev(我们在构建 ruby​​ 之前运行 apt-get install -y autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm3 libgdbm-dev

更新 2

我们正在为 VM 使用脚本化/可重复的构建过程(使用结构),这个问题在我们在 GCloud 上引导的多个 VM 上是一致的。然后,我们使用相同的引导脚本在 DigitalOcean 上尝试了一个 VM,但问题似乎没有出现在那里。

在这两种情况下,我们都选择了 Ubuntu 16.04 64 位基础映像,但显然内核版本、基础安装包等存在一些差异......

更新 3

问题就这样消失了。请参阅下面的答案。

【问题讨论】:

我意识到这不是 SO 的经典问题,但我们被困住了,真的需要我们能得到的任何帮助。 我想说这个问题说得很好,对 SO 来说完全没问题。赞成。 你能发布你完整的 systemd 单元文件吗?有时,systemd 会做一些奇怪的事情,比如系统调用过滤、设置 chroot 或资源约束……这可能会以奇怪的方式,有时是不确定的方式影响已启动的进程。 我们不使用 systemd .service 文件。我们使用 init.d 文件。我们实际上尝试创建一个 .service 文件,但遇到了同样的问题。 在您的 systemd 服务文件中,您应该像在 init.d 文件中一样设置路径以进行奇偶校验:Environment="PATH=/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin:/sbin" 【参考方案1】:

@gingerlime 我在 GCP 上的 Jenkins 也遇到过类似的情况,我们使用的是 ChefDK 3.1.0(ruby embeed 2.5.1p57)——也尝试过其他的,通过运行在 systemd(Ubuntu 16.04)上的 Jenkins ) 和 upstart (Ubuntu 14.04) -- 我们在这两个版本上都进行了尝试,现在在 4.15.0-1023-gcp 内核版本中运行超过 16.04,使用 kitchen-docker 运行一些作业,这个问题总是在少数情况下出现。

我深入研究并发现这仅在调用Etc.getlogin 类时发生(for me here),这不会返回任何错误,它返回正确的信息,正确的类类型(String ),但一旦接到电话,Unsupported digest algorithm 就会被提升。

如果我由rootjenkins 用户手动启动该过程,则不会发生此问题。我尝试以几种不同的方式实现Etc.getlogin,例如使用ENV['USER']、固定字符串或Etc 中的其他类,例如getpwuid,模拟来自Etc.getlogin 的返回类和值,以及错误不会被提升。

我不确定这是否是与 ruby​​ 版本和 GCP 实例使用的自定义内核相关的错误,但它发生在与您类似的情况下,对我来说,Etc.getlogin 是问题所在。现在,我通过使用自定义配置进行了修复,该配置无法从该函数获取调用,并且可以正常工作。

【讨论】:

是的,我认为 GCP 上有些问题,但我无法弄清楚是什么。即使有金牌支持,他们也不会告诉我他们的平台做了哪些更改可能导致/解决了这些问题。【参考方案2】:

一种选择是,这根本不是sysVinitsystemd 的问题,但您还没有触发sysVinit 脚本的问题。

当您通过systemctl 命令运行您的svsVinit 脚本时,它会通过一个兼容层,并且那里可能存在问题。如果您直接使用systemd 服务文件复制问题并共享该文件,您自己和我们都会简化您的问题。

您提到了调试 ENV,但没有准确提及您在 ENV 中检查的内容。这绝对是systemd 可以发挥作用的地方。如man systemd.exec 中所见,systemd 将环境中的 $PATH 设置为固定值:

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

如果这与直接作为 sysVinit 脚本运行时不完全相同,那可能是个问题。

我还会检查系统上的所有 SSL 副本。你有不止一个吗?在哪里?您是否加载了多个 ruby openssl 模块的副本?

 locate -r lib/.*libssl.*so

另请参阅常见问题解答:Why do things behave differently under systemd?

【讨论】:

“我还会检查您系统上的所有 SSL 副本...” - +1。我有兴趣了解更多关于系统上安装的不同 OpenSSL 的信息。而且我想知道编译和链接到哪一个 Ruby;以及它运行时链接到哪一个。由于混合/匹配 OpenSSL 版本,我感觉这是一个间歇性内存错误。 感谢马克和@jww。我试图回答您的问题并提供更多信息。请参阅有关该问题的更新 1。很高兴运行更多的东西,回答更多的问题,尝试一些东西......我们在试图解决这个问题时感到沮丧。 有关SSLError (SSL_CTX_new: (null) 的相关帖子指出该问题与涉及的多个 SSL 版本有关,您的调试输出似乎确认系统上正在发生该问题。您可以尝试使用strace 运行应用程序,以确认崩溃前文件正在被访问。 @MarkStosberg 感谢您的帮助。赞成。问题突然消失了。这确实令人困惑和沮丧,但我们无法一下子重现它。而且它不只是在一个地方。在多个实例上,即使从快照恢复。请参阅上面的答案,尽管它并没有真正说明这一点。不过,我真的很感谢你的帮助。 感谢@MarkStosberg。有趣的理论! ...但我认为它不适用。我们可以使用本地 Rails 应用程序触发它,该应用程序仅使用根本不使用 SSL 的 mysql2 gem 连接到本地 sphinx 服务器。我不太熟悉 mysql2 gem 内部结构,也不太熟悉 sphinx 可以绝对肯定地告诉你。这个问题在这个本地设置上也突然消失了。此外,Digital Ocean 并没有发生这个问题,例如使用相同的外部资源......而且它还表现在非 SSL 本地操作,如 SHA1 摘要等......【参考方案3】:

(也发布在this github issue)

看起来问题刚刚消失。我们在 Google Cloud 上的多个 Compute Engine 实例中一致地测试和重现它。在某些条件下(由 systemd 启动的 unicorn / puma 等),无论是使用我们自己的 rails 应用程序还是使用我们为测试目的设置的普通 vanilla rails 应用程序,它都是完全可重现的。它也可以在多个 ruby​​ 版本中重现(我们测试了 2.3.4、2.3.6 和 2.5.0)。

突然间,所有持续失败的实例 开始工作而没有出现这些问题。就像它从未存在过一样。我们甚至没有重新启动其中的一些实例,我们也没有看到任何无人值守升级发生的证据……我们还有一个存在此问题的系统快照,并且我们可以可靠地在其上进行复制。从这个快照创建一个实例也从几个小时前的那个特定时间点开始停止展示它。

我们对可能导致它的原因以及可能导致它消失的原因完全感到困惑......但是,现在无法重现它,我想让这个问题保持开放是没有意义的,所以将其关闭.我想把它归结为Deus ex machina。 (也许是google支持大神,但他们还没有反馈给我们)

【讨论】:

以上是关于ruby、openssl、unicorn、systemd (Gcloud) 的行为非常奇怪的主要内容,如果未能解决你的问题,请参考以下文章

ruby unicorn.rb

ruby unicorn.rb

ruby 使用Unicorn作为Rails 3开发服务器

Ruby on Rails全栈课程5.5 项目上线--nginx+unicorn部署项目域名映射

ruby Ruby脚本,看看是否用openssl编译了ruby

text Ruby OpenSSL #memo #ruby