Предисловие переводчика: Когда мы собрались наконец-то подготовить свой материал по разворачиванию Ceph в Kubernetes, нашли уже готовую и, что немаловажно, свежую (от апреля 2017 года) инструкцию от компании Cron (из Боснии и Герцеговины) на английском языке. Убедившись в её простоте и практичности, решили поделиться с другими системными администраторами и DevOps-инженерами в формате «как есть», лишь добавив в листинги один небольшой недостающий фрагмент.
Программно-определяемые хранилища данных набирают популярность последние несколько лет, особенно с масштабным распространением частных облачных инфраструктур. Такие хранилища являются критической частью Docker-контейнеров, а самое популярное из них — Ceph. Если хранилище Ceph уже используется у вас, то благодаря его полной поддержке в Kubernetes легко настроить динамическое создание томов для хранения (volume provisioning) по запросу пользователей. Автоматизация их создания реализуется использованием Kubernetes StorageClasses. В этой инструкции показано, как в кластере Kubernetes реализуется хранилище Ceph. (Создание тестовой инсталляции Kubernetes, управляемой kubeadm, описано в этом материале на английском языке.)
Для начала вам также [помимо инсталляции Kubernetes] понадобится функционирующий кластер Ceph и наличие клиента rbd
на всех узлах Kubernetes. Прим. перев.: RBD или RADOS Block Device — драйвер Linux-ядра, позволяющий подключать объекты Ceph как блочные устройства. Автор статьи использует кластер Ceph версии Jewel и Linux-дистрибутив Ubuntu 16.04 на узлах Kubernetes, поэтому установка клиентских библиотек Ceph (включая упомянутый rbd
) выглядит просто:
$ sudo apt-get install ceph-common
В официальном образе kube-controller-manager
нет установленного клиента rbd
, поэтому будем использовать другой образ. Для этого смените имя образа в /etc/kubernetes/manifests/kube-controller-manager.yaml
на quay.io/attcomdev/kube-controller-manager:v1.6.1
(на текущий момент уже доступна версия 1.6.3, но конкретно мы тестировали только на 1.5.3 и 1.6.1 — прим. перев.) и дождитесь, пока kube-controller-manager
перезапустится с новым образом.
Чтобы kube-controller-manager
мог выполнять provisioning для хранилища, ему нужен ключ администратора из Ceph. Получить этот ключ можно так:
$ sudo ceph --cluster ceph auth get-key client.admin
Добавьте его в секреты Kubernetes:
$ kubectl create secret generic ceph-secret --type="kubernetes.io/rbd"
--from-literal=key='AQBwruNY/lEmCxAAKS7tzZHSforkUE85htnA/g==' --namespace=kube-system
Для узлов Kubernetes в кластере Ceph создадим отдельный пул — именно его будем использовать в rbd на узлах:
$ sudo ceph --cluster ceph osd pool create kube 1024 1024
Также создадим клиентский ключ (в кластере Ceph включена аутентификация cephx):
$ sudo ceph --cluster ceph auth get-or-create client.kube mon 'allow r' osd 'allow rwx pool=kube'
Для большей изоляции между разными пространствами имён создадим отдельный пул для каждого пространства имён в кластере Kubernetes. Получим ключ client.kube
:
$ sudo ceph --cluster ceph auth get-key client.kube
И создадим новый секрет в пространстве имён по умолчанию:
$ kubectl create secret generic ceph-secret-kube --type="kubernetes.io/rbd"
--from-literal=key='AQC/c+dYsXNUNBAAMTEW1/WnzXdmDZIBhcw6ug==' --namespace=default
Когда оба секрета добавлены, можно определить и создать новый StorageClass:
$ cat > ceph-storage-fast_rbd.yml <<EOF
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast_rbd
provisioner: kubernetes.io/rbd
parameters:
monitors: <monitor-1-ip>:6789, <monitor-2-ip>:6789, <monitor-3-ip>:6789
adminId: admin
adminSecretName: ceph-secret
adminSecretNamespace: "kube-system"
pool: kube
userId: kube
userSecretName: ceph-secret-kube
EOF
(Прим. перев.: этот код по какой-то причине отсутствует в оригинальной статье, поэтому мы добавили свой и сообщили автору об обнаруженном упущении.)
Теперь создадим «заявку на постоянный том» (PersistentVolumeClaim) с использованием созданного StorageClass под названием fast_rbd
:
$ cat > ceph-vc.yml <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: claim1
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
storageClassName: fast_rbd
EOF
$ kubectl create -f ceph-vc.yml --namespace=default
Проверим, что всё работает корректно:
$ kubectl describe pvc
Name: claim1
Namespace: default
StorageClass: fast_rbd
Status: Bound
Volume: pvc-c1ffa983-1b8f-11e7-864f-0243fc58af9d
Labels:
Annotations: pv.kubernetes.io/bind-completed=yes
pv.kubernetes.io/bound-by-controller=yes
volume.beta.kubernetes.io/storage-provisioner=kubernetes.io/rbd
Capacity: 3Gi
Access Modes: RWO
Events:
FirstSeen LastSeen Count From SubObjectPath Type …
--------- -------- ----- ---- ------------- -------- …
3m 3m 1 persistentvolume-controller Normal …
… Reason Message
… ------ -------
… ProvisioningSucceeded Successfully provisioned volume pvc-c1ffa983-… using kubernetes.io/rbd
$ kubectl describe pv
Name: pvc-c1ffa983-1b8f-11e7-864f-0243fc58af9d
Labels:
Annotations: pv.kubernetes.io/bound-by-controller=yes
pv.kubernetes.io/provisioned-by=kubernetes.io/rbd
StorageClass: fast_rbd
Status: Bound
Claim: default/claim1
Reclaim Policy: Delete
Access Modes: RWO
Capacity: 3Gi
Message:
Source:
Type: RBD (a Rados Block Device mount on the host that shares a pod's lifetime)
CephMonitors: [192.168.42.10:6789]
RBDImage: kubernetes-dynamic-pvc-c201abb5-1b8f-11e7-84a4-0243fc58af9d
FSType:
RBDPool: kube
RadosUser: kube
Keyring: /etc/ceph/keyring
SecretRef: &{ceph-secret-kube}
ReadOnly: false
Events:
Последний шаг — создать тестовый под с использованием созданного PersistentVolumeClaim (claim1
):
$ cat > pod.yml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx
spec:
replicas: 1
selector:
app: nginx
template:
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- mountPath: /var/lib/www/html
name: mypvc
volumes:
- name: mypvc
persistentVolumeClaim:
claimName: claim1
EOF
$ kubectl create -f pod.yml --namespace=default
Всё: новый контейнер использует образ Ceph, который динамически создан по запросу пользователя (PersistentVolumeClaim).
Автор: Флант