To Rook or not to Rook - det er spørgsmålet

To Rook or not to Rook - det er spørgsmålet

I begyndelsen af ​​denne måned, den 3. maj, blev en større udgivelse af et "styringssystem til distribueret datalagring i Kubernetes" annonceret - Røg 1.0.0. For mere end et år siden vi allerede offentliggjort generel oversigt over Rook. Så blev vi bedt om at tale om hans oplevelse bruge i praksis — og nu, lige i tide til en så betydningsfuld milepæl i projektets historie, deler vi gerne vores akkumulerede indtryk.

Kort sagt, Rook er et sæt operatører for Kubernetes, som tager fuld kontrol over udrulning, administration, automatisk gendannelse af datalagringsløsninger såsom Ceph, EdgeFS, Minio, Cassandra, CockroachDB.

I øjeblikket er de mest udviklede (og den eneste ene в stabil fase) er løsningen tårn-ceph-operatør.

Bemærk: Blandt de væsentlige ændringer i Rook 1.0.0-udgivelsen relateret til Ceph, kan vi notere understøttelse af Ceph Nautilus og muligheden for at bruge NFS til CephFS eller RGW buckets. Det, der blandt andre skiller sig ud, er modningen af ​​EdgeFS-understøttelse til beta-niveau.

Så i denne artikel:

  • Lad os besvare spørgsmålet om, hvilke fordele vi ser ved at bruge Rook til at implementere Ceph i en Kubernetes-klynge;
  • Vi deler vores erfaringer og indtryk af at bruge Rook i produktionen;
  • Lad os fortælle dig, hvorfor vi siger "Ja!" til Rook, og om vores planer for ham.

Lad os starte med generelle begreber og teori.

"Jeg har en fordel ved en Rook!" (ukendt skakspiller)

To Rook or not to Rook - det er spørgsmålet

En af de vigtigste fordele ved Rook er, at interaktion med datalagre udføres gennem Kubernetes-mekanismer. Det betyder, at du ikke længere behøver at kopiere kommandoerne for at konfigurere Ceph fra arket til konsollen.

— Vil du implementere CephFS i en klynge? Bare skriv en YAML-fil!
- Hvad? Vil du også implementere et objektlager med S3 API? Bare skriv en anden YAML-fil!

Rook er skabt i henhold til alle reglerne for en typisk operatør. Interaktion med ham opstår ved hjælp af CRD (Custom Resource Definitions), hvori vi beskriver egenskaberne ved Ceph-enheder, vi har brug for (da dette er den eneste stabile implementering, vil denne artikel som standard tale om Ceph, medmindre andet er udtrykkeligt angivet). I henhold til de specificerede parametre vil operatøren automatisk udføre de kommandoer, der er nødvendige for konfigurationen.

Lad os se på detaljerne ved at bruge eksemplet med at oprette et objektlager, eller rettere - 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 }}

De parametre, der er angivet i listen, er ret standard og behøver næppe kommentarer, men det er værd at være særlig opmærksom på dem, der er allokeret til skabelonvariabler.

Det generelle arbejdsskema kommer ned til, at vi "bestiller" ressourcer gennem en YAML-fil, for hvilken operatøren udfører de nødvendige kommandoer og returnerer os en "ikke-så-virkelig" hemmelighed, som vi kan arbejde videre med (se nedenunder). Og fra de variabler, der er anført ovenfor, vil kommandoen og det hemmelige navn blive kompileret.

Hvad er det for et hold? Når du opretter en bruger til objektlagring, vil Rook-operatøren inde i poden gøre følgende:

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

Resultatet af at udføre denne kommando vil være en JSON-struktur:

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

Keys - hvilke fremtidige applikationer skal bruge for at få adgang til objektlagring via S3 API. Rook-operatøren udvælger dem venligt og lægger dem i sit navneområde i form af en hemmelighed med navnet rook-ceph-object-user-{{ $.Values.s3.crdName }}-{{ $.Values.s3.username }}.

For at bruge dataene fra denne hemmelighed skal du blot tilføje dem til containeren som miljøvariabler. Som et eksempel vil jeg give en skabelon til Job, hvor vi automatisk opretter buckets for hvert brugermiljø:

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

Alle handlinger anført i dette job blev udført inden for rammerne af Kubernetes. Strukturerne beskrevet i YAML-filer gemmes i et Git-lager og genbruges mange gange. Vi ser dette som et stort plus for DevOps-ingeniører og CI/CD-processen som helhed.

Glad for Rook og Rados

Brug af Ceph + RBD-kombinationen pålægger visse begrænsninger for montering af volumener til pods.

Navneområdet skal især indeholde en hemmelighed for at få adgang til Ceph, for at stateful-applikationer kan fungere. Det er ok, hvis du har 2-3 miljøer i deres navneområder: du kan kopiere hemmeligheden manuelt. Men hvad hvis der for hver funktion oprettes et separat miljø med sit eget navneområde til udviklere?

Vi løste dette problem selv vha shell-operatør, som automatisk kopierede hemmeligheder til nye navnerum (et eksempel på en sådan hook er beskrevet i denne artikel).

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

Men når du bruger Rook, eksisterer dette problem simpelthen ikke. Monteringsprocessen foregår ved hjælp af sine egne drivere baseret på Flexvolumen eller CSI (stadig i beta-stadiet) og kræver derfor ikke hemmeligheder.

Rook løser automatisk mange problemer, hvilket tilskynder os til at bruge det i nye projekter.

Belejring af Rook

Lad os færdiggøre den praktiske del ved at implementere Rook og Ceph, så vi kan udføre vores egne eksperimenter. For at gøre det lettere at storme dette uindtagelige tårn, har udviklerne udarbejdet en Helm-pakke. Lad os downloade det:

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

I fil rook-ceph/values.yaml du kan finde mange forskellige indstillinger. Det vigtigste er at specificere tolerancer for agenter og søgning. Vi beskrev i detaljer, hvad mekanismen for urenheder/tolerancer kan bruges til denne artikel.

Kort sagt, vi ønsker ikke, at klientapplikationens pods skal være placeret på de samme noder som datalagringsdiskene. Årsagen er enkel: På denne måde vil Rook-agenternes arbejde ikke påvirke selve applikationen.

Så åbn filen rook-ceph/values.yaml med din yndlingseditor og tilføj følgende blok til sidst:

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

For hver node, der er reserveret til datalagring, skal du tilføje den tilsvarende farve:

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

Installer derefter Helm-diagrammet med kommandoen:

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

Nu skal du oprette en klynge og angive placeringen 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"

Tjek Ceph-status - forvent at se 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

Lad os samtidig kontrollere, at pods med klientapplikationen ikke ender på noder reserveret til Ceph:

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

Yderligere kan yderligere komponenter konfigureres efter ønske. Flere detaljer om dem er angivet i dokumentation. Til administration anbefaler vi kraftigt at installere dashboardet og værktøjskassen.

Rook og kroge: er Rook nok til alt?

Som du kan se, er udviklingen af ​​Rook i fuld gang. Men der er stadig problemer, der ikke tillader os helt at opgive manuel konfiguration af Ceph:

  • Ingen Rook Driver kan ikke eksportmålinger om brugen af ​​monterede blokke, hvilket fratager os overvågning.
  • Flexvolume og CSI ved ikke hvordan ændre størrelsen af ​​volumener (i modsætning til den samme RBD), så Rook er frataget et nyttigt (og nogle gange kritisk nødvendigt!) værktøj.
  • Rook er stadig ikke så fleksibel som almindelig Ceph. Hvis vi ønsker at konfigurere puljen til at CephFS-metadata skal lagres på SSD, og ​​selve dataene skal lagres på HDD, bliver vi nødt til manuelt at registrere separate grupper af enheder i CRUSH-kort.
  • På trods af at rook-ceph-operator anses for at være stabil, er der i øjeblikket nogle problemer ved opgradering af Ceph fra version 13 til 14.

Fund

"Lige nu er Rook lukket af fra omverdenen af ​​bønder, men vi tror på, at hun en dag vil spille en afgørende rolle i spillet!" (citat opfundet specifikt til denne artikel)

Rook-projektet har uden tvivl vundet vores hjerter - vi mener, at det [med alle dets fordele og ulemper] bestemt fortjener din opmærksomhed.

Vores fremtidsplaner går ud på at gøre rook-ceph til et modul til addon-operatør, som vil gøre brugen af ​​den i vores mange Kubernetes-klynger endnu enklere og mere bekvem.

PS

Læs også på vores blog:

Kilde: www.habr.com

Tilføj en kommentar