Не может создать монтирование общего тома через emptyDir на одном узле kubernetes (на centos), но это работает с многоузловой установкой k8s

TL;DR - Решение проблемы, благодаря Полу

Если у вас есть проблема, описанная ниже, проще всего решить ее, выполнив следующую команду перед запуском Recipe для загрузки одного узла 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".
Для простоты у меня есть только один контейнер в определении контроллера повторений (так что на самом деле не происходит большого обмена).

Теперь, когда я предоставляю этот 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 в Контейнер nginx и попробуйте выполнить ту же команду touch, что и выше, но в случае с одним узлом я получаю сообщение об ошибке: touch: не может коснуться '/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 - которую мы используем для случая с несколькими узлами - имеет некоторые изменения, размещенные поверх "стандартных" kubernetes, но я уверен, что ни одно из этих изменений не имеет отношения к монтированию папок).

Эпилог - подробнее о запрете доступа к общей папке в SELinux

В ответ на запрос Павла о более подробной информации, здесь мы идем:

Во-первых, верните принудительное возвращение к "да" через: "setenforce 1"

Затем убейте все док-контейнеры, затем перезапустите один узел k8s с помощью 3-х шагов, описанных выше.

Далее, модуль обеспечения через "kubectl create -f shared.folder.json"

Затем добавьте оболочку в контейнер с помощью: "kubectl exec -i -t foo-podxxx -c nginx - bash "

В оболочке bash: "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 ответ

Вот полный скрипт запуска одного узла k8s, который устраняет мою проблему. Спасибо Полу Мори за предоставленную мне информацию о решении (волшебная первая строка в сценарии).

Обновление Вот обновление, которое Пол послал мне о том, почему используется chcon: в основном он меняет тип SELinux для каталога томов, который содержит все тома pod, на svirt_sandbox_file_t, который является контекстом, в котором большинство политик SELinux разрешают контейнеры (обычно выполняющиеся с svirt_lxc_net_t) для использования.
Итак, TLDR, эта команда делает каталог томов kube пригодным для использования док-контейнерами (хотя, конечно, контейнеры имеют доступ только к томам, которые используются в их модуле и затем монтируются в контейнер).

Насколько я понимаю, что обычно контейнер Docker работает изолированно и не может видеть файловые системы друг друга, chcon позволяет нам разорвать эту изоляцию контролируемым образом, так что это позволяет только совместное использование директив монтирования тома. Это объяснение кажется актуальным.

#   magic selinux context set command is required. for details, see: http://stackru.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
Другие вопросы по тегам