1

我正在使用 Kubernetes v1.2.4(在 CoreOS stable 1010.5.0 之上)并且想挂载 rbd/ceph 卷。基本上我已经关注了https://github.com/kubernetes/kubernetes/tree/master/examples/rbd,除了我更喜欢 YAML 而不是 JSON。

注意到必须同时存在:

secretRef:
  name: ceph-secret

keyring: /etc/ceph/keyring

否则 kubectl 抱怨。这是预期的行为吗?

似乎 kubelet 试图直接在主机上调用 rbd 二进制文件(这对于像 CoreOS 这样的“裸系统”来说是一个问题)。由于复制二进制文件和依赖项会有点麻烦,我做了这个技巧:

$ cat /opt/bin/rbd
#!/bin/sh
docker run -v /etc/ceph:/etc/ceph ceph/rbd $@

负责 /etc/ceph 配置,使 shell 脚本可执行等等 - 如果我在 CoreOS 上执行“rbd list”,一切正常。/opt/bin(除了默认在 CoreOS 上的 PATH 上)也在 kubelet 进程的 PATH 中(我可以通过 /proc/kubelet pid/environ 确认)。

但是,如果我启动(测试)pod,我会收到此错误(在 kubectl pod describe 中):

Events:
  FirstSeen LastSeen    Count   From                SubobjectPath   Type        Reason      Message
  --------- --------    -----   ----                -------------   --------    ------      -------
  5s        5s      1   {default-scheduler }                Normal      Scheduled   Successfully assigned busybox4 to some-host
  4s        4s      1   {kubelet some-host}         Warning     FailedMount Unable to mount volumes for pod "busybox4_default(5386c7f3-3959-11e6-a768-aa00009a7832)": rbd: map failed fork/exec /opt/bin/rbd: invalid argument
  4s        4s      1   {kubelet some-host}         Warning     FailedSync  Error syncing pod, skipping: rbd: map failed fork/exec /opt/bin/rbd: invalid argument

所以 fork() 或 execve() 返回 EINVAL?通过阅读一些手册页,我发现只有 exec 实际上可能会因 EINVAL 而失败,因为

An ELF executable had more than one PT_INTERP segment (i.e., tried to name more than one interpreter)

但这似乎很模糊。

知道问题是什么或如何解决/解决问题吗?

编辑:我尝试了 strace -fp pid 并且有很多我认为来自 golang os/exec LookPath 的 stat() 调用。但是,我没有在“rbd”上看到任何 execve(),也没有任何系统调用因 EINVAL 而失败。为了确保它与舰队(systemd)无关,我还尝试以 root 身份直接在控制台上运行 kubelet。结果是一样的。

4

3 回答 3

0

部分答案: rbd 是一个shell脚本并不重要。通过在调用其他外部工具时查看 kubelet 的 strace 输出,我发现使用了 clone()。我编写了一些简短的测试代码来验证失败时会发生什么。

#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>

int test(void *p) {
  printf("Hello there!");
  return 0;
}

int main() {
  if (clone(test, NULL, CLONE_THREAD, NULL) == -1) {
    perror("clone");
  }
  return 0;
}

现在如果我这样做

strace ./test 2>&1  | grep clone

输出是

write(2, "clone: Invalid argument\n", 24clone: Invalid argument

这解释了其中的一部分奥秘。当 clone() 因 EINVAL 失败时,strace 根本不会显示它。

然后我一直在查看 Kubernetes 源代码和

https://github.com/kubernetes/kubernetes/blob/master/pkg/volume/rbd/rbd_util.go#L218

似乎很有魅力

[pid 25039] execve("/usr/sbin/modprobe", ["modprobe", "rbd"], [/* 4 vars */] <unfinished ...>

想知道为什么在https://github.com/kubernetes/kubernetes/blob/master/pkg/volume/rbd/rbd_util.go#L231https://github.com/kubernetes/kubernetes/blob/master/pkg调用/volume/rbd/rbd_util.go#L234不会(或者特别是什么会使那里的 clone() 调用失败)

于 2016-07-02T19:17:48.350 回答
0

我不太熟悉 kubernetes 如何启动 rbd 脚本,但我认为问题在于它是一个脚本。脚本不能通过调用 exec 直接运行 kubernetes 正在执行的操作。

#!/bin/sh文件顶部的行不会自动为您启动 shell。这实际上是由另一个 shell 解释的。所以你真正想要的而不是直接在你的 kubernetes 配置中调用你的脚本 /opt/bin/rbd 。您想将其更改为:

/bin/sh -c "/opt/bin/rbd" ...

然后它应该工作。

事实上,我会稍微改变一下脚本

#!/bin/sh
exec docker run -v /etc/ceph:/etc/ceph ceph/rbd $@

但也许您真正想做的是查看本指南:

在 kubernetes 上使用 krbd 为您的容器带来持久存储

事情有了进展。

于 2016-06-30T23:59:15.287 回答
0

只是对这个问题的跟进。

同时,我已经使用 Kubernetes v1.3.5 升级到 CoreOS stable (1068.9.0)。

我的 /opt/bin/rbd 看起来像这样:

#!/bin/sh
exec docker run -v /dev:/dev -v /sys:/sys --net=host --privileged=true -v /etc/ceph:/etc/ceph ceph/rbd $@

(部分基于您的建议)。现在一切都像魅力一样运作。所以我想这是一些修复的错误(现在 kubectl 也不再需要 secretRef 和 keyring 了)。也许有人可以评论实际问题是什么,但其他人认为此案已结案。

于 2016-08-27T10:24:05.340 回答