Создаём постоянное хранилище с provisioning в Kubernetes на базе Ceph

https://crondev.com/kubernetes-persistent-storage-ceph/
  • Перевод
  • Tutorial

Предисловие переводчика: Когда мы собрались наконец-то подготовить свой материал по разворачиванию 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).
  • +20
  • 12,9k
  • 8

Флант

379,00

Специалисты по DevOps и высоким нагрузкам в вебе

Поделиться публикацией

Похожие публикации

Комментарии 8
    +1
    monitors: <monitor-1-ip>:6789, <monitor-2-ip>:6789, <monitor-3-ip>:6789

    Выглядит ужасно… Почему нельзя использовать ServiceIP?

      0
      Да, можно и ServiceIP, но мы почему-то пока не разворачиваем ceph средствами kubernetes, а делаем это по старинке. Однако ничего не мешает сделать service указав endpoint вручную.
      0
      Я когда пытался прикрутить rbd к kuberneteis'у, то мне надо было сперва вручную создать rbd и его правильно отформатировать иначе pod не запускался, у вас этот момент пропущет или теперь уже можно делать по другому? Вот тут кстати написано, что надо форматировать сперва rbd.
        +1
        Это может быть необходимо при создании PV вручную. Мы используем связку StatefulSet + PersistentVolumeClaim и динамически получаем уже готовые тома отформатированные в ext4, как на 1.5, так и на 1.6
        0

        Нужно ли включать krbd в кластере ceph?

          0
          А что это?
            0

            Модуль ядра, позволяющий мапить объект в блочное устройство.

              0
              В нашей конфигурации на Ubuntu 16.04 в отношении модулей ядра никаких манипуляций не проводилось, всё работает и /dev/rbd* мапятся и монтируются из коробки.

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое