Buildah 脚本故障排除

问题的根源通常在你最意想不到的地方。
233 位读者喜欢这篇文章。
GitHub launches Open Source Friday 

Opensource.com

作为一名青少年的父亲和一名软件工程师,我大部分时间都在处理问题。无论问题是大是小,很多时候你都无法通过直接观察来找到问题的原因。相反,你需要退后一步,调查问题存在的环境。我最近意识到了这一点,当时一位同事向我寻求帮助,他经常演示容器技术,包括像 容器管理器,例如 BuildahPodman。他计划在几天后的一次会议上展示一个演示脚本,但遇到了问题。

这个脚本过去运行良好,但现在却不行了,他正处于困境。这是一个演示脚本,它使用 Buildah 创建一个基于 Fedora 28 的容器,并在其中安装 NGINX HTTPD 服务器。然后它使用 Podman 运行容器并启动 NGINX 服务器。最后,脚本执行一个快速的 curl 命令来拉取 index.html 文件,以证明服务器已启动并响应。所有这些命令在设置和测试期间都运行良好,但现在 curl 失败了。(顺便说一句,如果你想了解 Buildah 或运行演示,请查看我的同事的 完整脚本,因为它是一个很好的脚本。)

我与 Podman 团队的人员进行了交谈,他们无法重现这个问题,所以我认为这可能是 Buildah 中的问题。我们进行了一系列调试和检查配置代码,以确保端口设置正确,镜像被正确拉取,并且一切都被保存。一切都检查完毕。之前的演示运行都已成功完成:NGINX 服务器会按预期提供 index.html。这很奇怪,并且 Buildah 代码最近的更改不太可能破坏任何这些。

随着会议截止日期临近,我开始调查,并将脚本缩小到以下内容。

cat ~/tom_nginx.sh
#!/bin/bash

# docker-compatibility-demo.sh
# author : demodude
# Assumptions install buildah, podman & docker
# Do NOT start the docker deamon
# Set some of the variables below

demoimg=dockercompatibilitydemo
quayuser=ipbabble
myname="Demo King"
distro=fedora
distrorelease=28
pkgmgr=dnf # switch to yum if using yum

#Setting up some colors for helping read the demo output
bold=$(tput bold)
red=$(tput setaf 1)
green=$(tput setaf 2)
yellow=$(tput setaf 3)
blue=$(tput setaf 4)
cyan=$(tput setaf 6)
reset=$(tput sgr0)

echo -e "Using ${green}GREEN${reset} to introduce Buildah steps"
echo -e "Using ${yellow}YELLOW${reset} to introduce code"
echo -e "Using ${blue}BLUE${reset} to introduce Podman steps"
echo -e "Using ${cyan}CYAN${reset} to introduce bash commands"
echo -e "Using ${red}RED${reset} to introduce Docker commands"

echo -e "Building an image called ${demoimg}"

set -x
newcontainer=$(buildah from ${distro})
buildah run $newcontainer -- ${pkgmgr} -y update && ${pkgmgr} -y clean all
buildah run $newcontainer -- ${pkgmgr} -y install nginx && ${pkgmgr} -y clean all
buildah run $newcontainer bash -c 'echo "daemon off;" >> /etc/nginx/nginx.conf'
buildah run $newcontainer bash -c 'echo "nginx on OCI Fedora image, built using Buildah" > /usr/share/nginx/html/index.html'
buildah config --port 80 --entrypoint /usr/sbin/nginx $newcontainer
buildah config --created-by "${quayuser}" $newcontainer
buildah config --author "${myname}" --label name=$demoimg $newcontainer
buildah inspect $newcontainer
buildah commit $newcontainer $demoimg
buildah images
containernum=$(podman run -d -p 80:80 $demoimg)
curl localhost # Failed
podman ps
podman stop $containernum
podman rm $containernum

脚本的作用

set -x 部分开始,你可以看到脚本使用 buildah from 创建一个新的 Fedora 容器。接下来的四个步骤使用 buildah run 在容器中进行一些配置:前两个步骤使用 DNF 软件包管理器进行更新、安装 NGINX 并清理所有内容;第三步和第四步准备运行 NGINX——第三步设置 /etc/nginx/nginx.conf 文件并设置 daemon off,第四步中的 run 命令创建要显示的 index.html 文件。

随后的三个 buildah config 命令在容器内进行一些内务处理。它们设置端口 80,设置 NGINX 的入口点,并润色新容器中的 created-byauthorlabel 字段。此时,容器已设置为运行 NGINX,buildah inspect 命令允许你浏览容器的字段和关联的元数据,以验证所有这些。

此脚本使用 Podman 运行容器和 NGINX 服务器。Podman 是一个新的开源实用程序,用于处理 Linux 容器和 Kubernetes Pod,它模拟 Docker 命令行的许多功能,但不需要像 Docker 那样的守护程序。为了让 Podman 运行容器,必须首先将其保存为镜像——这就是 buildah commit 行的作用。

最后,podman run 行启动容器,并且——由于我们使用入口点和设置端口的方式配置了它——NGINX 服务器启动并可供使用。说服务器“正在运行”总是很高兴,但能够与服务器交互才是证明。因此,脚本执行一个简单的 curl localhost;如果它工作正常,index.html 应该包含

nginx on OCI Fedora image, built using Buildah

然而,在距离下一次演示只有几个小时的时候,它却返回了

curl: (7) Failed to connect to jappa.cos.redhat.com port 80: Connection refused

现在,这不太好。

诊断问题

我在我的开发虚拟机 (VM) 上反复遇到这个问题。我添加了调试语句,但仍然没有发现任何问题。奇怪的是,我发现如果在脚本中将 podman 替换为 docker,一切都运行良好。我通常对我的开发虚拟机不太友好,所以我设置了一个新的虚拟机,并安装了所有全新的东西。

脚本在那里也失败了,所以不是我的开发虚拟机本身行为不端。我在思考问题时多次运行脚本,希望从输出中获得任何线索。我的下一个想法是进入容器并在其中查看。我注释掉了 stoprm 行,并使用以下命令重新运行脚本

podman exec --tty 129d4d33169f /bin/bash

其中 129d4d33169f 是容器的 podman ps 命令中的 CONTAINER ID 值。我在容器内运行 curl localhost!我收到了来自 index.html 的正确输出。然后我退出了容器,并再次从运行容器的主机尝试了 curl 命令,这次它工作了。

最后,我恍然大悟。在过去的测试中,我一直在使用 Apache HTTPD 服务器,并尝试从另一个会话连接到它。在这些测试中,如果我操作太快,服务器会拒绝我。

可能就这么简单吗?

事实证明,就是这么简单。我们在 podman runcurl localhost 命令之间添加了一个 sleep 3 行,一切都按预期工作了。似乎发生的情况是 podman run 命令非常快速地启动了容器和 NGINX 服务器,并返回到命令行。如果你不等待几秒钟,NGINX 服务器就没有时间启动并开始接受连接请求。

在我们使用 Docker 进行的测试中,情况并非如此。我没有深入研究它,但我的假设是 Docker 花费与 Docker 守护程序通信的时间足以让 NGINX 服务器完全启动。这就是 Buildah 和 Podman 非常有用和强大的原因:没有守护程序,开销更少。但你需要在演示中考虑到这一点!

问题确实是工程师们解决的,而且答案通常不在代码本身中。在查看问题时,最好退后一步,不要太专注于位和字节。


本文的早期版本最初出现在 ProjectAtomic.io 博客上。

标签
User profile image.
Red Hat 的软件工程师,致力于容器技术。丈夫和 3 个孩子的父亲,只是想管住他们!

评论已关闭。

© . All rights reserved.