Rook eller ikke Rook — det er spørgsmålet

Rook eller ikke Rook — det er spørgsmålet

I begyndelsen af denne måned, den 3. maj, blev en stor udgivelse af "styringssystemet til distribuerede datalagre i Kubernetes" annonceret — Rook 1.0.0. For mere end et år siden offentliggjorde vi allerede en generel oversigt over Rook. Dengang blev vi bedt om at dele erfaringer med det i praksis — og i takt med denne vigtige milepæl i projektets historie er vi glade for at dele vores samlede indtryk. Kort sagt, Rook er et sæt

operatorer til Kubernetes, der fuldstændigt tager kontrol over udrulning, administrations, og automatisk genopretning af datalagringsløsninger som Ceph, EdgeFS, Minio, Cassandra, CockroachDB. I øjeblikket er den mest udviklede (og

den eneste stabile i stadium) løsning : blandt de betydelige ændringer i Rook 1.0.0, relateret til Ceph, kan nævnes støtte til Ceph Nautilus og muligheden for at bruge NFS til CephFS- eller RGW-bakker. Blandt andet er "modningen" af EdgeFS-supporten nået beta-niveau. rook-ceph-operator.

BemærkSå i denne artikel vil vi:

svare på spørgsmålet om, hvilke fordele vi ser ved at bruge Rook til udrulning af Ceph i en Kubernetes-kluster;

  • dele erfaringer og indtryk fra brugen af Rook i produktion;
  • forklare, hvorfor vi siger Rook ‘Ja!’ og om vores fremtidsplaner for det.
  • Lad os starte med de overordnede koncepter og teori.

"Jeg har en fordel med en Tur!" (ukendt skakspiller)

En af de største fordele ved Rook er, at interaktionen med datalagre sker via Kubernetes-mekanismer. Det betyder, at der ikke længere er behov for at kopiere kommandoer til at konfigurere Ceph fra et papir ind i konsollen.

Rook eller ikke Rook — det er spørgsmålet

— Vil du udrulle CephFS i klusteren? Bare skriv en YAML-fil!

— Hvad? Vil du også udrulle en objektlagringsløsning med S3 API? Bare skriv en anden YAML-fil!
Rook er skabt i henhold til alle reglerne for en typisk operator. Interaktionen med det sker ved hjælp af

CRD (Custom Resource Definitions) , hvori vi beskriver de nødvendige egenskaber for Ceph-enhederne(da dette er den eneste stabile implementering, vil artiklen som standard fokusere på Ceph, medmindre andet er angivet) . I henhold til de angivne parametre vil operatøren automatisk udføre de nødvendige kommandoer for at konfigurere.Lad os se på detaljerne ved at oprette en Object Store, mere specifikt —

CephObjectStoreUser 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 kræver næppe kommentarer; dog bør der lægges særlig vægt på de, der er fremhævet som skabelonvariabler.

Den overordnede arbejdsgang går ud på, at vi via en YAML-fil "bestiller" ressourcer, hvorefter operatøren udfører de nødvendige kommandoer og returnerer os en "ikke helt ægte" hemmelighed, som vi kan arbejde videre med. (se nedenfor). Og ud fra de ovennævnte variabler vil der blive sammensat en kommando og navnet på hemmeligheden.

Hvad er det så for en kommando? Når en bruger oprettes til objektlageret, vil Rook-operatøren inden for pod'en udføre følgende:

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

Resultatet af 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"
        }
    ],
    ...
}

Nøgler — det, som applikationerne i fremtiden vil have brug for for at få adgang til objektlageret via S3 API. Rook-operatøren vælger venligst dem og gemmer dem i sit namespace som en hemmelighed med navnet rook-ceph-object-user-{{ $.Values.s3.crdName }}-{{ $.Values.s3.username }}.

For at bruge dataene fra denne hemmelighed er det tilstrækkeligt at tilføje dem til containeren som miljøvariabler. Som eksempel vil jeg give en skabelon til Job, hvor vi automatisk opretter buckets for hvert brugerens miljø:

{{- 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 beskrevet i denne job blev udført uden at forlade Kubernetes. De strukturer, der er beskrevet i YAML-filerne, er gemt i et Git-repositorium og kan genbruges mange gange. Dette er en stor fordel for DevOps-ingeniører og CI/CD-processen generelt.

Med Rook og Rados er det en fornøjelse

Brugen af kombinationen Ceph + RBD medfører visse begrænsninger for montering af volumener til pods.

Der skal for eksempel være en hemmelighed i navnerummet for at give adgang til Ceph, så stateful-applikationer kan fungere. Det er fint, hvis man har 2-3 miljøer i sine navnerum: man kan gå ind og kopiere hemmeligheden manuelt. Men hvad gør man, hvis der oprettes et separat miljø for hver funktion for udviklerne med sit eget namespace?

Vi løste dette problem ved hjælp af shell-operator, som automatisk kopierede hemmeligheder til nye namespaces (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 ved brug af Rook eksisterer dette problem slet ikke. Monteringsprocessen sker ved hjælp af egne drivere, der er baseret på Flexvolume eller CSI (fortsat i beta-fase) og kræver derfor ikke hemmeligheder.

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

Rook-belægring

Lad os afslutte den praktiske del med at implementere Rook og Ceph for at muliggøre egne eksperimenter. For at gøre angrebet på dette utilgængelige tårn lettere, har udviklerne forberedt en Helm-pakke. Lad os hente den:

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

I filen rook-ceph/values.yaml kan man finde mange forskellige indstillinger. Det vigtigste er at angive tolerations for agenter og søgning. Hvad taints/tolerations-mekanismen kan bruges til, har vi beskrevet i detaljer i denne artikel.

Kort sagt ønsker vi ikke, at pods med klientapplikationen ligger på de samme noder, hvor dataopbevaringsdiskene er placeret. Årsagen er enkel: på den måde vil arbejdet fra Rook-agenterne ikke påvirke selve applikationen.

Så lad os åbne filen rook-ceph/values.yaml i vores foretrukne editor og tilføje følgende blok i slutningen:

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

Til hver node, der er reserveret til dataopbevaring, tilføjer vi den tilsvarende taint:

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

Herefter installerer vi Helm-diagrammet med kommandoen:

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

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

Vi tjekker status for Ceph - vi forventer 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

Vi tjekker også, at pods med klientapplikationen ikke lander på de noder, der er reserveret til Ceph:

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

Dernæst kan yderligere komponenter konfigureres efter behov. Mere information om dem findes i dokumentationen. Vi anbefaler kraftigt at installere dashboard og toolbox til administration.

Rook-hjørner: Strækker Rook sig tilstrækkeligt?

Som det fremgår, er udviklingen af Rook i fuld gang. Men der er stadig problemer, der forhindrer os i fuldstændigt at opgive manuel konfiguration af Ceph:

  • Ingen Rook-driver kan eksportere metrikker for brugen af monterede blokke, hvilket frarøver os overvågning.
  • Flexvolume og CSI kan ikke kan ikke ændre størrelsen på volumener (i modsætning til RBD), så Rook mister 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, så puljen for metadata CephFS opbevares på SSD, mens selve dataene opbevares på HDD, kræver det, at vi manuelt angiver separate enhedsgrupper i CRUSH maps.
  • På trods af at rook-ceph-operator betragtes som stabil, er der i øjeblikket visse problemer ved opgradering af Ceph fra version 13 til 14.

Konklusioner

«Lige nu er Tårnet lukket mod den ydre verden af bønder, men vi tror, at det en dag vil spille en afgørende rolle i partiet!» (citat skabt specifikt til denne artikel)

Projektet Rook har uden tvivl vundet vores hjerter — vi mener, at [med alle sine fordele og ulemper] det helt klart fortjener jeres opmærksomhed.

Vores fremtidige planer er at gøre rook-ceph til et modul for addon-operator, hvilket vil gøre det endnu lettere og mere bekvemt at bruge i vores mange Kubernetes-klynger.

P.S.

Læs også på vores blog:

Kilde: habr.com

Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere 🔥 Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster