无法通过' emptyDir'创建共享卷装载在单节点kubernetes(在centos上),但这适用于多节点k8s安装

时间:2016-01-13 21:13:11

标签: kubernetes mount

TL; DR - 问题的解决方案,感谢Paul

如果遇到下面描述的问题,解决问题的最简单方法是在运行配方以启动单节点k8s之前执行以下命令:

   sudo chcon -Rt svirt_sandbox_file_t /var/lib/kubelet

原始问题说明

我正在尝试将基于此配方的k8s环境放在一起>     https://github.com/kubernetes/kubernetes/blob/release-1.1/docs/getting-started-guides/docker.md 为了集成测试我们的代码库,它在k8s集群中提供容器。 为了方便复制/粘贴,我在配方中包含了所有命令'运行配方',

我有一个简单的复制控制器定义(在下面的“复制控制器定义'”中重现) 对于非常标准的图像(nginx。)在此RC定义中,我尝试使用' emptyDir'来安装共享文件夹。 为简单起见,我在rep控制器定义中只有一个容器(因此实际上没有太多共享。)

现在,当我通过以下命令为我们的多节点集群配置此RC时:' kubectl create -f shared.folder.json'
我可以登录容器&nginx'并执行以下操作:

touch /backup-folder/fooFile

我们的多节点群集的版本信息是:

Server Version: 
    version.Info{
        Major:"1", 
        Minor:"1+", 
        GitVersion:"v1.1.3-beta.0.308+71b088a96ee101-dirty", 
        GitCommit:"71b088a96ee101967fc06e1f95b1cade8f6e30f9", GitTreeState:"dirty"}

但是......当我使用'运行配方'中的步骤启动单个节点k8s群集时 使用命令' kubectl create -f shared.folder.json'然后我产生一个bash shell 在nginx容器中并尝试与上面相同的触摸命令,但在单节点情况下,我得到一个 错误:触摸:无法触摸' / backup-folder / fooo':权限被拒绝

如果它在这里有用,那么我在两种情况下运行mount -l得到的信息:

1)单节点k8s

  root@foo-hzxd6:/# mount -l  | grep backup-folder
  /dev/mapper/cl-root on /backup-folder type xfs (rw,relatime,seclabel,attr2,inode64,noquota)

2)多节点k8s

  root@foo-vcbc9:/# mount -l  | grep backup-folder
 /dev/vdb on /backup-folder type ext3 (rw,relatime,data=ordered)

复制控制器定义

shared.folder.json

{
  "kind": "ReplicationController",
  "apiVersion": "v1",
  "metadata":{
      "name":"foo",
      "labels":{
         "app":"foo",
         "role":"foo"
      }
  },
  "spec": {
    "replicas": 1,
    "selector": {
      "name": "nginx"
    },
    "template": {
          "metadata": {
            "name": "nginx",
            "labels": {
              "name": "nginx"
            }
          },
          "spec": {
            "containers": [
              {
                "name": "nginx",
                "image": "nginx",
                        "imagePullPolicy": "Always",
                "ports": [
                  {
                    "containerPort": 8080
                  },
                  {
                    "containerPort": 8081
                  }
                ],
                        "command": ["sleep", "10000"],
                        "volumeMounts": [
                      {
                        "name": "shared-volume",
                        "mountPath": "/backup-folder"
                      }
                    ]
              }
            ],
            "volumes": [
              {
                "name": "shared-volume",
                "emptyDir": { }
              }
            ]
          }
    }
  }
} 

运行食谱

docker run --net=host -d gcr.io/google_containers/etcd:2.0.12 /usr/local/bin/etcd --addr=127.0.0.1:4001 --bind-addr=0.0.0.0:4001 --data-dir=/var/etcd/data


docker run \
    --volume=/:/rootfs:ro \
    --volume=/sys:/sys:ro \
    --volume=/dev:/dev \
    --volume=/var/lib/docker/:/var/lib/docker:ro \
    --volume=/var/lib/kubelet/:/var/lib/kubelet:rw \
    --volume=/var/run:/var/run:rw \
    --net=host \
    --pid=host \
    --privileged=true \
    -d \
    gcr.io/google_containers/hyperkube:v1.0.1 \
    /hyperkube kubelet --containerized --hostname-override="127.0.0.1" --address="0.0.0.0" --api-servers=http://localhost:8080 --config=/etc/kubernetes/manifests


docker run -d --net=host --privileged gcr.io/google_containers/hyperkube:v1.0.1 /hyperkube proxy --master=http://127.0.0.1:8080 --v=2

旁注

(我们的k8s版本 - 我们用于多节点案例 - 在' stock' kubernetes之上有一些变化,但我很确定这些变化都没有与安装文件夹有关。)

结语 - 有关SELinux拒绝访问共享文件夹的详细信息

在回答保罗关于更多细节的要求时,我们走了:

首先,将执法转回“是”'通过:" setenforce 1"

接下来,杀死所有docker容器,然后通过上面提供的3步配方重新启动k8s单节点。

接下来,通过" kubectl create -f shared.folder.json"

配置pod

接下来,通过以下方式将shell放入容器:" kubectl exec -i -t foo-podxxx -c nginx - bash"

在bash shell中:" touch / backup-folder / blah"

结果:

> sudo ausearch -ts recent -m AVC
----
time->Tue Jan 19 11:33:19 2016
type=SYSCALL msg=audit(1453231999.925:865015): arch=c000003e syscall=2 success=no exit=-13 a0=7ffd65fc1e45 a1=941 a2=1b6 a3=7ffd65fc09f0 items=0 ppid=25089 pid=25127 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts4 ses=4294967295 comm="touch" exe="/bin/touch" subj=system_u:system_r:svirt_lxc_net_t:s0:c202,c694 key=(null)
type=AVC msg=audit(1453231999.925:865015): avc:  denied  { create } for  pid=25127 comm="touch" name="blah" scontext=system_u:system_r:svirt_lxc_net_t:s0:c202,c694 tcontext=system_u:object_r:docker_var_lib_t:s0 tclass=file
(backup-agent-scripts) /home/chris/dev/krylov/scripts > 

kubelet日志:https://dl.dropboxusercontent.com/u/9940067/kubelet.log

1 个答案:

答案 0 :(得分:1)

这是完整的单节点k8s启动脚本,使我的问题消失了。 感谢Paul Morie为我提供解决方案(脚本中神奇的第一行)。

<强> 更新 以下是Paul向我发送的有关chcon使用原因的更新: 它的作用基本上是为包含所有pod的卷目录更改SELinux类型 卷到svirt_sandbox_file_t,这是大多数SELinux策略允许容器的上下文 (通常使用svirt_lxc_net_t运行)使用。
所以,TLDR,该命令使得kube卷目录可以被docker容器使用(当然当然是容器) 只能访问其pod中使用的卷,然后将其装入容器中。

我对此的理解是,通常Docker容器是孤立运行的,并且看不到彼此 文件系统,chcon允许我们以受控的方式打破这种隔离 只使用卷装指令才允许这种共享发生。 This explanation似乎很有用。

#   magic selinux context set command is required. for details, see: http://stackoverflow.com/questions/34777111/cannot-create-a-shared-volume-mount-via-emptydir-on-single-node-kubernetes-on
#
sudo chcon -Rt svirt_sandbox_file_t /var/lib/kubelet


docker run --net=host -d gcr.io/google_containers/etcd:2.0.12 /usr/local/bin/etcd --addr=127.0.0.1:4001 --bind-addr=0.0.0.0:4001 --data-dir=/var/etcd/data


docker run \
    --volume=/:/rootfs:ro \
    --volume=/sys:/sys:ro \
    --volume=/dev:/dev \
    --volume=/var/lib/docker/:/var/lib/docker:ro \
    --volume=/var/lib/kubelet/:/var/lib/kubelet:rw \
    --volume=/var/run:/var/run:rw \
    --net=host \
    --pid=host \
    --privileged=true \
    -d \
    gcr.io/google_containers/hyperkube:v1.0.1 \
    /hyperkube kubelet --containerized --hostname-override="127.0.0.1" --address="0.0.0.0" --api-servers=http://localhost:8080 --config=/etc/kubernetes/manifests

docker run -d --net=host --privileged gcr.io/google_containers/hyperkube:v1.0.1 /hyperkube proxy --master=http://127.0.0.1:8080 --v=2

sleep 20   # give everything time to launch