Rook of niet, dat is de vraag

Rook of niet, dat is de vraag

Begin deze maand, op 3 mei, werd een grote release aangekondigd van een “beheersysteem voor gedistribueerde dataopslag in Kubernetes” - Roek 1.0.0. Ruim een ​​jaar geleden zijn wij alweer gepubliceerd algemeen overzicht van Rook. Vervolgens werden we gevraagd om over zijn ervaringen te praten gebruik in de praktijk – en nu, net op tijd voor zo’n belangrijke mijlpaal in de geschiedenis van het project, delen we graag onze opgebouwde indrukken.

Kortom, Rook is een set operators voor Kubernetes, dat de volledige controle over de implementatie, het beheer en het automatische herstel van gegevensopslagoplossingen zoals Ceph, EdgeFS, Minio, Cassandra en CockroachDB overneemt.

Op dit moment zijn de meest ontwikkelde (en de enige в stal fase) de oplossing is rook-ceph-operator.

Noot: Onder de significante veranderingen in de Rook 1.0.0 release met betrekking tot Ceph kunnen we ondersteuning voor Ceph Nautilus en de mogelijkheid om NFS voor CephFS- of RGW-buckets te gebruiken vermelden. Wat onder andere opvalt is de rijping van EdgeFS-ondersteuning naar het bètaniveau.

Dus in dit artikel:

  • Laten we de vraag beantwoorden welke voordelen we zien in het gebruik van Rook om Ceph in een Kubernetes-cluster te implementeren;
  • We delen onze ervaringen en indrukken met betrekking tot het gebruik van Rook in productie;
  • Laten we je vertellen waarom we “Ja!” zeggen tegen Rook, en wat onze plannen voor hem zijn.

Laten we beginnen met algemene concepten en theorie.

“Ik heb één Rook in het voordeel!” (onbekende schaker)

Rook of niet, dat is de vraag

Een van de belangrijkste voordelen van Rook is dat de interactie met datastores wordt uitgevoerd via Kubernetes-mechanismen. Dit betekent dat u de opdrachten om Ceph te configureren niet langer van het blad naar de console hoeft te kopiëren.

— Wilt u CephFS in een cluster inzetten? Schrijf gewoon een YAML-bestand!
- Wat? Wilt u ook een objectstore inzetten met S3 API? Schrijf gewoon een tweede YAML-bestand!

Rook is gemaakt volgens alle regels van een typische operator. Interactie met hem vindt plaats via CRD (aangepaste resourcedefinities), waarin we de kenmerken beschrijven van Ceph-entiteiten die we nodig hebben (aangezien dit de enige stabiele implementatie is, gaat dit artikel standaard over Ceph, tenzij expliciet anders vermeld). Volgens de opgegeven parameters voert de operator automatisch de opdrachten uit die nodig zijn voor de configuratie.

Laten we naar de details kijken aan de hand van het voorbeeld van het maken van een Object Store, of beter gezegd: 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 parameters die in de lijst worden aangegeven, zijn vrij standaard en behoeven nauwelijks commentaar, maar het is de moeite waard speciale aandacht te besteden aan de parameters die zijn toegewezen aan sjabloonvariabelen.

Het algemene werkschema komt erop neer dat we bronnen ‘bestellen’ via een YAML-bestand, waarvoor de operator de nodige commando’s uitvoert en ons een ‘niet zo echt’ geheim teruggeeft waarmee we verder kunnen werken. (zie hieronder). En uit de hierboven genoemde variabelen worden het commando en de geheime naam samengesteld.

Wat voor team is dit? Bij het aanmaken van een gebruiker voor objectopslag zal de Rook-operator in de pod het volgende doen:

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

Het resultaat van het uitvoeren van deze opdracht is een JSON-structuur:

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

Keys - welke toekomstige applicaties nodig hebben om toegang te krijgen tot objectopslag via de S3 API. De Rook-operator selecteert ze vriendelijk en plaatst ze in zijn naamruimte in de vorm van een geheim met de naam rook-ceph-object-user-{{ $.Values.s3.crdName }}-{{ $.Values.s3.username }}.

Om de gegevens uit dit geheim te gebruiken, voegt u deze gewoon als omgevingsvariabelen aan de container toe. Als voorbeeld geef ik een sjabloon voor Job, waarin we automatisch buckets maken voor elke gebruikersomgeving:

{{- 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 in deze Job genoemde acties zijn uitgevoerd binnen het raamwerk van Kubernetes. De structuren die worden beschreven in YAML-bestanden worden opgeslagen in een Git-repository en vele malen hergebruikt. We zien dit als een groot pluspunt voor DevOps-ingenieurs en het CI/CD-proces als geheel.

Blij met Rook en Rados

Het gebruik van de combinatie Ceph + RBD legt bepaalde beperkingen op aan het monteren van volumes op pods.

In het bijzonder moet de naamruimte een geheim bevatten voor toegang tot Ceph, zodat stateful applicaties kunnen functioneren. Het is prima als je 2-3 omgevingen in hun naamruimten hebt: je kunt het geheim handmatig kopiëren. Maar wat als er voor elke feature een aparte omgeving met een eigen naamruimte wordt gecreëerd voor ontwikkelaars?

Wij hebben dit probleem zelf opgelost met behulp van shell-operator, die geheimen automatisch naar nieuwe naamruimten kopieerde (een voorbeeld van zo'n hook wordt beschreven in dit 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

Bij gebruik van Rook bestaat dit probleem echter eenvoudigweg niet. Het montageproces vindt plaats met behulp van eigen stuurprogramma's op basis van Flexvolume of CSI (nog in bètafase) en vereist daarom geen geheimen.

Rook lost veel problemen automatisch op, wat ons aanmoedigt om het in nieuwe projecten te gebruiken.

Belegering van Rook

Laten we het praktische gedeelte afronden door Rook en Ceph in te zetten, zodat we onze eigen experimenten kunnen uitvoeren. Om het gemakkelijker te maken deze onneembare toren te bestormen, hebben de ontwikkelaars een Helm-pakket voorbereid. Laten we het downloaden:

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

In bestand rook-ceph/values.yaml je kunt veel verschillende instellingen vinden. Het allerbelangrijkste is het specificeren van toleranties voor agenten en zoeken. We hebben in detail beschreven waarvoor het taints/tolerations-mechanisme kan worden gebruikt dit artikel.

Kortom, we willen niet dat de clienttoepassingspods zich op dezelfde knooppunten bevinden als de gegevensopslagschijven. De reden is simpel: op deze manier heeft het werk van Rook-agenten geen invloed op de applicatie zelf.

Open dus het bestand rook-ceph/values.yaml met je favoriete editor en voeg aan het einde het volgende blok toe:

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

Voeg voor elk knooppunt dat is gereserveerd voor gegevensopslag de bijbehorende taint toe:

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

Installeer vervolgens het Helm-diagram met de opdracht:

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

Nu moet u een cluster maken en de locatie opgeven 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-status controleren - verwacht het te zien 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

Laten we tegelijkertijd controleren of de pods met de clientapplicatie niet op knooppunten terechtkomen die zijn gereserveerd voor Ceph:

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

Verder kunnen aanvullende componenten naar wens worden geconfigureerd. Meer details over hen zijn aangegeven in documentatie. Voor het beheer raden wij ten zeerste aan om het dashboard en de toolbox te installeren.

Rook en haken: is Rook genoeg voor alles?

Zoals je ziet is de ontwikkeling van Rook in volle gang. Maar er zijn nog steeds problemen waardoor we de handmatige configuratie van Ceph niet volledig kunnen verlaten:

  • Geen Rook-chauffeur kan niet exporteer statistieken over het gebruik van gemonteerde blokken, waardoor we geen controle meer hebben.
  • Flexvolume en CSI weet niet hoe verander de grootte van volumes (in tegenstelling tot dezelfde RBD), zodat Rook verstoken blijft van een nuttig (en soms essentieel noodzakelijk!) hulpmiddel.
  • Rook is nog steeds niet zo flexibel als gewone Ceph. Als we de pool willen configureren zodat CephFS-metagegevens op SSD worden opgeslagen, en de gegevens zelf op HDD worden opgeslagen, zullen we afzonderlijke groepen apparaten handmatig in CRUSH-kaarten moeten registreren.
  • Ondanks het feit dat rook-ceph-operator als stabiel wordt beschouwd, zijn er momenteel enkele problemen bij het upgraden van Ceph van versie 13 naar 14.

Bevindingen

“Op dit moment is Rook door pionnen afgesloten van de buitenwereld, maar wij geloven dat ze ooit een beslissende rol zal spelen in het spel!” (citaat speciaal voor dit artikel uitgevonden)

Het Rook-project heeft ongetwijfeld ons hart veroverd; wij zijn van mening dat het [met al zijn voor- en nadelen] zeker uw aandacht verdient.

Onze toekomstplannen komen erop neer dat we van Rook-ceph een module maken add-on-operator, wat het gebruik ervan in onze talrijke Kubernetes-clusters nog eenvoudiger en handiger zal maken.

PS

Lees ook op onze blog:

Bron: www.habr.com

Voeg een reactie