Не может создать монтирование общего тома через 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