Rook sau nu Rook, aceasta este întrebarea

Rook sau nu Rook, aceasta este întrebarea

La începutul acestei luni, pe 3 mai, a fost anunțată o lansare majoră a unui „sistem de management pentru stocarea distribuită a datelor în Kubernetes” - Rook 1.0.0. În urmă cu mai bine de un an, deja publicat prezentare generală a Rook. Apoi ni s-a cerut să vorbim despre experiența lui utilizarea în practică — și acum, tocmai la timp pentru o astfel de piatră de hotar semnificativă în istoria proiectului, suntem bucuroși să ne împărtășim impresiile acumulate.

Pe scurt, Rook este un set operatori pentru Kubernetes, care preia controlul deplin asupra implementării, gestionării, recuperării automate a soluțiilor de stocare a datelor precum Ceph, EdgeFS, Minio, Cassandra, CockroachDB.

În acest moment, cel mai dezvoltat (și singurul в grajd etapa) solutia este rook-ceph-operator.

Nota: Printre modificările semnificative ale versiunii Rook 1.0.0 legate de Ceph, putem remarca suportul pentru Ceph Nautilus și capacitatea de a utiliza NFS pentru găleți CephFS sau RGW. Ceea ce iese în evidență printre altele este maturizarea suportului EdgeFS la nivelul beta.

Deci, în acest articol:

  • Să răspundem la întrebarea despre ce avantaje vedem în utilizarea Rook pentru a implementa Ceph într-un cluster Kubernetes;
  • Vom împărtăși experiența și impresiile noastre despre utilizarea Rook în producție;
  • Să vă spunem de ce îi spunem „Da!” lui Rook și despre planurile noastre pentru el.

Să începem cu concepte generale și teorie.

„Am un avantaj de un Rook!” (jucator de sah necunoscut)

Rook sau nu Rook, aceasta este întrebarea

Unul dintre principalele avantaje ale Rook este că interacțiunea cu depozitele de date se realizează prin mecanismele Kubernetes. Aceasta înseamnă că nu mai trebuie să copiați comenzile pentru a configura Ceph din foaie în consolă.

— Doriți să implementați CephFS într-un cluster? Doar scrieți un fișier YAML!
- Ce? Doriți să implementați și un magazin de obiecte cu S3 API? Doar scrieți un al doilea fișier YAML!

Rook este creat conform tuturor regulilor unui operator tipic. Interacțiunea cu el are loc folosind CRD (definiții personalizate de resurse), în care descriem caracteristicile entităților Ceph de care avem nevoie (Deoarece aceasta este singura implementare stabilă, în mod implicit, acest articol va vorbi despre Ceph, dacă nu este specificat în mod explicit altfel). Conform parametrilor specificati, operatorul va executa automat comenzile necesare configurarii.

Să ne uităm la detalii folosind exemplul de creare a unui depozit de obiecte, sau mai degrabă - 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 }}

Parametrii indicați în listare sunt destul de standard și nu au nevoie de comentarii, dar merită să acordați o atenție deosebită celor alocați variabilelor șablon.

Schema generală de lucru se rezumă la faptul că „comandăm” resurse printr-un fișier YAML, pentru care operatorul execută comenzile necesare și ne returnează un secret „deloc real” cu care putem lucra în continuare. (Vezi mai jos). Și din variabilele enumerate mai sus, comanda și numele secret vor fi compilate.

Ce fel de echipa este asta? La crearea unui utilizator pentru stocarea obiectelor, operatorul Rook din interiorul podului va face următoarele:

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

Rezultatul executării acestei comenzi va fi o structură JSON:

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

Keys - ce aplicații viitoare vor avea nevoie pentru a accesa stocarea obiectelor prin API-ul S3. Operatorul Rook le selectează cu amabilitate și le pune în spațiul său de nume sub forma unui secret cu numele rook-ceph-object-user-{{ $.Values.s3.crdName }}-{{ $.Values.s3.username }}.

Pentru a utiliza datele din acest secret, trebuie doar să le adăugați în container ca variabile de mediu. Ca exemplu, voi oferi un șablon pentru Job, în ​​care creăm automat găleți pentru fiecare mediu de utilizator:

{{- 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 }}

Toate acțiunile enumerate în acest Job au fost efectuate în cadrul Kubernetes. Structurile descrise în fișierele YAML sunt stocate într-un depozit Git și reutilizate de multe ori. Considerăm acest lucru ca un plus imens pentru inginerii DevOps și pentru procesul CI/CD în ansamblu.

Mulțumit de Rook și Rados

Utilizarea combinației Ceph + RBD impune anumite restricții privind montarea volumelor pe poduri.

În special, spațiul de nume trebuie să conțină un secret pentru accesarea Ceph pentru ca aplicațiile cu stare să funcționeze. Este în regulă dacă aveți 2-3 medii în spațiile lor de nume: puteți merge și copia secretul manual. Dar ce se întâmplă dacă pentru fiecare caracteristică este creat un mediu separat cu propriul spațiu de nume pentru dezvoltatori?

Am rezolvat singuri această problemă folosind operator-shell, care a copiat automat secretele în spații de nume noi (un exemplu de astfel de cârlig este descris în acest articol).

#! /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

Cu toate acestea, atunci când utilizați Rook, această problemă pur și simplu nu există. Procesul de montare are loc folosind propriile drivere bazate pe Flexvolum sau CSI (încă în stadiul beta) și, prin urmare, nu necesită secrete.

Rook rezolvă automat multe probleme, ceea ce ne încurajează să-l folosim în proiecte noi.

Asediul lui Rook

Să finalizăm partea practică prin desfășurarea lui Rook și Ceph, astfel încât să ne putem conduce propriile experimente. Pentru a facilita asaltarea acestui turn inexpugnabil, dezvoltatorii au pregătit un pachet Helm. Hai să-l descarcăm:

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

În dosar rook-ceph/values.yaml puteți găsi multe setări diferite. Cel mai important lucru este să specificați toleranțe pentru agenți și căutare. Am descris în detaliu pentru ce poate fi folosit mecanismul de tolere/tolerații acest articol.

Pe scurt, nu dorim ca pod-urile aplicației client să fie localizate pe aceleași noduri ca și discurile de stocare a datelor. Motivul este simplu: în acest fel munca agenților Rook nu va afecta aplicația în sine.

Deci, deschideți fișierul rook-ceph/values.yaml cu editorul tău preferat și adaugă următorul bloc la sfârșit:

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

Pentru fiecare nod rezervat pentru stocarea datelor, adăugați pata corespunzătoare:

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

Apoi instalați diagrama Helm cu comanda:

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

Acum trebuie să creați un cluster și să specificați locația 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"

Se verifică starea Ceph - așteptați să vedeți 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

În același timp, să verificăm că pod-urile cu aplicația client nu ajung pe noduri rezervate pentru Ceph:

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

În plus, componentele suplimentare pot fi configurate după cum doriți. Mai multe detalii despre ele sunt indicate în documentație. Pentru administrare, vă recomandăm insistent instalarea tabloului de bord și a casetei de instrumente.

Rook și cârlige: este Rook suficient pentru toate?

După cum puteți vedea, dezvoltarea lui Rook este în plină desfășurare. Dar există încă probleme care nu ne permit să renunțăm complet la configurarea manuală a Ceph:

  • Fără șofer Rook nu poti export metrics privind utilizarea blocurilor montate, ceea ce ne privează de monitorizare.
  • Flexvolume și CSI Nu știu cum modificați dimensiunea volumelor (spre deosebire de același RBD), astfel încât Rook este lipsit de un instrument util (și uneori extrem de necesar!).
  • Rook încă nu este la fel de flexibil ca Ceph obișnuit. Dacă dorim să configuram pool-ul pentru ca metadatele CephFS să fie stocate pe SSD, iar datele în sine să fie stocate pe HDD, va trebui să înregistrăm manual grupuri separate de dispozitive în hărțile CRUSH.
  • În ciuda faptului că rook-ceph-operator este considerat stabil, în prezent există unele probleme la actualizarea Ceph de la versiunea 13 la 14.

Constatări

„În acest moment, Rook este închisă de lumea exterioară de pioni, dar credem că într-o zi va juca un rol decisiv în joc!” (citat inventat special pentru acest articol)

Proiectul Rook ne-a cucerit, fără îndoială, inimile - credem că [cu toate avantajele și dezavantajele sale] merită cu siguranță atenția ta.

Planurile noastre de viitor se rezumă la a face din rook-ceph un modul pentru addon-operator, ceea ce va face ca utilizarea sa în numeroasele noastre clustere Kubernetes să fie și mai simplă și mai convenabilă.

PS

Citește și pe blogul nostru:

Sursa: www.habr.com

Adauga un comentariu