На топ или не на топ - това е въпросът

На топ или не на топ - това е въпросът

В началото на този месец, на 3 май, беше обявено голямо издание на „система за управление на разпределено съхранение на данни в Kubernetes“ - Топ 1.0.0. Преди повече от година ние вече публикувани общ преглед на Rook. Тогава бяхме помолени да говорим за неговия опит използване на практика — и сега, точно навреме за такъв важен момент в историята на проекта, ние сме щастливи да споделим нашите натрупани впечатления.

Накратко, Топът е комплект оператори за Kubernetes, които поемат пълен контрол върху внедряването, управлението, автоматичното възстановяване на решения за съхранение на данни като Ceph, EdgeFS, Minio, Cassandra, CockroachDB.

В момента най-развитите (и единствения в стабилен етап) решението е топ-цеф-оператор.

Внимание: Сред значителните промени в изданието Rook 1.0.0, свързани с Ceph, можем да отбележим поддръжката за Ceph Nautilus и възможността за използване на NFS за CephFS или RGW кофи. Това, което се откроява сред другите, е узряването на поддръжката на EdgeFS до бета ниво.

И така, в тази статия ние:

  • Нека отговорим на въпроса какви предимства виждаме в използването на Rook за внедряване на Ceph в клъстер на Kubernetes;
  • Ще споделим нашия опит и впечатления от използването на Rook в производството;
  • Нека ви кажем защо казваме „Да!“ на Рук и какви са плановете ни за него.

Нека започнем с общи понятия и теория.

„Имам предимство от един топ!“ (неизвестен шахматист)

На топ или не на топ - това е въпросът

Едно от основните предимства на Rook е, че взаимодействието със хранилищата на данни се осъществява чрез механизмите на Kubernetes. Това означава, че вече не е необходимо да копирате командите за конфигуриране на Ceph от листа в конзолата.

— Искате ли да внедрите CephFS в клъстер? Просто напишете YAML файл!
- Какво? Искате ли също така да внедрите хранилище на обекти със S3 API? Просто напишете втори YAML файл!

Топът е създаден според всички правила на типичен оператор. Взаимодействието с него става с помощта CRD (дефиниции на персонализирани ресурси), в който описваме характеристиките на Ceph обектите, от които се нуждаем (тъй като това е единственото стабилно изпълнение, по подразбиране тази статия ще говори за Ceph, освен ако изрично не е посочено друго). Според зададените параметри, операторът автоматично ще изпълни командите, необходими за конфигуриране.

Нека да разгледаме спецификата, използвайки примера за създаване на Object Store, или по-скоро - CephObjectStoreUser.

apiVersion: ceph.rook.io/v1
kind: CephObjectStore
metadata:
  name: {{ .Values.s3.crdName }}
  namespace: kube-rook
spec:
  metadataPool:
    failureDomain: host
    replicated:
      size: 3
  dataPool:
    failureDomain: host
    erasureCoded:
      dataChunks: 2
      codingChunks: 1
  gateway:
    type: s3
    sslCertificateRef:
    port: 80
    securePort:
    instances: 1
    allNodes: false
---
apiVersion: ceph.rook.io/v1
kind: CephObjectStoreUser
metadata:
  name: {{ .Values.s3.crdName }}
  namespace: kube-rook
spec:
  store: {{ .Values.s3.crdName }}
  displayName: {{ .Values.s3.username }}

Параметрите, посочени в списъка, са доста стандартни и едва ли се нуждаят от коментари, но си струва да се обърне специално внимание на тези, разпределени към променливите на шаблона.

Общата схема на работа се свежда до факта, че ние „поръчваме“ ресурси чрез YAML файл, за който операторът изпълнява необходимите команди и ни връща „не толкова реална“ тайна, с която можем да работим по-нататък (виж отдолу). И от променливите, изброени по-горе, командата и тайното име ще бъдат компилирани.

Що за отбор е това? Когато създавате потребител за съхранение на обекти, операторът Rook вътре в групата ще направи следното:

radosgw-admin user create --uid="rook-user" --display-name="{{ .Values.s3.username }}"

Резултатът от изпълнението на тази команда ще бъде JSON структура:

{
    "user_id": "rook-user",
    "display_name": "{{ .Values.s3.username }}",
    "keys": [
        {
           "user": "rook-user",
           "access_key": "NRWGT19TWMYOB1YDBV1Y",
           "secret_key": "gr1VEGIV7rxcP3xvXDFCo4UDwwl2YoNrmtRlIAty"
        }
    ],
    ...
}

Keys - какви бъдещи приложения ще имат нужда за достъп до съхранение на обекти чрез S3 API. Операторът Rook любезно ги избира и ги поставя в своето име под формата на тайна с името rook-ceph-object-user-{{ $.Values.s3.crdName }}-{{ $.Values.s3.username }}.

За да използвате данните от тази тайна, просто я добавете към контейнера като променливи на средата. Като пример ще дам шаблон за Job, в който автоматично създаваме кофи за всяка потребителска среда:

{{- range $bucket := $.Values.s3.bucketNames }}
apiVersion: batch/v1
kind: Job
metadata:
  name: create-{{ $bucket }}-bucket-job
  annotations:
    "helm.sh/hook": post-install
    "helm.sh/hook-weight": "2"
spec:
  template:
    metadata:
      name: create-{{ $bucket }}-bucket-job
    spec:
      restartPolicy: Never
      initContainers:
      - name: waitdns
        image: alpine:3.6
        command: ["/bin/sh", "-c", "while ! getent ahostsv4 rook-ceph-rgw-{{ $.Values.s3.crdName }}; do sleep 1; done" ]
      - name: config
        image: rook/ceph:v1.0.0
        command: ["/bin/sh", "-c"]
        args: ["s3cmd --configure --access_key=$(ACCESS-KEY) --secret_key=$(SECRET-KEY) -s --no-ssl --dump-config | tee /config/.s3cfg"]
        volumeMounts:
        - name: config
          mountPath: /config
        env:
        - name: ACCESS-KEY
          valueFrom:
            secretKeyRef:
              name: rook-ceph-object-user-{{ $.Values.s3.crdName }}-{{ $.Values.s3.username }}
              key: AccessKey
        - name: SECRET-KEY
          valueFrom:
            secretKeyRef:
              name: rook-ceph-object-user-{{ $.Values.s3.crdName }}-{{ $.Values.s3.username }}
              key: SecretKey
      containers:
      - name: create-bucket
        image: rook/ceph:v1.0.0
        command: 
        - "s3cmd"
        - "mb"
        - "--host=rook-ceph-rgw-{{ $.Values.s3.crdName }}"
        - "--host-bucket= "
        - "s3://{{ $bucket }}"
        ports:
        - name: s3-no-sll
          containerPort: 80
        volumeMounts:
        - name: config
          mountPath: /root
      volumes:
      - name: config
        emptyDir: {}
---
{{- end }}

Всички действия, изброени в това задание, бяха извършени в рамките на Kubernetes. Структурите, описани в YAML файловете, се съхраняват в Git хранилище и се използват многократно. Виждаме това като огромен плюс за инженерите на DevOps и процеса на CI/CD като цяло.

Доволни от Рук и Радос

Използването на комбинацията Ceph + RBD налага определени ограничения върху монтираните обеми към капсулите.

По-специално, пространството от имена трябва да съдържа тайна за достъп до Ceph, за да функционират приложенията със състояние. Добре е, ако имате 2-3 среди в техните пространства от имена: можете да отидете и да копирате тайната ръчно. Но какво ще стане, ако за всяка функция се създаде отделна среда със собствено пространство от имена за разработчиците?

Решихме този проблем сами с помощта на shell-оператор, който автоматично копира тайни в нови пространства от имена (пример за такава кука е описан в тази статия).

#! /bin/bash

if [[ $1 == “--config” ]]; then
   cat <<EOF
{"onKubernetesEvent":[
 {"name": "OnNewNamespace",
  "kind": "namespace",
  "event": ["add"]
  }
]}
EOF
else
    NAMESPACE=$(kubectl get namespace -o json | jq '.items | max_by( .metadata.creationTimestamp ) | .metadata.name')
    kubectl -n ${CEPH_SECRET_NAMESPACE} get secret ${CEPH_SECRET_NAME} -o json | jq ".metadata.namespace="${NAMESPACE}"" | kubectl apply -f -
fi

Въпреки това, когато използвате Rook, този проблем просто не съществува. Процесът на монтиране се извършва с помощта на собствени драйвери, базирани на Гъвкав обем или CSI (все още в бета етап) и следователно не изисква тайни.

Rook автоматично решава много проблеми, което ни насърчава да го използваме в нови проекти.

Обсада на Рук

Нека завършим практическата част, като разположим Rook и Ceph, за да можем да проведем наши собствени експерименти. За да улеснят щурмуването на тази непревземаема кула, разработчиците са подготвили пакет Helm. Нека го изтеглим:

$ helm fetch rook-master/rook-ceph --untar --version 1.0.0

Във файла rook-ceph/values.yaml можете да намерите много различни настройки. Най-важното е да посочите толеранси за агенти и търсене. Описахме подробно за какво може да се използва механизмът за замърсяване/толерации тази статия.

Накратко, ние не искаме модулите на клиентските приложения да бъдат разположени на същите възли като дисковете за съхранение на данни. Причината е проста: по този начин работата на Rook агентите няма да повлияе на самото приложение.

И така, отворете файла rook-ceph/values.yaml с любимия си редактор и добавете следния блок в края:

discover:
  toleration: NoExecute
  tolerationKey: node-role/storage
agent:
  toleration: NoExecute
  tolerationKey: node-role/storage
  mountSecurityMode: Any

За всеки възел, запазен за съхранение на данни, добавете съответното петно:

$ kubectl taint node ${NODE_NAME} node-role/storage="":NoExecute

След това инсталирайте диаграмата Helm с командата:

$ helm install --namespace ${ROOK_NAMESPACE} ./rook-ceph

Сега трябва да създадете клъстер и да посочите местоположението OSD:

apiVersion: ceph.rook.io/v1
kind: CephCluster
metadata:
  clusterName: "ceph"
  finalizers:
  - cephcluster.ceph.rook.io
  generation: 1
  name: rook-ceph
spec:
  cephVersion:
    image: ceph/ceph:v13
  dashboard:
    enabled: true
  dataDirHostPath: /var/lib/rook/osd
  mon:
    allowMultiplePerNode: false
    count: 3
  network:
    hostNetwork: true
  rbdMirroring:
    workers: 1
  placement:
    all:
      tolerations:
      - key: node-role/storage
        operator: Exists
  storage:
    useAllNodes: false
    useAllDevices: false
    config:
      osdsPerDevice: "1"
      storeType: filestore
    resources:
      limits:
        memory: "1024Mi"
      requests:
        memory: "1024Mi"
    nodes:
    - name: host-1
      directories:
      - path: "/mnt/osd"
    - name: host-2
      directories:
      - path: "/mnt/osd"
    - name: host-3
      directories:
      - path: "/mnt/osd"

Проверка на състоянието на Ceph - очаквайте да видите HEALTH_OK:

$ kubectl -n ${ROOK_NAMESPACE} exec $(kubectl -n ${ROOK_NAMESPACE} get pod -l app=rook-ceph-operator -o name -o jsonpath='{.items[0].metadata.name}') -- ceph -s

В същото време нека проверим дали подовете с клиентското приложение не се озовават на възли, запазени за Ceph:

$ kubectl -n ${APPLICATION_NAMESPACE} get pods -o custom-columns=NAME:.metadata.name,NODE:.spec.nodeName

Освен това допълнителни компоненти могат да бъдат конфигурирани по желание. Повече подробности за тях са посочени в документация. За администриране силно препоръчваме да инсталирате таблото за управление и кутията с инструменти.

Топ и куки: Топът достатъчен ли е за всичко?

Както можете да видите, развитието на Rook е в разгара си. Но все още има проблеми, които не ни позволяват напълно да изоставим ръчната конфигурация на Ceph:

  • Няма Rook Driver не мога експортиране на показатели за използването на монтирани блокове, което ни лишава от наблюдение.
  • Flexvolume и CSI не знам как промяна на размера на обемите (за разлика от същия RBD), така че Rook е лишен от полезен (и понякога критично необходим!) инструмент.
  • Топът все още не е толкова гъвкав, колкото обикновения Цеф. Ако искаме да конфигурираме пула за CephFS метаданни, които да се съхраняват на SSD, а самите данни да се съхраняват на HDD, ще трябва ръчно да регистрираме отделни групи устройства в CRUSH карти.
  • Въпреки факта, че rook-ceph-operator се счита за стабилен, в момента има някои проблеми при надграждането на Ceph от версия 13 на 14.

Данни

„В момента Рук е изолиран от външния свят с пешки, но ние вярваме, че един ден тя ще играе решаваща роля в играта!“ (цитат, измислен специално за тази статия)

Проектът Rook несъмнено спечели сърцата ни - вярваме, че [с всичките му плюсове и минуси] той определено заслужава вашето внимание.

Бъдещите ни планове се свеждат до това да направим rook-ceph модул за addon-оператор, което ще направи използването му в нашите многобройни клъстери Kubernetes още по-опростено и удобно.

PS

Прочетете също в нашия блог:

Източник: www.habr.com

Добавяне на нов коментар