Rook alebo nerook — to je otázka

Rook alebo nerook — to je otázka

Na začiatku tohto mesiaca, 3. mája, bol ohlásený významný release "systému správy pre distribuované úložiská dát v Kubernetes" – Rook 1.0.0. Pred viac ako rokom sme už publikovali všeobecný prehľad Rook. Vtedy nás požiadali, aby sme sa podelili o skúsenosti z jeho používania v praxi — a teraz, pri tejto významnej míľnikovej udalosti v histórii projektu, sme radi, že môžeme zdieľať naše nahromadené dojmy.

V skratke, Rook predstavuje súbor operátorov pre Kubernetes, ktoré plne preberajú kontrolu nad nasadením, správou a automatickým obnovením riešení na ukladanie dát, ako sú Ceph, EdgeFS, Minio, Cassandra, CockroachDB.

V súčasnosti je najrozvinutejším (a jediným v stabilným riešením na rook-ceph-operator.

Poznámka: medzi významné zmeny v release Rook 1.0.0, týkajúce sa Ceph, patrí podpora Ceph Nautilus a možnosť používať NFS pre CephFS alebo RGW bucket. Medzi ďalšie sa vyznačuje „zrenie“ podpory EdgeFS na úroveň beta.

Takže, v tomto článku:

  • odpovieme na otázku, aké výhody vidíme v používaní Rook na nasadenie Ceph v klastri Kubernetes;
  • podelíme sa o skúsenosti a dojmy z používania Rook v produkcii;
  • rozprávame, prečo hovoríme Rooku "Áno!" a o našich plánoch s ním.

Začneme so základnými konceptmi a teóriou.

"Mám výhodu v jednej veži!" (neznámy šachista)

Rook alebo nerook — to je otázka

Jednou z hlavných výhod Rook je, že interakcia s úložiskami dát sa uskutočňuje prostredníctvom mechanizmov Kubernetes. To znamená, že už nie je potrebné kopírovať príkazy na konfiguráciu Ceph z lístka do konzoly.

— Chceš nasadiť CephFS v klastri? Jednoducho napíš YAML súbor!
­— Čo? Chceš nasadiť aj object store so S3 API? Jednoducho napíš druhý YAML súbor!

Rook bol vytvorený podľa všetkých pravidiel typického operátora. Interakcia s ním prebieha pomocou CRD (Custom Resource Definitions), v ktorých opisujeme potrebné vlastnosti entít Ceph (keďže ide o jedinú stabilnú implementáciu, v článku sa predpokladá, že sa hovorí práve o Ceph, pokiaľ nie je výslovne uvedené inak). Na základe zadaných parametrov operátor automaticky vykoná potrebné príkazy na konfiguráciu.

Konkrétnosť si priblížime na príklade vytvorenia Object Store, a to konkrétne — 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 }}

Parametre uvedené v zozname sú dostatočne štandardné a asi si nevyžadujú komentáre, ale je potrebné venovať osobitnú pozornosť tým, ktoré sú zdôraznené v premenných šablón.

Celkovo schéma práce spočíva v tom, že prostredníctvom YAML súboru „objednávame“ zdroje, pre ktoré operátor vykonáva potrebné príkazy a vracia nám „nie úplne pravý“ tajný kľúč, s ktorým môžeme ďalej pracovať. (pozri nižšie). A z premenných, ktoré sú uvedené vyššie, bude zostavený príkaz a meno tajného kľúča.

Aký je tento príkaz? Pri vytváraní používateľa pre objektové úložisko Rook-operátor vykoná v podcaste nasledujúce:

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

Výsledkom vykonania tohto príkazu bude JSON štruktúra:

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

Kľúče — to, čo bude potrebné v budúcnosti aplikáciám na prístup k objektovému úložisku cez S3 API. Rook-operátor ich láskavo vyberie a uloží vo svojom namespace ako tajný kľúč s názvom rook-ceph-object-user-{{ $.Values.s3.crdName }}-{{ $.Values.s3.username }}.

Aby bolo možné použiť údaje z tohto tajného kľúča, stačí ich pridať do kontajnera ako premenné prostredia. Ako príklad uvediem šablónu pre Job, v ktorej automaticky vytvárame bucket'y pre každé používateľské prostredie:

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

Všetky akcie popísané v tejto úlohe sa uskutočnili bez opustenia Kubernetes. Štruktúry opísané v YAML súboroch sú uložené v Git repozitári a opakovane sa používajú. Toto vidíme ako obrovskú výhodu pre DevOps inžinierov a proces CI/CD ako celok.

S Rook a Rados je to radosť

Použitie kombinácie Ceph + RBD kladie určité obmedzenia na pripojenie objemov k podom.

Konkrétne, v namespace musí byť prítomný tajný kľúč na prístup k Ceph, aby mohli stateful aplikácie fungovať. Je v poriadku, ak máte 2-3 prostredia vo svojich menných priestoroch: môžete ísť a manuálne skopírovať tajný kľúč. Ale čo robiť, ak sa pre každú funkciu vytvorí samostatné prostredie so svojím namespace?

U nás sme tento problém vyriešili pomocou shell-operator, ktorý automaticky kopíroval tajné kľúče do nových namespace (príklad podobného hooku je opísaný v tomto článku).

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

Avšak pri použití Rook tento problém jednoducho neexistuje. Proces pripojenia prebieha pomocou vlastných ovládačov na báze Flexvolume alebo CSI (ešte v beta fáze) a preto nevyžaduje tajné kľúče.

Rook automaticky rieši mnohé problémy, čo nás motivuje používať ho v nových projektoch.

Obliehanie Rook

Dokončíme praktickou část rozbalením Rook a Ceph pro provádění vlastních experimentů. Aby bylo snadnější dobýt tuto nedobytnou věž, vývojáři připravili Helm balíček. Pojďme si ho stáhnout:

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

V súbore rook-ceph/values.yaml nalezneme mnoho různých nastavení. Nejdůležitější je uvést tolerances pro agenty a vyhledávání. O tom, k čemu lze použít mechanismus taints/tolerations, jsme podrobně hovořili v tomto článku.

Stručně řečeno, nechceme, aby pod'y s klientskou aplikací byly umístěny na těch stejných uzlech, kde jsou umístěny disky pro ukládání dat. Důvod je jednoduchý: tím nebude činnost agentů Rook ovlivňovat samotnou aplikaci.

Tak otevřeme soubor rook-ceph/values.yaml v oblíbeném editoru a na konec přidáme následující blok:

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

Na každý uzel vyhrazený pro ukládání dat přidáme odpovídající taint:

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

Po čemž nainstalujeme Helm chart příkazem:

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

Nyní je nutné vytvořit klastr a uvést umístění 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"

Kontrolujeme stav Ceph — očekáváme, že uvidíme 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

Zároveň zkontrolujeme, že pod'y s klientskou aplikací nezamíří na vyhrazené uzly Ceph:

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

Dále podle přání nastavujeme další komponenty. Více informací o nich je uvedeno v dokumenácie. Pro správu důrazně doporučujeme nainstalovat dashboard a toolbox.

Rook’en kroužky: stačí Rook na všechno?

Ako je vidno, vývoj Rook prebieha naplno. No stále sú problémy, ktoré nám bránia úplne sa vzdať ručného nastavenia Ceph:

  • Žiadny ovládač Rook nedokáže exportovať metriky o využití pripojených blokov, čo nás zbavuje monitorovania.
  • Flexvolume a CSI nedokážu meniť veľkosť zväzkov (na rozdiel od RBD), takže Rook prichádza o užitočný (a niekedy aj kriticky potrebný!) nástroj.
  • Rook stále nie je tak flexibilný ako bežný Ceph. Ak budeme chcieť nastaviť, aby zásobník pre metadáta CephFS bol uložený na SSD, zatiaľ čo samotné údaje budú na HDD, bude potrebné ručne zapisovať samostatné skupiny zariadení do CRUSH máp.
  • Napriek tomu, že rook-ceph-operator sa považuje za stabilný, v súčasnosti existujú určité problémy pri aktualizácii Ceph z verzie 13 na 14.

Zhrnutie

„Teraz je Rook uzavretý pred vonkajším svetom pešiakmi, ale veríme, že raz bude hrať rozhodujúcu úlohu v partii!“ (citát vymyslený špeciálne pre tento článok)

Projekt Rook si bezpochyby získal naše srdcia - považujeme ho za [so všetkými jeho plusmi a minusmi] zaslúži si aj vašu pozornosť.

Naše ďalšie plány sú zamerané na to, aby sme urobili rook-ceph modulom pre addon-operator, čo uľahčí jeho používanie v našich mnohých Kubernetes klastra ešte jednoduchšie a pohodlnejšie.

P.S.

Prečítajte si tiež na našom blogu:

Zdroj: habr.com

Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster