在coreos上从kubernetes调用rbd(docker)会返回fork / exec无效参数

时间:2016-06-23 16:21:56

标签: linux kubernetes coreos ceph

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

注意到必须有两个:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Starting");
        var mainVm = new MainViewModel();
        mainVm.GetStatuses();
        mainVm.GetMro();

        Console.WriteLine("Status: {0} {1}", mainVm.StatusVm.Name, mainVm.StatusVm.CreateDate);
        Console.WriteLine("MroVm: {0} {1}", mainVm.MroVm.Name, mainVm.MroVm.CreateDate);
    }
}

public class MainViewModel
{
    public StatusViewModel StatusVm { get; set; }
    public MroViewModel MroVm { get; set; }

    public void GetStatuses()
    {
        var result =  Get(VmKind.Status);
        StatusVm = result.SingleOrDefault(c => c.StatusId.Equals(-1)) as StatusViewModel;
    }
    public void GetMro()
    {
        var result = Get(VmKind.Mro);
        MroVm = result.SingleOrDefault(c => c.StatusId.Equals(-1)) as MroViewModel;
    }

    public IEnumerable<IVm> Get(VmKind vmKind)
    {
        var dataService = new MyDataService();
        return dataService.Get(vmKind);
    }


}

public interface IVm
{
    int StatusId { get; set; }
    DateTime CreateDate { get; set; }
    string Name { get; }
}

public class StatusViewModel : IVm
{
    public DateTime CreateDate { get; set; }
    public int StatusId { get; set; }
    public string Name { get { return "StatusViewModel"; } }
}

public class MroViewModel : IVm
{
    public DateTime CreateDate { get; set; }
    public int StatusId { get; set; }
    public string Name { get { return "MroViewModel"; } }
}

public enum VmKind    {Status, Mro }

#region Strategy

public interface IDataGetter
{
    IEnumerable<IVm> Get(VmKind vmKind);
}

public class MyDataService : IDataGetter {
    public IEnumerable<IVm> Get(VmKind vmKind)
    {
        switch (vmKind)
        {
            case VmKind.Status:
                return GetStatuses();
                //break;
            case VmKind.Mro:
                return GetMro();
                //break;
            default:
                throw new ArgumentException("Unknown VM type");
        }
    }

    private IEnumerable<IVm> GetMro()
    {
        return new List<MroViewModel> {
            new MroViewModel { StatusId = -1, CreateDate = DateTime.Now },
            new MroViewModel { StatusId = 2, CreateDate = DateTime.Now }
        };
    }

    private IEnumerable<StatusViewModel> GetStatuses()
    {
        return new List<StatusViewModel> {
            new StatusViewModel { StatusId = -1, CreateDate = DateTime.Now },
            new StatusViewModel { StatusId = 2, CreateDate = DateTime.Now }
        };
    }
}
#endregion

#region Factory
public class VmFactory {
    static IVm Create(VmKind vmKind)
    {
        IVm result = null;
        switch (vmKind)
        {
            case VmKind.Status:
                result = new StatusViewModel { StatusId = -1, CreateDate = DateTime.Now };
                break;
            case VmKind.Mro:
                result = new MroViewModel { StatusId = -1, CreateDate = DateTime.Now };
                break;
            default:
                throw new ArgumentException("Unknown VM type");
                //break;
        }
        return result;
    }
}
#endregion

secretRef:
  name: ceph-secret

其他kubectl抱怨。这是预期的行为吗?

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

keyring: /etc/ceph/keyring

照顾/ etc / ceph配置,使shell脚本可执行等等 - 如果我这样做&#34; rbd list&#34;在CoreOS上一切正常。 / opt / bin(默认情况下在CoreOS上的PATH旁边)也在kubelet进程的PATH中(我可以通过/ proc / kubelet pid / environ确认)。

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

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

所以fork()或execve()返回EINVAL?通过阅读几个手册页,我发现由于

,只有exec可能因EINVAL而失败
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

但这似乎很模糊。

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

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

3 个答案:

答案 0 :(得分: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 $@

但也许你真正想要做的就是看看这个指南:

Bring persistent storage for your containers with krbd on kubernetes

事情已经取得了进展。

答案 1 :(得分: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()调用失败)

答案 2 :(得分: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 $@

(部分基于您的建议)。而现在一切都像魅力一样。所以我想这是一些修复过的bug(同样也是secretRef和keyring现在不再需要了kubectl)。也许有人可以评论实际问题是什么,但是请考虑结案。