我正在使用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。结果是一样的。
答案 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#L231或https://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)。也许有人可以评论实际问题是什么,但是请考虑结案。